From d411b6e3cb33043de0943f6066bea77a7a962823 Mon Sep 17 00:00:00 2001 From: SkywalkerSW5 Date: Sat, 18 Dec 2021 20:07:34 +0000 Subject: release --- ittpd.c | 195 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 195 insertions(+) create mode 100644 ittpd.c (limited to 'ittpd.c') diff --git a/ittpd.c b/ittpd.c new file mode 100644 index 0000000..d4bfa37 --- /dev/null +++ b/ittpd.c @@ -0,0 +1,195 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define VERSION 23 +#define BUFSIZE 8096 +#define ERROR 42 +#define LOG 44 +#define FORBIDDEN 403 +#define NOTFOUND 404 + +struct { + char *ext; + char *filetype; +} extensions [] = { + {"gif", "image/gif" }, + {"jpg", "image/jpg" }, + {"jpeg","image/jpeg"}, + {"png", "image/png" }, + {"ico", "image/ico" }, + {"zip", "image/zip" }, + {"gz", "image/gz" }, + {"tar", "image/tar" }, + {"htm", "text/html" }, + {"html","text/html" }, + {"css", "text/css" }, + {"js", "text/js" }, + {"json","application/json" }, + {0,0} }; + +void logger(int type, char *s1, char *s2, int socket_fd) +{ + int fd ; + char logbuffer[BUFSIZE*2]; + + switch (type) { + case ERROR: (void)sprintf(logbuffer,"ERROR: %s:%s Errno=%d exiting pid=%d",s1, s2, errno,getpid()); + break; + case FORBIDDEN: + (void)write(socket_fd, "HTTP/1.1 403 Forbidden\nContent-Length: 185\nConnection: close\nContent-Type: text/html\n\n\n403 Forbidden\n\n

Forbidden

\nThe requested URL, file type or operation is not allowed on this simple static file webserver.\n\n",271); + (void)sprintf(logbuffer,"FORBIDDEN: %s:%s",s1, s2); + break; + case NOTFOUND: + (void)write(socket_fd, "HTTP/1.1 404 Not Found\nContent-Length: 136\nConnection: close\nContent-Type: text/html\n\n\n404 Not Found\n\n

Not Found

\nThe requested URL was not found on this server.\n\n",224); + (void)sprintf(logbuffer,"NOT FOUND: %s:%s",s1, s2); + break; + case LOG: (void)sprintf(logbuffer," INFO: %s:%s:%d",s1, s2,socket_fd); break; + } + /* No checks here, nothing can be done with a failure anyway */ + if((fd = open("ittpd.log", O_CREAT| O_WRONLY | O_APPEND,0644)) >= 0) { + (void)write(fd,logbuffer,strlen(logbuffer)); + (void)write(fd,"\n",1); + (void)close(fd); + } + if(type == ERROR || type == NOTFOUND || type == FORBIDDEN) exit(3); +} + +/* this is a child web server process, so we can exit on errors */ +void web(int fd, int hit) +{ + int j, file_fd, buflen; + long i, ret, len; + char * fstr; + static char buffer[BUFSIZE+1]; /* static so zero filled */ + + ret =read(fd,buffer,BUFSIZE); /* read Web request in one go */ + if(ret == 0 || ret == -1) { /* read failure stop now */ + logger(FORBIDDEN,"failed to read browser request","",fd); + } + if(ret > 0 && ret < BUFSIZE) /* return code is valid chars */ + buffer[ret]=0; /* terminate the buffer */ + else buffer[0]=0; + for(i=0;i 0 ) { + (void)write(fd,buffer,ret); + } + sleep(1); /* allow socket to drain before signalling the socket is closed */ + close(fd); + exit(1); +} + +int main(int argc, char **argv) +{ + int i, port, pid, listenfd, socketfd, hit; + socklen_t length; + static struct sockaddr_in cli_addr; /* static = initialised to zeros */ + static struct sockaddr_in serv_addr; /* static = initialised to zeros */ + + if( argc < 3 || argc > 3 || !strcmp(argv[1], "-?") ) { + (void)printf("hint: ittpd Port-Number Top-Directory\t\tversion %d\n\n" + "ittpd is a very small web server\n" + "\n" + "example: ittpd 8181 /server/website\n" + ); + exit(0); + } + if( !strncmp(argv[2],"/" ,2 ) || !strncmp(argv[2],"/etc", 5 ) || + !strncmp(argv[2],"/bin",5 ) || !strncmp(argv[2],"/lib", 5 ) || + !strncmp(argv[2],"/tmp",5 ) || !strncmp(argv[2],"/usr", 5 ) || + !strncmp(argv[2],"/dev",5 ) || !strncmp(argv[2],"/sbin",6) ){ + (void)printf("ERROR: Bad top directory %s, see ittpd -?\n",argv[2]); + exit(3); + } + if(chdir(argv[2]) == -1){ + (void)printf("ERROR: Can't Change to directory %s\n",argv[2]); + exit(4); + } + /* Become deamon + unstopable and no zombies children (= no wait()) */ + if(fork() != 0) + return 0; /* parent returns OK to shell */ + (void)signal(SIGCHLD, SIG_IGN); /* ignore child death */ + (void)signal(SIGHUP, SIG_IGN); /* ignore terminal hangups */ + for(i=0;i<32;i++) + (void)close(i); /* close open files */ + (void)setpgrp(); /* break away from process group */ + logger(LOG,"ittpd starting",argv[1],getpid()); + /* setup the network socket */ + if((listenfd = socket(AF_INET, SOCK_STREAM,0)) <0) + logger(ERROR, "system call","socket",0); + port = atoi(argv[1]); + if(port < 0 || port >60000) + logger(ERROR,"Invalid port number (try 1->60000)",argv[1],0); + serv_addr.sin_family = AF_INET; + serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); + serv_addr.sin_port = htons(port); + if(bind(listenfd, (struct sockaddr *)&serv_addr,sizeof(serv_addr)) <0) + logger(ERROR,"system call","bind",0); + if( listen(listenfd,64) <0) + logger(ERROR,"system call","listen",0); + for(hit=1; ;hit++) { + length = sizeof(cli_addr); + if((socketfd = accept(listenfd, (struct sockaddr *)&cli_addr, &length)) < 0) + logger(ERROR,"system call","accept",0); + if((pid = fork()) < 0) { + logger(ERROR,"system call","fork",0); + } + else { + if(pid == 0) { /* child */ + (void)close(listenfd); + web(socketfd,hit); /* never returns */ + } else { /* parent */ + (void)close(socketfd); + } + } + } +} \ No newline at end of file -- cgit v1.2.3