From ef18215493fbf5180b9a9b016ac70e0f3766f59c Mon Sep 17 00:00:00 2001 From: Dmitry Bogatov Date: Thu, 15 Nov 2018 15:59:22 +0000 Subject: Import Upstream version 1.21 --- Makefile | 46 +++-- README | 8 +- contrib/redhat-rpm/mini_httpd.spec | 28 +-- htpasswd.c | 10 +- match.h | 2 +- mime_types.txt | 29 +-- mini_httpd.8 | 20 +- mini_httpd.c | 367 ++++++++++++++++++++++++------------- port.h | 8 + scripts/500.mini_httpd-rotate | 16 +- scripts/mini_httpd.sh | 59 ++++-- scripts/mini_httpd_wrapper | 27 +-- tdate_parse.c | 11 +- tdate_parse.h | 2 +- version.h | 2 +- 15 files changed, 389 insertions(+), 246 deletions(-) diff --git a/Makefile b/Makefile index 04766ae..79c5e81 100644 --- a/Makefile +++ b/Makefile @@ -16,33 +16,31 @@ CRYPT_LIB = -lcrypt # it may be in /usr/local instead of /usr/local/ssl. #SSL_TREE = /usr/local/ssl #SSL_DEFS = -DUSE_SSL -#SSL_INC = -I${SSL_TREE}/include -#SSL_LIBS = -L${SSL_TREE}/lib -lssl -lcrypto +#SSL_INC = -I$(SSL_TREE)/include +#SSL_LIBS = -L$(SSL_TREE)/lib -lssl -lcrypto BINDIR = /usr/local/sbin MANDIR = /usr/local/man -CC = gcc -CDEFS = ${SSL_DEFS} ${SSL_INC} -CFLAGS = -O ${CDEFS} -#CFLAGS = -g ${CDEFS} +CC = cc +CDEFS = $(SSL_DEFS) $(SSL_INC) +CFLAGS = -O $(CDEFS) -ansi -pedantic -U__STRICT_ANSI__ -Wall -Wpointer-arith -Wshadow -Wcast-qual -Wcast-align -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wredundant-decls -Wno-long-long LDFLAGS = -s -#LDFLAGS = -g -LDLIBS = ${SSL_LIBS} ${SYSV_LIBS} ${CRYPT_LIB} +LDLIBS = $(CRYPT_LIB) $(SSL_LIBS) $(SYSV_LIBS) all: mini_httpd htpasswd mini_httpd: mini_httpd.o match.o tdate_parse.o - ${CC} ${CFLAGS} ${LDFLAGS} mini_httpd.o match.o tdate_parse.o ${LDLIBS} -o mini_httpd + $(CC) $(LDFLAGS) mini_httpd.o match.o tdate_parse.o $(LDLIBS) -o mini_httpd mini_httpd.o: mini_httpd.c version.h port.h match.h tdate_parse.h mime_encodings.h mime_types.h - ${CC} ${CFLAGS} -c mini_httpd.c + $(CC) $(CFLAGS) -c mini_httpd.c match.o: match.c match.h - ${CC} ${CFLAGS} -c match.c + $(CC) $(CFLAGS) -c match.c tdate_parse.o: tdate_parse.c tdate_parse.h - ${CC} ${CFLAGS} -c tdate_parse.c + $(CC) $(CFLAGS) -c tdate_parse.c mime_encodings.h: mime_encodings.txt rm -f mime_encodings.h @@ -58,34 +56,34 @@ mime_types.h: mime_types.txt htpasswd: htpasswd.o - ${CC} ${CFLAGS} ${LDFLAGS} htpasswd.o ${CRYPT_LIB} -o htpasswd + $(CC) $(LDFLAGS) htpasswd.o $(CRYPT_LIB) -o htpasswd htpasswd.o: htpasswd.c - ${CC} ${CFLAGS} -c htpasswd.c + $(CC) $(CFLAGS) -c htpasswd.c cert: mini_httpd.pem mini_httpd.pem: mini_httpd.cnf - openssl req -new -x509 -days 365 -nodes -config mini_httpd.cnf -out mini_httpd.pem -keyout mini_httpd.pem + openssl req -new -x509 -days 3650 -nodes -config mini_httpd.cnf -out mini_httpd.pem -keyout mini_httpd.pem openssl x509 -subject -dates -fingerprint -noout -in mini_httpd.pem chmod 600 mini_httpd.pem install: all - rm -f ${BINDIR}/mini_httpd ${BINDIR}/htpasswd - -mkdir -p ${BINDIR} - cp mini_httpd htpasswd ${BINDIR} - rm -f ${MANDIR}/man8/mini_httpd.8 ${MANDIR}/man1/htpasswd.1 - -mkdir -p ${MANDIR}/man8 - cp mini_httpd.8 ${MANDIR}/man8 - -mkdir -p ${MANDIR}/man1 - cp htpasswd.1 ${MANDIR}/man1 + rm -f $(BINDIR)/mini_httpd $(BINDIR)/htpasswd + -mkdir -p $(BINDIR) + cp mini_httpd htpasswd $(BINDIR) + rm -f $(MANDIR)/man8/mini_httpd.8 $(MANDIR)/man1/htpasswd.1 + -mkdir -p $(MANDIR)/man8 + cp mini_httpd.8 $(MANDIR)/man8 + -mkdir -p $(MANDIR)/man1 + cp htpasswd.1 $(MANDIR)/man1 clean: rm -f mini_httpd mime_encodings.h mime_types.h htpasswd mini_httpd.rnd *.o core core.* *.core tar: - @name=`sed -n -e '/SERVER_SOFTWARE/!d' -e 's,.*mini_httpd/,mini_httpd-,' -e 's, .*,,p' version.h` ; \ + @name=`sed -n -e '/#define SERVER_SOFTWARE /!d' -e 's,.*mini_httpd/,mini_httpd-,' -e 's, .*,,p' version.h` ; \ rm -rf $$name ; \ mkdir $$name ; \ tar cf - `cat FILES` | ( cd $$name ; tar xfBp - ) ; \ diff --git a/README b/README index 8a7b9f7..14c1cc5 100644 --- a/README +++ b/README @@ -1,5 +1,5 @@ mini_httpd - small HTTP server - version 1.19 of 19dec2003 + version 1.21 of 18oct2004 mini_httpd is a small HTTP server. Its performance is not great, but for low or medium traffic sites it's quite adequate. It implements all the @@ -48,9 +48,9 @@ If you're doing SSL, uncomment those lines too. Otherwise, just do a make. On Red Hat Linux systems you can use RPM to install mini_httpd, like so: cd /usr/src/redhat/SOURCES - wget http://www.acme.com/software/mini_httpd/mini_httpd-1.19.tar.gz - rpm -ta mini_httpd-1.19.tar.gz - rpm -i /usr/src/redhat/RPMS/i386/mini_httpd-1.19-1.i386.rpm + wget http://www.acme.com/software/mini_httpd/mini_httpd-1.20.tar.gz + rpm -ta mini_httpd-1.20.tar.gz + rpm -i /usr/src/redhat/RPMS/i386/mini_httpd-1.20-1.i386.rpm Feedback is welcome - send bug reports, enhancements, checks, money orders, etc. to the addresses below. diff --git a/contrib/redhat-rpm/mini_httpd.spec b/contrib/redhat-rpm/mini_httpd.spec index 14d88ad..3f52202 100644 --- a/contrib/redhat-rpm/mini_httpd.spec +++ b/contrib/redhat-rpm/mini_httpd.spec @@ -1,6 +1,6 @@ Summary: small, simple http daemon, supports SSL Name: mini_httpd -Version: 1.19 +Version: 1.21 Release: 1 Copyright: Freely Redistributable Packager: Bennett Todd @@ -57,18 +57,20 @@ install contrib/redhat-rpm/mini_httpd.init \ %changelog -* Mon Oct 27 2003 Version 1.19 -* Sat Sep 13 2003 Version 1.18 -* Sat May 25 2002 Version 1.17 -* Mon May 07 2001 Version 1.16 -* Tue May 01 2001 Version 1.15c -* Sat Apr 21 2001 Version 1.15b -* Wed Sep 20 2000 Version 1.15 -* Thu Jun 15 2000 Version 1.14 -* Fri May 26 2000 Version 1.13 -* Wed Mar 01 2000 Version 1.12 -* Sun Feb 06 2000 Version 1.11 -* Wed Feb 02 2000 Version 1.10 +* Sat Oct 18 2014 Version 1.21 +* Thu Jan 08 2004 Version 1.20 +* Mon Oct 27 2003 Version 1.19 +* Sat Sep 13 2003 Version 1.18 +* Sat May 25 2002 Version 1.17 +* Mon May 07 2001 Version 1.16 +* Tue May 01 2001 Version 1.15c +* Sat Apr 21 2001 Version 1.15b +* Wed Sep 20 2000 Version 1.15 +* Thu Jun 15 2000 Version 1.14 +* Fri May 26 2000 Version 1.13 +* Wed Mar 01 2000 Version 1.12 +* Sun Feb 06 2000 Version 1.11 +* Wed Feb 02 2000 Version 1.10 * Mon Jan 31 2000 Version 1.09, added init script * Wed Jan 19 2000 Version 1.08, reset release to 1 * Mon Dec 13 1999 diff --git a/htpasswd.c b/htpasswd.c index e01ea1d..8ffda29 100644 --- a/htpasswd.c +++ b/htpasswd.c @@ -16,8 +16,6 @@ #include #include -extern char *crypt(const char *key, const char *setting); - #define LF 10 #define CR 13 @@ -49,8 +47,8 @@ static void getword(char *word, char *line, char stop) { while((line[y++] = line[x++])); } -static int getline(char *s, int n, FILE *f) { - register int i=0; +static int my_getline(char *s, int n, FILE *f) { + int i=0; while(1) { s[i] = (char)fgetc(f); @@ -78,7 +76,7 @@ static void putline(FILE *f,char *l) { static unsigned char itoa64[] = /* 0 ... 63 => ascii - 64 */ "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; -static void to64(register char *s, register long v, register int n) { +static void to64(char *s, long v, int n) { while (--n >= 0) { *s++ = itoa64[v&0x3f]; v >>= 6; @@ -189,7 +187,7 @@ int main(int argc, char *argv[]) { strcpy(user,argv[2]); found = 0; - while(!(getline(line,MAX_STRING_LEN,f))) { + while(!(my_getline(line,MAX_STRING_LEN,f))) { if(found || (line[0] == '#') || (!line[0])) { putline(tfp,line); continue; diff --git a/match.h b/match.h index f46dd00..01c5f2a 100644 --- a/match.h +++ b/match.h @@ -31,6 +31,6 @@ /* Simple shell-style filename pattern matcher. Only does ? * and **, and ** multiple patterns separated by |. Returns 1 or 0. */ -extern int match( const char* pattern, const char* string ); +int match( const char* pattern, const char* string ); #endif /* _MATCH_H_ */ diff --git a/mime_types.txt b/mime_types.txt index db49c54..d4725d9 100644 --- a/mime_types.txt +++ b/mime_types.txt @@ -11,7 +11,7 @@ ai application/postscript aif audio/x-aiff aifc audio/x-aiff aiff audio/x-aiff -asc text/plain +asc text/plain; charset=%s asf video/x-ms-asf asx video/x-ms-asf au audio/basic @@ -26,7 +26,7 @@ cpt application/mac-compactpro crl application/x-pkcs7-crl crt application/x-x509-ca-cert csh application/x-csh -css text/css +css text/css; charset=%s dcr application/x-director dir application/x-director djv image/vnd.djvu @@ -34,7 +34,7 @@ djvu image/vnd.djvu dll application/octet-stream dms application/octet-stream doc application/msword -dtd text/xml +dtd text/xml; charset=%s dump application/octet-stream dvi application/x-dvi dxr application/x-director @@ -66,8 +66,11 @@ jpeg image/jpeg jpg image/jpeg js application/x-javascript kar audio/midi +kml application/vnd.google-earth.kml+xml +kmz application/vnd.google-earth.kmz latex application/x-latex lha application/octet-stream +loc application/xml-loc lzh application/octet-stream m3u audio/x-mpegurl man application/x-troff-man @@ -95,7 +98,7 @@ mxu video/vnd.mpegurl nc application/x-netcdf o application/octet-stream oda application/oda -ogg application/x-ogg +ogg application/ogg pac application/x-ns-proxy-autoconfig pbm image/x-portable-bitmap pdb chemical/x-pdb @@ -117,10 +120,10 @@ rm audio/x-pn-realaudio roff application/x-troff rpm audio/x-pn-realaudio-plugin rss application/rss+xml -rtf text/rtf -rtx text/richtext -sgm text/sgml -sgml text/sgml +rtf text/rtf; charset=%s +rtx text/richtext; charset=%s +sgm text/sgml; charset=%s +sgml text/sgml; charset=%s sh application/x-sh shar application/x-shar silo model/mesh @@ -160,7 +163,7 @@ tif image/tiff tiff image/tiff tr application/x-troff tsp application/dsptype -tsv text/tab-separated-values +tsv text/tab-separated-values; charset=%s txt text/plain; charset=%s ustar application/x-ustar vcd application/x-cdlink @@ -184,12 +187,12 @@ wrl model/vrml wsrc application/x-wais-source wvx video/x-ms-wvx xbm image/x-xbitmap -xht application/xhtml+xml -xhtml application/xhtml+xml +xht application/xhtml+xml; charset=%s +xhtml application/xhtml+xml; charset=%s xls application/vnd.ms-excel -xml text/xml +xml text/xml; charset=%s xpm image/x-xpixmap -xsl text/xml +xsl text/xml; charset=%s xwd image/x-xwindowdump xyz chemical/x-xyz zip application/zip diff --git a/mini_httpd.8 b/mini_httpd.8 index 8c4695e..f4d4dd4 100644 --- a/mini_httpd.8 +++ b/mini_httpd.8 @@ -153,7 +153,7 @@ The config-file option name for this flag is "pidfile". .TP .B -T Specifies the character set to use with text MIME types. -The default is "iso-8859-1". +The default is "UTF-8". The config-file option name for this flag is "charset". .TP .B -P @@ -362,34 +362,34 @@ virtual host's web tree. mini_httpd will look first in the virtual host errors directory, and then in the server-wide errors directory, and if neither of those has an appropriate error file then it will generate the built-in error. -.SH "NON-LOCAL REFERERS" +.SH "NON-LOCAL REFERRERS" .PP Sometimes another site on the net will embed your image files in their HTML files, which basically means they're stealing your bandwidth. -You can prevent them from doing this by using non-local referer filtering. -With this option, certain files can only be fetched via a local referer. +You can prevent them from doing this by using non-local referrer filtering. +With this option, certain files can only be fetched via a local referrer. The files have to be referenced by a local web page. If a web page on some other site references the files, that fetch will be blocked. There are three config-file variables for this feature: .TP .B urlpat -A wildcard pattern for the URLs that should require a local referer. +A wildcard pattern for the URLs that should require a local referrer. This is typically just image files, sound files, and so on. For example: .nf urlpat=**.jpg|**.gif|**.au|**.wav .fi -For most sites, that one setting is all you need to enable referer filtering. +For most sites, that one setting is all you need to enable referrer filtering. .TP -.B noemptyreferers -By default, requests with no referer at all, or a null referer, or a -referer with no apparent hostname, are allowed. +.B noemptyreferrers +By default, requests with no referrer at all, or a null referrer, or a +referrer with no apparent hostname, are allowed. With this variable set, such requests are disallowed. .TP .B localpat A wildcard pattern that specifies the local host or hosts. -This is used to determine if the host in the referer is local or not. +This is used to determine if the host in the referrer is local or not. If not specified it defaults to the actual local hostname. .SH SIGNALS .PP diff --git a/mini_httpd.c b/mini_httpd.c index f2a00b1..881843f 100644 --- a/mini_httpd.c +++ b/mini_httpd.c @@ -65,13 +65,16 @@ # endif /* HAVE_LINUX_SENDFILE */ #endif /* HAVE_SENDFILE */ +#if defined(TCP_CORK) && !defined(TCP_NOPUSH) +#define TCP_NOPUSH TCP_CORK +/* (Linux's TCP_CORK is basically the same as BSD's TCP_NOPUSH.) */ +#endif + #ifdef USE_SSL #include #include #endif /* USE_SSL */ -extern char* crypt( const char* key, const char* setting ); - #if defined(AF_INET6) && defined(IN6_IS_ADDR_V4MAPPED) #define USE_IPV6 @@ -147,8 +150,11 @@ typedef long long int64_t; #define WRITE_TIMEOUT 300 #endif /* WRITE_TIMEOUT */ #ifndef DEFAULT_CHARSET -#define DEFAULT_CHARSET "iso-8859-1" +#define DEFAULT_CHARSET "UTF-8" #endif /* DEFAULT_CHARSET */ +#ifndef MAX_SEND_BUFFER_SIZE +#define MAX_SEND_BUFFER_SIZE 1048576 +#endif /* MAX_SEND_BUFFER_SIZE */ #define METHOD_UNKNOWN 0 @@ -178,7 +184,7 @@ static int vhost; static char* user; static char* cgi_pattern; static char* url_pattern; -static int no_empty_referers; +static int no_empty_referrers; static char* local_pattern; static char* hostname; static char hostname_buf[500]; @@ -224,7 +230,7 @@ static char* content_type; static char* cookie; static char* host; static time_t if_modified_since; -static char* referer; +static char* referrer; static char* useragent; static char* remoteuser; @@ -237,12 +243,12 @@ static void value_required( char* name, char* value ); static void no_value_required( char* name, char* value ); static int initialize_listen_socket( usockaddr* usaP ); static void handle_request( void ); -static void de_dotdot( char* file ); +static void de_dotdot( char* f ); static int get_pathinfo( void ); static void do_file( void ); static void do_dir( void ); #ifdef HAVE_SCANDIR -static char* file_details( const char* dir, const char* name ); +static char* file_details( const char* d, const char* name ); static void strencode( char* to, size_t tosize, const char* from ); #endif /* HAVE_SCANDIR */ static void do_cgi( void ); @@ -254,7 +260,7 @@ static char** make_envp( void ); static char* build_env( char* fmt, char* arg ); static void auth_check( char* dirname ); static void send_authenticate( char* realm ); -static char* virtual_file( char* file ); +static char* virtual_file( char* f ); static void send_error( int s, char* title, char* extra_header, char* text ); static void send_error_body( int s, char* title, char* text ); static int send_error_file( char* filename ); @@ -267,15 +273,16 @@ static void start_response( void ); static void add_to_response( char* str, size_t len ); static void send_response( void ); static void send_via_write( int fd, off_t size ); +static void send_via_sendfile( int fd, int s, off_t size ); static ssize_t my_read( char* buf, size_t size ); -static ssize_t my_write( char* buf, size_t size ); +static ssize_t my_write( void* buf, size_t size ); #ifdef HAVE_SENDFILE -static int my_sendfile( int fd, int socket, off_t offset, size_t nbytes ); +static int my_sendfile( int fd, int s, off_t offset, size_t nbytes ); #endif /* HAVE_SENDFILE */ static void add_to_buf( char** bufP, size_t* bufsizeP, size_t* buflenP, char* str, size_t len ); static void make_log_entry( void ); -static void check_referer( void ); -static int really_check_referer( void ); +static void check_referrer( void ); +static int really_check_referrer( void ); static char* get_method_str( int m ); static void init_mime( void ); static const char* figure_mime( char* name, char* me, size_t me_size ); @@ -315,7 +322,8 @@ main( int argc, char** argv ) fd_set lfdset; int maxfd; usockaddr usa; - int sz, r; + socklen_t sz; + int r; char* cp; /* Parse args. */ @@ -328,7 +336,7 @@ main( int argc, char** argv ) vhost = 0; cgi_pattern = (char*) 0; url_pattern = (char*) 0; - no_empty_referers = 0; + no_empty_referrers = 0; local_pattern = (char*) 0; charset = DEFAULT_CHARSET; p3p = (char*) 0; @@ -543,6 +551,7 @@ main( int argc, char** argv ) SSL_load_error_strings(); SSLeay_add_ssl_algorithms(); ssl_ctx = SSL_CTX_new( SSLv23_server_method() ); + SSL_CTX_set_options( ssl_ctx, SSL_OP_NO_SSLv3 ); if ( certfile[0] != '\0' ) if ( SSL_CTX_use_certificate_file( ssl_ctx, certfile, SSL_FILETYPE_PEM ) == 0 || SSL_CTX_use_PrivateKey_file( ssl_ctx, certfile, SSL_FILETYPE_PEM ) == 0 || @@ -676,6 +685,7 @@ main( int argc, char** argv ) ** tree. */ if ( logfile != (char*) 0 ) + { if ( strncmp( logfile, cwd, strlen( cwd ) ) == 0 ) { (void) strcpy( logfile, &logfile[strlen( cwd ) - 1] ); @@ -689,6 +699,7 @@ main( int argc, char** argv ) syslog( LOG_WARNING, "logfile is not within the chroot tree, you will not be able to re-open it" ); (void) fprintf( stderr, "%s: logfile is not within the chroot tree, you will not be able to re-open it\n", argv0 ); } + } (void) strcpy( cwd, "/" ); /* Always chdir to / after a chroot. */ if ( chdir( cwd ) < 0 ) @@ -816,7 +827,7 @@ main( int argc, char** argv ) } if ( conn_fd < 0 ) { - if ( errno == EINTR || errno == EAGAIN ) + if ( errno == EINTR || errno == EAGAIN || errno == ECONNABORTED ) continue; /* try again */ #ifdef EPROTO if ( errno == EPROTO ) @@ -950,10 +961,11 @@ read_config( char* filename ) value_required( name, value ); url_pattern = e_strdup( value ); } - else if ( strcasecmp( name, "noemptyreferers" ) == 0 ) + else if ( strcasecmp( name, "noemptyreferers" ) == 0 || + strcasecmp( name, "noemptyreferrers" ) == 0 ) { value_required( name, value ); - no_empty_referers = 1; + no_empty_referrers = 1; } else if ( strcasecmp( name, "localpat" ) == 0 ) { @@ -1157,7 +1169,7 @@ handle_request( void ) cookie = (char*) 0; host = (char*) 0; if_modified_since = (time_t) -1; - referer = ""; + referrer = ""; useragent = ""; #ifdef TCP_NOPUSH @@ -1189,13 +1201,13 @@ handle_request( void ) for (;;) { char buf[10000]; - int r = my_read( buf, sizeof(buf) ); - if ( r < 0 && ( errno == EINTR || errno == EAGAIN ) ) + int rr = my_read( buf, sizeof(buf) ); + if ( rr < 0 && ( errno == EINTR || errno == EAGAIN ) ) continue; - if ( r <= 0 ) + if ( rr <= 0 ) break; (void) alarm( READ_TIMEOUT ); - add_to_request( buf, r ); + add_to_request( buf, rr ); if ( strstr( request, "\015\012\015\012" ) != (char*) 0 || strstr( request, "\012\012" ) != (char*) 0 ) break; @@ -1268,7 +1280,13 @@ handle_request( void ) { cp = &line[8]; cp += strspn( cp, " \t" ); - referer = cp; + referrer = cp; + } + else if ( strncasecmp( line, "Referrer:", 9 ) == 0 ) + { + cp = &line[9]; + cp += strspn( cp, " \t" ); + referrer = cp; } else if ( strncasecmp( line, "User-Agent:", 11 ) == 0 ) { @@ -1368,14 +1386,14 @@ handle_request( void ) static void -de_dotdot( char* file ) +de_dotdot( char* f ) { char* cp; char* cp2; int l; /* Collapse any multiple / sequences. */ - while ( ( cp = strstr( file, "//") ) != (char*) 0 ) + while ( ( cp = strstr( f, "//") ) != (char*) 0 ) { for ( cp2 = cp + 2; *cp2 == '/'; ++cp2 ) continue; @@ -1383,31 +1401,31 @@ de_dotdot( char* file ) } /* Remove leading ./ and any /./ sequences. */ - while ( strncmp( file, "./", 2 ) == 0 ) - (void) strcpy( file, file + 2 ); - while ( ( cp = strstr( file, "/./") ) != (char*) 0 ) + while ( strncmp( f, "./", 2 ) == 0 ) + (void) strcpy( f, f + 2 ); + while ( ( cp = strstr( f, "/./") ) != (char*) 0 ) (void) strcpy( cp, cp + 2 ); /* Alternate between removing leading ../ and removing xxx/../ */ for (;;) { - while ( strncmp( file, "../", 3 ) == 0 ) - (void) strcpy( file, file + 3 ); - cp = strstr( file, "/../" ); + while ( strncmp( f, "../", 3 ) == 0 ) + (void) strcpy( f, f + 3 ); + cp = strstr( f, "/../" ); if ( cp == (char*) 0 ) break; - for ( cp2 = cp - 1; cp2 >= file && *cp2 != '/'; --cp2 ) + for ( cp2 = cp - 1; cp2 >= f && *cp2 != '/'; --cp2 ) continue; (void) strcpy( cp2 + 1, cp + 4 ); } /* Also elide any xxx/.. at the end. */ - while ( ( l = strlen( file ) ) > 3 && - strcmp( ( cp = file + l - 3 ), "/.." ) == 0 ) + while ( ( l = strlen( f ) ) > 3 && + strcmp( ( cp = f + l - 3 ), "/.." ) == 0 ) { - for ( cp2 = cp - 1; cp2 >= file && *cp2 != '/'; --cp2 ) + for ( cp2 = cp - 1; cp2 >= f && *cp2 != '/'; --cp2 ) continue; - if ( cp2 < file ) + if ( cp2 < f ) break; *cp2 = '\0'; } @@ -1475,8 +1493,8 @@ do_file( void ) send_error( 403, "Forbidden", "", "File is protected." ); } - /* Referer check. */ - check_referer(); + /* Referrer check. */ + check_referrer(); /* Is it CGI? */ if ( cgi_pattern != (char*) 0 && match( cgi_pattern, file ) ) @@ -1519,12 +1537,12 @@ do_file( void ) #ifdef HAVE_SENDFILE #ifndef USE_SSL - (void) my_sendfile( fd, conn_fd, 0, sb.st_size ); + send_via_sendfile( fd, conn_fd, sb.st_size ); #else /* USE_SSL */ if ( do_ssl ) send_via_write( fd, sb.st_size ); else - (void) my_sendfile( fd, conn_fd, 0, sb.st_size ); + send_via_sendfile( fd, conn_fd, sb.st_size ); #endif /* USE_SSL */ #else /* HAVE_SENDFILE */ @@ -1560,8 +1578,8 @@ do_dir( void ) /* Check authorization for this directory. */ auth_check( file ); - /* Referer check. */ - check_referer(); + /* Referrer check. */ + check_referrer(); #ifdef HAVE_SCANDIR n = scandir( file, &dl, NULL, alphasort ); @@ -1576,11 +1594,18 @@ do_dir( void ) contents_size = 0; buflen = snprintf( buf, sizeof(buf), "\ -\n\ -Index of %s\n\ -\n\ -

