mirror of
https://gitlab.rtems.org/rtems/rtos/rtems.git
synced 2026-11-09 08:37:58 +08:00
Remove.
This commit is contained in:
1 parent
c7bdd7749c
commit
dc35201765
36 files changed
-8068
No files matched your search
@@ -1,12 +0,0 @@
|
||||
dnl $Id$
|
||||
|
||||
AC_DEFUN([RTEMS_ENABLE_SHTTPD],
|
||||
[
|
||||
AC_ARG_ENABLE([shttpd],
|
||||
AS_HELP_STRING([--enable-shttpd],[enable (small httpd) shttpd (DEPRECATED)]),
|
||||
[case "${enableval}" in
|
||||
yes) enable_shttpd=yes ;;
|
||||
no) enable_shttpd=no ;;
|
||||
*) AC_MSG_ERROR(bad value ${enableval} for enable-shttpd option) ;;
|
||||
esac],[enable_shttpd=no])
|
||||
])
|
||||
@@ -1,2 +0,0 @@
|
||||
Makefile.in
|
||||
Makefile
|
||||
@@ -1,70 +0,0 @@
|
||||
# DEPRECATED, don't use.
|
||||
|
||||
include $(top_srcdir)/automake/compile.am
|
||||
|
||||
if LIBSHTTPD
|
||||
include_shttpddir = $(includedir)/shttpd
|
||||
|
||||
project_lib_LIBRARIES = libshttpd.a
|
||||
libshttpd_a_CPPFLAGS = $(AM_CPPFLAGS) -DHAVE_MD5
|
||||
|
||||
# HACK ALERT:
|
||||
# prefix all non-public symbols with _shttp_
|
||||
# FIXME: There must be something better than this
|
||||
libshttpd_a_CPPFLAGS += -Dcheck_authorization=_shttpd_check_authorization
|
||||
libshttpd_a_CPPFLAGS += -Ddecode_url_encoded_string=_shttpd_decode_url_encoded_string
|
||||
libshttpd_a_CPPFLAGS += -Dedit_passwords=_shttpd_edit_passwords
|
||||
libshttpd_a_CPPFLAGS += -Delog=_shttpd_elog
|
||||
libshttpd_a_CPPFLAGS += -Dget_dir=_shttpd_get_dir
|
||||
libshttpd_a_CPPFLAGS += -Dget_file=_shttpd_get_file
|
||||
libshttpd_a_CPPFLAGS += -Dget_headers_len=_shttpd_get_headers_len
|
||||
libshttpd_a_CPPFLAGS += -Dget_mime_type=_shttpd_get_mime_type
|
||||
libshttpd_a_CPPFLAGS += -Dinit_from_argc_argv=_shttpd_init_from_argc_argv
|
||||
libshttpd_a_CPPFLAGS += -Dis_authorized_for_put=_shttpd_is_authorized_for_put
|
||||
libshttpd_a_CPPFLAGS += -Dis_registered_uri=_shttpd_is_registered_uri
|
||||
libshttpd_a_CPPFLAGS += -Dlog_access=_shttpd_log_access
|
||||
libshttpd_a_CPPFLAGS += -Dparse_headers=_shttpd_parse_headers
|
||||
libshttpd_a_CPPFLAGS += -Dput_dir=_shttpd_put_dir
|
||||
libshttpd_a_CPPFLAGS += -Dsend_authorization_request=_shttpd_send_authorization_request
|
||||
libshttpd_a_CPPFLAGS += -Dsend_server_error=_shttpd_send_server_error
|
||||
libshttpd_a_CPPFLAGS += -Dset_close_on_exec=_shttpd_set_close_on_exec
|
||||
libshttpd_a_CPPFLAGS += -Dset_mime_types=_shttpd_set_mime_types
|
||||
libshttpd_a_CPPFLAGS += -Dset_non_blocking_mode=_shttpd_set_non_blocking_mode
|
||||
libshttpd_a_CPPFLAGS += -Dsetup_embedded_stream=_shttpd_setup_embedded_stream
|
||||
libshttpd_a_CPPFLAGS += -Dstop_stream=_shttpd_stop_stream
|
||||
libshttpd_a_CPPFLAGS += -Dusage=_shttpd_usage
|
||||
|
||||
libshttpd_a_CPPFLAGS += -Dknown_http_methods=_shttpd_known_http_methods
|
||||
libshttpd_a_CPPFLAGS += -Doptions=_shttpd_options
|
||||
libshttpd_a_CPPFLAGS += -Dio_file=_shttpd_io_file
|
||||
libshttpd_a_CPPFLAGS += -Dio_socket=_shttpd_io_socket
|
||||
libshttpd_a_CPPFLAGS += -Dio_embedded=_shttpd_io_embedded
|
||||
libshttpd_a_CPPFLAGS += -Dio_dir=_shttpd_io_dir
|
||||
libshttpd_a_CPPFLAGS += -Dio_cgi=_shttpd_io_cgi
|
||||
|
||||
libshttpd_a_CPPFLAGS += -Dcurrent_time=_shttpd_current_time
|
||||
libshttpd_a_CPPFLAGS += -Dtz_offset=_shttpd_tz_offset
|
||||
|
||||
SRCS= string.c shttpd.c log.c auth.c md5.c \
|
||||
cgi.c mime_type.c config.c \
|
||||
io_file.c io_socket.c io_ssl.c io_emb.c io_dir.c io_cgi.c
|
||||
HDRS= defs.h llist.h shttpd.h std_includes.h io.h md5.h ssl.h \
|
||||
compat_unix.h compat_win32.h compat_rtems.h
|
||||
|
||||
libshttpd_a_SOURCES = $(SRCS) $(HDRS)
|
||||
libshttpd_a_SOURCES += compat_rtems.c
|
||||
include_shttpd_HEADERS = shttpd.h
|
||||
|
||||
# Possible flags: (in brackets are rough numbers for 'gcc -O2' on i386)
|
||||
# -DHAVE_MD5 - use system md5 library (-2kb)
|
||||
# -DNDEBUG - strip off all debug code (-5kb)
|
||||
# -D_DEBUG - build debug version (very noisy) (+6kb)
|
||||
# -DNO_CGI - disable CGI support (-5kb)
|
||||
# -DNO_SSL - disable SSL functionality (-2kb)
|
||||
# -DNO_AUTH - disable authorization support (-4kb)
|
||||
# -DNO_GUI - Win32 only. Build console version, no GUI
|
||||
# -DCONFIG=\"file\" - use `file' as the default config file
|
||||
endif
|
||||
|
||||
include $(srcdir)/preinstall.am
|
||||
include $(top_srcdir)/automake/local.am
|
||||
@@ -1,50 +0,0 @@
|
||||
SRCS= string.c shttpd.c log.c auth.c md5.c \
|
||||
cgi.c mime_type.c config.c \
|
||||
io_file.c io_socket.c io_ssl.c io_emb.c io_dir.c io_cgi.c
|
||||
HDRS= defs.h llist.h shttpd.h std_includes.h io.h md5.h ssl.h \
|
||||
compat_unix.h compat_win32.h compat_rtems.h
|
||||
PROG= shttpd
|
||||
|
||||
# Possible flags: (in brackets are rough numbers for 'gcc -O2' on i386)
|
||||
# -DHAVE_MD5 - use system md5 library (-2kb)
|
||||
# -DNDEBUG - strip off all debug code (-5kb)
|
||||
# -D_DEBUG - build debug version (very noisy) (+6kb)
|
||||
# -DNO_CGI - disable CGI support (-5kb)
|
||||
# -DNO_SSL - disable SSL functionality (-2kb)
|
||||
# -DNO_AUTH - disable authorization support (-4kb)
|
||||
# -DNO_GUI - Win32 only. Build console version, no GUI
|
||||
# -DCONFIG=\"file\" - use `file' as the default config file
|
||||
|
||||
CL_FLAGS= /O1 /MD /TC /nologo /DNDEBUG
|
||||
|
||||
all:
|
||||
@echo "make (unix|msvc|mingw|rtems)"
|
||||
|
||||
unix:
|
||||
$(CC) -c $(CFLAGS) -DEMBEDDED $(SRCS) compat_unix.c
|
||||
$(AR) -r lib$(PROG).a *.o && ranlib lib$(PROG).a
|
||||
$(CC) $(CFLAGS) $(SRCS) compat_unix.c standalone.c -o $(PROG) $(LIBS)
|
||||
|
||||
rtems:
|
||||
$(CC) -c $(CFLAGS) -DEMBEDDED $(SRCS) compat_rtems.c
|
||||
$(AR) -r lib$(PROG).a *.o && ranlib lib$(PROG).a
|
||||
|
||||
msvc:
|
||||
cl $(SRCS) /c $(CL_FLAGS) /DEMBEDDED
|
||||
lib *.obj /out:shttpd.lib
|
||||
rc resources.rc
|
||||
cl $(SRCS) compat_win32.c standalone.c $(CL_FLAGS) \
|
||||
/link resources.res /out:$(PROG).exe /machine:ix86
|
||||
|
||||
mingw:
|
||||
$(CC) -c $(CFLAGS) -DEMBEDDED $(SRCS) compat_win32.c
|
||||
$(AR) -r lib$(PROG).a *.o && ranlib lib$(PROG).a
|
||||
windres resources.rc resources.o
|
||||
$(CC) $(CFLAGS) $(SRCS) compat_win32.c standalone.c resources.o -o $(PROG) $(LIBS) -lws2_32 -lcomdlg32 -lcomctl32
|
||||
|
||||
man:
|
||||
cat shttpd.1 | tbl | groff -man -Tascii | col -b > shttpd.1.txt
|
||||
cat shttpd.1 | tbl | groff -man -Tascii | less
|
||||
|
||||
clean:
|
||||
rm -rf *.o *.core $(PROG) lib$(PROG).a
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -1,200 +0,0 @@
|
||||
/**********************************************************************
|
||||
*
|
||||
* rtems shttpd management
|
||||
*
|
||||
* FILE NAME : rtems_shttpd.c
|
||||
*
|
||||
* AUTHOR : Steven Johnson
|
||||
*
|
||||
* DESCRIPTION : Defines the interface functions to the shttp daemon
|
||||
*
|
||||
* REVISION : $Id$
|
||||
*
|
||||
* COMMENTS :
|
||||
*
|
||||
**********************************************************************/
|
||||
|
||||
/**********************************************************************
|
||||
* INCLUDED MODULES
|
||||
**********************************************************************/
|
||||
#include <rtems.h>
|
||||
#include "defs.h"
|
||||
|
||||
#define MAX_WEB_BASE_PATH_LENGTH 256
|
||||
#define MIN_SHTTPD_STACK (8*1024)
|
||||
|
||||
typedef struct RTEMS_HTTPD_ARGS {
|
||||
rtems_shttpd_init init_callback;
|
||||
rtems_shttpd_addpages addpages_callback;
|
||||
unsigned int port;
|
||||
char webroot[MAX_WEB_BASE_PATH_LENGTH];
|
||||
} RTEMS_HTTPD_ARGS;
|
||||
|
||||
static int rtems_webserver_running = FALSE; /* not running. */
|
||||
|
||||
static rtems_task rtems_httpd_daemon(rtems_task_argument args)
|
||||
{
|
||||
RTEMS_HTTPD_ARGS *httpd_args = (RTEMS_HTTPD_ARGS*)args;
|
||||
|
||||
struct shttpd_ctx *ctx;
|
||||
|
||||
if (httpd_args != NULL)
|
||||
if (httpd_args->init_callback != NULL)
|
||||
httpd_args->init_callback();
|
||||
|
||||
/**************************************
|
||||
* Initialize the web server
|
||||
*/
|
||||
/*
|
||||
* Initialize SHTTPD context.
|
||||
* Set WWW root to current WEB_ROOT_PATH.
|
||||
*/
|
||||
ctx = shttpd_init(NULL, "document_root", httpd_args->webroot, NULL);
|
||||
|
||||
if (httpd_args != NULL)
|
||||
if (httpd_args->addpages_callback != NULL)
|
||||
httpd_args->addpages_callback(ctx);
|
||||
|
||||
/* Finished with args, so free them */
|
||||
if (httpd_args != NULL)
|
||||
free(httpd_args);
|
||||
|
||||
/* Open listening socket */
|
||||
shttpd_listen(ctx, httpd_args->port);
|
||||
|
||||
rtems_webserver_running = TRUE;
|
||||
|
||||
/* Serve connections infinitely until someone kills us */
|
||||
while (rtems_webserver_running)
|
||||
shttpd_poll(ctx, 1000);
|
||||
|
||||
/* Unreached, because we will be killed by a signal */
|
||||
shttpd_fini(ctx);
|
||||
|
||||
rtems_task_delete( RTEMS_SELF );
|
||||
}
|
||||
|
||||
rtems_status_code rtems_initialize_webserver(
|
||||
rtems_task_priority initial_priority,
|
||||
size_t stack_size,
|
||||
rtems_mode initial_modes,
|
||||
rtems_attribute attribute_set,
|
||||
rtems_shttpd_init init_callback,
|
||||
rtems_shttpd_addpages addpages_callback,
|
||||
char *webroot,
|
||||
unsigned int port
|
||||
)
|
||||
{
|
||||
rtems_status_code sc;
|
||||
rtems_id tid;
|
||||
RTEMS_HTTPD_ARGS *args;
|
||||
|
||||
if (stack_size < MIN_SHTTPD_STACK)
|
||||
stack_size = MIN_SHTTPD_STACK;
|
||||
|
||||
args = malloc(sizeof(RTEMS_HTTPD_ARGS));
|
||||
|
||||
if (args != NULL) {
|
||||
args->init_callback = init_callback;
|
||||
args->addpages_callback = addpages_callback;
|
||||
args->port = port;
|
||||
strncpy(args->webroot,webroot,MAX_WEB_BASE_PATH_LENGTH);
|
||||
|
||||
sc = rtems_task_create(rtems_build_name('H', 'T', 'P', 'D'),
|
||||
initial_priority,
|
||||
stack_size,
|
||||
initial_modes,
|
||||
attribute_set,
|
||||
&tid);
|
||||
|
||||
if (sc == RTEMS_SUCCESSFUL) {
|
||||
sc = rtems_task_start(tid, rtems_httpd_daemon, (rtems_task_argument)args);
|
||||
}
|
||||
} else {
|
||||
sc = RTEMS_NO_MEMORY;
|
||||
}
|
||||
|
||||
return sc;
|
||||
}
|
||||
|
||||
void rtems_terminate_webserver(void)
|
||||
{
|
||||
rtems_webserver_running = FALSE; /* not running, so terminate */
|
||||
}
|
||||
|
||||
int rtems_webserver_ok(void)
|
||||
{
|
||||
return rtems_webserver_running;
|
||||
}
|
||||
|
||||
void
|
||||
set_close_on_exec(int fd)
|
||||
{
|
||||
/*
|
||||
* RTEMS Does not have a functional "execve"
|
||||
* so technically this call does not do anything,
|
||||
* but it doesnt hurt either.
|
||||
*/
|
||||
(void) fcntl(fd, F_SETFD, FD_CLOEXEC);
|
||||
}
|
||||
#ifndef __rtems__
|
||||
int
|
||||
my_stat(const char *path, struct stat *stp)
|
||||
{
|
||||
return (stat(path, stp));
|
||||
}
|
||||
|
||||
int
|
||||
my_open(const char *path, int flags, int mode)
|
||||
{
|
||||
return (open(path, flags, mode));
|
||||
}
|
||||
|
||||
int
|
||||
my_remove(const char *path)
|
||||
{
|
||||
return (remove(path));
|
||||
}
|
||||
|
||||
int
|
||||
my_rename(const char *path1, const char *path2)
|
||||
{
|
||||
return (rename(path1, path2));
|
||||
}
|
||||
|
||||
int
|
||||
my_mkdir(const char *path, int mode)
|
||||
{
|
||||
return (mkdir(path, mode));
|
||||
}
|
||||
|
||||
char *
|
||||
my_getcwd(char *buffer, int maxlen)
|
||||
{
|
||||
return (getcwd(buffer, maxlen));
|
||||
}
|
||||
#endif
|
||||
int
|
||||
set_non_blocking_mode(int fd)
|
||||
{
|
||||
int ret = -1;
|
||||
int flags;
|
||||
|
||||
if ((flags = fcntl(fd, F_GETFL, 0)) == -1) {
|
||||
DBG(("nonblock: fcntl(F_GETFL): %d", ERRNO));
|
||||
} else if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) != 0) {
|
||||
DBG(("nonblock: fcntl(F_SETFL): %d", ERRNO));
|
||||
} else {
|
||||
ret = 0; /* Success */
|
||||
}
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
#if !defined(NO_CGI)
|
||||
int
|
||||
spawn_process(struct conn *c, const char *prog, char *envblk, char **envp)
|
||||
{
|
||||
return (-1); // RTEMS does not have subprocess support as standard.
|
||||
}
|
||||
#endif
|
||||
@@ -1,69 +0,0 @@
|
||||
/**
|
||||
* @file rtems/rtems-shttpd.h
|
||||
*/
|
||||
|
||||
#ifndef _rtems_rtems_webserver_h
|
||||
#define _rtems_rtems_webserver_h
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "shttpd.h"
|
||||
|
||||
#include <rtems.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/select.h>
|
||||
#include <netinet/in.h>
|
||||
#include <dirent.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
/* RTEMS is an Real Time Embedded operating system, for operation in hardware.
|
||||
It does not have SSL or CGI support, as it does not have dynamic library
|
||||
loading or sub-processes. */
|
||||
#define EMBEDDED
|
||||
#define NO_SSL
|
||||
#define NO_CGI
|
||||
|
||||
#define DIRSEP '/'
|
||||
#define IS_DIRSEP_CHAR(c) ((c) == '/')
|
||||
#define O_BINARY 0
|
||||
#define closesocket(a) close(a)
|
||||
#define ERRNO errno
|
||||
|
||||
/* RTEMS version is Thread Safe */
|
||||
#define InitializeCriticalSection(x) rtems_semaphore_create( \
|
||||
rtems_build_name('H','T','P','X'), \
|
||||
1, /* Not Held Yet.*/ \
|
||||
RTEMS_FIFO | \
|
||||
RTEMS_BINARY_SEMAPHORE, \
|
||||
0, \
|
||||
x);
|
||||
#define EnterCriticalSection(x) rtems_semaphore_obtain(*(x),RTEMS_WAIT,RTEMS_NO_TIMEOUT)
|
||||
#define LeaveCriticalSection(x) rtems_semaphore_release(*(x))
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef void (*rtems_shttpd_addpages)(struct shttpd_ctx *ctx);
|
||||
typedef void (*rtems_shttpd_init)(void);
|
||||
|
||||
rtems_status_code rtems_initialize_webserver(rtems_task_priority initial_priority,
|
||||
size_t stack_size,
|
||||
rtems_mode initial_modes,
|
||||
rtems_attribute attribute_set,
|
||||
rtems_shttpd_init init_callback,
|
||||
rtems_shttpd_addpages addpages_callback,
|
||||
char *webroot,
|
||||
unsigned int port
|
||||
);
|
||||
void rtems_terminate_webserver(void);
|
||||
int rtems_webserver_ok(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@@ -1,123 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2005 Sergey Lyubka <valenok@gmail.com>
|
||||
* All rights reserved
|
||||
*
|
||||
* "THE BEER-WARE LICENSE" (Revision 42):
|
||||
* Sergey Lyubka wrote this file. As long as you retain this notice you
|
||||
* can do whatever you want with this stuff. If we meet some day, and you think
|
||||
* this stuff is worth it, you can buy me a beer in return.
|
||||
*/
|
||||
|
||||
#include "defs.h"
|
||||
|
||||
void
|
||||
set_close_on_exec(int fd)
|
||||
{
|
||||
(void) fcntl(fd, F_SETFD, FD_CLOEXEC);
|
||||
}
|
||||
|
||||
int
|
||||
my_stat(const char *path, struct stat *stp)
|
||||
{
|
||||
return (stat(path, stp));
|
||||
}
|
||||
|
||||
int
|
||||
my_open(const char *path, int flags, int mode)
|
||||
{
|
||||
return (open(path, flags, mode));
|
||||
}
|
||||
|
||||
int
|
||||
my_remove(const char *path)
|
||||
{
|
||||
return (remove(path));
|
||||
}
|
||||
|
||||
int
|
||||
my_rename(const char *path1, const char *path2)
|
||||
{
|
||||
return (rename(path1, path2));
|
||||
}
|
||||
|
||||
int
|
||||
my_mkdir(const char *path, int mode)
|
||||
{
|
||||
return (mkdir(path, mode));
|
||||
}
|
||||
|
||||
char *
|
||||
my_getcwd(char *buffer, int maxlen)
|
||||
{
|
||||
return (getcwd(buffer, maxlen));
|
||||
}
|
||||
|
||||
int
|
||||
set_non_blocking_mode(int fd)
|
||||
{
|
||||
int ret = -1;
|
||||
int flags;
|
||||
|
||||
if ((flags = fcntl(fd, F_GETFL, 0)) == -1) {
|
||||
DBG(("nonblock: fcntl(F_GETFL): %d", ERRNO));
|
||||
} else if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) != 0) {
|
||||
DBG(("nonblock: fcntl(F_SETFL): %d", ERRNO));
|
||||
} else {
|
||||
ret = 0; /* Success */
|
||||
}
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
#ifndef NO_CGI
|
||||
int
|
||||
spawn_process(struct conn *c, const char *prog, char *envblk,
|
||||
char *envp[], int sock, const char *dir)
|
||||
{
|
||||
int ret;
|
||||
pid_t pid;
|
||||
|
||||
envblk = NULL; /* unused */
|
||||
|
||||
if ((pid = vfork()) == -1) {
|
||||
|
||||
ret = -1;
|
||||
elog(E_LOG, c, "redirect: fork: %s", strerror(errno));
|
||||
|
||||
} else if (pid == 0) {
|
||||
|
||||
/* Child */
|
||||
(void) chdir(dir);
|
||||
(void) dup2(sock, 0);
|
||||
(void) dup2(sock, 1);
|
||||
(void) closesocket(sock);
|
||||
|
||||
/* If error file is specified, send errors there */
|
||||
if (c->ctx->error_log)
|
||||
(void) dup2(fileno(c->ctx->error_log), 2);
|
||||
|
||||
/* Execute CGI program */
|
||||
if (c->ctx->cgi_interpreter == NULL) {
|
||||
(void) execle(prog, prog, NULL, envp);
|
||||
elog(E_FATAL, c, "redirect: exec(%s)", prog);
|
||||
} else {
|
||||
(void) execle(c->ctx->cgi_interpreter,
|
||||
c->ctx->cgi_interpreter, prog, NULL, envp);
|
||||
elog(E_FATAL, c, "redirect: exec(%s %s)",
|
||||
c->ctx->cgi_interpreter, prog);
|
||||
}
|
||||
|
||||
/* UNREACHED */
|
||||
ret = -1;
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
} else {
|
||||
|
||||
/* Parent */
|
||||
ret = 0;
|
||||
(void) closesocket(sock);
|
||||
}
|
||||
|
||||
return (ret);
|
||||
}
|
||||
#endif /* !NO_CGI */
|
||||
@@ -1,33 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2007 Sergey Lyubka <valenok@gmail.com>
|
||||
* All rights reserved
|
||||
*
|
||||
* "THE BEER-WARE LICENSE" (Revision 42):
|
||||
* Sergey Lyubka wrote this file. As long as you retain this notice you
|
||||
* can do whatever you want with this stuff. If we meet some day, and you think
|
||||
* this stuff is worth it, you can buy me a beer in return.
|
||||
*/
|
||||
|
||||
#include <sys/wait.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/mman.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <pwd.h>
|
||||
#include <unistd.h>
|
||||
#include <dirent.h>
|
||||
#include <dlfcn.h>
|
||||
#define SSL_LIB "libssl.so"
|
||||
#define DIRSEP '/'
|
||||
#define IS_DIRSEP_CHAR(c) ((c) == '/')
|
||||
#define O_BINARY 0
|
||||
#define closesocket(a) close(a)
|
||||
#define ERRNO errno
|
||||
#define NO_GUI
|
||||
|
||||
#define InitializeCriticalSection(x) /* FIXME UNIX version is not MT safe */
|
||||
#define EnterCriticalSection(x)
|
||||
#define LeaveCriticalSection(x)
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,93 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2007 Sergey Lyubka <valenok@gmail.com>
|
||||
* All rights reserved
|
||||
*
|
||||
* "THE BEER-WARE LICENSE" (Revision 42):
|
||||
* Sergey Lyubka wrote this file. As long as you retain this notice you
|
||||
* can do whatever you want with this stuff. If we meet some day, and you think
|
||||
* this stuff is worth it, you can buy me a beer in return.
|
||||
*/
|
||||
|
||||
/* Tip from Justin Maximilian, suppress errors from winsock2.h */
|
||||
#define _WINSOCKAPI_
|
||||
|
||||
#include <windows.h>
|
||||
#include <winsock2.h>
|
||||
#include <commctrl.h>
|
||||
#include <winnls.h>
|
||||
#include <shlobj.h>
|
||||
#include <shellapi.h>
|
||||
|
||||
#ifndef _WIN32_WCE
|
||||
|
||||
#ifdef _MSC_VER /* pragmas not valid on MinGW */
|
||||
#pragma comment(lib,"ws2_32")
|
||||
#pragma comment(lib,"user32")
|
||||
#pragma comment(lib,"comctl32")
|
||||
#pragma comment(lib,"comdlg32")
|
||||
#pragma comment(lib,"shell32")
|
||||
#ifdef NO_GUI
|
||||
#pragma comment(linker,"/subsystem:console")
|
||||
#else
|
||||
#pragma comment(linker,"/subsystem:windows")
|
||||
#endif /* NO_GUI */
|
||||
#endif /* _MSC_VER */
|
||||
#include <process.h>
|
||||
#include <direct.h>
|
||||
#include <io.h>
|
||||
|
||||
#else /* _WIN32_WCE */
|
||||
|
||||
/* Windows CE-specific definitions */
|
||||
#define NO_CGI /* WinCE has no pipes */
|
||||
#define NO_GUI /* temporarily until it is fixed */
|
||||
#pragma comment(lib,"ws2")
|
||||
/* WinCE has both Unicode and ANSI versions of GetProcAddress */
|
||||
#undef GetProcAddress
|
||||
#define GetProcAddress GetProcAddressA
|
||||
#include "compat_wince.h"
|
||||
|
||||
#endif /* _WIN32_WCE */
|
||||
|
||||
#define ERRNO GetLastError()
|
||||
#define NO_SOCKLEN_T
|
||||
#define SSL_LIB L"libssl32.dll"
|
||||
#define DIRSEP '\\'
|
||||
#define IS_DIRSEP_CHAR(c) ((c) == '/' || (c) == '\\')
|
||||
#define O_NONBLOCK 0
|
||||
#define EWOULDBLOCK WSAEWOULDBLOCK
|
||||
#define snprintf _snprintf
|
||||
#define vsnprintf _vsnprintf
|
||||
#define mkdir(x,y) _mkdir(x)
|
||||
#define dlopen(x,y) LoadLibraryW(x)
|
||||
#define dlsym(x,y) (void *) GetProcAddress(x,y)
|
||||
#define _POSIX_
|
||||
|
||||
#ifdef __LCC__
|
||||
#include <stdint.h>
|
||||
#endif /* __LCC__ */
|
||||
|
||||
#ifdef _MSC_VER /* MinGW already has these */
|
||||
typedef unsigned int uint32_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef __int64 uint64_t;
|
||||
#define S_ISDIR(x) ((x) & _S_IFDIR)
|
||||
#endif /* _MSC_VER */
|
||||
|
||||
/*
|
||||
* POSIX dirent interface
|
||||
*/
|
||||
struct dirent {
|
||||
char d_name[FILENAME_MAX];
|
||||
};
|
||||
|
||||
typedef struct DIR {
|
||||
HANDLE handle;
|
||||
WIN32_FIND_DATAW info;
|
||||
struct dirent result;
|
||||
char *name;
|
||||
} DIR;
|
||||
|
||||
extern DIR *opendir(const char *name);
|
||||
extern int closedir(DIR *dir);
|
||||
extern struct dirent *readdir(DIR *dir);
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,145 +0,0 @@
|
||||
|
||||
#ifndef INCLUDE_WINCE_COMPAT_H
|
||||
#define INCLUDE_WINCE_COMPAT_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*** ANSI C library ***/
|
||||
|
||||
/* Missing ANSI C definitions */
|
||||
|
||||
#define BUFSIZ 4096
|
||||
|
||||
#define ENOMEM ERROR_NOT_ENOUGH_MEMORY
|
||||
#define EBADF ERROR_INVALID_HANDLE
|
||||
#define EINVAL ERROR_INVALID_PARAMETER
|
||||
#define ENOENT ERROR_FILE_NOT_FOUND
|
||||
#define ERANGE ERROR_INSUFFICIENT_BUFFER
|
||||
#define EINTR WSAEINTR
|
||||
|
||||
/*
|
||||
* Because we need a per-thread errno, we define a function
|
||||
* pointer that we can call to return a pointer to the errno
|
||||
* for the current thread. Then we define a macro for errno
|
||||
* that dereferences this function's result.
|
||||
*
|
||||
* This makes it syntactically just like the "real" errno.
|
||||
*
|
||||
* Using a function pointer allows us to use a very fast
|
||||
* function when there are no threads running and a slower
|
||||
* function when there are multiple threads running.
|
||||
*/
|
||||
void __WinCE_Errno_New_Thread(int *Errno_Pointer);
|
||||
void __WinCE_Errno_Thread_Exit(void);
|
||||
extern int *(*__WinCE_Errno_Pointer_Function)(void);
|
||||
|
||||
#define errno (*(*__WinCE_Errno_Pointer_Function)())
|
||||
|
||||
char *strerror(int errnum);
|
||||
|
||||
struct tm {
|
||||
int tm_sec; /* seconds after the minute - [0,59] */
|
||||
int tm_min; /* minutes after the hour - [0,59] */
|
||||
int tm_hour; /* hours since midnight - [0,23] */
|
||||
int tm_mday; /* day of the month - [1,31] */
|
||||
int tm_mon; /* months since January - [0,11] */
|
||||
int tm_year; /* years since 1900 */
|
||||
int tm_wday; /* days since Sunday - [0,6] */
|
||||
int tm_yday; /* days since January 1 - [0,365] */
|
||||
int tm_isdst; /* daylight savings time flag */
|
||||
};
|
||||
|
||||
struct tm *gmtime(const time_t *TimeP); /* for future use */
|
||||
struct tm *localtime(const time_t *TimeP);
|
||||
time_t mktime(struct tm *tm);
|
||||
time_t time(time_t *TimeP);
|
||||
|
||||
size_t strftime(char *s, size_t maxsize, const char *format, const struct tm *tim_p);
|
||||
|
||||
int _wrename(const wchar_t *oldname, const wchar_t *newname);
|
||||
int _wremove(const wchar_t *filename);
|
||||
|
||||
/* Environment variables are not supported */
|
||||
#define getenv(x) (NULL)
|
||||
|
||||
/* Redefine fileno so that it returns an integer */
|
||||
#undef fileno
|
||||
#define fileno(f) (int)_fileno(f)
|
||||
|
||||
/* Signals are not supported */
|
||||
#define signal(num, handler) (0)
|
||||
#define SIGTERM 0
|
||||
#define SIGINT 0
|
||||
|
||||
|
||||
/*** POSIX API ***/
|
||||
|
||||
/* Missing POSIX definitions */
|
||||
|
||||
#define FILENAME_MAX MAX_PATH
|
||||
|
||||
struct _stat {
|
||||
unsigned long st_size;
|
||||
unsigned long st_ino;
|
||||
int st_mode;
|
||||
unsigned long st_atime;
|
||||
unsigned long st_mtime;
|
||||
unsigned long st_ctime;
|
||||
unsigned short st_dev;
|
||||
unsigned short st_nlink;
|
||||
unsigned short st_uid;
|
||||
unsigned short st_gid;
|
||||
};
|
||||
|
||||
#define S_IFMT 0170000
|
||||
#define S_IFDIR 0040000
|
||||
#define S_IFREG 0100000
|
||||
#define S_IEXEC 0000100
|
||||
#define S_IWRITE 0000200
|
||||
#define S_IREAD 0000400
|
||||
|
||||
#define _S_IFDIR S_IFDIR /* MSVCRT compatibilit */
|
||||
|
||||
int _fstat(int handle, struct _stat *buffer);
|
||||
int _wstat(const wchar_t *path, struct _stat *buffer);
|
||||
|
||||
#define stat _stat /* NOTE: applies to _stat() and also struct _stat */
|
||||
#define fstat _fstat
|
||||
|
||||
#define O_RDWR (1<<0)
|
||||
#define O_RDONLY (2<<0)
|
||||
#define O_WRONLY (3<<0)
|
||||
#define O_MODE_MASK (3<<0)
|
||||
#define O_TRUNC (1<<2)
|
||||
#define O_EXCL (1<<3)
|
||||
#define O_CREAT (1<<4)
|
||||
#define O_BINARY 0
|
||||
|
||||
int _wopen(const wchar_t *filename, int oflag, ...);
|
||||
int _close(int handle);
|
||||
int _write(int handle, const void *buffer, unsigned int count);
|
||||
int _read(int handle, void *buffer, unsigned int count);
|
||||
long _lseek(int handle, long offset, int origin);
|
||||
|
||||
#define close _close
|
||||
#define write _write
|
||||
#define read _read
|
||||
#define lseek _lseek
|
||||
|
||||
/* WinCE has only a Unicode version of this function */
|
||||
FILE *fdopen(int handle, const char *mode);
|
||||
|
||||
int _wmkdir(const wchar_t *dirname);
|
||||
|
||||
/* WinCE has no concept of current directory so we return a constant path */
|
||||
wchar_t *_wgetcwd(wchar_t *buffer, int maxlen);
|
||||
|
||||
#define freopen(path, mode, stream) assert(0)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* INCLUDE_WINCE_COMPAT_H */
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -1,97 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2005 Sergey Lyubka <valenok@gmail.com>
|
||||
* All rights reserved
|
||||
*
|
||||
* "THE BEER-WARE LICENSE" (Revision 42):
|
||||
* Sergey Lyubka wrote this file. As long as you retain this notice you
|
||||
* can do whatever you want with this stuff. If we meet some day, and you think
|
||||
* this stuff is worth it, you can buy me a beer in return.
|
||||
*/
|
||||
|
||||
#ifndef IO_HEADER_INCLUDED
|
||||
#define IO_HEADER_INCLUDED
|
||||
|
||||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
|
||||
/*
|
||||
* I/O buffer descriptor
|
||||
*/
|
||||
struct io {
|
||||
char *buf; /* IO Buffer */
|
||||
size_t size; /* IO buffer size */
|
||||
size_t head; /* Bytes read */
|
||||
size_t tail; /* Bytes written */
|
||||
size_t total; /* Total bytes read */
|
||||
};
|
||||
|
||||
static __inline void
|
||||
io_clear(struct io *io)
|
||||
{
|
||||
assert(io->buf != NULL);
|
||||
assert(io->size > 0);
|
||||
io->total = io->tail = io->head = 0;
|
||||
}
|
||||
|
||||
static __inline char *
|
||||
io_space(struct io *io)
|
||||
{
|
||||
assert(io->buf != NULL);
|
||||
assert(io->size > 0);
|
||||
assert(io->head <= io->size);
|
||||
return (io->buf + io->head);
|
||||
}
|
||||
|
||||
static __inline char *
|
||||
io_data(struct io *io)
|
||||
{
|
||||
assert(io->buf != NULL);
|
||||
assert(io->size > 0);
|
||||
assert(io->tail <= io->size);
|
||||
return (io->buf + io->tail);
|
||||
}
|
||||
|
||||
static __inline size_t
|
||||
io_space_len(const struct io *io)
|
||||
{
|
||||
assert(io->buf != NULL);
|
||||
assert(io->size > 0);
|
||||
assert(io->head <= io->size);
|
||||
return (io->size - io->head);
|
||||
}
|
||||
|
||||
static __inline size_t
|
||||
io_data_len(const struct io *io)
|
||||
{
|
||||
assert(io->buf != NULL);
|
||||
assert(io->size > 0);
|
||||
assert(io->head <= io->size);
|
||||
assert(io->tail <= io->head);
|
||||
return (io->head - io->tail);
|
||||
}
|
||||
|
||||
static __inline void
|
||||
io_inc_tail(struct io *io, size_t n)
|
||||
{
|
||||
assert(io->buf != NULL);
|
||||
assert(io->size > 0);
|
||||
assert(io->tail <= io->head);
|
||||
assert(io->head <= io->size);
|
||||
io->tail += n;
|
||||
assert(io->tail <= io->head);
|
||||
if (io->tail == io->head)
|
||||
io->head = io->tail = 0;
|
||||
}
|
||||
|
||||
static __inline void
|
||||
io_inc_head(struct io *io, size_t n)
|
||||
{
|
||||
assert(io->buf != NULL);
|
||||
assert(io->size > 0);
|
||||
assert(io->tail <= io->head);
|
||||
io->head += n;
|
||||
io->total += n;
|
||||
assert(io->head <= io->size);
|
||||
}
|
||||
|
||||
#endif /* IO_HEADER_INCLUDED */
|
||||
@@ -1,124 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2005 Sergey Lyubka <valenok@gmail.com>
|
||||
* All rights reserved
|
||||
*
|
||||
* "THE BEER-WARE LICENSE" (Revision 42):
|
||||
* Sergey Lyubka wrote this file. As long as you retain this notice you
|
||||
* can do whatever you want with this stuff. If we meet some day, and you think
|
||||
* this stuff is worth it, you can buy me a beer in return.
|
||||
*/
|
||||
|
||||
#include "defs.h"
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
static int
|
||||
write_cgi(struct stream *stream, const void *buf, size_t len)
|
||||
{
|
||||
assert(stream->chan.sock != -1);
|
||||
assert(stream->flags & FLAG_W);
|
||||
|
||||
return (send(stream->chan.sock, buf, len, 0));
|
||||
}
|
||||
|
||||
static int
|
||||
read_cgi(struct stream *stream, void *buf, size_t len)
|
||||
{
|
||||
struct headers parsed;
|
||||
char status[4];
|
||||
int n;
|
||||
|
||||
assert(stream->chan.sock != -1);
|
||||
assert(stream->flags & FLAG_R);
|
||||
|
||||
stream->flags &= ~FLAG_DONT_CLOSE;
|
||||
|
||||
n = recv(stream->chan.sock, buf, len, 0);
|
||||
|
||||
if (stream->flags & FLAG_HEADERS_PARSED)
|
||||
return (n);
|
||||
|
||||
if (n <= 0 && ERRNO != EWOULDBLOCK) {
|
||||
send_server_error(stream->conn, 500, "Error running CGI");
|
||||
return (n);
|
||||
}
|
||||
|
||||
/*
|
||||
* CGI script may output Status: and Location: headers, which
|
||||
* may alter the status code. Buffer in headers, parse
|
||||
* them, send correct status code and then forward all data
|
||||
* from CGI script back to the remote end.
|
||||
* Reply line was alredy appended to the IO buffer in
|
||||
* decide_what_to_do(), with blank status code.
|
||||
*/
|
||||
|
||||
stream->flags |= FLAG_DONT_CLOSE;
|
||||
io_inc_head(&stream->io, n);
|
||||
|
||||
stream->headers_len = get_headers_len(stream->io.buf, stream->io.head);
|
||||
if (stream->headers_len < 0) {
|
||||
stream->flags &= ~FLAG_DONT_CLOSE;
|
||||
send_server_error(stream->conn, 500, "Bad headers sent");
|
||||
elog(E_LOG, stream->conn, "CGI script sent invalid headers: "
|
||||
"[%.*s]", stream->io.head - CGI_REPLY_LEN,
|
||||
stream->io.buf + CGI_REPLY_LEN);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* If we did not received full headers yet, we must not send any
|
||||
* data read from the CGI back to the client. Suspend sending by
|
||||
* setting tail = head, which tells that there is no data in IO buffer
|
||||
*/
|
||||
|
||||
if (stream->headers_len == 0) {
|
||||
stream->io.tail = stream->io.head;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Received all headers. Set status code for the connection. */
|
||||
(void) memset(&parsed, 0, sizeof(parsed));
|
||||
parse_headers(stream->io.buf, stream->headers_len, &parsed);
|
||||
stream->content_len = parsed.cl.v_big_int;
|
||||
stream->conn->status = (int) parsed.status.v_big_int;
|
||||
|
||||
/* If script outputs 'Location:' header, set status code to 302 */
|
||||
if (parsed.location.v_vec.len > 0)
|
||||
stream->conn->status = 302;
|
||||
|
||||
/*
|
||||
* If script did not output neither 'Location:' nor 'Status' headers,
|
||||
* set the default status code 200, which means 'success'.
|
||||
*/
|
||||
if (stream->conn->status == 0)
|
||||
stream->conn->status = 200;
|
||||
|
||||
/* Append the status line to the beginning of the output */
|
||||
(void) my_snprintf(status, sizeof(status), "%3d", stream->conn->status);
|
||||
(void) memcpy(stream->io.buf + 9, status, 3);
|
||||
DBG(("read_cgi: content len %lu status %s",
|
||||
stream->content_len, status));
|
||||
|
||||
/* Next time, pass output directly back to the client */
|
||||
assert((big_int_t) stream->headers_len <= stream->io.total);
|
||||
stream->io.total -= stream->headers_len;
|
||||
stream->io.tail = 0;
|
||||
stream->flags |= FLAG_HEADERS_PARSED;
|
||||
|
||||
/* Return 0 because we've already shifted the head */
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
close_cgi(struct stream *stream)
|
||||
{
|
||||
assert(stream->chan.sock != -1);
|
||||
(void) closesocket(stream->chan.sock);
|
||||
}
|
||||
|
||||
const struct io_class io_cgi = {
|
||||
"cgi",
|
||||
read_cgi,
|
||||
write_cgi,
|
||||
close_cgi
|
||||
};
|
||||
@@ -1,143 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2005 Sergey Lyubka <valenok@gmail.com>
|
||||
* All rights reserved
|
||||
*
|
||||
* "THE BEER-WARE LICENSE" (Revision 42):
|
||||
* Sergey Lyubka wrote this file. As long as you retain this notice you
|
||||
* can do whatever you want with this stuff. If we meet some day, and you think
|
||||
* this stuff is worth it, you can buy me a beer in return.
|
||||
*/
|
||||
|
||||
#include "defs.h"
|
||||
|
||||
/*
|
||||
* For a given PUT path, create all intermediate subdirectories
|
||||
* for given path. Return 0 if the path itself is a directory,
|
||||
* or -1 on error, 1 if OK.
|
||||
*/
|
||||
int
|
||||
put_dir(const char *path)
|
||||
{
|
||||
char buf[FILENAME_MAX];
|
||||
const char *s, *p;
|
||||
struct stat st;
|
||||
size_t len;
|
||||
|
||||
for (s = p = path + 2; (p = strchr(s, '/')) != NULL; s = ++p) {
|
||||
len = p - path;
|
||||
assert(len < sizeof(buf));
|
||||
(void) memcpy(buf, path, len);
|
||||
buf[len] = '\0';
|
||||
|
||||
/* Try to create intermediate directory */
|
||||
if (my_stat(buf, &st) == -1 && my_mkdir(buf, 0755) != 0)
|
||||
return (-1);
|
||||
|
||||
/* Is path itself a directory ? */
|
||||
if (p[1] == '\0')
|
||||
return (0);
|
||||
}
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
static int
|
||||
read_dir(struct stream *stream, void *buf, size_t len)
|
||||
{
|
||||
struct dirent *dp = NULL;
|
||||
char file[FILENAME_MAX], line[FILENAME_MAX + 512],
|
||||
size[64], mod[64];
|
||||
struct stat st;
|
||||
struct conn *c = stream->conn;
|
||||
int n, nwritten = 0;
|
||||
const char *slash = "";
|
||||
|
||||
assert(stream->chan.dir.dirp != NULL);
|
||||
assert(stream->conn->uri[0] != '\0');
|
||||
|
||||
do {
|
||||
if (len < sizeof(line))
|
||||
break;
|
||||
|
||||
if ((dp = readdir(stream->chan.dir.dirp)) == NULL) {
|
||||
stream->flags |= FLAG_CLOSED;
|
||||
break;
|
||||
}
|
||||
DBG(("read_dir: %s", dp->d_name));
|
||||
|
||||
/* Do not show current dir and passwords file */
|
||||
if (strcmp(dp->d_name, ".") == 0 ||
|
||||
strcmp(dp->d_name, HTPASSWD) == 0)
|
||||
continue;
|
||||
|
||||
(void) my_snprintf(file, sizeof(file),
|
||||
"%s%s%s", stream->chan.dir.path, slash, dp->d_name);
|
||||
(void) my_stat(file, &st);
|
||||
if (S_ISDIR(st.st_mode)) {
|
||||
my_snprintf(size,sizeof(size),"%s","<DIR>");
|
||||
} else {
|
||||
if (st.st_size < 1024)
|
||||
(void) my_snprintf(size, sizeof(size),
|
||||
"%lu", (unsigned long) st.st_size);
|
||||
else if (st.st_size < ((size_t)1024 * (size_t)1024))
|
||||
(void) my_snprintf(size, sizeof(size), "%luk",
|
||||
(unsigned long) (st.st_size >> 10) + 1);
|
||||
else
|
||||
(void) my_snprintf(size, sizeof(size),
|
||||
"%.1fM", (float) st.st_size / 1048576);
|
||||
}
|
||||
(void) strftime(mod, sizeof(mod), "%d-%b-%Y %H:%M",
|
||||
localtime(&st.st_mtime));
|
||||
|
||||
n = my_snprintf(line, sizeof(line),
|
||||
"<tr><td><a href=\"%s%s%s\">%s%s</a></td>"
|
||||
"<td> %s</td><td> %s</td></tr>\n",
|
||||
c->uri, slash, dp->d_name, dp->d_name,
|
||||
S_ISDIR(st.st_mode) ? "/" : "", mod, size);
|
||||
(void) memcpy(buf, line, n);
|
||||
buf = (char *) buf + n;
|
||||
nwritten += n;
|
||||
len -= n;
|
||||
} while (dp != NULL);
|
||||
|
||||
return (nwritten);
|
||||
}
|
||||
|
||||
static void
|
||||
close_dir(struct stream *stream)
|
||||
{
|
||||
assert(stream->chan.dir.dirp != NULL);
|
||||
assert(stream->chan.dir.path != NULL);
|
||||
(void) closedir(stream->chan.dir.dirp);
|
||||
free(stream->chan.dir.path);
|
||||
}
|
||||
|
||||
void
|
||||
get_dir(struct conn *c)
|
||||
{
|
||||
if ((c->loc.chan.dir.dirp = opendir(c->loc.chan.dir.path)) == NULL) {
|
||||
(void) free(c->loc.chan.dir.path);
|
||||
send_server_error(c, 500, "Cannot open directory");
|
||||
} else {
|
||||
c->loc.io.head = my_snprintf(c->loc.io.buf, c->loc.io.size,
|
||||
"HTTP/1.1 200 OK\r\n"
|
||||
"Content-Type: text/html; charset=utf-8\r\n\r\n"
|
||||
"<html><head><title>Index of %s</title>"
|
||||
"<style>th {text-align: left;}</style></head>"
|
||||
"<body><h1>Index of %s</h1><pre><table cellpadding=\"0\">"
|
||||
"<tr><th>Name</th><th>Modified</th><th>Size</th></tr>"
|
||||
"<tr><td colspan=\"3\"><hr></td></tr>",
|
||||
c->uri, c->uri);
|
||||
io_clear(&c->rem.io);
|
||||
c->status = 200;
|
||||
c->loc.io_class = &io_dir;
|
||||
c->loc.flags |= FLAG_R | FLAG_ALWAYS_READY;
|
||||
}
|
||||
}
|
||||
|
||||
const struct io_class io_dir = {
|
||||
"dir",
|
||||
read_dir,
|
||||
NULL,
|
||||
close_dir
|
||||
};
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,156 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2005 Sergey Lyubka <valenok@gmail.com>
|
||||
* All rights reserved
|
||||
*
|
||||
* "THE BEER-WARE LICENSE" (Revision 42):
|
||||
* Sergey Lyubka wrote this file. As long as you retain this notice you
|
||||
* can do whatever you want with this stuff. If we meet some day, and you think
|
||||
* this stuff is worth it, you can buy me a beer in return.
|
||||
*/
|
||||
|
||||
#include "defs.h"
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
static int
|
||||
write_file(struct stream *stream, const void *buf, size_t len)
|
||||
{
|
||||
struct stat st;
|
||||
struct stream *rem = &stream->conn->rem;
|
||||
int n, fd = stream->chan.fd;
|
||||
|
||||
assert(fd != -1);
|
||||
n = write(fd, buf, len);
|
||||
|
||||
DBG(("put_file(%p, %d): %d bytes", (void *) stream, len, n));
|
||||
|
||||
if (n <= 0 || (rem->io.total >= (big_int_t) rem->headers_len)) {
|
||||
(void) fstat(fd, &st);
|
||||
stream->io.head = stream->headers_len =
|
||||
my_snprintf(stream->io.buf,
|
||||
stream->io.size, "HTTP/1.1 %d OK\r\n"
|
||||
"Content-Length: %lu\r\nConnection: close\r\n\r\n",
|
||||
stream->conn->status, st.st_size);
|
||||
stop_stream(stream);
|
||||
}
|
||||
|
||||
return (n);
|
||||
}
|
||||
|
||||
static int
|
||||
read_file(struct stream *stream, void *buf, size_t len)
|
||||
{
|
||||
#ifdef USE_SENDFILE
|
||||
struct iovec vec;
|
||||
struct sf_hdtr hd = {&vec, 1, NULL, 0}, *hdp = &hd;
|
||||
int sock, fd, n;
|
||||
size_t nbytes;
|
||||
off_t sent;
|
||||
|
||||
sock = stream->conn->rem.chan.sock;
|
||||
fd = stream->chan.fd;
|
||||
|
||||
/* If this is the first call for this file, send the headers */
|
||||
vec.iov_base = stream->io.buf;
|
||||
vec.iov_len = stream->headers_len;
|
||||
if (stream->io.total > 0)
|
||||
hdp = NULL;
|
||||
|
||||
nbytes = stream->content_len - stream->io.total;
|
||||
n = sendfile(fd, sock, lseek(fd, 0, SEEK_CUR), nbytes, hdp, &sent, 0);
|
||||
|
||||
if (n == -1 && ERRNO != EAGAIN) {
|
||||
stream->flags &= ~FLAG_DONT_CLOSE;
|
||||
return (n);
|
||||
}
|
||||
|
||||
stream->conn->ctx->out += sent;
|
||||
|
||||
/* If we have sent the HTTP headers in this turn, clear them off */
|
||||
if (stream->io.total == 0) {
|
||||
assert(sent >= stream->headers_len);
|
||||
sent -= stream->headers_len;
|
||||
io_clear(&stream->io);
|
||||
}
|
||||
|
||||
(void) lseek(fd, sent, SEEK_CUR);
|
||||
stream->io.total += sent;
|
||||
stream->flags |= FLAG_DONT_CLOSE;
|
||||
|
||||
return (0);
|
||||
#endif /* USE_SENDFILE */
|
||||
|
||||
assert(stream->chan.fd != -1);
|
||||
return (read(stream->chan.fd, buf, len));
|
||||
}
|
||||
|
||||
static void
|
||||
close_file(struct stream *stream)
|
||||
{
|
||||
assert(stream->chan.fd != -1);
|
||||
(void) close(stream->chan.fd);
|
||||
}
|
||||
|
||||
void
|
||||
get_file(struct conn *c, struct stat *stp)
|
||||
{
|
||||
char date[64], lm[64], etag[64], range[64] = "";
|
||||
size_t n, status = 200;
|
||||
unsigned long r1, r2;
|
||||
const char *fmt = "%a, %d %b %Y %H:%M:%S GMT", *msg = "OK";
|
||||
big_int_t cl; /* Content-Length */
|
||||
|
||||
if (c->mime_type == NULL)
|
||||
c->mime_type = get_mime_type(c->ctx, c->uri, strlen(c->uri));
|
||||
cl = (big_int_t) stp->st_size;
|
||||
|
||||
/* If Range: header specified, act accordingly */
|
||||
if (c->ch.range.v_vec.len > 0 &&
|
||||
(n = sscanf(c->ch.range.v_vec.ptr,"bytes=%lu-%lu",&r1, &r2)) > 0) {
|
||||
status = 206;
|
||||
(void) lseek(c->loc.chan.fd, r1, SEEK_SET);
|
||||
cl = n == 2 ? r2 - r1 + 1: cl - r1;
|
||||
(void) my_snprintf(range, sizeof(range),
|
||||
"Content-Range: bytes %lu-%lu/%lu\r\n",
|
||||
r1, r1 + cl - 1, (unsigned long) stp->st_size);
|
||||
msg = "Partial Content";
|
||||
}
|
||||
|
||||
/* Prepare Etag, Date, Last-Modified headers */
|
||||
(void) strftime(date, sizeof(date), fmt, localtime(¤t_time));
|
||||
(void) strftime(lm, sizeof(lm), fmt, localtime(&stp->st_mtime));
|
||||
(void) my_snprintf(etag, sizeof(etag), "%lx.%lx",
|
||||
(unsigned long) stp->st_mtime, (unsigned long) stp->st_size);
|
||||
|
||||
/*
|
||||
* We do not do io_inc_head here, because it will increase 'total'
|
||||
* member in io. We want 'total' to be equal to the content size,
|
||||
* and exclude the headers length from it.
|
||||
*/
|
||||
c->loc.io.head = c->loc.headers_len = my_snprintf(c->loc.io.buf,
|
||||
c->loc.io.size,
|
||||
"HTTP/1.1 %d %s\r\n"
|
||||
"Date: %s\r\n"
|
||||
"Last-Modified: %s\r\n"
|
||||
"Etag: \"%s\"\r\n"
|
||||
"Content-Type: %s\r\n"
|
||||
"Content-Length: %lu\r\n"
|
||||
"Connection: close\r\n"
|
||||
"%s\r\n",
|
||||
status, msg, date, lm, etag, c->mime_type, cl, range);
|
||||
|
||||
c->status = status;
|
||||
c->loc.content_len = cl;
|
||||
c->loc.io_class = &io_file;
|
||||
c->loc.flags |= FLAG_R | FLAG_ALWAYS_READY;
|
||||
|
||||
if (c->method == METHOD_HEAD)
|
||||
stop_stream(&c->loc);
|
||||
}
|
||||
|
||||
const struct io_class io_file = {
|
||||
"file",
|
||||
read_file,
|
||||
write_file,
|
||||
close_file
|
||||
};
|
||||
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2005 Sergey Lyubka <valenok@gmail.com>
|
||||
* All rights reserved
|
||||
*
|
||||
* "THE BEER-WARE LICENSE" (Revision 42):
|
||||
* Sergey Lyubka wrote this file. As long as you retain this notice you
|
||||
* can do whatever you want with this stuff. If we meet some day, and you think
|
||||
* this stuff is worth it, you can buy me a beer in return.
|
||||
*/
|
||||
|
||||
#include "defs.h"
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
static int
|
||||
read_socket(struct stream *stream, void *buf, size_t len)
|
||||
{
|
||||
assert(stream->chan.sock != -1);
|
||||
return (recv(stream->chan.sock, buf, len, 0));
|
||||
}
|
||||
|
||||
static int
|
||||
write_socket(struct stream *stream, const void *buf, size_t len)
|
||||
{
|
||||
assert(stream->chan.sock != -1);
|
||||
return (send(stream->chan.sock, buf, len, 0));
|
||||
}
|
||||
|
||||
static void
|
||||
close_socket(struct stream *stream)
|
||||
{
|
||||
assert(stream->chan.sock != -1);
|
||||
(void) closesocket(stream->chan.sock);
|
||||
}
|
||||
|
||||
const struct io_class io_socket = {
|
||||
"socket",
|
||||
read_socket,
|
||||
write_socket,
|
||||
close_socket
|
||||
};
|
||||
@@ -1,85 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2005 Sergey Lyubka <valenok@gmail.com>
|
||||
* All rights reserved
|
||||
*
|
||||
* "THE BEER-WARE LICENSE" (Revision 42):
|
||||
* Sergey Lyubka wrote this file. As long as you retain this notice you
|
||||
* can do whatever you want with this stuff. If we meet some day, and you think
|
||||
* this stuff is worth it, you can buy me a beer in return.
|
||||
*/
|
||||
|
||||
#include "defs.h"
|
||||
|
||||
#if !defined(NO_SSL)
|
||||
struct ssl_func ssl_sw[] = {
|
||||
{"SSL_free", {0}},
|
||||
{"SSL_accept", {0}},
|
||||
{"SSL_connect", {0}},
|
||||
{"SSL_read", {0}},
|
||||
{"SSL_write", {0}},
|
||||
{"SSL_get_error", {0}},
|
||||
{"SSL_set_fd", {0}},
|
||||
{"SSL_new", {0}},
|
||||
{"SSL_CTX_new", {0}},
|
||||
{"SSLv23_server_method", {0}},
|
||||
{"SSL_library_init", {0}},
|
||||
{"SSL_CTX_use_PrivateKey_file", {0}},
|
||||
{"SSL_CTX_use_certificate_file",{0}},
|
||||
{NULL, {0}}
|
||||
};
|
||||
|
||||
void
|
||||
ssl_handshake(struct stream *stream)
|
||||
{
|
||||
int n;
|
||||
|
||||
if ((n = SSL_accept(stream->chan.ssl.ssl)) == 0) {
|
||||
n = SSL_get_error(stream->chan.ssl.ssl, n);
|
||||
if (n != SSL_ERROR_WANT_READ && n != SSL_ERROR_WANT_WRITE)
|
||||
stream->flags |= FLAG_CLOSED;
|
||||
elog(E_LOG, stream->conn, "SSL_accept error %d", n);
|
||||
} else {
|
||||
DBG(("handshake: SSL accepted"));
|
||||
stream->flags |= FLAG_SSL_ACCEPTED;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
read_ssl(struct stream *stream, void *buf, size_t len)
|
||||
{
|
||||
int nread = 0;
|
||||
|
||||
assert(stream->chan.ssl.ssl != NULL);
|
||||
|
||||
if (!(stream->flags & FLAG_SSL_ACCEPTED))
|
||||
ssl_handshake(stream);
|
||||
|
||||
if (stream->flags & FLAG_SSL_ACCEPTED)
|
||||
nread = SSL_read(stream->chan.ssl.ssl, buf, len);
|
||||
|
||||
return (nread);
|
||||
}
|
||||
|
||||
static int
|
||||
write_ssl(struct stream *stream, const void *buf, size_t len)
|
||||
{
|
||||
assert(stream->chan.ssl.ssl != NULL);
|
||||
return (SSL_write(stream->chan.ssl.ssl, buf, len));
|
||||
}
|
||||
|
||||
static void
|
||||
close_ssl(struct stream *stream)
|
||||
{
|
||||
assert(stream->chan.ssl.sock != -1);
|
||||
assert(stream->chan.ssl.ssl != NULL);
|
||||
(void) closesocket(stream->chan.ssl.sock);
|
||||
SSL_free(stream->chan.ssl.ssl);
|
||||
}
|
||||
|
||||
const struct io_class io_ssl = {
|
||||
"ssl",
|
||||
read_ssl,
|
||||
write_ssl,
|
||||
close_ssl
|
||||
};
|
||||
#endif /* !NO_SSL */
|
||||
@@ -1,59 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2005 Sergey Lyubka <valenok@gmail.com>
|
||||
* All rights reserved
|
||||
*
|
||||
* "THE BEER-WARE LICENSE" (Revision 42):
|
||||
* Sergey Lyubka wrote this file. As long as you retain this notice you
|
||||
* can do whatever you want with this stuff. If we meet some day, and you think
|
||||
* this stuff is worth it, you can buy me a beer in return.
|
||||
*/
|
||||
|
||||
#ifndef LLIST_HEADER_INCLUDED
|
||||
#define LLIST_HEADER_INCLUDED
|
||||
|
||||
/*
|
||||
* Linked list macros.
|
||||
*/
|
||||
struct llhead {
|
||||
struct llhead *prev;
|
||||
struct llhead *next;
|
||||
};
|
||||
|
||||
#define LL_INIT(N) ((N)->next = (N)->prev = (N))
|
||||
|
||||
#define LL_HEAD(H) struct llhead H = { &H, &H }
|
||||
|
||||
#define LL_ENTRY(P,T,N) ((T *)((char *)(P) - offsetof(T, N)))
|
||||
|
||||
#define LL_ADD(H, N) \
|
||||
do { \
|
||||
((H)->next)->prev = (N); \
|
||||
(N)->next = ((H)->next); \
|
||||
(N)->prev = (H); \
|
||||
(H)->next = (N); \
|
||||
} while (0)
|
||||
|
||||
#define LL_TAIL(H, N) \
|
||||
do { \
|
||||
((H)->prev)->next = (N); \
|
||||
(N)->prev = ((H)->prev); \
|
||||
(N)->next = (H); \
|
||||
(H)->prev = (N); \
|
||||
} while (0)
|
||||
|
||||
#define LL_DEL(N) \
|
||||
do { \
|
||||
((N)->next)->prev = ((N)->prev); \
|
||||
((N)->prev)->next = ((N)->next); \
|
||||
LL_INIT(N); \
|
||||
} while (0)
|
||||
|
||||
#define LL_EMPTY(N) ((N)->next == (N))
|
||||
|
||||
#define LL_FOREACH(H,N) for (N = (H)->next; N != (H); N = (N)->next)
|
||||
|
||||
#define LL_FOREACH_SAFE(H,N,T) \
|
||||
for (N = (H)->next, T = (N)->next; N != (H); \
|
||||
N = (T), T = (N)->next)
|
||||
|
||||
#endif /* LLIST_HEADER_INCLUDED */
|
||||
@@ -1,141 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2005 Sergey Lyubka <valenok@gmail.com>
|
||||
* All rights reserved
|
||||
*
|
||||
* "THE BEER-WARE LICENSE" (Revision 42):
|
||||
* Sergey Lyubka wrote this file. As long as you retain this notice you
|
||||
* can do whatever you want with this stuff. If we meet some day, and you think
|
||||
* this stuff is worth it, you can buy me a beer in return.
|
||||
*/
|
||||
|
||||
#include "defs.h"
|
||||
|
||||
/*
|
||||
* Log function
|
||||
*/
|
||||
void
|
||||
elog(int flags, struct conn *c, const char *fmt, ...)
|
||||
{
|
||||
char date[64], buf[URI_MAX];
|
||||
int len;
|
||||
FILE *fp = c == NULL ? NULL : c->ctx->error_log;
|
||||
va_list ap;
|
||||
|
||||
/* Print to stderr */
|
||||
if (c == NULL || c->ctx->inetd_mode == 0) {
|
||||
va_start(ap, fmt);
|
||||
(void) vfprintf(stderr, fmt, ap);
|
||||
(void) fputc('\n', stderr);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
strftime(date, sizeof(date), "%a %b %d %H:%M:%S %Y",
|
||||
localtime(¤t_time));
|
||||
|
||||
len = my_snprintf(buf, sizeof(buf),
|
||||
"[%s] [error] [client %s] \"%s\" ",
|
||||
date, c ? inet_ntoa(c->sa.u.sin.sin_addr) : "-",
|
||||
c && c->request ? c->request : "-");
|
||||
|
||||
va_start(ap, fmt);
|
||||
(void) vsnprintf(buf + len, sizeof(buf) - len, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
buf[sizeof(buf) - 1] = '\0';
|
||||
|
||||
if (fp != NULL && (flags & (E_FATAL | E_LOG))) {
|
||||
(void) fprintf(fp, "%s\n", buf);
|
||||
(void) fflush(fp);
|
||||
}
|
||||
|
||||
#if defined(_WIN32) && !defined(NO_GUI)
|
||||
{
|
||||
extern HWND hLog;
|
||||
|
||||
if (hLog != NULL)
|
||||
SendMessage(hLog, WM_APP, 0, (LPARAM) buf);
|
||||
}
|
||||
#endif /* _WIN32 */
|
||||
|
||||
if (flags & E_FATAL)
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/*
|
||||
* HACK: m68k-gcc <= 4.2.1 ICEs on the snprintf below for some
|
||||
* coldfire variants for yet unknown reasons.
|
||||
* C.f.: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=32307
|
||||
|
||||
* T.S, 2008/3/25 -- 4.2.3 still has this problem
|
||||
*/
|
||||
#if defined(__GNUC__) && \
|
||||
( (__GNUC__ < 4 ) || \
|
||||
( (__GNUC__ == 4 ) && (__GNUC_MINOR__ < 2 ) ) || \
|
||||
( (__GNUC__ == 4 ) && (__GNUC_MINOR__ == 2 ) && (__GNUC_PATCHLEVEL__ <= 3 ) ) )
|
||||
#if defined(__mcoldfire__)
|
||||
#define SPLIT_SNPRINTF 1
|
||||
#endif /* __mcoldfire__ */
|
||||
#endif /* __GNUC__ */
|
||||
|
||||
void
|
||||
log_access(FILE *fp, const struct conn *c)
|
||||
{
|
||||
static const struct vec dash = {"-", 1};
|
||||
|
||||
const struct vec *user = &c->ch.user.v_vec;
|
||||
const struct vec *referer = &c->ch.referer.v_vec;
|
||||
const struct vec *user_agent = &c->ch.useragent.v_vec;
|
||||
char date[64], buf[URI_MAX], *q1 = "\"", *q2 = "\"";
|
||||
|
||||
if (user->len == 0)
|
||||
user = ‐
|
||||
|
||||
if (referer->len == 0) {
|
||||
referer = ‐
|
||||
q1 = "";
|
||||
}
|
||||
|
||||
if (user_agent->len == 0) {
|
||||
user_agent = ‐
|
||||
q2 = "";
|
||||
}
|
||||
|
||||
(void) strftime(date, sizeof(date), "%d/%b/%Y:%H:%M:%S",
|
||||
localtime(¤t_time));
|
||||
|
||||
#if SPLIT_SNPRINTF
|
||||
{
|
||||
int num;
|
||||
num = my_snprintf(buf, sizeof(buf),
|
||||
"%s - %.*s [%s %+05d] \"%s\" %d %lu",
|
||||
inet_ntoa(c->sa.u.sin.sin_addr), user->len, user->ptr,
|
||||
date, tz_offset, c->request ? c->request : "-",
|
||||
c->status, c->loc.io.total );
|
||||
my_snprintf(&buf[num], sizeof(buf)-num, " %s%.*s%s" " %s%.*s%s",
|
||||
q1, referer->len, referer->ptr, q1,
|
||||
q2, user_agent->len, user_agent->ptr, q2);
|
||||
}
|
||||
#else
|
||||
(void) my_snprintf(buf, sizeof(buf),
|
||||
"%s - %.*s [%s %+05d] \"%s\" %d %lu %s%.*s%s %s%.*s%s",
|
||||
inet_ntoa(c->sa.u.sin.sin_addr), user->len, user->ptr,
|
||||
date, tz_offset, c->request ? c->request : "-",
|
||||
c->status, (unsigned long) c->loc.io.total,
|
||||
q1, referer->len, referer->ptr, q1,
|
||||
q2, user_agent->len, user_agent->ptr, q2);
|
||||
#endif
|
||||
|
||||
if (fp != NULL) {
|
||||
(void) fprintf(fp, "%s\n", buf);
|
||||
(void) fflush(fp);
|
||||
}
|
||||
|
||||
#if defined(_WIN32) && !defined(NO_GUI)
|
||||
{
|
||||
extern HWND hLog;
|
||||
|
||||
if (hLog != NULL)
|
||||
SendMessage(hLog, WM_APP, 0, (LPARAM) buf);
|
||||
}
|
||||
#endif /* _WIN32 */
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,24 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2005 Sergey Lyubka <valenok@gmail.com>
|
||||
* All rights reserved
|
||||
*
|
||||
* "THE BEER-WARE LICENSE" (Revision 42):
|
||||
* Sergey Lyubka wrote this file. As long as you retain this notice you
|
||||
* can do whatever you want with this stuff. If we meet some day, and you think
|
||||
* this stuff is worth it, you can buy me a beer in return.
|
||||
*/
|
||||
|
||||
#ifndef MD5_HEADER_INCLUDED
|
||||
#define MD5_HEADER_INCLUDED
|
||||
|
||||
typedef struct MD5Context {
|
||||
uint32_t buf[4];
|
||||
uint32_t bits[2];
|
||||
unsigned char in[64];
|
||||
} MD5_CTX;
|
||||
|
||||
extern void MD5Init(MD5_CTX *ctx);
|
||||
extern void MD5Update(MD5_CTX *ctx, unsigned char const *buf, unsigned len);
|
||||
extern void MD5Final(unsigned char digest[16], MD5_CTX *ctx);
|
||||
|
||||
#endif /*MD5_HEADER_INCLUDED */
|
||||
@@ -1,108 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2005 Sergey Lyubka <valenok@gmail.com>
|
||||
* All rights reserved
|
||||
*
|
||||
* "THE BEER-WARE LICENSE" (Revision 42):
|
||||
* Sergey Lyubka wrote this file. As long as you retain this notice you
|
||||
* can do whatever you want with this stuff. If we meet some day, and you think
|
||||
* this stuff is worth it, you can buy me a beer in return.
|
||||
*/
|
||||
|
||||
#include "defs.h"
|
||||
|
||||
#ifdef HAVE_STRINGS_H
|
||||
#include <strings.h>
|
||||
#endif
|
||||
|
||||
static const struct mime_type default_mime_types[] = {
|
||||
{"html", 4, "text/html" },
|
||||
{"htm", 3, "text/html" },
|
||||
{"txt", 3, "text/plain" },
|
||||
{"css", 3, "text/css" },
|
||||
{"ico", 3, "image/x-icon" },
|
||||
{"gif", 3, "image/gif" },
|
||||
{"jpg", 3, "image/jpeg" },
|
||||
{"jpeg", 4, "image/jpeg" },
|
||||
{"png", 3, "image/png" },
|
||||
{"svg", 3, "image/svg+xml" },
|
||||
{"torrent", 7, "application/x-bittorrent" },
|
||||
{"wav", 3, "audio/x-wav" },
|
||||
{"mp3", 3, "audio/x-mp3" },
|
||||
{"mid", 3, "audio/mid" },
|
||||
{"m3u", 3, "audio/x-mpegurl" },
|
||||
{"ram", 3, "audio/x-pn-realaudio" },
|
||||
{"ra", 2, "audio/x-pn-realaudio" },
|
||||
{"doc", 3, "application/msword", },
|
||||
{"exe", 3, "application/octet-stream" },
|
||||
{"zip", 3, "application/x-zip-compressed" },
|
||||
{"xls", 3, "application/excel" },
|
||||
{"tgz", 3, "application/x-tar-gz" },
|
||||
{"tar.gz", 6, "application/x-tar-gz" },
|
||||
{"tar", 3, "application/x-tar" },
|
||||
{"gz", 2, "application/x-gunzip" },
|
||||
{"arj", 3, "application/x-arj-compressed" },
|
||||
{"rar", 3, "application/x-arj-compressed" },
|
||||
{"rtf", 3, "application/rtf" },
|
||||
{"pdf", 3, "application/pdf" },
|
||||
{"mpg", 3, "video/mpeg" },
|
||||
{"mpeg", 4, "video/mpeg" },
|
||||
{"asf", 3, "video/x-ms-asf" },
|
||||
{"avi", 3, "video/x-msvideo" },
|
||||
{"bmp", 3, "image/bmp" },
|
||||
{NULL, 0, NULL }
|
||||
};
|
||||
|
||||
const char *
|
||||
get_mime_type(struct shttpd_ctx *ctx, const char *uri, int len)
|
||||
{
|
||||
struct llhead *lp;
|
||||
const struct mime_type *mt;
|
||||
struct mime_type_link *mtl;
|
||||
const char *s;
|
||||
|
||||
/* Firt, loop through the custom mime types if any */
|
||||
LL_FOREACH(&ctx->mime_types, lp) {
|
||||
mtl = LL_ENTRY(lp, struct mime_type_link, link);
|
||||
s = uri + len - mtl->ext_len;
|
||||
if (s > uri && s[-1] == '.' &&
|
||||
!my_strncasecmp(mtl->ext, s, mtl->ext_len))
|
||||
return (mtl->mime);
|
||||
}
|
||||
|
||||
/* If no luck, try built-in mime types */
|
||||
for (mt = default_mime_types; mt->ext != NULL; mt++) {
|
||||
s = uri + len - mt->ext_len;
|
||||
if (s > uri && s[-1] == '.' &&
|
||||
!my_strncasecmp(mt->ext, s, mt->ext_len))
|
||||
return (mt->mime);
|
||||
}
|
||||
|
||||
/* Oops. This extension is unknown to us. Fallback to text/plain */
|
||||
return ("text/plain");
|
||||
}
|
||||
|
||||
void
|
||||
set_mime_types(struct shttpd_ctx *ctx, const char *path)
|
||||
{
|
||||
FILE *fp;
|
||||
char line[512], ext[sizeof(line)], mime[sizeof(line)], *s;
|
||||
|
||||
if ((fp = fopen(path, "r")) == NULL)
|
||||
elog(E_FATAL, NULL, "set_mime_types: fopen(%s): %s",
|
||||
path, strerror(errno));
|
||||
|
||||
while (fgets(line, sizeof(line), fp) != NULL) {
|
||||
/* Skip empty lines */
|
||||
if (line[0] == '#' || line[0] == '\n')
|
||||
continue;
|
||||
if (sscanf(line, "%s", mime)) {
|
||||
s = line + strlen(mime);
|
||||
while (*s && *s != '\n' && sscanf(s, "%s", ext)) {
|
||||
shttpd_add_mime_type(ctx, ext, mime);
|
||||
s += strlen(mime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(void) fclose(fp);
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
## Automatically generated by ampolish3 - Do not edit
|
||||
|
||||
if AMPOLISH3
|
||||
$(srcdir)/preinstall.am: Makefile.am
|
||||
$(AMPOLISH3) $(srcdir)/Makefile.am > $(srcdir)/preinstall.am
|
||||
endif
|
||||
|
||||
PREINSTALL_DIRS =
|
||||
DISTCLEANFILES = $(PREINSTALL_DIRS)
|
||||
|
||||
all-local: $(TMPINSTALL_FILES)
|
||||
|
||||
TMPINSTALL_FILES =
|
||||
CLEANFILES = $(TMPINSTALL_FILES)
|
||||
|
||||
all-am: $(PREINSTALL_FILES)
|
||||
|
||||
PREINSTALL_FILES =
|
||||
CLEANFILES += $(PREINSTALL_FILES)
|
||||
|
||||
$(PROJECT_LIB)/$(dirstamp):
|
||||
@$(MKDIR_P) $(PROJECT_LIB)
|
||||
@: > $(PROJECT_LIB)/$(dirstamp)
|
||||
PREINSTALL_DIRS += $(PROJECT_LIB)/$(dirstamp)
|
||||
|
||||
if LIBSHTTPD
|
||||
$(PROJECT_INCLUDE)/shttpd/$(dirstamp):
|
||||
@$(MKDIR_P) $(PROJECT_INCLUDE)/shttpd
|
||||
@: > $(PROJECT_INCLUDE)/shttpd/$(dirstamp)
|
||||
PREINSTALL_DIRS += $(PROJECT_INCLUDE)/shttpd/$(dirstamp)
|
||||
|
||||
$(PROJECT_LIB)/libshttpd.a: libshttpd.a $(PROJECT_LIB)/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_LIB)/libshttpd.a
|
||||
TMPINSTALL_FILES += $(PROJECT_LIB)/libshttpd.a
|
||||
|
||||
$(PROJECT_INCLUDE)/shttpd/shttpd.h: shttpd.h $(PROJECT_INCLUDE)/shttpd/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/shttpd/shttpd.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/shttpd/shttpd.h
|
||||
endif
|
||||
@@ -1,135 +0,0 @@
|
||||
.\" Process this file with
|
||||
.\" groff -man -Tascii shttpd.1
|
||||
.\" $Id$
|
||||
.Dd Nov 10, 2006
|
||||
.Dt SHTTPD 1
|
||||
.Sh NAME
|
||||
.Nm shttpd
|
||||
.Nd lightweight web server
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Ar OPTIONS
|
||||
.Op Ar config_file
|
||||
.Nm
|
||||
.Fl A Ar htpasswd_file realm username password
|
||||
.Sh DESCRIPTION
|
||||
.Nm
|
||||
is small, fast and easy to use web server with CGI, SSL, Digest Authorization
|
||||
support. It can be run as stand-alone server, be managed by
|
||||
.Xr inetd 8
|
||||
, or be embedded into existing C/C++ application.
|
||||
.Pp
|
||||
Unlike other web servers,
|
||||
.Nm
|
||||
does not expect CGI scirpts to be put in a special directory. They may be
|
||||
anywhere. CGI files are recognized by an extension, which is
|
||||
.Dq .cgi
|
||||
by default.
|
||||
.Pp
|
||||
By default
|
||||
.Nm
|
||||
does not use SSL and starts listening on port 80. Specifying the
|
||||
.Fl s Ar pem_file
|
||||
option automatically switches
|
||||
.Nm
|
||||
to SSL mode on port 443.
|
||||
.Pp
|
||||
.Nm
|
||||
can take configuration parameters from two sources: from the command
|
||||
line and from the configuration file. Command line parameters have
|
||||
higher priority. Every command line parameter has associated configuration
|
||||
file keyword, except
|
||||
.Fl A
|
||||
parameter.
|
||||
In the configuration file, blank lines and lines started with
|
||||
.Dq #
|
||||
character are ignored. All other lines must start with the keyword
|
||||
followed by a whitespace followed by keyword's value.
|
||||
If both command line parameter and configuration
|
||||
file option are not specified, the default value is taken. The configuration
|
||||
file may not be present at all.
|
||||
.Pp
|
||||
If
|
||||
.Nm
|
||||
should be managed by
|
||||
.Xr inetd 8 ,
|
||||
add this line to
|
||||
.Pa inetd.conf :
|
||||
.Pp
|
||||
.Dl http stream tcp nowait nobody /path/to/shttpd shttpd -I1 -d /my/www
|
||||
.Pp
|
||||
.Sh OPTIONS
|
||||
Below is the list of command line parameters. In the brackets there are
|
||||
corresponding configuration file keywords.
|
||||
.Bl -tag -width indent
|
||||
.It Fl A Ar htpasswd server_name user_name user_password
|
||||
Edit the passwords file. Functionality similar to Apache's
|
||||
.Ic htdigest
|
||||
utility.
|
||||
.It Fl C Ar file ( Cm cgi_interpreter Ar file )
|
||||
Force
|
||||
.Ar file
|
||||
to be a CGI interpreter for all CGI scripts. Default: none.
|
||||
.It Fl D Ar 0|1 ( Cm list_directories Ar 0|1 )
|
||||
Disable directory listing. Default: enabled.
|
||||
.It Fl I Ar 0|1 ( Cm inetd_mode Ar 0|1 )
|
||||
Enable inetd mode. Default: disabled.
|
||||
.It Fl N Ar realm ( Cm server_name Ar realm )
|
||||
Authorization realm. Default:
|
||||
.Dq mydomain.com .
|
||||
.It Fl P Ar file ( Cm global_htpasswd Ar file )
|
||||
Location of global passwords file. Per-directory .htpasswd files are
|
||||
ignored, if this option is set. Default: not set.
|
||||
.It Fl U Ar file ( Cm put_auth Ar file )
|
||||
PUT and DELETE passwords file. This must be specified if PUT or
|
||||
DELETE methods are used. Default: none.
|
||||
.It Fl V Ar string ( Cm cgi_envvar Ar string )
|
||||
Pass additional environment variables to the CGI script. These must be
|
||||
comma-separated list of var=val pairs, like this: "VAR1=VAL1,VAR2=VAL2".
|
||||
Default: not set.
|
||||
.It Fl a Ar string ( Cm aliases Ar string )
|
||||
Attach directories (even those outside document_root) to URIs. The
|
||||
.Ar string
|
||||
must be comma-separated list of var=val pairs, like this:
|
||||
"/etc/=/my_etc,/tmp=/my_tmp". Default: not set.
|
||||
.It Fl c Ar string ( Cm cgi_extension Ar string )
|
||||
CGI filename pattern. For every requested file,
|
||||
.Nm
|
||||
uses the pattern to figure out whether to return the file content,
|
||||
ot run the file as CGI application. Default:
|
||||
.Dq .cgi .
|
||||
.It Fl d Ar directory ( Cm document_root Ar directory )
|
||||
Location of the WWW root directory. Default: working directory from which
|
||||
.Nm
|
||||
has been started.
|
||||
.It Fl e Ar file ( Cm error_log Ar file )
|
||||
Error log file. Default: not set, no errors are logged.
|
||||
.It Fl l Ar file ( Cm access_log Ar file )
|
||||
Access log file. Default: not set, no logging is done.
|
||||
.It Fl m Ar file ( Cm mime_types Ar file )
|
||||
Location of mime types file. Default: not set, builtins are used.
|
||||
.It Fl p Ar port ( Cm listen_port Ar port )
|
||||
Listening port. Default: 80 for non-SSL and 443 for SSL mode.
|
||||
.It Fl s Ar pem_file ( Cm ssl_certificate Ar pem_file )
|
||||
Location of SSL certificate file. Default: not set.
|
||||
.It Fl u Ar login ( Cm runtime_uid Ar login )
|
||||
Switch to given user ID after startup. Default: not set
|
||||
.El
|
||||
.Pp
|
||||
.Sh EMBEDDING
|
||||
.Nm
|
||||
can be built as a library to embed web server functionality
|
||||
into C/C++ application. The API functions are declared in a header
|
||||
file
|
||||
.Pa shttpd.h .
|
||||
Please refer to the source package for a header file and the examples.
|
||||
.Sh FILES
|
||||
.Pa /usr/local/etc/shttpd.conf
|
||||
.br
|
||||
.Sh SEE ALSO
|
||||
.Xr inetd 8 .
|
||||
.Sh COPYRIGHT
|
||||
.Nm
|
||||
is licensed under the terms of beerware license.
|
||||
.Sh AUTHOR
|
||||
.An Sergey Lyubka Aq valenok@gmail.com .
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,129 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2005 Sergey Lyubka <valenok@gmail.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef SHTTPD_HEADER_INCLUDED
|
||||
#define SHTTPD_HEADER_INCLUDED
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/*
|
||||
* This structure is passed to the user callback function
|
||||
*/
|
||||
struct shttpd_arg {
|
||||
void *priv; /* Private! Do not touch! */
|
||||
void *state; /* User state */
|
||||
void *user_data; /* User-defined data */
|
||||
|
||||
struct {
|
||||
char *buf; /* Buffer pointer */
|
||||
int len; /* Size of a buffer */
|
||||
int num_bytes; /* Bytes processed by callback */
|
||||
} in, out; /* POST data buffer (in) and output buffer (out) */
|
||||
|
||||
unsigned int flags;
|
||||
#define SHTTPD_END_OF_OUTPUT 1
|
||||
#define SHTTPD_CONNECTION_ERROR 2
|
||||
#define SHTTPD_MORE_POST_DATA 4
|
||||
#define SHTTPD_POST_BUFFER_FULL 8
|
||||
};
|
||||
|
||||
/*
|
||||
* User callback function. Called when certain registered URLs have been
|
||||
* requested. These are the requirements to the callback function:
|
||||
*
|
||||
* 1. it must copy data into 'out_buf', not more than 'out_buf_max_len' bytes,
|
||||
* and record how many bytes are copied, into 'out_buf_written_len'
|
||||
* 2. it must not block the execution
|
||||
* 3. it must set 'last' in shttpd_arg to 1 if there is no more data
|
||||
* 4. for POST requests, it must process the incoming data (in_buf), and
|
||||
* set 'in_buf_read_len', which is how many bytes of POST data is read
|
||||
* and can be discarded by SHTTPD.
|
||||
*/
|
||||
typedef void (*shttpd_callback_t)(struct shttpd_arg *);
|
||||
|
||||
/*
|
||||
* shttpd_init Initialize shttpd context. Parameters: configuration
|
||||
* file name (may be NULL), then NULL-terminated
|
||||
* sequence of pairs "option_name", "option_value".
|
||||
* shttpd_init2 Same as shttpd_init, but the list of option/value
|
||||
* pairs is passed in arrays
|
||||
* shttpd_fini Dealocate the context
|
||||
* shttpd_register_uri Setup the callback function for specified URL.
|
||||
* shttpd_protect_uri Associate authorization file with an URL.
|
||||
* shttpd_add_mime_type Add mime type
|
||||
* shtppd_listen Setup a listening socket in the SHTTPD context
|
||||
* shttpd_poll Do connections processing
|
||||
* shttpd_version return string with SHTTPD version
|
||||
* shttpd_get_var Return POST/GET variable value for given variable name.
|
||||
* shttpd_get_header return value of the specified HTTP header
|
||||
* shttpd_get_env return string values for the following
|
||||
* pseudo-variables: "REQUEST_METHOD", "REQUEST_URI",
|
||||
* "REMOTE_USER" and "REMOTE_ADDR".
|
||||
*/
|
||||
|
||||
struct shttpd_ctx;
|
||||
|
||||
struct shttpd_ctx *shttpd_init(const char *config_file, ...);
|
||||
struct shttpd_ctx *shttpd_init2(const char *config_file,
|
||||
char *names[], char *values[], size_t num_options);
|
||||
void shttpd_fini(struct shttpd_ctx *);
|
||||
void shttpd_add_mime_type(struct shttpd_ctx *,
|
||||
const char *ext, const char *mime);
|
||||
int shttpd_listen(struct shttpd_ctx *ctx, int port);
|
||||
void shttpd_register_uri(struct shttpd_ctx *ctx,
|
||||
const char *uri, shttpd_callback_t callback, void *user_data);
|
||||
void shttpd_protect_uri(struct shttpd_ctx *ctx,
|
||||
const char *uri, const char *file);
|
||||
void shttpd_poll(struct shttpd_ctx *, int milliseconds);
|
||||
const char *shttpd_version(void);
|
||||
int shttpd_get_var(const char *var, const char *buf, int buf_len,
|
||||
char *value, int value_len);
|
||||
const char *shttpd_get_header(struct shttpd_arg *, const char *);
|
||||
const char *shttpd_get_env(struct shttpd_arg *, const char *);
|
||||
void shttpd_get_http_version(struct shttpd_arg *,
|
||||
unsigned long *major, unsigned long *minor);
|
||||
size_t shttpd_printf(struct shttpd_arg *, const char *fmt, ...);
|
||||
void shttpd_handle_error(struct shttpd_ctx *ctx, int status,
|
||||
shttpd_callback_t func, void *data);
|
||||
|
||||
/*
|
||||
* The following three functions are for applications that need to
|
||||
* load-balance the connections on their own. Many threads may be spawned
|
||||
* with one SHTTPD context per thread. Boss thread may only wait for
|
||||
* new connections by means of shttpd_accept(). Then it may scan thread
|
||||
* pool for the idle thread by means of shttpd_active(), and add new
|
||||
* connection to the context by means of shttpd_add().
|
||||
*/
|
||||
void shttpd_add_socket(struct shttpd_ctx *, int sock);
|
||||
int shttpd_accept(int lsn_sock, int milliseconds);
|
||||
int shttpd_active(struct shttpd_ctx *);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* SHTTPD_HEADER_INCLUDED */
|
||||
@@ -1,52 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2005 Sergey Lyubka <valenok@gmail.com>
|
||||
* All rights reserved
|
||||
*
|
||||
* "THE BEER-WARE LICENSE" (Revision 42):
|
||||
* Sergey Lyubka wrote this file. As long as you retain this notice you
|
||||
* can do whatever you want with this stuff. If we meet some day, and you think
|
||||
* this stuff is worth it, you can buy me a beer in return.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Snatched from OpenSSL includes. I put the prototypes here to be independent
|
||||
* from the OpenSSL source installation. Having this, shttpd + SSL can be
|
||||
* built on any system with binary SSL libraries installed.
|
||||
*/
|
||||
|
||||
typedef struct ssl_st SSL;
|
||||
typedef struct ssl_method_st SSL_METHOD;
|
||||
typedef struct ssl_ctx_st SSL_CTX;
|
||||
|
||||
#define SSL_ERROR_WANT_READ 2
|
||||
#define SSL_ERROR_WANT_WRITE 3
|
||||
#define SSL_FILETYPE_PEM 1
|
||||
|
||||
/*
|
||||
* Dynamically loaded SSL functionality
|
||||
*/
|
||||
struct ssl_func {
|
||||
const char *name; /* SSL function name */
|
||||
union variant ptr; /* Function pointer */
|
||||
};
|
||||
|
||||
extern struct ssl_func ssl_sw[];
|
||||
|
||||
#define FUNC(x) ssl_sw[x].ptr.v_func
|
||||
|
||||
#define SSL_free(x) (* (void (*)(SSL *)) FUNC(0))(x)
|
||||
#define SSL_accept(x) (* (int (*)(SSL *)) FUNC(1))(x)
|
||||
#define SSL_connect(x) (* (int (*)(SSL *)) FUNC(2))(x)
|
||||
#define SSL_read(x,y,z) (* (int (*)(SSL *, void *, int)) FUNC(3))((x),(y),(z))
|
||||
#define SSL_write(x,y,z) \
|
||||
(* (int (*)(SSL *, const void *,int)) FUNC(4))((x), (y), (z))
|
||||
#define SSL_get_error(x,y)(* (int (*)(SSL *, int)) FUNC(5))((x), (y))
|
||||
#define SSL_set_fd(x,y) (* (int (*)(SSL *, int)) FUNC(6))((x), (y))
|
||||
#define SSL_new(x) (* (SSL * (*)(SSL_CTX *)) FUNC(7))(x)
|
||||
#define SSL_CTX_new(x) (* (SSL_CTX * (*)(SSL_METHOD *)) FUNC(8))(x)
|
||||
#define SSLv23_server_method() (* (SSL_METHOD * (*)(void)) FUNC(9))()
|
||||
#define SSL_library_init() (* (int (*)(void)) FUNC(10))()
|
||||
#define SSL_CTX_use_PrivateKey_file(x,y,z) (* (int (*)(SSL_CTX *, \
|
||||
const char *, int)) FUNC(11))((x), (y), (z))
|
||||
#define SSL_CTX_use_certificate_file(x,y,z) (* (int (*)(SSL_CTX *, \
|
||||
const char *, int)) FUNC(12))((x), (y), (z))
|
||||
@@ -1,92 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2005 Sergey Lyubka <valenok@gmail.com>
|
||||
* All rights reserved
|
||||
*
|
||||
* "THE BEER-WARE LICENSE" (Revision 42):
|
||||
* Sergey Lyubka wrote this file. As long as you retain this notice you
|
||||
* can do whatever you want with this stuff. If we meet some day, and you think
|
||||
* this stuff is worth it, you can buy me a beer in return.
|
||||
*/
|
||||
|
||||
#include "defs.h"
|
||||
|
||||
static const char *config_file = CONFIG;
|
||||
static int exit_flag;
|
||||
|
||||
static void
|
||||
signal_handler(int sig_num)
|
||||
{
|
||||
switch (sig_num) {
|
||||
#ifndef _WIN32
|
||||
case SIGCHLD:
|
||||
while (waitpid(-1, &sig_num, WNOHANG) > 0) ;
|
||||
break;
|
||||
#endif /* !_WIN32 */
|
||||
default:
|
||||
exit_flag = sig_num;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
struct shttpd_ctx *ctx;
|
||||
|
||||
current_time = time(NULL);
|
||||
if (argc > 1 && argv[argc - 2][0] != '-' && argv[argc - 1][0] != '-')
|
||||
config_file = argv[argc - 1];
|
||||
|
||||
#if !defined(NO_AUTH)
|
||||
if (argc > 1 && argv[1][0] == '-' && argv[1][1] == 'A') {
|
||||
if (argc != 6)
|
||||
usage(argv[0]);
|
||||
exit(edit_passwords(argv[2],argv[3],argv[4],argv[5]));
|
||||
}
|
||||
#endif /* NO_AUTH */
|
||||
|
||||
ctx = init_from_argc_argv(config_file, argc, argv);
|
||||
|
||||
if (ctx->inetd_mode)
|
||||
(void) freopen("/dev/null", "a", stderr);
|
||||
|
||||
if (ctx->inetd_mode)
|
||||
shttpd_add_socket(ctx, fileno(stdin));
|
||||
else if (shttpd_listen(ctx, ctx->port) == -1)
|
||||
elog(E_FATAL, NULL, "Cannot open socket on port %d", ctx->port);
|
||||
|
||||
#ifndef _WIN32
|
||||
/* Switch to alternate UID, it is safe now, after shttpd_listen() */
|
||||
if (ctx->uid != NULL) {
|
||||
struct passwd *pw;
|
||||
|
||||
if ((pw = getpwnam(ctx->uid)) == NULL)
|
||||
elog(E_FATAL, 0, "main: unknown user [%s]", ctx->uid);
|
||||
else if (setgid(pw->pw_gid) == -1)
|
||||
elog(E_FATAL, NULL, "main: setgid(%s): %s",
|
||||
ctx->uid, strerror(errno));
|
||||
else if (setuid(pw->pw_uid) == -1)
|
||||
elog(E_FATAL, NULL, "main: setuid(%s): %s",
|
||||
ctx->uid, strerror(errno));
|
||||
}
|
||||
(void) signal(SIGCHLD, signal_handler);
|
||||
(void) signal(SIGPIPE, SIG_IGN);
|
||||
#endif /* _WIN32 */
|
||||
|
||||
(void) signal(SIGTERM, signal_handler);
|
||||
(void) signal(SIGINT, signal_handler);
|
||||
|
||||
elog(E_LOG, NULL, "shttpd %s started on port %d, serving %s",
|
||||
VERSION, ctx->port, ctx->document_root);
|
||||
|
||||
while (exit_flag == 0)
|
||||
shttpd_poll(ctx, 5000);
|
||||
|
||||
elog(E_LOG, NULL, "%d requests %.2lf Mb in %.2lf Mb out. "
|
||||
"Exit on signal %d", ctx->nrequests, (double) (ctx->in / 1048576),
|
||||
(double) ctx->out / 1048576, exit_flag);
|
||||
|
||||
shttpd_fini(ctx);
|
||||
|
||||
return (EXIT_SUCCESS);
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2005 Sergey Lyubka <valenok@gmail.com>
|
||||
* All rights reserved
|
||||
*
|
||||
* "THE BEER-WARE LICENSE" (Revision 42):
|
||||
* Sergey Lyubka wrote this file. As long as you retain this notice you
|
||||
* can do whatever you want with this stuff. If we meet some day, and you think
|
||||
* this stuff is worth it, you can buy me a beer in return.
|
||||
*/
|
||||
|
||||
#ifndef STD_HEADERS_INCLUDED
|
||||
#define STD_HEADERS_INCLUDED
|
||||
|
||||
#ifndef _WIN32_WCE /* Some ANSI #includes are not available on Windows CE */
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <fcntl.h>
|
||||
#endif /* _WIN32_WCE */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <limits.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <wchar.h>
|
||||
|
||||
#if defined(_WIN32) /* Windows specific */
|
||||
#include "compat_win32.h"
|
||||
#elif defined(__rtems__) /* RTEMS specific */
|
||||
#include "compat_rtems.h"
|
||||
#else /* UNIX specific */
|
||||
#include "compat_unix.h"
|
||||
#endif /* _WIN32 */
|
||||
|
||||
#endif /* STD_HEADERS_INCLUDED */
|
||||
@@ -1,85 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2005 Sergey Lyubka <valenok@gmail.com>
|
||||
* All rights reserved
|
||||
*
|
||||
* "THE BEER-WARE LICENSE" (Revision 42):
|
||||
* Sergey Lyubka wrote this file. As long as you retain this notice you
|
||||
* can do whatever you want with this stuff. If we meet some day, and you think
|
||||
* this stuff is worth it, you can buy me a beer in return.
|
||||
*/
|
||||
|
||||
#include "defs.h"
|
||||
|
||||
#ifndef HAVE_STRLCPY
|
||||
void
|
||||
my_strlcpy(register char *dst, register const char *src, size_t n)
|
||||
{
|
||||
for (; *src != '\0' && n > 1; n--)
|
||||
*dst++ = *src++;
|
||||
*dst = '\0';
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_STRNCASECMP
|
||||
int
|
||||
my_strncasecmp(const char *str1, const char *str2, size_t len)
|
||||
{
|
||||
register const unsigned char *s1 = (unsigned char *) str1,
|
||||
*s2 = (unsigned char *) str2, *e;
|
||||
int ret;
|
||||
|
||||
for (e = s1 + len - 1; s1 < e && *s1 != '\0' && *s2 != '\0' &&
|
||||
tolower(*s1) == tolower(*s2); s1++, s2++) ;
|
||||
ret = tolower(*s1) - tolower(*s2);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_STRNDUP
|
||||
char *
|
||||
my_strndup(const char *ptr, size_t len)
|
||||
{
|
||||
char *p;
|
||||
|
||||
if ((p = malloc(len + 1)) != NULL)
|
||||
my_strlcpy(p, ptr, len + 1);
|
||||
|
||||
return (p);
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_STRDUP
|
||||
char *
|
||||
my_strdup(const char *str)
|
||||
{
|
||||
return (my_strndup(str, strlen(str)));
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Sane snprintf(). Acts like snprintf(), but never return -1 or the
|
||||
* value bigger than supplied buffer.
|
||||
* Thanks Adam Zeldis to pointing snprintf()-caused vulnerability
|
||||
* in his audit report.
|
||||
*/
|
||||
int
|
||||
my_snprintf(char *buf, size_t buflen, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int n;
|
||||
|
||||
if (buflen == 0)
|
||||
return (0);
|
||||
|
||||
va_start(ap, fmt);
|
||||
n = vsnprintf(buf, buflen, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
if (n < 0 || (size_t) n >= buflen)
|
||||
n = buflen - 1;
|
||||
buf[n] = '\0';
|
||||
|
||||
return (n);
|
||||
}
|
||||
Reference in new issue
Block a user