1 /* httpd.c: A very simple http server
2 * Copyright (C) 2000 Lineo, Inc. (www.lineo.com)
3 * Copyright (c) 1997-1999 D. Jeff Dionne <jeff@lineo.ca>
4 * Copyright (c) 1998 Kenneth Albanowski <kjahds@kjahds.com>
5 * Copyright (c) 1999 Nick Brok <nick@nbrok.iaehv.nl>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
18 #include <sys/types.h>
19 #include <sys/socket.h>
20 #include <netinet/in.h>
39 #define SERVER_PORT 80
41 int PrintHeader(FILE *f, int content_type)
45 fprintf(f,"HTTP/1.0 200 OK\n");
49 fprintf(f,"Content-type: text/plain\n");
52 fprintf(f,"Content-type: image/gif\n");
55 fprintf(f,"Content-type: image/jpeg\n");
58 fprintf(f,"Content-type: text/html\n");
61 fprintf(f,"Server: uClinux-httpd 0.2.2\n");
62 fprintf(f,"Expires: 0\n");
69 DoJpeg(FILE *f, char *name)
75 if (!(infile = fopen(name, "r"))) {
77 fprintf(stderr, "Unable to open JPEG file %s, %d\n", name, errno);
85 copy(infile,f); /* prints the page */
95 DoGif(FILE *f, char *name)
101 if (!(infile = fopen(name, "r"))) {
103 fprintf(stderr, "Unable to open GIF file %s, %d\n", name, errno);
111 copy(infile,f); /* prints the page */
121 DoDir(FILE *f, char *name)
125 struct dirent * dirent;
127 if ((dir = opendir(name))== 0) {
128 fprintf(stderr, "Unable to open directory %s, %d\n", name, errno);
136 fprintf(f, "<H1>Index of %s</H1>\n\n",name);
139 if (name[strlen(name)-1] != '/') {
143 while(dirent = readdir(dir)) {
146 fprintf(f, "<p><a href=\"/%s%s\">%s</a></p>\n", name, dirent->d_name, dirent->d_name);
155 DoHTML(FILE *f, char *name)
162 if (!(infile = fopen(name,"r"))) {
164 fprintf(stderr, "Unable to open HTML file %s, %d\n", name, errno);
171 copy(infile,f); /* prints the page */
181 DoText(FILE *f, char *name)
187 if (!(infile = fopen(name,"r"))) {
189 fprintf(stderr, "Unable to open text file %s, %d\n", name, errno);
196 copy(infile,f); /* prints the page */
206 ParseReq(FILE *f, char *r)
216 printf("req is '%s'\n", r);
219 while(*(++r) != ' '); /*skip non-white space*/
229 while(*r && (*(r) != ' ') && (*(r) != '?'))
233 printf("bp='%s', r='%s'\n", bp, r);
241 if (e = strchr(arg,' '))
253 if (c[0] == '\0') strcat(c,".");
255 if (c && !stat(c, &stbuf))
257 if (S_ISDIR(stbuf.st_mode))
259 char * end = c + strlen(c);
260 strcat(c, "/index.html");
261 if (!stat(c, &stbuf))
271 else if (!strcmp(r - 4, ".gif"))
273 else if (!strcmp(r - 4, ".jpg") || !strcmp(r - 5, ".jpeg"))
275 else if (!strcmp(r - 4, ".htm") || !strcmp(r - 5, ".html"))
283 fprintf(f, "<html><head><title>404 File Not Found</title></head>\n");
284 fprintf(f, "<body>The requested URL was not found on this server</body></html>\n");
290 void sigalrm(int signo)
292 /* got an alarm, exit & recycle */
297 HandleConnect(int fd)
306 fprintf(stderr, "httpd: Unable to open httpd input fd, error %d\n", errno);
316 if (!fgets(buf, 150, f)) {
317 fprintf(stderr, "httpd: Error reading connection, error %d\n", errno);
323 printf("buf = '%s'\n", buf);
332 while (fgets(buf1, 150, f) && (strlen(buf1) > 2)) {
335 printf("Got buf1 '%s'\n", buf1);
337 if (!strncasecmp(buf1, "Referer:", 8)) {
342 } else if (!strncasecmp(buf1, "Referrer:", 9)) {
347 } else if (!strncasecmp(buf1, "Content-length:", 15)) {
348 content_length = atoi(buf1+15);
355 fprintf(stderr, "http: Error continuing reading connection, error %d\n", errno);
371 main(int argc, char *argv[])
375 volatile int true = 1;
376 struct sockaddr_in ec;
377 struct sockaddr_in server_sockaddr;
379 signal(SIGCHLD, SIG_IGN);
380 signal(SIGPIPE, SIG_IGN);
381 signal(SIGALRM, sigalrm);
383 chroot(HTTPD_DOCUMENT_ROOT);
386 if (argc > 1 && !strcmp(argv[1], "-i")) {
387 /* I'm running from inetd, handle the request on stdin */
393 if((s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
394 perror("Unable to obtain network");
398 if((setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void *)&true,
399 sizeof(true))) == -1) {
400 perror("setsockopt failed");
404 server_sockaddr.sin_family = AF_INET;
405 server_sockaddr.sin_port = htons(SERVER_PORT);
406 server_sockaddr.sin_addr.s_addr = htonl(INADDR_ANY);
408 if(bind(s, (struct sockaddr *)&server_sockaddr,
409 sizeof(server_sockaddr)) == -1) {
410 perror("Unable to bind socket");
414 if(listen(s, 8*3) == -1) { /* Arbitrary, 8 files/page, 3 clients */
415 perror("Unable to listen");
422 if((fd = accept(s, (void *)&ec, &len)) == -1) {