1
0
mirror of https://github.com/gophernicus/gophernicus.git synced 2024-06-16 06:25:23 +00:00

change indentation from tabs to spaces

This commit is contained in:
fosslinux 2019-08-03 18:30:05 +10:00
parent b0f8d60f93
commit b25c484c92
9 changed files with 2110 additions and 2121 deletions

81
bin2c.c
View File

@ -38,58 +38,57 @@
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
FILE *fp; FILE *fp;
char *source = NULL; char *source = NULL;
char *name = NULL; char *name = NULL;
int first = 1; int first = 1;
int zero = 0; int zero = 0;
int c; int c;
int i; int i;
/* Parse args */ /* Parse args */
while ((c = getopt(argc, argv, "n:0")) != -1) { while ((c = getopt(argc, argv, "n:0")) != -1) {
switch(c) { switch(c) {
case 'n': name = optarg; break; case 'n': name = optarg; break;
case '0': zero = 1; break; case '0': zero = 1; break;
} }
} }
source = argv[optind]; source = argv[optind];
if (!name) name = source; if (!name) name = source;
/* Check args */ /* Check args */
if (!source) { if (!source) {
fprintf(stderr, "Usage: %s [-0] [-n <name>] <source>\n", argv[0]); fprintf(stderr, "Usage: %s [-0] [-n <name>] <source>\n", argv[0]);
return 1; return 1;
} }
/* Try to open the source file */ /* Try to open the source file */
if ((fp = fopen(source, "r")) == NULL) { if ((fp = fopen(source, "r")) == NULL) {
perror("Couldn't open source file"); perror("Couldn't open source file");
return 1; return 1;
} }
/* Convert */ /* Convert */
printf("/* Automatically generated from %s */\n\n" printf("/* Automatically generated from %s */\n\n"
"#define %s { \\\n", source, name); "#define %s { \\\n", source, name);
do { do {
for (i = 0; i < 16; i++) { for (i = 0; i < 16; i++) {
if ((c = fgetc(fp)) == EOF) { if ((c = fgetc(fp)) == EOF) {
if (zero--) c = '\0'; if (zero--) c = '\0';
else break; else break;
} }
if (i == 0 && !first) printf(", \\\n"); if (i == 0 && !first) printf(", \\\n");
if (i > 0) printf(", "); if (i > 0) printf(", ");
printf("0x%02x", c); printf("0x%02x", c);
first = 0; first = 0;
} }
} while (c != EOF); } while (c != EOF);
printf("}\n\n"); printf("}\n\n");
fclose(fp); fclose(fp);
return 0; return 0;
} }

550
file.c
View File

