1
0
mirror of https://github.com/gophernicus/gophernicus.git synced 2024-06-09 06:20:43 +00:00

Spaces to Tabs as per consensus in #56

This commit is contained in:
fosslinux 2020-02-05 19:19:42 +11:00
parent ee757fedcc
commit 37ac8823b0
No known key found for this signature in database
GPG Key ID: 7D7996D0C25B63A3
8 changed files with 2028 additions and 2028 deletions

View File

@ -8,11 +8,11 @@
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright * * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. * notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright * * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
@ -38,57 +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;
} }

View File

@ -8,11 +8,11 @@
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright * * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. * notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright * * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
@ -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,44 +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

File diff suppressed because it is too large Load Diff

View File

@ -8,11 +8,11 @@
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright * * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. * notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright * * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
@ -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,118 +93,118 @@ 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, while ((opt = getopt(argc, argv,
#ifdef __OpenBSD__ #ifdef __OpenBSD__
"U:" /* extra unveil(2) paths are OpenBSD only */ "U:" /* extra unveil(2) paths are OpenBSD only */
#endif #endif
"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) { "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, "US-ASCII") == MATCH) st->out_charset = US_ASCII; if (sstrncasecmp(optarg, "US-ASCII") == MATCH) st->out_charset = US_ASCII;
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;
#ifdef __OpenBSD__ #ifdef __OpenBSD__
case 'U': st->extra_unveil_paths = optarg; break; case 'U': st->extra_unveil_paths = optarg; break;
#endif #endif
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

@ -8,11 +8,11 @@
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright * * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. * notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright * * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
@ -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,32 +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
} }

View File

@ -8,11 +8,11 @@
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright * * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. * notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright * * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
@ -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,72 +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

View File

@ -8,11 +8,11 @@
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright * * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. * notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright * * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
@ -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