Index of %s

\n\ -
\n",
+\n\
+\n\
+\n\
+\n\
+  \n\
+    \n\
+    Index of %s\n\
+  \n\
+\n\
+  \n\
+    

Index of %s

\n\ +
\n",
 	file, file );
     add_to_buf( &contents, &contents_size, &contents_len, buf, buflen );
 
@@ -1600,7 +1625,7 @@ do_dir( void )
 	{
 	(void) snprintf(
 	    command, sizeof(command),
-	    "ls -lgF '%s' | tail +2 | sed -e 's/^\\([^ ][^ ]*\\)\\(  *[^ ][^ ]*  *[^ ][^ ]*  *[^ ][^ ]*\\)\\(  *[^ ][^ ]*\\)  *\\([^ ][^ ]*  *[^ ][^ ]*  *[^ ][^ ]*\\)  *\\(.*\\)$/\\1 \\3  \\4  |\\5/' -e '/ -> /!s,|\\([^*]*\\)$,|\\1,' -e '/ -> /!s,|\\(.*\\)\\([*]\\)$,|\\1\\2,' -e '/ -> /s,|\\([^@]*\\)\\(@* -> \\),|\\1\\2,' -e 's/|//'",
+	    "ls -lgF '%s' | tail +2 | sed -e 's/^\\([^ ][^ ]*\\)\\(  *[^ ][^ ]*  *[^ ][^ ]*  *[^ ][^ ]*\\)\\(  *[^ ][^ ]*\\)  *\\([^ ][^ ]*  *[^ ][^ ]*  *[^ ][^ ]*\\)  *\\(.*\\)$/\\1 \\3  \\4  |\\5/' -e '/ -> /!s,|\\([^*]*\\)$,|\\1,' -e '/ -> /!s,|\\(.*\\)\\([*]\\)$,|\\1\\2,' -e '/ -> /s,|\\([^@]*\\)\\(@* -> \\),|\\1\\2,' -e 's/|//'",
 	    file );
 	fp = popen( command, "r" );
 	for (;;)
@@ -1616,11 +1641,15 @@ do_dir( void )
 #endif /* HAVE_SCANDIR */
 
     buflen = snprintf( buf, sizeof(buf), "\
-
\n\ -
\n\ -
%s
\n\ -\n\ -\n", +
\n\ +\n\ +
\n\ +\n\ +
%s
\n\ + \n\ + \n\ +\n\ +\n", SERVER_URL, SERVER_SOFTWARE ); add_to_buf( &contents, &contents_size, &contents_len, buf, buflen ); @@ -1634,21 +1663,21 @@ do_dir( void ) #ifdef HAVE_SCANDIR static char* -file_details( const char* dir, const char* name ) +file_details( const char* d, const char* name ) { - struct stat sb; - char f_time[20]; + struct stat sb2; + char timestr[16]; static char encname[1000]; static char buf[2000]; - (void) snprintf( buf, sizeof(buf), "%s/%s", dir, name ); - if ( lstat( buf, &sb ) < 0 ) + (void) snprintf( buf, sizeof(buf), "%s/%s", d, name ); + if ( lstat( buf, &sb2 ) < 0 ) return "???"; - (void) strftime( f_time, sizeof( f_time ), "%d%b%Y %H:%M", localtime( &sb.st_mtime ) ); + (void) strftime( timestr, sizeof(timestr), "%d%b%Y %H:%M", localtime( &sb2.st_mtime ) ); strencode( encname, sizeof(encname), name ); (void) snprintf( - buf, sizeof( buf ), "%-32.32s %15s %14lld\n", - encname, name, f_time, (int64_t) sb.st_size ); + buf, sizeof( buf ), "%-32.32s %15s %14lld\n", + encname, name, timestr, (long long) sb2.st_size ); return buf; } @@ -1952,7 +1981,7 @@ cgi_interpose_output( int rfd, int parse_headers ) size_t headers_size, headers_len; char* headers; char* br; - int status; + int s; char* title; char* cp; @@ -1983,22 +2012,22 @@ cgi_interpose_output( int rfd, int parse_headers ) return; /* Figure out the status. */ - status = 200; + s = 200; + if ( ( cp = strstr( headers, "Location:" ) ) != (char*) 0 && + cp < br && + ( cp == headers || *(cp-1) == '\012' ) ) + s = 302; if ( ( cp = strstr( headers, "Status:" ) ) != (char*) 0 && cp < br && ( cp == headers || *(cp-1) == '\012' ) ) { cp += 7; cp += strspn( cp, " \t" ); - status = atoi( cp ); + s = atoi( cp ); } - if ( ( cp = strstr( headers, "Location:" ) ) != (char*) 0 && - cp < br && - ( cp == headers || *(cp-1) == '\012' ) ) - status = 302; /* Write the status line. */ - switch ( status ) + switch ( s ) { case 200: title = "OK"; break; case 302: title = "Found"; break; @@ -2008,13 +2037,14 @@ cgi_interpose_output( int rfd, int parse_headers ) case 403: title = "Forbidden"; break; case 404: title = "Not Found"; break; case 408: title = "Request Timeout"; break; + case 451: title = "Unavailable For Legal Reasons"; break; case 500: title = "Internal Error"; break; case 501: title = "Not Implemented"; break; case 503: title = "Service Temporarily Overloaded"; break; default: title = "Something"; break; } (void) snprintf( - buf, sizeof(buf), "HTTP/1.0 %d %s\015\012", status, title ); + buf, sizeof(buf), "HTTP/1.0 %d %s\015\012", s, title ); (void) my_write( buf, strlen( buf ) ); /* Write the saved headers. */ @@ -2122,10 +2152,12 @@ make_envp( void ) envp[envn++] = build_env( "PATH=%s", CGI_PATH ); envp[envn++] = build_env( "LD_LIBRARY_PATH=%s", CGI_LD_LIBRARY_PATH ); envp[envn++] = build_env( "SERVER_SOFTWARE=%s", SERVER_SOFTWARE ); - if ( ! vhost ) - cp = hostname; - else + if ( vhost && req_hostname != (char*) 0 && req_hostname[0] != '\0' ) cp = req_hostname; /* already computed by virtual_file() */ + else if ( host != (char*) 0 && host[0] != '\0' ) + cp = host; + else + cp = hostname; if ( cp != (char*) 0 ) envp[envn++] = build_env( "SERVER_NAME=%s", cp ); envp[envn++] = "GATEWAY_INTERFACE=CGI/1.1"; @@ -2144,8 +2176,11 @@ make_envp( void ) if ( query[0] != '\0' ) envp[envn++] = build_env( "QUERY_STRING=%s", query ); envp[envn++] = build_env( "REMOTE_ADDR=%s", ntoa( &client_addr ) ); - if ( referer[0] != '\0' ) - envp[envn++] = build_env( "HTTP_REFERER=%s", referer ); + if ( referrer[0] != '\0' ) + { + envp[envn++] = build_env( "HTTP_REFERER=%s", referrer ); + envp[envn++] = build_env( "HTTP_REFERRER=%s", referrer ); + } if ( useragent[0] != '\0' ) envp[envn++] = build_env( "HTTP_USER_AGENT=%s", useragent ); if ( cookie != (char*) 0 ) @@ -2204,7 +2239,7 @@ static void auth_check( char* dirname ) { char authpath[10000]; - struct stat sb; + struct stat sb2; char authinfo[500]; char* authpass; char* colon; @@ -2220,7 +2255,7 @@ auth_check( char* dirname ) (void) snprintf( authpath, sizeof(authpath), "%s/%s", dirname, AUTH_FILE ); /* Does this directory have an auth file? */ - if ( stat( authpath, &sb ) < 0 ) + if ( stat( authpath, &sb2 ) < 0 ) /* Nope, let the request go through. */ return; @@ -2307,7 +2342,7 @@ send_authenticate( char* realm ) static char* -virtual_file( char* file ) +virtual_file( char* f ) { char* cp; static char vfile[10000]; @@ -2318,7 +2353,7 @@ virtual_file( char* file ) else { usockaddr usa; - int sz = sizeof(usa); + socklen_t sz = sizeof(usa); if ( getsockname( conn_fd, &usa.sa, &sz ) < 0 ) req_hostname = "UNKNOWN_HOST"; else @@ -2328,7 +2363,7 @@ virtual_file( char* file ) for ( cp = req_hostname; *cp != '\0'; ++cp ) if ( isupper( *cp ) ) *cp = tolower( *cp ); - (void) snprintf( vfile, sizeof(vfile), "%s/%s", req_hostname, file ); + (void) snprintf( vfile, sizeof(vfile), "%s/%s", req_hostname, f ); return vfile; } @@ -2378,10 +2413,18 @@ send_error_body( int s, char* title, char* text ) /* Send built-in error page. */ buflen = snprintf( buf, sizeof(buf), "\ -\n\ -%d %s\n\ -\n\ -

%d %s

\n", +\n\ +\n\ +\n\ +\n\ + \n\ + \n\ + %d %s\n\ + \n\ +\n\ + \n\ +\n\ +

%d %s

\n", s, title, s, title ); add_to_response( buf, buflen ); buflen = snprintf( buf, sizeof(buf), "%s\n", text ); @@ -2432,10 +2475,13 @@ send_error_tail( void ) } buflen = snprintf( buf, sizeof(buf), "\ -
\n\ -
%s
\n\ -\n\ -\n", +
\n\ +\n\ +
%s
\n\ +\n\ + \n\ +\n\ +\n", SERVER_URL, SERVER_SOFTWARE ); add_to_response( buf, buflen ); } @@ -2487,7 +2533,7 @@ add_headers( int s, char* title, char* extra_header, char* me, char* mt, off_t b if ( bytes >= 0 ) { buflen = snprintf( - buf, sizeof(buf), "Content-Length: %lld\015\012", (int64_t) bytes ); + buf, sizeof(buf), "Content-Length: %lld\015\012", (long long) bytes ); add_to_response( buf, buflen ); } if ( p3p != (char*) 0 && p3p[0] != '\0' ) @@ -2580,31 +2626,59 @@ send_response( void ) static void send_via_write( int fd, off_t size ) { + /* On some systems an off_t is 64 bits while a size_t is still only + ** 32 bits. The mmap() system call takes a size_t as the length argument, + ** so we can only use mmap() if the size will fit into a size_t. + */ if ( size <= SIZE_T_MAX ) { size_t size_size = (size_t) size; - void* ptr = mmap( 0, size_size, PROT_READ, MAP_PRIVATE, fd, 0 ); - if ( ptr != (void*) -1 ) + unsigned char* ptr = mmap( 0, size_size, PROT_READ, MAP_PRIVATE, fd, 0 ); + if ( ptr != (unsigned char*) -1 ) { - (void) my_write( ptr, size_size ); - (void) munmap( ptr, size_size ); - } + unsigned char* p = ptr; + size_t remaining_size = size_size; #ifdef MADV_SEQUENTIAL - /* If we have madvise, might as well call it. Although sequential - ** access is probably already the default. - */ - (void) madvise( ptr, size_size, MADV_SEQUENTIAL ); + /* If we have madvise, might as well call it. Although sequential + ** access is probably already the default. + */ + (void) madvise( ptr, size_size, MADV_SEQUENTIAL ); #endif /* MADV_SEQUENTIAL */ + /* We could send the whole file in a single write, but if + ** it's huge then we run the risk of hitting the timeout. + ** So we do a loop writing large segments, and reseting the + ** timeout each time through. + */ + while ( remaining_size > 0 ) + { + size_t buf_size = MIN( remaining_size, MAX_SEND_BUFFER_SIZE ); + ssize_t r = my_write( p, buf_size ); + if ( r < 0 && ( errno == EINTR || errno == EAGAIN ) ) + { + sleep( 1 ); + continue; + } + if ( r != buf_size ) + return; + remaining_size -= r; + p += r; + (void) alarm( WRITE_TIMEOUT ); + } + (void) munmap( ptr, size_size ); + } } else { - /* mmap can't deal with files larger than 2GB. */ + /* The file is too big for mmap, so we'll send it via read & write + ** instead. This would be less efficient for small files because + ** it bypasses the buffer cache, but with a file this huge the + ** cache will get blown anyway. + */ char buf[30000]; - ssize_t r, r2; for (;;) { - r = read( fd, buf, sizeof(buf) ); + ssize_t r = read( fd, buf, sizeof(buf) ); if ( r < 0 && ( errno == EINTR || errno == EAGAIN ) ) { sleep( 1 ); @@ -2614,7 +2688,7 @@ send_via_write( int fd, off_t size ) return; for (;;) { - r2 = my_write( buf, r ); + ssize_t r2 = my_write( buf, r ); if ( r2 < 0 && ( errno == EINTR || errno == EAGAIN ) ) { sleep( 1 ); @@ -2629,6 +2703,37 @@ send_via_write( int fd, off_t size ) } +static void +send_via_sendfile( int fd, int s, off_t size ) + { + /* We could send the whole file in a single sendfile, but if + ** it's huge then we run the risk of hitting the timeout. + ** So we do a loop writing large segments, and reseting the + ** timeout each time through. + ** + ** This also avoids the problem of using sendfile on a file larger + ** than 2GB, since each segment size will now fit into a size_t. + */ + off_t remaining_size = size; + off_t off = 0; + while ( remaining_size > 0 ) + { + size_t buf_size = MIN( remaining_size, MAX_SEND_BUFFER_SIZE ); + ssize_t r = my_sendfile( fd, s, off, buf_size ); + if ( r < 0 && ( errno == EINTR || errno == EAGAIN ) ) + { + sleep( 1 ); + continue; + } + if ( r != buf_size ) + return; + remaining_size -= r; + off += r; + (void) alarm( WRITE_TIMEOUT ); + } + } + + static ssize_t my_read( char* buf, size_t size ) { @@ -2644,7 +2749,7 @@ my_read( char* buf, size_t size ) static ssize_t -my_write( char* buf, size_t size ) +my_write( void* buf, size_t size ) { #ifdef USE_SSL if ( do_ssl ) @@ -2659,13 +2764,13 @@ my_write( char* buf, size_t size ) #ifdef HAVE_SENDFILE static int -my_sendfile( int fd, int socket, off_t offset, size_t nbytes ) +my_sendfile( int fd, int s, off_t offset, size_t nbytes ) { #ifdef HAVE_LINUX_SENDFILE off_t lo = offset; - return sendfile( socket, fd, &lo, nbytes ); + return sendfile( s, fd, &lo, nbytes ); #else /* HAVE_LINUX_SENDFILE */ - return sendfile( fd, socket, offset, nbytes, (struct sf_hdtr*) 0, (off_t*) 0, 0 ); + return sendfile( fd, s, offset, nbytes, (struct sf_hdtr*) 0, (off_t*) 0, 0 ); #endif /* HAVE_LINUX_SENDFILE */ } #endif /* HAVE_SENDFILE */ @@ -2733,7 +2838,7 @@ make_log_entry( void ) /* Format the bytes. */ if ( bytes >= 0 ) (void) snprintf( - bytes_str, sizeof(bytes_str), "%lld", (int64_t) bytes ); + bytes_str, sizeof(bytes_str), "%lld", (long long) bytes ); else (void) strcpy( bytes_str, "-" ); /* Format the time, forcing a numeric timezone (some log analyzers @@ -2760,7 +2865,7 @@ make_log_entry( void ) (void) fprintf( logfp, "%.80s - %.80s [%s] \"%.80s %.200s %.80s\" %d %s \"%.200s\" \"%.200s\"\n", ntoa( &client_addr ), ru, date, get_method_str( method ), url, - protocol, status, bytes_str, referer, useragent ); + protocol, status, bytes_str, referrer, useragent ); (void) fflush( logfp ); } @@ -2769,16 +2874,16 @@ make_log_entry( void ) ** and exits. */ static void -check_referer( void ) +check_referrer( void ) { char* cp; - /* Are we doing referer checking at all? */ + /* Are we doing referrer checking at all? */ if ( url_pattern == (char*) 0 ) return; /* Is it ok? */ - if ( really_check_referer() ) + if ( really_check_referrer() ) return; /* Lose. */ @@ -2789,15 +2894,15 @@ check_referer( void ) if ( cp == (char*) 0 ) cp = ""; syslog( - LOG_INFO, "%.80s non-local referer \"%.80s%.80s\" \"%.80s\"", - ntoa( &client_addr ), cp, path, referer ); - send_error( 403, "Forbidden", "", "You must supply a local referer." ); + LOG_INFO, "%.80s non-local referrer \"%.80s%.80s\" \"%.80s\"", + ntoa( &client_addr ), cp, path, referrer ); + send_error( 403, "Forbidden", "", "You must supply a local referrer." ); } /* Returns 1 if ok to serve the url, 0 if not. */ static int -really_check_referer( void ) +really_check_referrer( void ) { char* cp1; char* cp2; @@ -2805,18 +2910,18 @@ really_check_referer( void ) char* refhost; char *lp; - /* Check for an empty referer. */ - if ( referer == (char*) 0 || referer[0] == '\0' || - ( cp1 = strstr( referer, "//" ) ) == (char*) 0 ) + /* Check for an empty referrer. */ + if ( referrer == (char*) 0 || referrer[0] == '\0' || + ( cp1 = strstr( referrer, "//" ) ) == (char*) 0 ) { - /* Disallow if we require a referer and the url matches. */ - if ( no_empty_referers && match( url_pattern, path ) ) + /* Disallow if we require a referrer and the url matches. */ + if ( no_empty_referrers && match( url_pattern, path ) ) return 0; /* Otherwise ok. */ return 1; } - /* Extract referer host. */ + /* Extract referrer host. */ cp1 += 2; for ( cp2 = cp1; *cp2 != '/' && *cp2 != ':' && *cp2 != '\0'; ++cp2 ) continue; @@ -2856,7 +2961,7 @@ really_check_referer( void ) } } - /* If the referer host doesn't match the local host pattern, and + /* If the referrer host doesn't match the local host pattern, and ** the URL does match the url pattern, it's an illegal reference. */ if ( ! match( lp, refhost ) && match( url_pattern, path ) ) @@ -2895,13 +3000,13 @@ static struct mime_entry typ_tab[] = { static const int n_typ_tab = sizeof(typ_tab) / sizeof(*typ_tab); -/* qsort comparison routine - declared old-style on purpose, for portability. */ +/* qsort comparison routine */ static int -ext_compare( a, b ) - struct mime_entry* a; - struct mime_entry* b; +ext_compare( const void* v1, const void* v2 ) { - return strcmp( a->ext, b->ext ); + const struct mime_entry* m1 = (const struct mime_entry*) v1; + const struct mime_entry* m2 = (const struct mime_entry*) v2; + return strcmp( m1->ext, m2->ext ); } @@ -3065,7 +3170,7 @@ handle_sigchld( int sig ) { const int oerrno = errno; pid_t pid; - int status; + int s; #ifndef HAVE_SIGSET /* Set up handler again. */ @@ -3076,9 +3181,9 @@ handle_sigchld( int sig ) for (;;) { #ifdef HAVE_WAITPID - pid = waitpid( (pid_t) -1, &status, WNOHANG ); + pid = waitpid( (pid_t) -1, &s, WNOHANG ); #else /* HAVE_WAITPID */ - pid = wait3( &status, WNOHANG, (struct rusage*) 0 ); + pid = wait3( &s, WNOHANG, (struct rusage*) 0 ); #endif /* HAVE_WAITPID */ if ( (int) pid == 0 ) /* none left */ break; @@ -3422,7 +3527,7 @@ b64_decode( const char* str, unsigned char* space, int size ) phase = 0; for ( cp = str; *cp != '\0'; ++cp ) { - d = b64_decode_table[(int) *cp]; + d = b64_decode_table[(int) ((unsigned char) *cp)]; if ( d != -1 ) { switch ( phase ) diff --git a/port.h b/port.h index ac57d2c..7d451a9 100644 --- a/port.h +++ b/port.h @@ -37,6 +37,7 @@ # define HAVE_SENDFILE # define HAVE_SCANDIR # define HAVE_INT64T +# define HAVE_SRANDOMDEV # ifdef SO_ACCEPTFILTER # define HAVE_ACCEPT_FILTERS # if ( __FreeBSD_version >= 411000 ) @@ -86,6 +87,7 @@ # define HAVE_MEMORY_H # define HAVE_SIGSET # define HAVE_INT64T +# define HAVE_RAND #endif /* OS_Solaris */ #ifdef OS_DigitalUnix @@ -103,4 +105,10 @@ # define HAVE_WAITPID # define HAVE_MEMORY_H # define HAVE_SIGSET +# define HAVE_RAND #endif /* OS_Solaris */ + +#ifdef HAVE_RAND +# define srandom srand +# define random rand +#endif /* HAVE_RAND */ diff --git a/scripts/500.mini_httpd-rotate b/scripts/500.mini_httpd-rotate index 5af4573..ccce57e 100755 --- a/scripts/500.mini_httpd-rotate +++ b/scripts/500.mini_httpd-rotate @@ -6,12 +6,14 @@ # tells mini_httpd to re-open its log file. cd /usr/local/www/chroot/logs -rm -f mini_httpd_log.7 -mv mini_httpd_log.6 mini_httpd_log.7 -mv mini_httpd_log.5 mini_httpd_log.6 -mv mini_httpd_log.4 mini_httpd_log.5 -mv mini_httpd_log.3 mini_httpd_log.4 -mv mini_httpd_log.2 mini_httpd_log.3 -mv mini_httpd_log.1 mini_httpd_log.2 +rm -f mini_httpd_log.7.gz +mv mini_httpd_log.6.gz mini_httpd_log.7.gz +mv mini_httpd_log.5.gz mini_httpd_log.6.gz +mv mini_httpd_log.4.gz mini_httpd_log.5.gz +mv mini_httpd_log.3.gz mini_httpd_log.4.gz +mv mini_httpd_log.2.gz mini_httpd_log.3.gz +mv mini_httpd_log.1.gz mini_httpd_log.2.gz mv mini_httpd_log mini_httpd_log.1 kill -HUP `cat /var/run/mini_httpd.pid` +sleep 1 +gzip -f mini_httpd_log.1 diff --git a/scripts/mini_httpd.sh b/scripts/mini_httpd.sh index 0dde12e..372ecee 100755 --- a/scripts/mini_httpd.sh +++ b/scripts/mini_httpd.sh @@ -3,23 +3,46 @@ # mini_httpd.sh - startup script for mini_httpd on FreeBSD # # This goes in /usr/local/etc/rc.d and gets run at boot-time. +# +# Variables available: +# mini_httpd_enable='YES/NO' +# mini_httpd_program='path' +# mini_httpd_pidfile='path' +# mini_httpd_devfs='path' +# +# PROVIDE: mini_httpd +# REQUIRE: LOGIN FILESYSTEMS +# KEYWORD: shutdown + +. /etc/rc.subr + +name='mini_httpd' +rcvar='mini_httpd_enable' + +load_rc_config "$name" -case "$1" in - - start) - if [ -x /usr/local/sbin/mini_httpd_wrapper ] ; then - echo -n " mini_httpd" - /usr/local/sbin/mini_httpd_wrapper & +# Defaults. +mini_httpd_enable="${mini_httpd_enable:-'NO'}" +mini_httpd_program="${mini_httpd_program:-'/usr/local/sbin/mini_httpd'}" +mini_httpd_pidfile="${mini_httpd_pidfile:-'/var/run/mini_httpd.pid'}" + +mini_httpd_precmd () + { + if [ '' != "$mini_httpd_devfs" ] ; then + mount -t devfs devfs "$mini_httpd_devfs" + devfs -m "$mini_httpd_devfs" rule -s 1 applyset + devfs -m "$mini_httpd_devfs" rule -s 2 applyset fi - ;; - - stop) - kill -USR1 `cat /var/run/mini_httpd.pid` - ;; - - *) - echo "usage: $0 { start | stop }" >&2 - exit 1 - ;; - -esac + } + +mini_httpd_stop () + { + kill -USR1 `cat "$pidfile"` + } + +command="$mini_httpd_program" +pidfile="$mini_httpd_pidfile" +start_precmd='mini_httpd_precmd' +stop_cmd='mini_httpd_stop' + +run_rc_command "$1" diff --git a/scripts/mini_httpd_wrapper b/scripts/mini_httpd_wrapper index d197d79..9980a11 100755 --- a/scripts/mini_httpd_wrapper +++ b/scripts/mini_httpd_wrapper @@ -2,20 +2,23 @@ # # mini_httpd_wrapper - wrapper script for mini_httpd on FreeBSD # -# This goes in /usr/local/sbin. It runs mini_httpd in a loop. If mini_httpd -# exits then the script restarts it automatically. +# This goes in /usr/local/sbin. It backgrounds itself, and then runs +# mini_httpd in a loop. If mini_httpd exits then the script restarts +# it automatically. # # The -D flag tells mini_httpd to *not* put itself into the background, # and the -C flag tells it to get the rest of its configuration from # the specified config file. -while true ; do - /usr/local/sbin/mini_httpd -D -C /usr/local/www/mini_httpd_config - if [ -f /var/run/nologin ] ; then - exit - fi - sleep 10 - egrep ' mini_httpd\[' /var/log/messages | - tail -33 | - mail -s "mini_httpd on `hostname` restarted" root -done +( + while true ; do + /usr/local/sbin/mini_httpd -D -C /usr/local/www/mini_httpd_config + if [ -f /var/run/nologin ] ; then + exit + fi + sleep 10 + egrep ' mini_httpd[:\[]' /var/log/messages | + tail -33 | + mail -s "mini_httpd on `hostname` restarted" root + done +) & diff --git a/tdate_parse.c b/tdate_parse.c index ac9d2ca..a7ea7fa 100644 --- a/tdate_parse.c +++ b/tdate_parse.c @@ -59,12 +59,13 @@ pound_case( char* str ) } } + static int -strlong_compare( v1, v2 ) - char* v1; - char* v2; +strlong_compare( const void* v1, const void* v2 ) { - return strcmp( ((struct strlong*) v1)->s, ((struct strlong*) v2)->s ); + const struct strlong* s1 = (const struct strlong*) v1; + const struct strlong* s2 = (const struct strlong*) v2; + return strcmp( s1->s, s2->s ); } @@ -170,7 +171,7 @@ tm_to_time( struct tm* tmP ) /* Years since epoch, converted to days. */ t = ( tmP->tm_year - 70 ) * 365; - /* Leap days for previous years. */ + /* Leap days for previous years - this will break in 2100! */ t += ( tmP->tm_year - 69 ) / 4; /* Days for the beginning of this month. */ t += monthtab[tmP->tm_mon]; diff --git a/tdate_parse.h b/tdate_parse.h index b4c5720..aaf0b66 100644 --- a/tdate_parse.h +++ b/tdate_parse.h @@ -28,6 +28,6 @@ #ifndef _TDATE_PARSE_H_ #define _TDATE_PARSE_H_ -extern time_t tdate_parse( char* str ); +time_t tdate_parse( char* str ); #endif /* _TDATE_PARSE_H_ */ diff --git a/version.h b/version.h index 36e606e..b94e6a9 100644 --- a/version.h +++ b/version.h @@ -3,7 +3,7 @@ #ifndef _VERSION_H_ #define _VERSION_H_ -#define SERVER_SOFTWARE "mini_httpd/1.19 19dec2003" +#define SERVER_SOFTWARE "mini_httpd/1.21 18oct2014" #define SERVER_URL "http://www.acme.com/software/mini_httpd/" #endif /* _VERSION_H_ */ -- cgit v1.2.3