@ -35,29 +35,29 @@
*/ */
void send_binary_file(state *st) void send_binary_file(state *st)
{ {
/* Faster sendfile() version */ /* Faster sendfile() version */
#ifdef HAVE_SENDFILE #ifdef HAVE_SENDFILE
int fd; int fd;
off_t offset = 0; off_t offset = 0;
if (st->debug) syslog(LOG_INFO, "outputting binary file \"%s\"", st->req_realpath); if (st->debug) syslog(LOG_INFO, "outputting binary file \"%s\"", st->req_realpath);
if ((fd = open(st->req_realpath, O_RDONLY)) == ERROR) return; if ((fd = open(st->req_realpath, O_RDONLY)) == ERROR) return;
sendfile(1, fd, &offset, st->req_filesize); sendfile(1, fd, &offset, st->req_filesize);
close(fd); close(fd);
/* More compatible POSIX fread()/fwrite() version */ /* More compatible POSIX fread()/fwrite() version */
#else #else
FILE *fp; FILE *fp;
char buf[BUFSIZE]; char buf[BUFSIZE];
int bytes; int bytes;
if (st->debug) syslog(LOG_INFO, "outputting binary file \"%s\"", st->req_realpath); if (st->debug) syslog(LOG_INFO, "outputting binary file \"%s\"", st->req_realpath);
if ((fp = fopen(st->req_realpath , "r")) == NULL) return; if ((fp = fopen(st->req_realpath , "r")) == NULL) return;
while ((bytes = fread(buf, 1, sizeof(buf), fp)) > 0) while ((bytes = fread(buf, 1, sizeof(buf), fp)) > 0)
fwrite(buf, bytes, 1, stdout); fwrite(buf, bytes, 1, stdout);
fclose(fp); fclose(fp);
#endif #endif
} }
@ -67,37 +67,37 @@ void send_binary_file(state *st)
*/ */
void send_text_file(state *st) void send_text_file(state *st)
{ {
FILE *fp; FILE *fp;
char in[BUFSIZE]; char in[BUFSIZE];
char out[BUFSIZE]; char out[BUFSIZE];
int line; int line;
if (st->debug) syslog(LOG_INFO, "outputting text file \"%s\"", st->req_realpath); if (st->debug) syslog(LOG_INFO, "outputting text file \"%s\"", st->req_realpath);
if ((fp = fopen(st->req_realpath , "r")) == NULL) return; if ((fp = fopen(st->req_realpath , "r")) == NULL) return;
/* Loop through the file line by line */ /* Loop through the file line by line */
line = 0; line = 0;
while (fgets(in, sizeof(in), fp)) { while (fgets(in, sizeof(in), fp)) {
/* Covert to output charset & print */ /* Covert to output charset & print */
if (st->opt_iconv) sstrniconv(st->out_charset, out, in); if (st->opt_iconv) sstrniconv(st->out_charset, out, in);
else sstrlcpy(out, in); else sstrlcpy(out, in);
chomp(out); chomp(out);
#ifdef ENABLE_STRICT_RFC1436 #ifdef ENABLE_STRICT_RFC1436
if (strcmp(out, ".") == MATCH) printf(".." CRLF); if (strcmp(out, ".") == MATCH) printf(".." CRLF);
else else
#endif #endif
printf("%s" CRLF, out); printf("%s" CRLF, out);
line++; line++;
} }
#ifdef ENABLE_STRICT_RFC1436 #ifdef ENABLE_STRICT_RFC1436
printf("." CRLF); printf("." CRLF);
#endif #endif
fclose(fp); fclose(fp);
} }
@ -106,40 +106,40 @@ void send_text_file(state *st)
*/ */
void url_redirect(state *st) void url_redirect(state *st)
{ {
char dest[BUFSIZE]; char dest[BUFSIZE];
/* Basic security checking */ /* Basic security checking */
sstrlcpy(dest, st->req_selector + 4); sstrlcpy(dest, st->req_selector + 4);
if (sstrncmp(dest, "http://") != MATCH && if (sstrncmp(dest, "http://") != MATCH &&
sstrncmp(dest, "https://") != MATCH && sstrncmp(dest, "https://") != MATCH &&
sstrncmp(dest, "ftp://") != MATCH && sstrncmp(dest, "ftp://") != MATCH &&
sstrncmp(dest, "irc://") != MATCH && sstrncmp(dest, "irc://") != MATCH &&
sstrncmp(dest, "mailto:") != MATCH) sstrncmp(dest, "mailto:") != MATCH)
die(st, ERR_ACCESS, "Refusing to HTTP redirect unsafe protocols"); die(st, ERR_ACCESS, "Refusing to HTTP redirect unsafe protocols");
/* Log the redirect */ /* Log the redirect */
if (st->opt_syslog) { if (st->opt_syslog) {
syslog(LOG_INFO, "request for \"gopher%s://%s:%i/h%s\" from %s", syslog(LOG_INFO, "request for \"gopher%s://%s:%i/h%s\" from %s",
(st->server_port == st->server_tls_port ? "s" : ""), (st->server_port == st->server_tls_port ? "s" : ""),
st->server_host, st->server_host,
st->server_port, st->server_port,
st->req_selector, st->req_selector,
st->req_remote_addr); st->req_remote_addr);
} }
log_combined(st, HTTP_OK); log_combined(st, HTTP_OK);
/* Output HTML */ /* Output HTML */
printf("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2 Final//EN\">\n" printf("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2 Final//EN\">\n"
"<HTML>\n<HEAD>\n" "<HTML>\n<HEAD>\n"
" <META HTTP-EQUIV=\"Refresh\" content=\"1;URL=%1$s\">\n" " <META HTTP-EQUIV=\"Refresh\" content=\"1;URL=%1$s\">\n"
" <META HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html;charset=iso-8859-1\">\n" " <META HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html;charset=iso-8859-1\">\n"
" <TITLE>URL Redirect page</TITLE>\n" " <TITLE>URL Redirect page</TITLE>\n"
"</HEAD>\n<BODY>\n" "</HEAD>\n<BODY>\n"
"<STRONG>Redirecting to <A HREF=\"%1$s\">%1$s</A></STRONG>\n" "<STRONG>Redirecting to <A HREF=\"%1$s\">%1$s</A></STRONG>\n"
"<PRE>\n", dest); "<PRE>\n", dest);
footer(st); footer(st);
printf("</PRE>\n</BODY>\n</HTML>\n"); printf("</PRE>\n</BODY>\n</HTML>\n");
} }
@ -149,78 +149,78 @@ void url_redirect(state *st)
#ifdef HAVE_SHMEM #ifdef HAVE_SHMEM
void server_status(state *st, shm_state *shm, int shmid) void server_status(state *st, shm_state *shm, int shmid)
{ {
struct shmid_ds shm_ds; struct shmid_ds shm_ds;
time_t now; time_t now;
time_t uptime; time_t uptime;
int sessions; int sessions;
int i; int i;
/* Log the request */ /* Log the request */
if (st->opt_syslog) { if (st->opt_syslog) {
syslog(LOG_INFO, "request for \"gopher%s://%s:%i/0" SERVER_STATUS "\" from %s", syslog(LOG_INFO, "request for \"gopher%s://%s:%i/0" SERVER_STATUS "\" from %s",
(st->server_port == st->server_tls_port ? "s" : ""), (st->server_port == st->server_tls_port ? "s" : ""),
st->server_host, st->server_host,
st->server_port, st->server_port,
st->req_remote_addr); st->req_remote_addr);
} }
log_combined(st, HTTP_OK); log_combined(st, HTTP_OK);
/* Quit if shared memory isn't initialized yet */ /* Quit if shared memory isn't initialized yet */
if (!shm) return; if (!shm) return;
/* Update counters */ /* Update counters */
shm->hits++; shm->hits++;
shm->kbytes += 1; shm->kbytes += 1;
/* Get server uptime */ /* Get server uptime */
now = time(NULL); now = time(NULL);
uptime = (now - shm->start_time) + 1; uptime = (now - shm->start_time) + 1;
/* Get shared memory info */ /* Get shared memory info */
shmctl(shmid, IPC_STAT, &shm_ds); shmctl(shmid, IPC_STAT, &shm_ds);
/* Print statistics */ /* Print statistics */
printf("Total Accesses: %li" CRLF printf("Total Accesses: %li" CRLF
"Total kBytes: %li" CRLF "Total kBytes: %li" CRLF
"Uptime: %i" CRLF "Uptime: %i" CRLF
"ReqPerSec: %.3f" CRLF "ReqPerSec: %.3f" CRLF
"BytesPerSec: %li" CRLF "BytesPerSec: %li" CRLF
"BytesPerReq: %li" CRLF "BytesPerReq: %li" CRLF
"BusyServers: %i" CRLF "BusyServers: %i" CRLF
"IdleServers: 0" CRLF "IdleServers: 0" CRLF
"CPULoad: %.2f" CRLF, "CPULoad: %.2f" CRLF,
shm->hits, shm->hits,
shm->kbytes, shm->kbytes,
(int) uptime, (int) uptime,
(float) shm->hits / (float) uptime, (float) shm->hits / (float) uptime,
shm->kbytes * 1024 / (int) uptime, shm->kbytes * 1024 / (int) uptime,
shm->kbytes * 1024 / (shm->hits + 1), shm->kbytes * 1024 / (shm->hits + 1),
(int) shm_ds.shm_nattch, (int) shm_ds.shm_nattch,
loadavg()); loadavg());
/* Print active sessions */ /* Print active sessions */
sessions = 0; sessions = 0;
for (i = 0; i < SHM_SESSIONS; i++) { for (i = 0; i < SHM_SESSIONS; i++) {
if ((now - shm->session[i].req_atime) < st->session_timeout) { if ((now - shm->session[i].req_atime) < st->session_timeout) {
sessions++; sessions++;
if (st->debug) { if (st->debug) {
printf("Session: %-4i %-40s %-4li %-7li gopher%s://%s:%i/%c%s" CRLF, printf("Session: %-4i %-40s %-4li %-7li gopher%s://%s:%i/%c%s" CRLF,
(int) (now - shm->session[i].req_atime), (int) (now - shm->session[i].req_atime),
shm->session[i].req_remote_addr, shm->session[i].req_remote_addr,
shm->session[i].hits, shm->session[i].hits,
shm->session[i].kbytes, shm->session[i].kbytes,
(shm->session[i].server_port == st->server_tls_port ? "s" : ""), (shm->session[i].server_port == st->server_tls_port ? "s" : ""),
shm->session[i].server_host, shm->session[i].server_host,
shm->session[i].server_port, shm->session[i].server_port,
shm->session[i].req_filetype, shm->session[i].req_filetype,
shm->session[i].req_selector); shm->session[i].req_selector);
} }
} }
} }
printf("Total Sessions: %i" CRLF, sessions); printf("Total Sessions: %i" CRLF, sessions);
} }
#endif #endif
@ -230,62 +230,62 @@ void server_status(state *st, shm_state *shm, int shmid)
*/ */
void caps_txt(state *st, shm_state *shm) void caps_txt(state *st, shm_state *shm)
{ {
/* Log the request */ /* Log the request */
if (st->opt_syslog) { if (st->opt_syslog) {
syslog(LOG_INFO, "request for \"gopher%s://%s:%i/0" CAPS_TXT "\" from %s", syslog(LOG_INFO, "request for \"gopher%s://%s:%i/0" CAPS_TXT "\" from %s",
(st->server_port == st->server_tls_port ? "s" : ""), (st->server_port == st->server_tls_port ? "s" : ""),
st->server_host, st->server_host,
st->server_port, st->server_port,
st->req_remote_addr); st->req_remote_addr);
} }
log_combined(st, HTTP_OK); log_combined(st, HTTP_OK);
/* Update counters */ /* Update counters */
#ifdef HAVE_SHMEM #ifdef HAVE_SHMEM
if (shm) { if (shm) {
shm->hits++; shm->hits++;
shm->kbytes += 1; shm->kbytes += 1;
/* Update session data */ /* Update session data */
st->req_filesize += 1024; st->req_filesize += 1024;
update_shm_session(st, shm); update_shm_session(st, shm);
} }
#endif #endif
/* Standard caps.txt stuff */ /* Standard caps.txt stuff */
printf("CAPS" CRLF printf("CAPS" CRLF
CRLF CRLF
"##" CRLF "##" CRLF
"## This is an automatically generated caps file." CRLF "## This is an automatically generated caps file." CRLF
"##" CRLF "##" CRLF
CRLF CRLF
"CapsVersion=1" CRLF "CapsVersion=1" CRLF
"ExpireCapsAfter=%i" CRLF "ExpireCapsAfter=%i" CRLF
CRLF CRLF
"PathDelimeter=/" CRLF "PathDelimeter=/" CRLF
"PathIdentity=." CRLF "PathIdentity=." CRLF
"PathParent=.." CRLF "PathParent=.." CRLF
"PathParentDouble=FALSE" CRLF "PathParentDouble=FALSE" CRLF
"PathKeepPreDelimeter=FALSE" CRLF "PathKeepPreDelimeter=FALSE" CRLF
"ServerSupportsStdinScripts=TRUE" CRLF "ServerSupportsStdinScripts=TRUE" CRLF
"ServerDefaultEncoding=%s" CRLF "ServerDefaultEncoding=%s" CRLF
"ServerTLSPort=%i" CRLF "ServerTLSPort=%i" CRLF
CRLF CRLF
"ServerSoftware=" SERVER_SOFTWARE CRLF "ServerSoftware=" SERVER_SOFTWARE CRLF
"ServerSoftwareVersion=" VERSION " \"" CODENAME "\"" CRLF "ServerSoftwareVersion=" VERSION " \"" CODENAME "\"" CRLF
"ServerArchitecture=%s" CRLF, "ServerArchitecture=%s" CRLF,
st->session_timeout, st->session_timeout,
strcharset(st->out_charset), strcharset(st->out_charset),
st->server_tls_port, st->server_tls_port,
st->server_platform); st->server_platform);
/* Optional keys */ /* Optional keys */
if (*st->server_description) if (*st->server_description)
printf("ServerDescription=%s" CRLF, st->server_description); printf("ServerDescription=%s" CRLF, st->server_description);
if (*st->server_location) if (*st->server_location)
printf("ServerGeolocationString=%s" CRLF, st->server_location); printf("ServerGeolocationString=%s" CRLF, st->server_location);
if (*st->server_admin) if (*st->server_admin)
printf("ServerAdmin=%s" CRLF, st->server_admin); printf("ServerAdmin=%s" CRLF, st->server_admin);
} }
@ -294,71 +294,71 @@ void caps_txt(state *st, shm_state *shm)
*/ */
void setenv_cgi(state *st, char *script) void setenv_cgi(state *st, char *script)
{ {
char buf[BUFSIZE]; char buf[BUFSIZE];
/* Security */ /* Security */
setenv("PATH", SAFE_PATH, 1); setenv("PATH", SAFE_PATH, 1);
/* Set up the environment as per CGI spec */ /* Set up the environment as per CGI spec */
setenv("GATEWAY_INTERFACE", "CGI/1.1", 1); setenv("GATEWAY_INTERFACE", "CGI/1.1", 1);
setenv("CONTENT_LENGTH", "0", 1); setenv("CONTENT_LENGTH", "0", 1);
setenv("QUERY_STRING", st->req_query_string, 1); setenv("QUERY_STRING", st->req_query_string, 1);
snprintf(buf, sizeof(buf), SERVER_SOFTWARE_FULL, st->server_platform); snprintf(buf, sizeof(buf), SERVER_SOFTWARE_FULL, st->server_platform);
setenv("SERVER_SOFTWARE", buf, 1); setenv("SERVER_SOFTWARE", buf, 1);
setenv("SERVER_ARCH", st->server_platform, 1); setenv("SERVER_ARCH", st->server_platform, 1);
setenv("SERVER_DESCRIPTION", st->server_description, 1); setenv("SERVER_DESCRIPTION", st->server_description, 1);
snprintf(buf, sizeof(buf), SERVER_SOFTWARE "/" VERSION); snprintf(buf, sizeof(buf), SERVER_SOFTWARE "/" VERSION);
setenv("SERVER_VERSION", buf, 1); setenv("SERVER_VERSION", buf, 1);
if (st->req_protocol == PROTO_HTTP) if (st->req_protocol == PROTO_HTTP)
setenv("SERVER_PROTOCOL", "HTTP/0.9", 1); setenv("SERVER_PROTOCOL", "HTTP/0.9", 1);
else else
setenv("SERVER_PROTOCOL", "RFC1436", 1); setenv("SERVER_PROTOCOL", "RFC1436", 1);
if (st->server_port == st->server_tls_port) { if (st->server_port == st->server_tls_port) {
setenv("HTTPS", "on", 1); setenv("HTTPS", "on", 1);
setenv("TLS", "on", 1); setenv("TLS", "on", 1);
} }
setenv("SERVER_NAME", st->server_host, 1); setenv("SERVER_NAME", st->server_host, 1);
snprintf(buf, sizeof(buf), "%i", st->server_port); snprintf(buf, sizeof(buf), "%i", st->server_port);
setenv("SERVER_PORT", buf, 1); setenv("SERVER_PORT", buf, 1);
snprintf(buf, sizeof(buf), "%i", st->server_tls_port); snprintf(buf, sizeof(buf), "%i", st->server_tls_port);
setenv("SERVER_TLS_PORT", buf, 1); setenv("SERVER_TLS_PORT", buf, 1);
setenv("REQUEST_METHOD", "GET", 1); setenv("REQUEST_METHOD", "GET", 1);
setenv("DOCUMENT_ROOT", st->server_root, 1); setenv("DOCUMENT_ROOT", st->server_root, 1);
setenv("SCRIPT_NAME", st->req_selector, 1); setenv("SCRIPT_NAME", st->req_selector, 1);
setenv("SCRIPT_FILENAME", script, 1); setenv("SCRIPT_FILENAME", script, 1);
setenv("LOCAL_ADDR", st->req_local_addr, 1); setenv("LOCAL_ADDR", st->req_local_addr, 1);
setenv("REMOTE_ADDR", st->req_remote_addr, 1); setenv("REMOTE_ADDR", st->req_remote_addr, 1);
setenv("HTTP_REFERER", st->req_referrer, 1); setenv("HTTP_REFERER", st->req_referrer, 1);
#ifdef HAVE_SHMEM #ifdef HAVE_SHMEM
snprintf(buf, sizeof(buf), "%x", st->session_id); snprintf(buf, sizeof(buf), "%x", st->session_id);
setenv("SESSION_ID", buf, 1); setenv("SESSION_ID", buf, 1);
#endif #endif
setenv("HTTP_ACCEPT_CHARSET", strcharset(st->out_charset), 1); setenv("HTTP_ACCEPT_CHARSET", strcharset(st->out_charset), 1);
/* Gophernicus extras */ /* Gophernicus extras */
snprintf(buf, sizeof(buf), "%c", st->req_filetype); snprintf(buf, sizeof(buf), "%c", st->req_filetype);
setenv("GOPHER_FILETYPE", buf, 1); setenv("GOPHER_FILETYPE", buf, 1);
setenv("GOPHER_CHARSET", strcharset(st->out_charset), 1); setenv("GOPHER_CHARSET", strcharset(st->out_charset), 1);
setenv("GOPHER_REFERER", st->req_referrer, 1); setenv("GOPHER_REFERER", st->req_referrer, 1);
snprintf(buf, sizeof(buf), "%i", st->out_width); snprintf(buf, sizeof(buf), "%i", st->out_width);
setenv("COLUMNS", buf, 1); setenv("COLUMNS", buf, 1);
snprintf(buf, sizeof(buf), CODENAME); snprintf(buf, sizeof(buf), CODENAME);
setenv("SERVER_CODENAME", buf, 1); setenv("SERVER_CODENAME", buf, 1);
/* Bucktooth extras */ /* Bucktooth extras */
if (*st->req_query_string) { if (*st->req_query_string) {
snprintf(buf, sizeof(buf), "%s?%s", snprintf(buf, sizeof(buf), "%s?%s",
st->req_selector, st->req_query_string); st->req_selector, st->req_query_string);
setenv("SELECTOR", buf, 1); setenv("SELECTOR", buf, 1);
} }
else setenv("SELECTOR", st->req_selector, 1); else setenv("SELECTOR", st->req_selector, 1);
setenv("SERVER_HOST", st->server_host, 1); setenv("SERVER_HOST", st->server_host, 1);
setenv("REQUEST", st->req_selector, 1); setenv("REQUEST", st->req_selector, 1);
setenv("SEARCHREQUEST", st->req_search, 1); setenv("SEARCHREQUEST", st->req_search, 1);
} }
@ -367,18 +367,18 @@ void setenv_cgi(state *st, char *script)
*/ */
void run_cgi(state *st, char *script, char *arg) void run_cgi(state *st, char *script, char *arg)
{ {
if (st->opt_exec) { if (st->opt_exec) {
/* Setup environment & execute the binary */ /* Setup environment & execute the binary */
if (st->debug) syslog(LOG_INFO, "executing script \"%s\"", script); if (st->debug) syslog(LOG_INFO, "executing script \"%s\"", script);
setenv_cgi(st, script); setenv_cgi(st, script);
execl(script, script, arg, NULL); execl(script, script, arg, NULL);
} }
else if (st->debug) syslog(LOG_INFO, "script \"%s\" was blocked by -nx", script); else if (st->debug) syslog(LOG_INFO, "script \"%s\" was blocked by -nx", script);
/* Didn't work - die */ /* Didn't work - die */
die(st, ERR_ACCESS, NULL); die(st, ERR_ACCESS, NULL);
} }
@ -387,46 +387,44 @@ void run_cgi(state *st, char *script, char *arg)
*/ */
void gopher_file(state *st) void gopher_file(state *st)
{ {
struct stat file; struct stat file;
char buf[BUFSIZE]; char buf[BUFSIZE];
char *c; char *c;
/* Refuse to serve out gophermaps/tags */ /* Refuse to serve out gophermaps/tags */
if ((c = strrchr(st->req_realpath, '/'))) c++; if ((c = strrchr(st->req_realpath, '/'))) c++;
else c = st->req_realpath; else c = st->req_realpath;
if (strcmp(c, st->map_file) == MATCH) if (strcmp(c, st->map_file) == MATCH)
die(st, ERR_ACCESS, "Refusing to serve out a gophermap file"); die(st, ERR_ACCESS, "Refusing to serve out a gophermap file");
if (strcmp(c, st->tag_file) == MATCH) if (strcmp(c, st->tag_file) == MATCH)
die(st, ERR_ACCESS, "Refusing to serve out a gophertag file"); die(st, ERR_ACCESS, "Refusing to serve out a gophertag file");
/* Check for & run CGI and query scripts */ /* Check for & run CGI and query scripts */
if (strstr(st->req_realpath, st->cgi_file) || st->req_filetype == TYPE_QUERY) if (strstr(st->req_realpath, st->cgi_file) || st->req_filetype == TYPE_QUERY)
run_cgi(st, st->req_realpath, NULL); run_cgi(st, st->req_realpath, NULL);
/* Check for a file suffix filter */ /* Check for a file suffix filter */
if (*st->filter_dir && (c = strrchr(st->req_realpath, '.'))) { if (*st->filter_dir && (c = strrchr(st->req_realpath, '.'))) {
snprintf(buf, sizeof(buf), "%s/%s", st->filter_dir, c + 1); snprintf(buf, sizeof(buf), "%s/%s", st->filter_dir, c + 1);
/* Filter file through the script */ /* Filter file through the script */
if (stat(buf, &file) == OK && (file.st_mode & S_IXOTH)) if (stat(buf, &file) == OK && (file.st_mode & S_IXOTH))
run_cgi(st, buf, st->req_realpath); run_cgi(st, buf, st->req_realpath);
} }
/* Check for a filetype filter */ /* Check for a filetype filter */
if (*st->filter_dir) { if (*st->filter_dir) {
snprintf(buf, sizeof(buf), "%s/%c", st->filter_dir, st->req_filetype); snprintf(buf, sizeof(buf), "%s/%c", st->filter_dir, st->req_filetype);
/* Filter file through the script */ /* Filter file through the script */
if (stat(buf, &file) == OK && (file.st_mode & S_IXOTH)) if (stat(buf, &file) == OK && (file.st_mode & S_IXOTH))
run_cgi(st, buf, st->req_realpath); run_cgi(st, buf, st->req_realpath);
} }
/* Output regular files */ /* Output regular files */
if (st->req_filetype == TYPE_TEXT || st->req_filetype == TYPE_MIME) if (st->req_filetype == TYPE_TEXT || st->req_filetype == TYPE_MIME)
send_text_file(st); send_text_file(st);
else else
send_binary_file(st); send_binary_file(st);
} }

File diff suppressed because it is too large Load Diff

View File

@ -41,9 +41,9 @@
/* /*
* Features * Features
*/ */
#undef ENABLE_STRICT_RFC1436 /* Follow RFC1436 to the letter */ #undef ENABLE_STRICT_RFC1436 /* Follow RFC1436 to the letter */
#undef ENABLE_AUTOHIDING /* Hide manually listed resources from generated menus */ #undef ENABLE_AUTOHIDING /* Hide manually listed resources from generated menus */
#define ENABLE_HAPROXY1 /* Autodetect HAproxy/Stunnel proxy protocol v1 */ #define ENABLE_HAPROXY1 /* Autodetect HAproxy/Stunnel proxy protocol v1 */
/* /*
@ -51,17 +51,17 @@
*/ */
/* Defaults should fit standard POSIX systems */ /* Defaults should fit standard POSIX systems */
#define HAVE_IPv4 /* IPv4 should work anywhere */ #define HAVE_IPv4 /* IPv4 should work anywhere */
#define HAVE_IPv6 /* Requires modern POSIX */ #define HAVE_IPv6 /* Requires modern POSIX */
#define HAVE_PASSWD /* For systems with passwd-like userdb */ #define HAVE_PASSWD /* For systems with passwd-like userdb */
#define PASSWD_MIN_UID 100 /* Minimum allowed UID for ~userdirs */ #define PASSWD_MIN_UID 100 /* Minimum allowed UID for ~userdirs */
#define HAVE_LOCALES /* setlocale() and friends */ #define HAVE_LOCALES /* setlocale() and friends */
#define HAVE_SHMEM /* Shared memory support */ #define HAVE_SHMEM /* Shared memory support */
#define HAVE_UNAME /* uname() */ #define HAVE_UNAME /* uname() */
#define HAVE_POPEN /* popen() */ #define HAVE_POPEN /* popen() */
#undef HAVE_STRLCPY /* strlcpy() from OpenBSD */ #undef HAVE_STRLCPY /* strlcpy() from OpenBSD */
#undef HAVE_SENDFILE /* sendfile() in Linux & others */ #undef HAVE_SENDFILE /* sendfile() in Linux & others */
/* #undef HAVE_LIBWRAP autodetected, don't enable here */ /* #undef HAVE_LIBWRAP autodetected, don't enable here */
/* Linux */ /* Linux */
#ifdef __linux #ifdef __linux
@ -158,278 +158,278 @@ size_t strlcat(char *dst, const char *src, size_t siz);
*/ */
/* Common stuff */ /* Common stuff */
#define CRLF "\r\n" #define CRLF "\r\n"
#define EMPTY "" #define EMPTY ""
#define PARENT ".." #define PARENT ".."
#define ROOT "/" #define ROOT "/"
#define FALSE 0 #define FALSE 0
#define TRUE 1 #define TRUE 1
#define QUIT 1 #define QUIT 1
#define OK 0 #define OK 0
#define ERROR -1 #define ERROR -1
#define MATCH 0 #define MATCH 0
#define WRAP_DENIED 0 #define WRAP_DENIED 0
/* Gopher filetypes */ /* Gopher filetypes */
#define TYPE_TEXT '0' #define TYPE_TEXT '0'
#define TYPE_MENU '1' #define TYPE_MENU '1'
#define TYPE_ERROR '3' #define TYPE_ERROR '3'
#define TYPE_GZIP '5' #define TYPE_GZIP '5'
#define TYPE_QUERY '7' #define TYPE_QUERY '7'
#define TYPE_BINARY '9' #define TYPE_BINARY '9'
#define TYPE_GIF 'g' #define TYPE_GIF 'g'
#define TYPE_HTML 'h' #define TYPE_HTML 'h'
#define TYPE_INFO 'i' #define TYPE_INFO 'i'
#define TYPE_IMAGE 'I' #define TYPE_IMAGE 'I'
#define TYPE_MIME 'M' #define TYPE_MIME 'M'
#define TYPE_DOC 'd' #define TYPE_DOC 'd'
#define TYPE_TITLE '!' #define TYPE_TITLE '!'
/* Protocols */ /* Protocols */
#define PROTO_GOPHER 'g' #define PROTO_GOPHER 'g'
#define PROTO_HTTP 'h' #define PROTO_HTTP 'h'
/* Charsets */ /* Charsets */
#define AUTO 0 #define AUTO 0
#define US_ASCII 1 #define US_ASCII 1
#define ISO_8859_1 2 #define ISO_8859_1 2
#define UTF_8 3 #define UTF_8 3
/* HTTP protocol stuff for logging */ /* HTTP protocol stuff for logging */
#define HTTP_OK 200 #define HTTP_OK 200
#define HTTP_404 404 #define HTTP_404 404
#define HTTP_DATE "%d/%b/%Y:%T %z" #define HTTP_DATE "%d/%b/%Y:%T %z"
#define HTTP_USERAGENT "Unknown gopher client" #define HTTP_USERAGENT "Unknown gopher client"
/* Defaults for settings */ /* Defaults for settings */
#define DEFAULT_HOST "localhost" #define DEFAULT_HOST "localhost"
#define DEFAULT_PORT 70 #define DEFAULT_PORT 70
#define DEFAULT_TLS_PORT 0 #define DEFAULT_TLS_PORT 0
#define DEFAULT_TYPE TYPE_TEXT #define DEFAULT_TYPE TYPE_TEXT
#define DEFAULT_MAP "gophermap" #define DEFAULT_MAP "gophermap"
#define DEFAULT_TAG "gophertag" #define DEFAULT_TAG "gophertag"
#define DEFAULT_CGI "/cgi-bin/" #define DEFAULT_CGI "/cgi-bin/"
#define DEFAULT_USERDIR "public_gopher" #define DEFAULT_USERDIR "public_gopher"
#define DEFAULT_WIDTH 76 #define DEFAULT_WIDTH 76
#define DEFAULT_CHARSET US_ASCII #define DEFAULT_CHARSET US_ASCII
#define MIN_WIDTH 33 #define MIN_WIDTH 33
#define MAX_WIDTH 200 #define MAX_WIDTH 200
#define UNKNOWN_ADDR "unknown" #define UNKNOWN_ADDR "unknown"
/* Session defaults */ /* Session defaults */
#define DEFAULT_SESSION_TIMEOUT 1800 #define DEFAULT_SESSION_TIMEOUT 1800
#define DEFAULT_SESSION_MAX_KBYTES 4194304 #define DEFAULT_SESSION_MAX_KBYTES 4194304
#define DEFAULT_SESSION_MAX_HITS 4096 #define DEFAULT_SESSION_MAX_HITS 4096
/* Dummy values for gopher protocol */ /* Dummy values for gopher protocol */
#define DUMMY_SELECTOR "null" #define DUMMY_SELECTOR "null"
#define DUMMY_HOST "null.host\t1" #define DUMMY_HOST "null.host\t1"
/* Safe $PATH for exec() */ /* Safe $PATH for exec() */
#ifdef __HAIKU__ #ifdef __HAIKU__
#define SAFE_PATH "/boot/common/bin:/bin" #define SAFE_PATH "/boot/common/bin:/bin"
#else #else
#define SAFE_PATH "/usr/bin:/bin" #define SAFE_PATH "/usr/bin:/bin"
#endif #endif
/* Special requests */ /* Special requests */
#define SERVER_STATUS "/server-status" #define SERVER_STATUS "/server-status"
#define CAPS_TXT "/caps.txt" #define CAPS_TXT "/caps.txt"
/* Error messages */ /* Error messages */
#define ERR_ACCESS "Access denied!" #define ERR_ACCESS "Access denied!"
#define ERR_NOTFOUND "File or directory not found!" #define ERR_NOTFOUND "File or directory not found!"
#define ERROR_HOST "error.host\t1" #define ERROR_HOST "error.host\t1"
#define ERROR_PREFIX "Error: " #define ERROR_PREFIX "Error: "
/* Strings */ /* Strings */
#define SERVER_SOFTWARE "Gophernicus" #define SERVER_SOFTWARE "Gophernicus"
#define SERVER_SOFTWARE_FULL SERVER_SOFTWARE "/" VERSION " (%s)" #define SERVER_SOFTWARE_FULL SERVER_SOFTWARE "/" VERSION " (%s)"
#define HEADER_FORMAT "[%s]" #define HEADER_FORMAT "[%s]"
#define FOOTER_FORMAT "Gophered by Gophernicus/" VERSION " on %s" #define FOOTER_FORMAT "Gophered by Gophernicus/" VERSION " on %s"
#define UNITS "KB", "MB", "GB", "TB", "PB", NULL #define UNITS "KB", "MB", "GB", "TB", "PB", NULL
#define DATE_FORMAT "%Y-%b-%d %H:%M" /* See man 3 strftime */ #define DATE_FORMAT "%Y-%b-%d %H:%M" /* See man 3 strftime */
#define DATE_WIDTH 17 #define DATE_WIDTH 17
#define DATE_LOCALE "POSIX" #define DATE_LOCALE "POSIX"
#define USERDIR_FORMAT "~%s", pwd->pw_name /* See man 3 getpwent */ #define USERDIR_FORMAT "~%s", pwd->pw_name /* See man 3 getpwent */
#define VHOST_FORMAT "gopher://%s/" #define VHOST_FORMAT "gopher://%s/"
/* ISO-8859-1 to US-ASCII look-alike conversion table */ /* ISO-8859-1 to US-ASCII look-alike conversion table */
#define ASCII \ #define ASCII \
"E?,f..++^%S<??Z?" \ "E?,f..++^%S<??Z?" \
"?''\"\"*--~?s>??zY" \ "?''\"\"*--~?s>??zY" \
" !c_*Y|$\"C?<?-R-" \ " !c_*Y|$\"C?<?-R-" \
"??23'u?*,1?>????" \ "??23'u?*,1?>????" \
"AAAAAAACEEEEIIII" \ "AAAAAAACEEEEIIII" \
"DNOOOOO*OUUUUYTB" \ "DNOOOOO*OUUUUYTB" \
"aaaaaaaceeeeiiii" \ "aaaaaaaceeeeiiii" \
"dnooooo/ouuuuyty" "dnooooo/ouuuuyty"
#define UNKNOWN '?' #define UNKNOWN '?'
/* Sizes & maximums */ /* Sizes & maximums */
#define BUFSIZE 1024 /* Default size for string buffers */ #define BUFSIZE 1024 /* Default size for string buffers */
#define MAX_HIDDEN 32 /* Maximum number of hidden files */ #define MAX_HIDDEN 32 /* Maximum number of hidden files */
#define MAX_FILETYPES 128 /* Maximum number of suffix to filetype mappings */ #define MAX_FILETYPES 128 /* Maximum number of suffix to filetype mappings */
#define MAX_FILTERS 16 /* Maximum number of file filters */ #define MAX_FILTERS 16 /* Maximum number of file filters */
#define MAX_SDIRENT 1024 /* Maximum number of files per directory to handle */ #define MAX_SDIRENT 1024 /* Maximum number of files per directory to handle */
#define MAX_REWRITE 32 /* Maximum number of selector rewrite options */ #define MAX_REWRITE 32 /* Maximum number of selector rewrite options */
/* Struct for file suffix -> gopher filetype mapping */ /* Struct for file suffix -> gopher filetype mapping */
typedef struct { typedef struct {
char suffix[15]; char suffix[15];
char type; char type;
} ftype; } ftype;
/* Struct for selector rewriting */ /* Struct for selector rewriting */
typedef struct { typedef struct {
char match[BUFSIZE]; char match[BUFSIZE];
char replace[BUFSIZE]; char replace[BUFSIZE];
} srewrite; } srewrite;
/* Struct for keeping the current options & state */ /* Struct for keeping the current options & state */
typedef struct { typedef struct {
/* Request */ /* Request */
char req_selector[BUFSIZE]; char req_selector[BUFSIZE];
char req_realpath[BUFSIZE]; char req_realpath[BUFSIZE];
char req_query_string[BUFSIZE]; char req_query_string[BUFSIZE];
char req_search[BUFSIZE]; char req_search[BUFSIZE];
char req_referrer[BUFSIZE]; char req_referrer[BUFSIZE];
char req_local_addr[64]; char req_local_addr[64];
char req_remote_addr[64]; char req_remote_addr[64];
char req_filetype; char req_filetype;
char req_protocol; char req_protocol;
off_t req_filesize; off_t req_filesize;
/* Output */ /* Output */
int out_width; int out_width;
int out_charset; int out_charset;
/* Settings */ /* Settings */
char server_description[64]; char server_description[64];
char server_location[64]; char server_location[64];
char server_platform[64]; char server_platform[64];
char server_admin[64]; char server_admin[64];
char server_root[256]; char server_root[256];
char server_host_default[64]; char server_host_default[64];
char server_host[64]; char server_host[64];
int server_port; int server_port;
int server_tls_port; int server_tls_port;
char default_filetype; char default_filetype;
char map_file[64]; char map_file[64];
char tag_file[64]; char tag_file[64];
char cgi_file[64]; char cgi_file[64];
char user_dir[64]; char user_dir[64];
char log_file[256]; char log_file[256];
char hidden[MAX_HIDDEN][256]; char hidden[MAX_HIDDEN][256];
int hidden_count; int hidden_count;
ftype filetype[MAX_FILETYPES]; ftype filetype[MAX_FILETYPES];
int filetype_count; int filetype_count;
char filter_dir[64]; char filter_dir[64];
srewrite rewrite[MAX_REWRITE]; srewrite rewrite[MAX_REWRITE];
int rewrite_count; int rewrite_count;
/* Session */ /* Session */
int session_timeout; int session_timeout;
int session_max_kbytes; int session_max_kbytes;
int session_max_hits; int session_max_hits;
int session_id; int session_id;
/* Feature options */ /* Feature options */
char opt_parent; char opt_parent;
char opt_header; char opt_header;
char opt_footer; char opt_footer;
char opt_date; char opt_date;
char opt_syslog; char opt_syslog;
char opt_magic; char opt_magic;
char opt_iconv; char opt_iconv;
char opt_vhost; char opt_vhost;
char opt_query; char opt_query;
char opt_caps; char opt_caps;
char opt_status; char opt_status;
char opt_shm; char opt_shm;
char opt_root; char opt_root;
char opt_proxy; char opt_proxy;
char opt_exec; char opt_exec;
char opt_personal_spaces; char opt_personal_spaces;
char debug; char debug;
} state; } state;
/* Shared memory for session & accounting data */ /* Shared memory for session & accounting data */
#ifdef HAVE_SHMEM #ifdef HAVE_SHMEM
#define SHM_KEY 0xbeeb0008 /* Unique identifier + struct version */ #define SHM_KEY 0xbeeb0008 /* Unique identifier + struct version */
#define SHM_MODE 0600 /* Access mode for the shared memory */ #define SHM_MODE 0600 /* Access mode for the shared memory */
#define SHM_SESSIONS 256 /* Max amount of user sessions to track */ #define SHM_SESSIONS 256 /* Max amount of user sessions to track */
typedef struct { typedef struct {
long hits; long hits;
long kbytes; long kbytes;
time_t req_atime; time_t req_atime;
char req_selector[128]; char req_selector[128];
char req_remote_addr[64]; char req_remote_addr[64];
char req_filetype; char req_filetype;
int session_id; int session_id;
char server_host[64]; char server_host[64];
int server_port; int server_port;
} shm_session; } shm_session;
typedef struct { typedef struct {
time_t start_time; time_t start_time;
long hits; long hits;
long kbytes; long kbytes;
char server_platform[64]; char server_platform[64];
char server_description[64]; char server_description[64];
shm_session session[SHM_SESSIONS]; shm_session session[SHM_SESSIONS];
} shm_state; } shm_state;
#endif #endif
/* Struct for directory sorting */ /* Struct for directory sorting */
typedef struct { typedef struct {
char name[128]; /* Should be 256 but we're saving stack space */ char name[128]; /* Should be 256 but we're saving stack space */
mode_t mode; mode_t mode;
uid_t uid; uid_t uid;
gid_t gid; gid_t gid;
off_t size; off_t size;
time_t mtime; time_t mtime;
} sdirent; } sdirent;
/* File suffix to gopher filetype mappings */ /* File suffix to gopher filetype mappings */
#define FILETYPES \ #define FILETYPES \
"txt","0","pl","0","py","0","sh","0","tcl","0","c","0","cpp","0", "h","0","log","0", \ "txt","0","pl","0","py","0","sh","0","tcl","0","c","0","cpp","0", "h","0","log","0", \
"conf","0","php","0","php3","0", \ "conf","0","php","0","php3","0", \
"map","1","menu","1", \ "map","1","menu","1", \
"hqx","4", \ "hqx","4", \
"Z","5","gz","5","tgz","5","tar","5","zip","5","bz2","5","rar","5","sea","5", \ "Z","5","gz","5","tgz","5","tar","5","zip","5","bz2","5","rar","5","sea","5", \
"q","7","qry","7", \ "q","7","qry","7", \
"iso","9","so","9","o","9","rtf","9","ttf","9","bin","9", \ "iso","9","so","9","o","9","rtf","9","ttf","9","bin","9", \
"ics","c","ical","c", \ "ics","c","ical","c", \
"gif","g", \ "gif","g", \
"html","h","htm","h","xhtml","h","css","h","swf","h","rdf","h","rss","h","xml","h", \ "html","h","htm","h","xhtml","h","css","h","swf","h","rdf","h","rss","h","xml","h", \
"jpg","I","jpeg","I","png","I","bmp","I","svg","I","tif","I","tiff","I", \ "jpg","I","jpeg","I","png","I","bmp","I","svg","I","tif","I","tiff","I", \
"ico","I","xbm","I","xpm","I","pcx","I", \ "ico","I","xbm","I","xpm","I","pcx","I", \
"mbox","M", \ "mbox","M", \
"pdf","d","ps","d","doc","d","ppt","d","xls","d","xlsx","d","docx","d","pptx","d", \ "pdf","d","ps","d","doc","d","ppt","d","xls","d","xlsx","d","docx","d","pptx","d", \
"mp3","s","wav","s","mid","s","wma","s","flac","s","ogg","s","aiff","s","aac","s", \ "mp3","s","wav","s","mid","s","wma","s","flac","s","ogg","s","aiff","s","aac","s", \
"avi",";","mp4",";","mpg",";","mov",";","qt",";","asf",";","mpv",";","m4v",";","webm",";","ogv",";", \ "avi",";","mp4",";","mpg",";","mov",";","qt",";","asf",";","mpv",";","m4v",";","webm",";","ogv",";", \
NULL, NULL NULL, NULL
/* /*
* Useful macros * Useful macros
@ -450,5 +450,3 @@ typedef struct {
#include "files.h" #include "files.h"
#endif #endif

949
menu.c

File diff suppressed because it is too large Load Diff

249
options.c
View File

@ -35,33 +35,33 @@
*/ */
void add_ftype_mapping(state *st, char *suffix) void add_ftype_mapping(state *st, char *suffix)
{ {
char *type; char *type;
int i; int i;
/* Let's not do anything stupid */ /* Let's not do anything stupid */
if (!*suffix) return; if (!*suffix) return;
if (!(type = strchr(suffix, '='))) return; if (!(type = strchr(suffix, '='))) return;
/* Extract type from the suffix=X string */ /* Extract type from the suffix=X string */
*type++ = '\0'; *type++ = '\0';
if (!*type) return; if (!*type) return;
/* Loop through the filetype array */ /* Loop through the filetype array */
for (i = 0; i < st->filetype_count; i++) { for (i = 0; i < st->filetype_count; i++) {
/* Old entry found? */ /* Old entry found? */
if (strcasecmp(st->filetype[i].suffix, suffix) == MATCH) { if (strcasecmp(st->filetype[i].suffix, suffix) == MATCH) {
st->filetype[i].type = *type; st->filetype[i].type = *type;
return; return;
} }
} }
/* No old entry found - add new entry */ /* No old entry found - add new entry */
if (i < MAX_FILETYPES) { if (i < MAX_FILETYPES) {
sstrlcpy(st->filetype[i].suffix, suffix); sstrlcpy(st->filetype[i].suffix, suffix);
st->filetype[i].type = *type; st->filetype[i].type = *type;
st->filetype_count++; st->filetype_count++;
} }
} }
@ -70,21 +70,21 @@ void add_ftype_mapping(state *st, char *suffix)
*/ */
void add_rewrite_mapping(state *st, char *match) void add_rewrite_mapping(state *st, char *match)
{ {
char *replace; char *replace;
/* Check input and split it into match & replace */ /* Check input and split it into match & replace */
if (!*match) return; if (!*match) return;
if (!(replace = strchr(match, '='))) return; if (!(replace = strchr(match, '='))) return;
*replace++ = '\0'; *replace++ = '\0';
if (!*replace) return; if (!*replace) return;
/* Insert match/replace values into the array */ /* Insert match/replace values into the array */
if (st->rewrite_count < MAX_REWRITE) { if (st->rewrite_count < MAX_REWRITE) {
sstrlcpy(st->rewrite[st->rewrite_count].match, match); sstrlcpy(st->rewrite[st->rewrite_count].match, match);
sstrlcpy(st->rewrite[st->rewrite_count].replace, replace); sstrlcpy(st->rewrite[st->rewrite_count].replace, replace);
st->rewrite_count++; st->rewrite_count++;
} }
} }
@ -93,112 +93,111 @@ void add_rewrite_mapping(state *st, char *match)
*/ */
void parse_args(state *st, int argc, char *argv[]) void parse_args(state *st, int argc, char *argv[])
{ {
FILE *fp; FILE *fp;
static const char readme[] = README; static const char readme[] = README;
static const char license[] = LICENSE; static const char license[] = LICENSE;
struct stat file; struct stat file;
char buf[BUFSIZE]; char buf[BUFSIZE];
int opt; int opt;
/* Parse args */ /* Parse args */
while ((opt = getopt(argc, argv, "h:p:T:r:t:g:a:c:u:m:l:w:o:s:i:k:f:e:R:D:L:A:P:n:dbv?-")) != ERROR) { while ((opt = getopt(argc, argv, "h:p:T:r:t:g:a:c:u:m:l:w:o:s:i:k:f:e:R:D:L:A:P:n:dbv?-")) != ERROR) {
switch(opt) { switch(opt) {
case 'h': sstrlcpy(st->server_host, optarg); break; case 'h': sstrlcpy(st->server_host, optarg); break;
case 'p': st->server_port = atoi(optarg); break; case 'p': st->server_port = atoi(optarg); break;
case 'T': st->server_tls_port = atoi(optarg); break; case 'T': st->server_tls_port = atoi(optarg); break;
case 'r': sstrlcpy(st->server_root, optarg); break; case 'r': sstrlcpy(st->server_root, optarg); break;
case 't': st->default_filetype = *optarg; break; case 't': st->default_filetype = *optarg; break;
case 'g': sstrlcpy(st->map_file, optarg); break; case 'g': sstrlcpy(st->map_file, optarg); break;
case 'a': sstrlcpy(st->map_file, optarg); break; case 'a': sstrlcpy(st->map_file, optarg); break;
case 'c': sstrlcpy(st->cgi_file, optarg); break; case 'c': sstrlcpy(st->cgi_file, optarg); break;
case 'u': sstrlcpy(st->user_dir, optarg); break; case 'u': sstrlcpy(st->user_dir, optarg); break;
case 'm': /* obsolete, replaced by -l */ case 'm': /* obsolete, replaced by -l */
case 'l': sstrlcpy(st->log_file, optarg); break; case 'l': sstrlcpy(st->log_file, optarg); break;
case 'w': st->out_width = atoi(optarg); break; case 'w': st->out_width = atoi(optarg); break;
case 'o': case 'o':
if (sstrncasecmp(optarg, "UTF-8") == MATCH) st->out_charset = UTF_8; if (sstrncasecmp(optarg, "UTF-8") == MATCH) st->out_charset = UTF_8;
if (sstrncasecmp(optarg, "ISO-8859-1") == MATCH) st->out_charset = ISO_8859_1; if (sstrncasecmp(optarg, "ISO-8859-1") == MATCH) st->out_charset = ISO_8859_1;
break; break;
case 's': st->session_timeout = atoi(optarg); break; case 's': st->session_timeout = atoi(optarg); break;
case 'i': st->session_max_kbytes = abs(atoi(optarg)); break; case 'i': st->session_max_kbytes = abs(atoi(optarg)); break;
case 'k': st->session_max_hits = abs(atoi(optarg)); break; case 'k': st->session_max_hits = abs(atoi(optarg)); break;
case 'f': sstrlcpy(st->filter_dir, optarg); break; case 'f': sstrlcpy(st->filter_dir, optarg); break;
case 'e': add_ftype_mapping(st, optarg); break; case 'e': add_ftype_mapping(st, optarg); break;
case 'R': add_rewrite_mapping(st, optarg); break; case 'R': add_rewrite_mapping(st, optarg); break;
case 'D': sstrlcpy(st->server_description, optarg); break; case 'D': sstrlcpy(st->server_description, optarg); break;
case 'L': sstrlcpy(st->server_location, optarg); break; case 'L': sstrlcpy(st->server_location, optarg); break;
case 'A': sstrlcpy(st->server_admin, optarg); break; case 'A': sstrlcpy(st->server_admin, optarg); break;
case 'n': case 'n':
if (*optarg == 'v') { st->opt_vhost = FALSE; break; } if (*optarg == 'v') { st->opt_vhost = FALSE; break; }
if (*optarg == 'l') { st->opt_parent = FALSE; break; } if (*optarg == 'l') { st->opt_parent = FALSE; break; }
if (*optarg == 'h') { st->opt_header = FALSE; break; } if (*optarg == 'h') { st->opt_header = FALSE; break; }
if (*optarg == 'f') { st->opt_footer = FALSE; break; } if (*optarg == 'f') { st->opt_footer = FALSE; break; }
if (*optarg == 'd') { st->opt_date = FALSE; break; } if (*optarg == 'd') { st->opt_date = FALSE; break; }
if (*optarg == 'c') { st->opt_magic = FALSE; break; } if (*optarg == 'c') { st->opt_magic = FALSE; break; }
if (*optarg == 'o') { st->opt_iconv = FALSE; break; } if (*optarg == 'o') { st->opt_iconv = FALSE; break; }
if (*optarg == 'q') { st->opt_query = FALSE; break; } if (*optarg == 'q') { st->opt_query = FALSE; break; }
if (*optarg == 's') { st->opt_syslog = FALSE; break; } if (*optarg == 's') { st->opt_syslog = FALSE; break; }
if (*optarg == 'a') { st->opt_caps = FALSE; break; } if (*optarg == 'a') { st->opt_caps = FALSE; break; }
if (*optarg == 't') { st->opt_status = FALSE; break; } if (*optarg == 't') { st->opt_status = FALSE; break; }
if (*optarg == 'm') { st->opt_shm = FALSE; break; } if (*optarg == 'm') { st->opt_shm = FALSE; break; }
if (*optarg == 'r') { st->opt_root = FALSE; break; } if (*optarg == 'r') { st->opt_root = FALSE; break; }
if (*optarg == 'p') { st->opt_proxy = FALSE; break; } if (*optarg == 'p') { st->opt_proxy = FALSE; break; }
if (*optarg == 'x') { st->opt_exec = FALSE; break; } if (*optarg == 'x') { st->opt_exec = FALSE; break; }
if (*optarg == 'u') { st->opt_personal_spaces = FALSE; break; } if (*optarg == 'u') { st->opt_personal_spaces = FALSE; break; }
break; break;
case 'd': st->debug = TRUE; break; case 'd': st->debug = TRUE; break;
case 'b': puts(license); exit(EXIT_SUCCESS); case 'b': puts(license); exit(EXIT_SUCCESS);
case 'v': case 'v':
printf("%s/%s \"%s\" (built %s)\n", SERVER_SOFTWARE, VERSION, CODENAME, __DATE__); printf("%s/%s \"%s\" (built %s)\n", SERVER_SOFTWARE, VERSION, CODENAME, __DATE__);
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
default : puts(readme); exit(EXIT_SUCCESS); default : puts(readme); exit(EXIT_SUCCESS);
} }
} }
/* Sanitize options */ /* Sanitize options */
if (st->out_width > MAX_WIDTH) st->out_width = MAX_WIDTH; if (st->out_width > MAX_WIDTH) st->out_width = MAX_WIDTH;
if (st->out_width < MIN_WIDTH) st->out_width = MIN_WIDTH; if (st->out_width < MIN_WIDTH) st->out_width = MIN_WIDTH;
if (st->out_width < MIN_WIDTH + DATE_WIDTH) st->opt_date = FALSE; if (st->out_width < MIN_WIDTH + DATE_WIDTH) st->opt_date = FALSE;
if (!st->opt_syslog) st->debug = FALSE; if (!st->opt_syslog) st->debug = FALSE;
/* Primary vhost directory must exist or we disable vhosting */ /* Primary vhost directory must exist or we disable vhosting */
if (st->opt_vhost) { if (st->opt_vhost) {
snprintf(buf, sizeof(buf), "%s/%s", st->server_root, st->server_host); snprintf(buf, sizeof(buf), "%s/%s", st->server_root, st->server_host);
if (stat(buf, &file) == ERROR) st->opt_vhost = FALSE; if (stat(buf, &file) == ERROR) st->opt_vhost = FALSE;
} }
/* If -D arg looks like a file load the file contents */ /* If -D arg looks like a file load the file contents */
if (*st->server_description == '/') { if (*st->server_description == '/') {
if ((fp = fopen(st->server_description , "r"))) { if ((fp = fopen(st->server_description , "r"))) {
if (fgets(st->server_description, sizeof(st->server_description), fp) == NULL) if (fgets(st->server_description, sizeof(st->server_description), fp) == NULL)
strclear(st->server_description); strclear(st->server_description);
chomp(st->server_description); chomp(st->server_description);
fclose(fp); fclose(fp);
} }
else strclear(st->server_description); else strclear(st->server_description);
} }
/* If -L arg looks like a file load the file contents */ /* If -L arg looks like a file load the file contents */
if (*st->server_location == '/') { if (*st->server_location == '/') {
if ((fp = fopen(st->server_location , "r"))) { if ((fp = fopen(st->server_location , "r"))) {
if (fgets(st->server_location, sizeof(st->server_location), fp) == NULL) if (fgets(st->server_location, sizeof(st->server_location), fp) == NULL)
strclear(st->server_description); strclear(st->server_description);
chomp(st->server_location); chomp(st->server_location);
fclose(fp); fclose(fp);
} }
else strclear(st->server_location); else strclear(st->server_location);
} }
} }

