📄 cgi.c
字号:
/* * CGI C-library, v1.1.1 * * Copyright (C) '97,'98,'.. Rasca, Berlin * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */#include <stdlib.h> /* getenv() */#include <stdio.h> /* printf() */#include <string.h> /* strcat() */#include <limits.h> /* PATH_MAX */#include <unistd.h> /* getpid() */#include <sys/stat.h> /* stat() */#include <sys/utsname.h>/* uname() */#include <time.h> /* time() */#include "cgi.h"#define MAX_LINE 1024#define EMPTY '\0'static char *cgi_background = NULL;static char *cgi_foreground = NULL;static char *cgi_stylesheet = NULL;static char *cgi_source_url = NULL;static char *cgi_loggingdir = NULL;static char *cgi_defaultmta = NULL;static char *cgi_bottomline = NULL;static char *cgi_meta_desc = NULL;static char *cgi_meta_keyw = NULL;static char **cgi_form = NULL;static char **cgi_cfg = NULL;static char *program = NULL;static const char *prog_wp = NULL;static int run_as_nph = 0;static int cgi_refresh_time = 0;static char *cgi_refresh_url = 0;/* http 1.0 status codes */static http_code http[] = { /* status code, reason-phrase */ { 100, "Continue" }, /* 1.1 */ { 200, "Ok" }, { 201, "Created" }, { 202, "Accepted" }, { 203, "Non-Authoritative Information"}, /* 1.1 */ { 204, "No Content" }, { 205, "Reset Content" }, /* 1.1 */ { 301, "Moved Permanently" }, { 302, "Moved Temporarily" }, { 304, "Not Modified" }, { 305, "Use Proxy" }, /* 1.1 */ { 400, "Bad Request" }, { 401, "Unauthorized" }, { 403, "Forbidden" }, { 404, "Not Found" }, { 410, "Gone" }, /* 1.1 */ { 500, "Internal Server Error" }, { 501, "Not Implemented" }, { 502, "Bad Gateway" }, { 503, "Service Unavailable" }, { 000, NULL }, };/* * return RFC 822, 1123 date string * next call will override previous value! */char *cgi_gmt_str (long date){ char *day[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; char *mon[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; static char str[48]; /* should be enough */ struct tm *s; s = gmtime (&date); sprintf (str, "%s, %02d %s %d %02d:%02d:%02d GMT", day[s->tm_wday], s->tm_mday, mon[s->tm_mon], s->tm_year + 1900, s->tm_hour, s->tm_min, s->tm_sec); return (str);}/* * returns the url, where the cgi is included/started */const char *cgi_url_ref (){ char *url; static char urlb[URL_MAX+1]; url = getenv ("HTTP_REFERER"); if (!url) { /* not CGI conform, but try .. */ url = getenv ("REFERER_URL"); } if (!url) { url = getenv ("DOCUMENT_URI"); if (url) { urlb[0] = '\0'; strcat (urlb, "http://"); strcat (urlb, cgi_server_name()); strcat (urlb, ":"); strcat (urlb, getenv("SERVER_PORT")); strcat (urlb, url); url = urlb; } else { const char *server; /* may be lynx is starting local CGIs ..? */ server = cgi_server_software(); if (server && prog_wp) { if (strstr (server, "Lynx")) { if ((strlen (prog_wp) + 8) < URL_MAX) { sprintf (urlb, "lynxcgi:%s", prog_wp); url = urlb; } } } } } if (url) { if (*url == '\0') { url = NULL; } } return (url);}/* * returns the name of the server software */const char *cgi_server_software (void){ return (getenv ("SERVER_SOFTWARE"));}/* * returns the name of the server */const char *cgi_server_name (void){ const char *sn; struct utsname un; sn = getenv ("SERVER_NAME"); if (!sn) { sn = getenv ("HOSTNAME"); if (!sn) { uname (&un); sn = un.nodename; } } return (sn);}/* * returns the name of the script */const char *cgi_script_name (void){ const char *sn = NULL; const char *server; static char url[URL_MAX+1]; sn = getenv ("SCRIPT_NAME"); if (!sn) { /* lynx cgi ? */ server = cgi_server_software(); if (server && prog_wp) { if (strstr (server, "Lynx")) { if ((strlen (prog_wp) + 8) < URL_MAX) { sprintf (url, "lynxcgi:%s", prog_wp); sn = url; } } } } return (sn);}/* * returns the name of the browser software */const char *cgi_client_software (void){ return (getenv ("HTTP_USER_AGENT"));}/* */const char *cgi_remote_host (void){ const char *host; host = getenv ("REMOTE_HOST"); if (!host) return ( getenv ("REMOTE_ADDR") ); return ( host );}/* * print a http status line */voidcgi_status (int num){ printf ("HTTP/1.0 %d %s\r\n", http[num].num, http[num].str);}/* * send the content type given in "ct", if "name" is not * NULL it is added in the following way, e.g. * Content-Type: text/html; name="foo.gif" */voidcgi_content_type (const char *ct, const char *name){ if (run_as_nph) { cgi_status (http_ok); printf ("Server: %s/libcgi/%s\r\n", program, VER); printf ("Date: %s\r\n", cgi_gmt_str (time(NULL))); } if (name) { printf ("Content-Type: %s; name=\"%s\"\r\n\r\n", ct, name); } else { printf ("Content-Type: %s\r\n\r\n", ct); }}/* */voidcgi_multipart (const char *boundary){ if (run_as_nph) { cgi_status (http_ok); printf ("Server: %s/libcgi/%s\r\n", program, VER); printf ("Date: %s\r\n", cgi_gmt_str (time(NULL))); } printf ("Content-Type: multipart/x-mixed-replace;boundary=%s\n", boundary); printf ("\n%s\n", boundary);}/* * send a status line and content type if 'content_t' is not NULL, * e.g. cgi_response (http_ok, "text/html"); */voidcgi_response (int num, char *content_t){ if (run_as_nph) { cgi_status (num); printf ("Server: %s/libcgi/%s\r\n", program, VER); printf ("Date: %s\r\n", cgi_gmt_str (time(NULL))); } if (content_t) { printf ("Content-Type: %s\r\n", content_t); } printf ("\r\n");}/* * return the base url */const char *cgi_base (void){ static char base[URL_MAX+1]; const char *url_ref, *p; int i, len; url_ref = cgi_url_ref(); if (url_ref) { len = strlen (url_ref); if (url_ref[len-1] == '/') { strcpy (base, url_ref); } else { p = strrchr (url_ref, '/'); if (p) { i = 0; while (url_ref < (p+1)) { base[i] = *url_ref; url_ref++; i++; } base[i] = '\0'; } else { /* should never be reached ..! */ return (NULL); } } return (base); } return (NULL);}/* * redirect to the given url, which could be a relative or an * absolute url. note: relative urls could be a problem with * some browsers, cause sometimes there is no way to find out * the "REFERER".. */voidcgi_redirect (const char *url){ const char *p, *s, *hash; char buff[URL_MAX+1]; if (run_as_nph) { cgi_status (http_moved_permanently); printf ("Server: %s/libcgi/%s\r\n", program, VER); printf ("Date: %s\r\n", cgi_gmt_str (time(NULL))); } if (strstr (url, "://") > url) { /* it磗 an absolute URL .. */ printf ("Location: %s\r\n", url); } else if (*url == '/') { /* relative URL which starts at the root */ if ((s = p = cgi_base ()) != NULL ) { int i; for (i = 0; i < 3; i++) { if (p) { p = strchr (p, '/'); } p++; } if (p) { strncpy (buff, s, p-s-1); buff[p-s-1] = '\0'; printf ("Location: %s%s\r\n", buff, url); } else { printf ("Location: %s\r\n", url); } } else { printf ("Location: %s\r\n", url); } } else if (*url == '#') { p = cgi_url_ref(); if (p) { hash = strrchr (p, '#'); if (!hash) { printf ("Location: %s%s\r\n", p, url); } else { /* there is still a name value, we have to remove it .. */ strncpy (buff, p, hash-p); buff[hash-p] = '\0'; strcat (buff, url); printf ("Location: %s\r\n", buff); } } else printf ("Location: %s\r\n", url); } else { /* some other kind of relative URL.. */ p = cgi_base(); printf ("Location: %s%s\r\n", p ? p:"", url); } printf ("Content-Type: text/html\r\n\r\n");}/* * lock a name file */intcgi_lock (const char *file){ char pfile[PATH_MAX+1]; char lfile[PATH_MAX+1]; FILE *pfp; int pid, loop; struct stat info; loop = 5; /* try five times to lock .. */ pid = getpid(); strcpy (pfile, file); sprintf (pfile+strlen(file), ".%d", pid); strcpy (lfile, file); strcat (lfile, ".LCK"); pfp = fopen (pfile, "wb"); if (!pfp) { perror (pfile); return (0); } fwrite (&pid, sizeof (pid), 1, pfp); fclose (pfp); while ((stat (lfile, &info) == 0) || (link (pfile, lfile) != 0)) { sleep (1); loop--; if (loop < 1) { unlink (pfile); return (0); } } return (1);}/* * unlock the named file */intcgi_unlock (const char *file){ char pfile[PATH_MAX+1]; char lfile[PATH_MAX+1]; int pid; pid = getpid(); strcpy (pfile, file); sprintf (pfile+strlen(file), ".%d", pid); strcpy (lfile, file); strcat (lfile, ".LCK"); unlink (pfile); unlink (lfile); return (1);}/* */voidcgi_html_start (const char *title){ printf ("<HTML>\n"); printf ("<HEAD>\n"); printf ("\t<TITLE>%s</TITLE>\n", title); if (cgi_source_url) { printf ("\t<!-- source: %s -->\n", cgi_source_url); } if (cgi_meta_desc) { printf ("\t<META name=\"description\" content=\"%s\">\n", cgi_meta_desc); } if (cgi_meta_keyw) { printf ("\t<META name=\"keywords\" content=\"%s\">\n", cgi_meta_keyw); } if (cgi_refresh_time > 0) { printf ("\t<META http-equiv=refresh content=\"%d; url='", cgi_refresh_time); if (cgi_refresh_url) printf ("%s'\">\n", cgi_refresh_url); else if (getenv("QUERY_STRING")) printf ("%s?%s'\">\n", cgi_script_name(), getenv("QUERY_STRING")); else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -