diff options
author | Andrzej Bialecki <abial@FreeBSD.org> | 1998-08-27 17:38:45 +0000 |
---|---|---|
committer | Andrzej Bialecki <abial@FreeBSD.org> | 1998-08-27 17:38:45 +0000 |
commit | c9d8fd0a7bb8ae40b9da7c52caec851ca9d0cf3e (patch) | |
tree | 0f9c1dcefca21fb605aaf84b621c2813f01fa5e4 /release/picobsd/tinyware/simple_httpd/simple_httpd.c | |
parent | 0b0c1554a87b20eb1377566bce8833788ec96394 (diff) | |
download | src-c9d8fd0a7bb8ae40b9da7c52caec851ca9d0cf3e.tar.gz src-c9d8fd0a7bb8ae40b9da7c52caec851ca9d0cf3e.zip |
Initial import of PicoBSD v0.4 tree.
Notes
Notes:
svn path=/cvs2svn/branches/PICOBSD/; revision=38589
Diffstat (limited to 'release/picobsd/tinyware/simple_httpd/simple_httpd.c')
-rw-r--r-- | release/picobsd/tinyware/simple_httpd/simple_httpd.c | 356 |
1 files changed, 356 insertions, 0 deletions
diff --git a/release/picobsd/tinyware/simple_httpd/simple_httpd.c b/release/picobsd/tinyware/simple_httpd/simple_httpd.c new file mode 100644 index 000000000000..0a83f6737815 --- /dev/null +++ b/release/picobsd/tinyware/simple_httpd/simple_httpd.c @@ -0,0 +1,356 @@ +/* simpleHTTPd (C) 1998 netSTOR Technologies, Inc. ("netSTOR") + FreeBSD port and additional work by Marc Nicholas <marc@netstor.com> + Based on work by:- + Thierry Leconte & Yury Shimanovsky + My Russian webserver writing friends :-) + + This is an HTTP daemon that will serve up HTML, text files, JPEGs, + GIFs and do simple CGI work. + + You may use this code for non-commercial distribution only. Commercial + distribution requires the express, written permission of netSTOR. No + warranty is implied or given -- use at your own risk! +*/ + +/* + * $Id: simple_httpd.c,v 1.1 1998/08/19 16:24:06 abial Exp $ + */ + +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <sys/stat.h> +#include <sys/time.h> +#include <sys/types.h> +#include <time.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <netdb.h> +#include <fcntl.h> +#include <string.h> +#include <signal.h> +#include <sys/wait.h> + +int http_sock, con_sock; +int http_port = 80; +struct sockaddr_in source; +char homedir[100]; +char *adate(); +struct hostent *hst; + +void +init_servconnection(void) +{ + struct sockaddr_in server; + + /* Create a socket */ + http_sock = socket(AF_INET, SOCK_STREAM, 0); + if (http_sock < 0) { + perror("socket"); + exit(1); + } + server.sin_family = AF_INET; + server.sin_port = htons(http_port); + server.sin_addr.s_addr = INADDR_ANY; + if (bind(http_sock, (struct sockaddr *) & server, sizeof(server)) < 0) { + perror("bind socket"); + exit(1); + } + printf("simpleHTTPd running on %d port\n",http_port); +} + +attenteconnection(void) +{ + int lg; + + lg = sizeof(struct sockaddr_in); + + con_sock = accept(http_sock, (struct sockaddr *) & source, &lg); + if (con_sock <= 0) { + perror("accept"); + exit(1); + } +} + +outdate() +{ + time_t tl; + char buff[50]; + + tl = time(NULL); + strftime(buff, 50, "Date: %a, %d %h %Y %H:%M:%S %Z\r\n", gmtime(&tl)); + write(con_sock, buff, strlen(buff)); +} + +char *rep_err_nget[2] = {"<HTML><HEAD><TITLE>Error</TITLE></HEAD><BODY><H1>Error 405</H1>\ +This server is supports only GET and HEAD requests\n</BODY></HTML>\r\n", +"HTTP/1.0 405 Method Not allowed\r\nAllow: GET,HEAD\r\nServer: jhttpd\r\n"}; + +char *rep_err_acc[2] = {"<HTML><HEAD><TITLE>Error</TITLE></HEAD><BODY><H1>Error 404</H1>\ +Not found - file doesn't exist or is read protected\n</BODY></HTML>\r\n", +"HTTP/1.0 404 Not found\r\nServer: jhttpd\r\n"}; + +outerror(char **rep, int http1) /* Выдыча ошибки клиенту в html- виде */ +{ + + if (http1) { + write(con_sock, rep[1], strlen(rep[1])); + outdate(); + write(con_sock, "\r\n", 2); + } + write(con_sock, rep[0], strlen(rep[0])); +} + +char rep_head[] = "HTTP/1.0 200 OK\r\nServer: simpleHTTPD\r\n"; + +traite_req() +{ + char buff[8192]; + int fd, lg, cmd, http1, i; + char *filename, *c; + struct stat statres; + char req[1024]; + char logfile[80]; + char msg[1024]; + char *p, + *par; + long addr; + FILE *log; + + lg = read(con_sock, req, 1024); + + if (p=strstr(req,"\n")) *p=0; + if (p=strstr(req,"\r")) *p=0; + + if (geteuid()) + { + strcpy(logfile,getenv("HOME")); + strcat(logfile,"/"); + strcat(logfile,"jhttp.log"); + } + else strcpy(logfile,"/usr/adm/jhttpd.log"); + + if ( access(logfile,W_OK)) + { + lg=creat (logfile,O_WRONLY); + chmod (logfile,00600); + close(lg); + } + + strcpy(buff,inet_ntoa(source.sin_addr)); + + addr=inet_addr(buff); + + strcpy(msg,adate()); + strcat(msg," "); + hst=gethostbyaddr((char*) &addr, 4, AF_INET); + if (hst) strcat(msg,hst->h_name); + strcat(msg," ("); + strcat(msg,buff); + strcat(msg,") "); + strcat(msg,req); + + log=fopen(logfile,"a"); + fprintf(log,"%s\n",msg); + fclose(log); + + c = strtok(req, " "); + if (c == NULL) { + outerror(rep_err_nget, 0); + goto error; + } + cmd = 0; + if (strncmp(c, "GET", 3) == 0) + cmd = 1; + if (strncmp(c, "HEAD", 4) == 0) { + cmd = 2; + } + + filename = strtok(NULL, " "); + + http1 = 0; + c = strtok(NULL, " "); + if (c != NULL && strncmp(c, "HTTP", 4) == 0) + http1 = 1; + + if (cmd == 0) { + outerror(rep_err_nget, http1); + goto error; + } + + if (filename == NULL || + strlen(filename)==1) filename="/index.html"; + + while (filename[0]== '/') filename++; + + /**/ + if (!strncmp(filename,"cgi-bin/",8)) + { + par=0; + if (par=strstr(filename,"?")) + { + *par=0; + par++; + } + if (access(filename,X_OK)) goto conti; + stat (filename,&statres); + if (setuid(statres.st_uid)) return(0); + if (seteuid(statres.st_uid)) return(0); + if (!fork()) + { + close(1); + dup(con_sock); + printf("HTTP/1.0 200 OK\nContent-type: text/html\n\n\n"); + execlp (filename,filename,par,0); + } + wait(&i); + return(0); + } + conti: + if (filename == NULL) { + outerror(rep_err_acc, http1); + goto error; + } + /* interdit les .. dans le path */ + c = filename; + while (*c != '\0') + if (c[0] == '.' && c[1] == '.') { + outerror(rep_err_acc, http1); + goto error; + } else + c++; + + fd = open(filename, O_RDONLY); + if (fd < 0) { + outerror(rep_err_acc, http1); + goto error; + } + if (fstat(fd, &statres) < 0) { + outerror(rep_err_acc, http1); + goto error; + } + if (!S_ISREG(statres.st_mode)) + { + outerror(rep_err_acc, http1); + goto error; + } + if (http1) { + char buff[50]; + time_t tl; + + write(con_sock, rep_head, strlen(rep_head)); + sprintf(buff, "Content-length: %d\r\n", statres.st_size); + write(con_sock, buff, strlen(buff)); + outdate(); + + if (strstr(filename,".")) + { + strcpy(buff,"Content-type: "); + strcat(buff,strstr(filename,".")+1); + strcat(buff,"\r\n"); + write(con_sock,buff,strlen(buff)); + } + + if (strstr(filename,".txt")) + { + strcpy(buff,"Content-type: text/plain\r\n"); + write(con_sock, buff, strlen(buff)); + } + + if (strstr(filename,".html") || + strstr(filename,".htm")) + { + strcpy(buff,"Content-type: text/html\r\n"); + write(con_sock, buff, strlen(buff)); + } + + if (strstr(filename,".gif")) + { + strcpy(buff,"Content-type: image/gif\r\n"); + write(con_sock, buff, strlen(buff)); + } + + if (strstr(filename,".jpg")) + { + strcpy(buff,"Content-type: image/jpeg\r\n"); + write(con_sock, buff, strlen(buff)); + } + + strftime(buff, 50, "Last-Modified: %a, %d %h %Y %H:%M:%S %Z\r\n\r\n", gmtime(&statres.st_mtime)); + write(con_sock, buff, strlen(buff)); + } + if (cmd == 1) { + while (lg = read(fd, buff, 8192)) + write(con_sock, buff, lg); + } + +error: + close(fd); + close(con_sock); + +} + + +main(int argc, char **argv) +{ + int lg; + char hello[100]; + + if (argc<2 && geteuid()) + { + printf("Usage: simple_htppd <port>\n"); + exit(1); + } + + if (argc>=2) http_port = atoi(argv[1]); + + strcpy (homedir,getenv("HOME")); + if (!geteuid()) strcpy (homedir,"/httphome"); + else strcat (homedir,"/httphome"); + + strcpy(hello,homedir); + strcat(hello,"/0hello.html"); + + if (chdir(homedir)) + { + perror("chdir"); + puts(homedir); + exit(1); + } + init_servconnection(); + + if (fork()) exit(0); + + setpgrp(0,65534); + signal(SIGQUIT, SIG_IGN); + signal(SIGHUP, SIG_IGN); + + if (listen(http_sock,100) < 0) exit(1); + + label: + attenteconnection(); + if (fork()) + { + close(con_sock); + goto label; + } + alarm(1800); + traite_req(); + exit(0); +} + + + +char *adate() +{ + static char out[50]; + long now; + struct tm *t; + time(&now); + t = localtime(&now); + sprintf(out, "%02d:%02d:%02d %02d/%02d/%02d", + t->tm_hour, t->tm_min, t->tm_sec, + t->tm_mday, t->tm_mon+1, t->tm_year ); + return out; +} |