View File

@ -37,258 +37,258 @@ void platform(state *st)
{ {
#ifdef HAVE_UNAME #ifdef HAVE_UNAME
#if defined(_AIX) || defined(__linux) || defined(__APPLE__) #if defined(_AIX) || defined(__linux) || defined(__APPLE__)
FILE *fp; FILE *fp;
#endif #endif
#if defined(__linux) || defined(__APPLE__) #if defined(__linux) || defined(__APPLE__)
char buf[BUFSIZE]; char buf[BUFSIZE];
#endif #endif
#ifdef __linux #ifdef __linux
struct stat file; struct stat file;
#endif #endif
struct utsname name; struct utsname name;
char sysname[64]; char sysname[64];
char release[64]; char release[64];
char machine[64]; char machine[64];
char *c; char *c;
/* Fetch system information */ /* Fetch system information */
uname(&name); uname(&name);
strclear(sysname); strclear(sysname);
strclear(release); strclear(release);
strclear(machine); strclear(machine);
/* AIX-specific */ /* AIX-specific */
#ifdef _AIX #ifdef _AIX
/* Fix uname() results */ /* Fix uname() results */
sstrlcpy(machine, "powerpc"); sstrlcpy(machine, "powerpc");
snprintf(release, sizeof(release), "%s.%s", snprintf(release, sizeof(release), "%s.%s",
name.version, name.version,
name.release); name.release);
/* Get CPU type */ /* Get CPU type */
if ((fp = popen("/usr/sbin/getsystype -i", "r"))) { if ((fp = popen("/usr/sbin/getsystype -i", "r"))) {
if (fgets(machine, sizeof(machine), fp) != NULL) if (fgets(machine, sizeof(machine), fp) != NULL)
strreplace(machine, ' ', '_'); strreplace(machine, ' ', '_');
pclose(fp); pclose(fp);
} }
/* Get hardware name using shell uname */ /* Get hardware name using shell uname */
if (!*st->server_description && if (!*st->server_description &&
(fp = popen("/usr/bin/uname -M", "r"))) { (fp = popen("/usr/bin/uname -M", "r"))) {
if (fgets(st->server_description, sizeof(st->server_description), fp) != NULL) { if (fgets(st->server_description, sizeof(st->server_description), fp) != NULL) {
strreplace(st->server_description, ',', ' '); strreplace(st->server_description, ',', ' ');
chomp(st->server_description); chomp(st->server_description);
} }
pclose(fp); pclose(fp);
} }
#endif #endif
/* Mac OS X, just like Unix but totally different... */ /* Mac OS X, just like Unix but totally different... */
#ifdef __APPLE__ #ifdef __APPLE__
/* Hardcode OS name */ /* Hardcode OS name */
sstrlcpy(sysname, "MacOSX"); sstrlcpy(sysname, "MacOSX");
/* Get OS X version */ /* Get OS X version */
if ((fp = popen("/usr/bin/sw_vers -productVersion", "r"))) { if ((fp = popen("/usr/bin/sw_vers -productVersion", "r"))) {
if (fgets(release, sizeof(release), fp) == NULL) strclear(release); if (fgets(release, sizeof(release), fp) == NULL) strclear(release);
pclose(fp); pclose(fp);
} }
/* Get hardware name */ /* Get hardware name */
if (!*st->server_description && if (!*st->server_description &&
(fp = popen("/usr/sbin/sysctl -n hw.model", "r"))) { (fp = popen("/usr/sbin/sysctl -n hw.model", "r"))) {
/* Read hardware name */ /* Read hardware name */
if (fgets(buf, sizeof(buf), fp) != NULL) { if (fgets(buf, sizeof(buf), fp) != NULL) {
/* Clones are gone now so we'll hardcode the manufacturer */ /* Clones are gone now so we'll hardcode the manufacturer */
sstrlcpy(st->server_description, "Apple "); sstrlcpy(st->server_description, "Apple ");
sstrlcat(st->server_description, buf); sstrlcat(st->server_description, buf);
/* Remove hardware revision */ /* Remove hardware revision */
for (c = st->server_description; *c; c++) for (c = st->server_description; *c; c++)
if (*c >= '0' && *c <= '9') { *c = '\0'; break; } if (*c >= '0' && *c <= '9') { *c = '\0'; break; }
} }
pclose(fp); pclose(fp);
} }
#endif #endif
/* Linux uname() just says Linux/kernelversion - let's dig deeper... */ /* Linux uname() just says Linux/kernelversion - let's dig deeper... */
#ifdef __linux #ifdef __linux
/* Most Linux ARM/MIPS boards have hardware name in /proc/cpuinfo */ /* Most Linux ARM/MIPS boards have hardware name in /proc/cpuinfo */
#if defined(__arm__) || defined(__mips__) #if defined(__arm__) || defined(__mips__)
if (!*st->server_description && (fp = fopen("/proc/cpuinfo" , "r"))) { if (!*st->server_description && (fp = fopen("/proc/cpuinfo" , "r"))) {
while (fgets(buf, sizeof(buf), fp)) { while (fgets(buf, sizeof(buf), fp)) {
#ifdef __arm__ #ifdef __arm__
if ((c = strkey(buf, "Hardware"))) { if ((c = strkey(buf, "Hardware"))) {
#else #else
if ((c = strkey(buf, "machine"))) { if ((c = strkey(buf, "machine"))) {
#endif #endif
sstrlcpy(st->server_description, c); sstrlcpy(st->server_description, c);
chomp(st->server_description); chomp(st->server_description);
break; break;
} }
} }
fclose(fp); fclose(fp);
} }
#endif #endif
/* Get hardware type from DMI data */ /* Get hardware type from DMI data */
if (!*st->server_description && (fp = fopen("/sys/class/dmi/id/board_vendor" , "r"))) { if (!*st->server_description && (fp = fopen("/sys/class/dmi/id/board_vendor" , "r"))) {
if (fgets(buf, sizeof(buf), fp) != NULL) { if (fgets(buf, sizeof(buf), fp) != NULL) {
sstrlcpy(st->server_description, buf); sstrlcpy(st->server_description, buf);
chomp(st->server_description); chomp(st->server_description);
} }
fclose(fp); fclose(fp);
if ((fp = fopen("/sys/class/dmi/id/board_name" , "r"))) { if ((fp = fopen("/sys/class/dmi/id/board_name" , "r"))) {
if (fgets(buf, sizeof(buf), fp) != NULL) { if (fgets(buf, sizeof(buf), fp) != NULL) {
if (*st->server_description) sstrlcat(st->server_description, " "); if (*st->server_description) sstrlcat(st->server_description, " ");
sstrlcat(st->server_description, buf); sstrlcat(st->server_description, buf);
chomp(st->server_description); chomp(st->server_description);
} }
fclose(fp); fclose(fp);
} }
} }
/* No DMI? Get possible hypervisor name */ /* No DMI? Get possible hypervisor name */
if (!*st->server_description && (fp = fopen("/sys/hypervisor/type" , "r"))) { if (!*st->server_description && (fp = fopen("/sys/hypervisor/type" , "r"))) {
if (fgets(buf, sizeof(buf), fp) != NULL) { if (fgets(buf, sizeof(buf), fp) != NULL) {
chomp(buf); chomp(buf);
if (*buf) snprintf(st->server_description, sizeof(st->server_description), "%s virtual machine", buf); if (*buf) snprintf(st->server_description, sizeof(st->server_description), "%s virtual machine", buf);
} }
fclose(fp); fclose(fp);
} }
/* Identify Gentoo */ /* Identify Gentoo */
if (!*sysname && (fp = fopen("/etc/gentoo-release", "r"))) { if (!*sysname && (fp = fopen("/etc/gentoo-release", "r"))) {
if (fgets(sysname, sizeof(sysname), fp) != NULL) { if (fgets(sysname, sizeof(sysname), fp) != NULL) {
if ((c = strstr(sysname, "release "))) sstrlcpy(release, c + 8); if ((c = strstr(sysname, "release "))) sstrlcpy(release, c + 8);
if ((c = strchr(release, ' '))) *c = '\0'; if ((c = strchr(release, ' '))) *c = '\0';
if ((c = strchr(sysname, ' '))) *c = '\0'; if ((c = strchr(sysname, ' '))) *c = '\0';
} }
fclose(fp); fclose(fp);
} }
/* Identify RedHat */ /* Identify RedHat */
if (!*sysname && (fp = fopen("/etc/redhat-release", "r"))) { if (!*sysname && (fp = fopen("/etc/redhat-release", "r"))) {
if (fgets(sysname, sizeof(sysname), fp) != NULL) { if (fgets(sysname, sizeof(sysname), fp) != NULL) {
if ((c = strstr(sysname, "release "))) sstrlcpy(release, c + 8); if ((c = strstr(sysname, "release "))) sstrlcpy(release, c + 8);
if ((c = strchr(release, ' '))) *c = '\0'; if ((c = strchr(release, ' '))) *c = '\0';
if ((c = strchr(sysname, ' '))) *c = '\0'; if ((c = strchr(sysname, ' '))) *c = '\0';
if (strcmp(sysname, "Red") == MATCH) sstrlcpy(sysname, "RedHat"); if (strcmp(sysname, "Red") == MATCH) sstrlcpy(sysname, "RedHat");
} }
fclose(fp); fclose(fp);
} }
/* Identify Slackware */ /* Identify Slackware */
if (!*sysname && (fp = fopen("/etc/slackware-version", "r"))) { if (!*sysname && (fp = fopen("/etc/slackware-version", "r"))) {
if (fgets(sysname, sizeof(sysname), fp) != NULL) { if (fgets(sysname, sizeof(sysname), fp) != NULL) {
if ((c = strchr(sysname, ' '))) { if ((c = strchr(sysname, ' '))) {
sstrlcpy(release, c + 1); sstrlcpy(release, c + 1);
*c = '\0'; *c = '\0';
} }
if ((c = strchr(sysname, '-'))) *c = '\0'; if ((c = strchr(sysname, '-'))) *c = '\0';
} }
fclose(fp); fclose(fp);
} }
/* Identify CRUX */ /* Identify CRUX */
if (!*sysname && stat("/usr/bin/crux", &file) == OK && (file.st_mode & S_IXOTH)) { if (!*sysname && stat("/usr/bin/crux", &file) == OK && (file.st_mode & S_IXOTH)) {
sstrlcpy(sysname, "CRUX"); sstrlcpy(sysname, "CRUX");
if ((fp = popen("/usr/bin/crux", "r"))) { if ((fp = popen("/usr/bin/crux", "r"))) {
if (fgets(buf, sizeof(buf), fp) != NULL && if (fgets(buf, sizeof(buf), fp) != NULL &&
(c = strchr(buf, ' ')) && (c = strchr(buf, ' ')) &&
(c = strchr(c + 1, ' '))) sstrlcpy(release, c + 1); (c = strchr(c + 1, ' '))) sstrlcpy(release, c + 1);
pclose(fp); pclose(fp);
} }
} }
/* Uh-oh.... how about a standard Linux with lsb_release? */ /* Uh-oh.... how about a standard Linux with lsb_release? */
if (stat("/usr/bin/lsb_release", &file) == OK && (file.st_mode & S_IXOTH)) { if (stat("/usr/bin/lsb_release", &file) == OK && (file.st_mode & S_IXOTH)) {
if (!*sysname && (fp = popen("/usr/bin/lsb_release -i -s", "r"))) { if (!*sysname && (fp = popen("/usr/bin/lsb_release -i -s", "r"))) {
if (fgets(sysname, sizeof(sysname), fp) == NULL) strclear(sysname); if (fgets(sysname, sizeof(sysname), fp) == NULL) strclear(sysname);
pclose(fp); pclose(fp);
} }
if (!*release && (fp = popen("/usr/bin/lsb_release -r -s", "r"))) { if (!*release && (fp = popen("/usr/bin/lsb_release -r -s", "r"))) {
if (fgets(release, sizeof(release), fp) == NULL) strclear(release); if (fgets(release, sizeof(release), fp) == NULL) strclear(release);
pclose(fp); pclose(fp);
} }
} }
/* OK, nothing worked - let's try /etc/issue for sysname */ /* OK, nothing worked - let's try /etc/issue for sysname */
if (!*sysname && (fp = fopen("/etc/issue", "r"))) { if (!*sysname && (fp = fopen("/etc/issue", "r"))) {
if (fgets(sysname, sizeof(sysname), fp) != NULL) { if (fgets(sysname, sizeof(sysname), fp) != NULL) {
if ((c = strchr(sysname, ' '))) *c = '\0'; if ((c = strchr(sysname, ' '))) *c = '\0';
if ((c = strchr(sysname, '\\'))) *c = '\0'; if ((c = strchr(sysname, '\\'))) *c = '\0';
} }
fclose(fp); fclose(fp);
} }
/* Debian version should be in /etc/debian_version */ /* Debian version should be in /etc/debian_version */
if (!*release && (fp = fopen("/etc/debian_version", "r"))) { if (!*release && (fp = fopen("/etc/debian_version", "r"))) {
if (fgets (release, sizeof(release), fp) != NULL) if (fgets (release, sizeof(release), fp) != NULL)
if ((c = strchr(release, '/'))) *c = '\0'; if ((c = strchr(release, '/'))) *c = '\0';
fclose(fp); fclose(fp);
} }
#endif #endif
/* Haiku OS */ /* Haiku OS */
#ifdef __HAIKU__ #ifdef __HAIKU__
/* Fix release name */ /* Fix release name */
snprintf(release, sizeof(release), "R%s", name.release); snprintf(release, sizeof(release), "R%s", name.release);
#endif #endif
/* Fill in the blanks using uname() data */ /* Fill in the blanks using uname() data */
if (!*sysname) sstrlcpy(sysname, name.sysname); if (!*sysname) sstrlcpy(sysname, name.sysname);
if (!*release) sstrlcpy(release, name.release); if (!*release) sstrlcpy(release, name.release);
if (!*machine) sstrlcpy(machine, name.machine); if (!*machine) sstrlcpy(machine, name.machine);
/* I always liked weird Perl-only functions */ /* I always liked weird Perl-only functions */
chomp(sysname); chomp(sysname);
chomp(release); chomp(release);
chomp(machine); chomp(machine);
/* We're only interested in major.minor version */ /* We're only interested in major.minor version */
if ((c = strchr(release, '.'))) if ((c = strchr(c + 1, '.'))) *c = '\0'; if ((c = strchr(release, '.'))) if ((c = strchr(c + 1, '.'))) *c = '\0';
if ((c = strchr(release, '-'))) *c = '\0'; if ((c = strchr(release, '-'))) *c = '\0';
if ((c = strchr(release, '/'))) *c = '\0'; if ((c = strchr(release, '/'))) *c = '\0';
/* Create a nicely formatted platform string */ /* Create a nicely formatted platform string */
snprintf(st->server_platform, sizeof(st->server_platform), "%s/%s %s", snprintf(st->server_platform, sizeof(st->server_platform), "%s/%s %s",
sysname, sysname,
#if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__) #if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__)
machine, machine,
release); release);
#else #else
release, release,
machine); machine);
#endif #endif
/* Debug */ /* Debug */
if (st->debug) { if (st->debug) {
syslog(LOG_INFO, "generated platform string \"%s\"", syslog(LOG_INFO, "generated platform string \"%s\"",
st->server_platform); st->server_platform);
} }
#else #else
/* Fallback reply */ /* Fallback reply */
sstrlcpy(st->server_platform, "Unknown computer-like system"); sstrlcpy(st->server_platform, "Unknown computer-like system");
#endif #endif
} }
@ -298,34 +298,32 @@ void platform(state *st)
*/ */
float loadavg(void) float loadavg(void)
{ {
FILE *fp; FILE *fp;
char buf[BUFSIZE]; char buf[BUFSIZE];
/* Faster Linux version */ /* Faster Linux version */
#ifdef __linux #ifdef __linux
if ((fp = fopen("/proc/loadavg" , "r")) == NULL) return 0; if ((fp = fopen("/proc/loadavg" , "r")) == NULL) return 0;
if (fgets(buf, sizeof(buf), fp) == NULL) strclear(buf); if (fgets(buf, sizeof(buf), fp) == NULL) strclear(buf);
fclose(fp); fclose(fp);
return (float) atof(buf); return (float) atof(buf);
/* Generic slow version - parse the output of uptime */ /* Generic slow version - parse the output of uptime */
#else #else
#ifdef HAVE_POPEN #ifdef HAVE_POPEN
char *c; char *c;
if ((fp = popen("/usr/bin/uptime", "r"))) { if ((fp = popen("/usr/bin/uptime", "r"))) {
if (fgets(buf, sizeof(buf), fp) == NULL) strclear(buf); if (fgets(buf, sizeof(buf), fp) == NULL) strclear(buf);
pclose(fp); pclose(fp);
if ((c = strstr(buf, "average: ")) || (c = strstr(buf, "averages: "))) if ((c = strstr(buf, "average: ")) || (c = strstr(buf, "averages: ")))
return (float) atof(c + 9); return (float) atof(c + 9);
} }
#endif #endif
/* Fallback reply */ /* Fallback reply */
return 0; return 0;
#endif #endif
} }

145
session.c
View File

@ -36,21 +36,21 @@
#ifdef HAVE_SHMEM #ifdef HAVE_SHMEM
int get_shm_session_id(state *st, shm_state *shm) int get_shm_session_id(state *st, shm_state *shm)
{ {
time_t now; time_t now;
int i; int i;
/* Get current time */ /* Get current time */
now = time(NULL); now = time(NULL);
/* Locate user's old session using remote_addr */ /* Locate user's old session using remote_addr */
for (i = 0; i < SHM_SESSIONS; i++) { for (i = 0; i < SHM_SESSIONS; i++) {
if (strcmp(st->req_remote_addr, shm->session[i].req_remote_addr) == MATCH && if (strcmp(st->req_remote_addr, shm->session[i].req_remote_addr) == MATCH &&
(now - shm->session[i].req_atime) < st->session_timeout) break; (now - shm->session[i].req_atime) < st->session_timeout) break;
} }
/* Return -1 on error */ /* Return -1 on error */
if (i == SHM_SESSIONS) return ERROR; if (i == SHM_SESSIONS) return ERROR;
else return i; else return i;
} }
#endif #endif
@ -61,15 +61,15 @@ int get_shm_session_id(state *st, shm_state *shm)
#ifdef HAVE_SHMEM #ifdef HAVE_SHMEM
void get_shm_session(state *st, shm_state *shm) void get_shm_session(state *st, shm_state *shm)
{ {
int i; int i;
/* Get session id */ /* Get session id */
if ((i = get_shm_session_id(st, shm)) == ERROR) return; if ((i = get_shm_session_id(st, shm)) == ERROR) return;
/* Get session data */ /* Get session data */
if (st->opt_vhost) { if (st->opt_vhost) {
sstrlcpy(st->server_host, shm->session[i].server_host); sstrlcpy(st->server_host, shm->session[i].server_host);
} }
} }
#endif #endif
@ -80,73 +80,72 @@ void get_shm_session(state *st, shm_state *shm)
#ifdef HAVE_SHMEM #ifdef HAVE_SHMEM
void update_shm_session(state *st, shm_state *shm) void update_shm_session(state *st, shm_state *shm)
{ {
time_t now; time_t now;
char buf[BUFSIZE]; char buf[BUFSIZE];
int delay; int delay;
int i; int i;
/* Get current time */ /* Get current time */
now = time(NULL); now = time(NULL);
/* No existing session found? */ /* No existing session found? */
if ((i = get_shm_session_id(st, shm)) == ERROR) { if ((i = get_shm_session_id(st, shm)) == ERROR) {
/* Look for an empty/expired session slot */ /* Look for an empty/expired session slot */
for (i = 0; i < SHM_SESSIONS; i++) { for (i = 0; i < SHM_SESSIONS; i++) {
if ((now - shm->session[i].req_atime) > st->session_timeout) { if ((now - shm->session[i].req_atime) > st->session_timeout) {
/* Found slot -> initialize it */ /* Found slot -> initialize it */
sstrlcpy(shm->session[i].req_remote_addr, st->req_remote_addr); sstrlcpy(shm->session[i].req_remote_addr, st->req_remote_addr);
shm->session[i].hits = 0; shm->session[i].hits = 0;
shm->session[i].kbytes = 0; shm->session[i].kbytes = 0;
shm->session[i].session_id = rand(); shm->session[i].session_id = rand();
break; break;
} }
} }
} }
/* No available session slot found? */ /* No available session slot found? */
if (i == SHM_SESSIONS) return; if (i == SHM_SESSIONS) return;
/* Get referrer from old session data */ /* Get referrer from old session data */
if (*shm->session[i].server_host) { if (*shm->session[i].server_host) {
snprintf(buf, sizeof(buf), "gopher%s://%s:%i/%c%s", snprintf(buf, sizeof(buf), "gopher%s://%s:%i/%c%s",
(shm->session[i].server_port == st->server_tls_port ? "s" : ""), (shm->session[i].server_port == st->server_tls_port ? "s" : ""),
shm->session[i].server_host, shm->session[i].server_host,
shm->session[i].server_port, shm->session[i].server_port,
shm->session[i].req_filetype, shm->session[i].req_filetype,
shm->session[i].req_selector); shm->session[i].req_selector);
sstrlcpy(st->req_referrer, buf); sstrlcpy(st->req_referrer, buf);
} }
/* Get public session id */ /* Get public session id */
st->session_id = shm->session[i].session_id; st->session_id = shm->session[i].session_id;
/* Update session data */ /* Update session data */
sstrlcpy(shm->session[i].server_host, st->server_host); sstrlcpy(shm->session[i].server_host, st->server_host);
shm->session[i].server_port = st->server_port; shm->session[i].server_port = st->server_port;
sstrlcpy(shm->session[i].req_selector, st->req_selector); sstrlcpy(shm->session[i].req_selector, st->req_selector);
shm->session[i].req_filetype = st->req_filetype; shm->session[i].req_filetype = st->req_filetype;
shm->session[i].req_atime = now; shm->session[i].req_atime = now;
shm->session[i].hits++; shm->session[i].hits++;
shm->session[i].kbytes += st->req_filesize / 1024; shm->session[i].kbytes += st->req_filesize / 1024;
/* Transfer limits exceeded? */ /* Transfer limits exceeded? */
if ((st->session_max_kbytes && shm->session[i].kbytes > st->session_max_kbytes) || if ((st->session_max_kbytes && shm->session[i].kbytes > st->session_max_kbytes) ||
(st->session_max_hits && shm->session[i].hits > st->session_max_hits)) { (st->session_max_hits && shm->session[i].hits > st->session_max_hits)) {
/* Calculate throttle delay */ /* Calculate throttle delay */
delay = max(shm->session[i].kbytes / st->session_max_kbytes, delay = max(shm->session[i].kbytes / st->session_max_kbytes,
shm->session[i].hits / st->session_max_hits); shm->session[i].hits / st->session_max_hits);
/* Throttle user */ /* Throttle user */
syslog(LOG_INFO, "throttling user from %s for %i seconds", syslog(LOG_INFO, "throttling user from %s for %i seconds",
st->req_remote_addr, delay); st->req_remote_addr, delay);
sleep(delay); sleep(delay);
} }
} }
#endif #endif

410
string.c
View File

@ -35,8 +35,8 @@
*/ */
void strrepeat(char *dest, char c, size_t num) void strrepeat(char *dest, char c, size_t num)
{ {
memset(dest, c, num); memset(dest, c, num);
dest[num] = '\0'; dest[num] = '\0';
} }
@ -45,10 +45,10 @@ void strrepeat(char *dest, char c, size_t num)
*/ */
void strreplace(char *str, char from, char to) void strreplace(char *str, char from, char to)
{ {
while (*str) { while (*str) {
if (*str == from) *str = to; if (*str == from) *str = to;
str++; str++;
} }
} }
@ -57,26 +57,26 @@ void strreplace(char *str, char from, char to)
*/ */
size_t strcut(char *str, size_t width) size_t strcut(char *str, size_t width)
{ {
unsigned char c = '\0'; unsigned char c = '\0';
int w = 0; int w = 0;
int i; int i;
while (width-- && (c = *str++)) { while (width-- && (c = *str++)) {
if (c >= 0x80 && (*str & 0xc0) == 0x80) { if (c >= 0x80 && (*str & 0xc0) == 0x80) {
i = 0; i = 0;
if ((c & 0xf8) == 0xf0) i = 3; if ((c & 0xf8) == 0xf0) i = 3;
else if ((c & 0xf0) == 0xe0) i = 2; else if ((c & 0xf0) == 0xe0) i = 2;
else if ((c & 0xe0) == 0xc0) i = 1; else if ((c & 0xe0) == 0xc0) i = 1;
while (i--) if (!*str++) break; while (i--) if (!*str++) break;
} }
w++; w++;
} }
if (c) *str = '\0'; if (c) *str = '\0';
return w; return w;
} }
@ -85,22 +85,22 @@ size_t strcut(char *str, size_t width)
*/ */
char *strkey(char *header, char *key) char *strkey(char *header, char *key)
{ {
char *c; char *c;
size_t len; size_t len;
if ((len = strlen(key)) == 0) return NULL; if ((len = strlen(key)) == 0) return NULL;
if (strncasecmp(header, key, len) == MATCH) { if (strncasecmp(header, key, len) == MATCH) {
c = header + len; c = header + len;
do { c++; } while (*c == ' ' || *c == '\t'); do { c++; } while (*c == ' ' || *c == '\t');
if (*c != ':') return NULL; if (*c != ':') return NULL;
do { c++; } while (*c == ' ' || *c == '\t'); do { c++; } while (*c == ' ' || *c == '\t');
return c; return c;
} }
return NULL; return NULL;
} }
@ -109,10 +109,10 @@ char *strkey(char *header, char *key)
*/ */
char strlast(char *str) char strlast(char *str)
{ {
int len; int len;
if ((len = (int)strlen(str) - 1) >= 0) return str[len]; if ((len = (int)strlen(str) - 1) >= 0) return str[len];
else return 0; else return 0;
} }
@ -121,10 +121,10 @@ char strlast(char *str)
*/ */
void chomp(char *str) void chomp(char *str)
{ {
char *c; char *c;
if ((c = strrchr(str, '\n'))) *c = '\0'; if ((c = strrchr(str, '\n'))) *c = '\0';
if ((c = strrchr(str, '\r'))) *c = '\0'; if ((c = strrchr(str, '\r'))) *c = '\0';
} }
@ -133,12 +133,12 @@ void chomp(char *str)
*/ */
char *strcharset(int charset) char *strcharset(int charset)
{ {
if (charset == AUTO) return "auto"; if (charset == AUTO) return "auto";
if (charset == US_ASCII) return "US-ASCII"; if (charset == US_ASCII) return "US-ASCII";
if (charset == ISO_8859_1) return "ISO-8859-1"; if (charset == ISO_8859_1) return "ISO-8859-1";
if (charset == UTF_8) return "UTF-8"; if (charset == UTF_8) return "UTF-8";
return "(unknown)"; return "(unknown)";
} }
@ -147,93 +147,93 @@ char *strcharset(int charset)
*/ */
void strniconv(int charset, char *out, char *in, size_t outsize) void strniconv(int charset, char *out, char *in, size_t outsize)
{ {
char ascii[] = ASCII; char ascii[] = ASCII;
unsigned long c; unsigned long c;
size_t len; size_t len;
int i; int i;
/* Loop through the input string */ /* Loop through the input string */
len = strlen(in); len = strlen(in);
while (--outsize && len > 0) { while (--outsize && len > 0) {
/* Get one input char */ /* Get one input char */
c = (unsigned char) *in++; c = (unsigned char) *in++;
len--; len--;
/* 7-bit chars are the same in all three charsets */ /* 7-bit chars are the same in all three charsets */
if (c < 0x80) { if (c < 0x80) {
*out++ = (unsigned char) c; *out++ = (unsigned char) c;
continue; continue;
} }
/* Assume ISO-8859-1 which requires 0 extra bytes */ /* Assume ISO-8859-1 which requires 0 extra bytes */
i = 0; i = 0;
/* UTF-8? (We'll actually check the next char here, not current) */ /* UTF-8? (We'll actually check the next char here, not current) */
if ((*in & 0xc0) == 0x80) { if ((*in & 0xc0) == 0x80) {
/* Four-byte UTF-8? */ /* Four-byte UTF-8? */
if ((c & 0xf8) == 0xf0 && len >= 3) { c &= 0x07; i = 3; } if ((c & 0xf8) == 0xf0 && len >= 3) { c &= 0x07; i = 3; }
/* Three-byte UTF-8? */ /* Three-byte UTF-8? */
else if ((c & 0xf0) == 0xe0 && len >= 2) { c &= 0x0f; i = 2; } else if ((c & 0xf0) == 0xe0 && len >= 2) { c &= 0x0f; i = 2; }
/* Two-byte UTF-8? */ /* Two-byte UTF-8? */
else if ((c & 0xe0) == 0xc0 && len >= 1) { c &= 0x1f; i = 1; } else if ((c & 0xe0) == 0xc0 && len >= 1) { c &= 0x1f; i = 1; }
/* Parse rest of the UTF-8 bytes */ /* Parse rest of the UTF-8 bytes */
while (i--) { while (i--) {
c <<= 6; c <<= 6;
c |= *in++ & 0x3f; c |= *in++ & 0x3f;
len--; len--;
} }
} }
/* /*
* At this point we've got one 32bit UTF character in c and * At this point we've got one 32bit UTF character in c and
* we're ready to convert it to the specified output charset * we're ready to convert it to the specified output charset
*/ */
/* Handle UTF-8 */ /* Handle UTF-8 */
if (charset == UTF_8) { if (charset == UTF_8) {
i = 0; i = 0;
/* Two-byte encoding? */ /* Two-byte encoding? */
if (c < 0x800 && outsize > 2) { *out++ = (c >> 6) | 0xc0; i = 1; } if (c < 0x800 && outsize > 2) { *out++ = (c >> 6) | 0xc0; i = 1; }
/* Three-byte encoding? */ /* Three-byte encoding? */
else if (c < 0x10000 && outsize > 3) { *out++ = (c >> 12) | 0xe0; i = 2; } else if (c < 0x10000 && outsize > 3) { *out++ = (c >> 12) | 0xe0; i = 2; }
/* Four-byte encoding? */ /* Four-byte encoding? */
else if (c < 0x110000 && outsize > 4) { *out++ = (c >> 18) | 0xf0; i = 3; } else if (c < 0x110000 && outsize > 4) { *out++ = (c >> 18) | 0xf0; i = 3; }
/* Encode rest of the UTF-8 bytes */ /* Encode rest of the UTF-8 bytes */
while (i--) { while (i--) {
*out++ = ((c >> (i * 6)) & 0x3f) | 0x80; *out++ = ((c >> (i * 6)) & 0x3f) | 0x80;
outsize--; outsize--;
} }
continue; continue;
} }
/* Handle ISO-8859-1 */ /* Handle ISO-8859-1 */
if (charset == ISO_8859_1) { if (charset == ISO_8859_1) {
if (c >= 0xa0 && c <= 0xff) if (c >= 0xa0 && c <= 0xff)
*out++ = (unsigned char) c; *out++ = (unsigned char) c;
else else
*out++ = UNKNOWN; *out++ = UNKNOWN;
continue; continue;
} }
/* Handle all other charsets as 7-bit US-ASCII */ /* Handle all other charsets as 7-bit US-ASCII */
if (c >= 0x80 && c <= 0xff) if (c >= 0x80 && c <= 0xff)
*out++ = ascii[c - 0x80]; *out++ = ascii[c - 0x80];
else else
*out++ = UNKNOWN; *out++ = UNKNOWN;
} }
/* Zero-terminate output */ /* Zero-terminate output */
*out = '\0'; *out = '\0';
} }
@ -242,31 +242,31 @@ void strniconv(int charset, char *out, char *in, size_t outsize)
*/ */
void strnencode(char *out, const char *in, size_t outsize) void strnencode(char *out, const char *in, size_t outsize)
{ {
unsigned char c; unsigned char c;
/* Loop through the input string */ /* Loop through the input string */
while (--outsize) { while (--outsize) {
/* End of source? */ /* End of source? */
if (!(c = *in++)) break; if (!(c = *in++)) break;
/* Need to encode the char? */ /* Need to encode the char? */
if (c < '+' || c > '~') { if (c < '+' || c > '~') {
/* Can we fit the encoded version into outbuffer? */ /* Can we fit the encoded version into outbuffer? */
if (outsize < 5) break; if (outsize < 5) break;
/* Output encoded char */ /* Output encoded char */
snprintf(out, outsize, "#%.3o", c); snprintf(out, outsize, "#%.3o", c);
out += 4; out += 4;
} }
/* Copy regular chars */ /* Copy regular chars */
else *out++ = c; else *out++ = c;
} }
/* Zero-terminate output */ /* Zero-terminate output */
*out = '\0'; *out = '\0';
} }
@ -275,37 +275,37 @@ void strnencode(char *out, const char *in, size_t outsize)
*/ */
void strndecode(char *out, char *in, size_t outsize) void strndecode(char *out, char *in, size_t outsize)
{ {
unsigned char c; unsigned char c;
unsigned int i; unsigned int i;
/* Loop through the input string */ /* Loop through the input string */
while (--outsize) { while (--outsize) {
/* End of source? */ /* End of source? */
if (!(c = *in++)) break; if (!(c = *in++)) break;
/* Parse %hex encoding */ /* Parse %hex encoding */
if (c == '%' && strlen(in) >= 2) { if (c == '%' && strlen(in) >= 2) {
sscanf(in, "%2x", &i); sscanf(in, "%2x", &i);
*out++ = i; *out++ = i;
in += 2; in += 2;
continue; continue;
} }
/* Parse #octal encoding */ /* Parse #octal encoding */
if (c == '#' && strlen(in) >= 3) { if (c == '#' && strlen(in) >= 3) {
sscanf(in, "%3o", &i); sscanf(in, "%3o", &i);
*out++ = i; *out++ = i;
in += 3; in += 3;
continue; continue;
} }
/* Copy non-encoded chars */ /* Copy non-encoded chars */
*out++ = c; *out++ = c;
} }
/* Zero-terminate output */ /* Zero-terminate output */
*out = '\0'; *out = '\0';
} }
@ -314,22 +314,22 @@ void strndecode(char *out, char *in, size_t outsize)
*/ */
void strfsize(char *out, off_t size, size_t outsize) void strfsize(char *out, off_t size, size_t outsize)
{ {
static char *unit[] = { UNITS }; static char *unit[] = { UNITS };
int u; int u;
float s; float s;
/* Start with kilobytes */ /* Start with kilobytes */
s = ((float) size) / 1024; s = ((float) size) / 1024;
u = 0; u = 0;
/* Loop through the units until the size is small enough */ /* Loop through the units until the size is small enough */
while (s >= 1000 && unit[(u + 1)]) { while (s >= 1000 && unit[(u + 1)]) {
s = s / 1024; s = s / 1024;
u++; u++;
} }
/* Format size */ /* Format size */
snprintf(out, outsize, "%7.1f %s", s, unit[u]); snprintf(out, outsize, "%7.1f %s", s, unit[u]);
} }
@ -360,27 +360,27 @@ void strfsize(char *out, off_t size, size_t outsize)
*/ */
size_t strlcpy(char *dst, const char *src, size_t siz) size_t strlcpy(char *dst, const char *src, size_t siz)
{ {
char *d = dst; char *d = dst;
const char *s = src; const char *s = src;
size_t n = siz; size_t n = siz;
/* Copy as many bytes as will fit */ /* Copy as many bytes as will fit */
if (n != 0) { if (n != 0) {
while (--n != 0) { while (--n != 0) {
if ((*d++ = *s++) == '\0') if ((*d++ = *s++) == '\0')
break; break;
} }
} }
/* Not enough room in dst, add NUL and traverse rest of src */ /* Not enough room in dst, add NUL and traverse rest of src */
if (n == 0) { if (n == 0) {
if (siz != 0) if (siz != 0)
*d = '\0'; /* NUL-terminate dst */ *d = '\0'; /* NUL-terminate dst */
while (*s++) while (*s++)
; ;
} }
return(s - src - 1); /* count does not include NUL */ return(s - src - 1); /* count does not include NUL */
} }
/* /*
@ -392,29 +392,29 @@ size_t strlcpy(char *dst, const char *src, size_t siz)
*/ */
size_t strlcat(char *dst, const char *src, size_t siz) size_t strlcat(char *dst, const char *src, size_t siz)
{ {
char *d = dst; char *d = dst;
const char *s = src; const char *s = src;
size_t n = siz; size_t n = siz;
size_t dlen; size_t dlen;
/* Find the end of dst and adjust bytes left but don't go past end */ /* Find the end of dst and adjust bytes left but don't go past end */
while (n-- != 0 && *d != '\0') while (n-- != 0 && *d != '\0')
d++; d++;
dlen = d - dst; dlen = d - dst;
n = siz - dlen; n = siz - dlen;
if (n == 0) if (n == 0)
return(dlen + strlen(s)); return(dlen + strlen(s));
while (*s != '\0') { while (*s != '\0') {
if (n != 1) { if (n != 1) {
*d++ = *s; *d++ = *s;
n--; n--;
} }
s++; s++;
} }
*d = '\0'; *d = '\0';
return(dlen + (s - src)); /* count does not include NUL */ return(dlen + (s - src)); /* count does not include NUL */
} }
#endif #endif