176 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			176 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /* httpd.c
 | |
|  *
 | |
|  * httpd	A Server implementing the HTTP protocol.
 | |
|  *
 | |
|  * usage:	tcpd http httpd &
 | |
|  *
 | |
|  * 02/17/1996 			Michael Temari <Michael@TemWare.Com>
 | |
|  * 07/07/1996 Initial Release	Michael Temari <Michael@TemWare.Com>
 | |
|  * 12/29/2002 			Michael Temari <Michael@TemWare.Com>
 | |
|  * 07/04/2003			Al Woodhull <asw@woodhull.com>
 | |
|  *
 | |
|  */
 | |
| 
 | |
| #include <stdlib.h>	
 | |
| #include <sys/types.h>
 | |
| #include <pwd.h>
 | |
| #include <stdio.h>
 | |
| #include <unistd.h>
 | |
| #include <string.h>
 | |
| #include "http.h"
 | |
| #include "utility.h"
 | |
| #include "net.h"
 | |
| #include "config.h"
 | |
| 
 | |
| FILE *stdlog = (FILE *)NULL;
 | |
| FILE *dbglog = (FILE *)NULL;
 | |
| 
 | |
| char umsg[80];
 | |
| 
 | |
| _PROTOTYPE(int main, (int argc, char *argv[]));
 | |
| 
 | |
| struct http_request request;
 | |
| struct http_reply reply;
 | |
| 
 | |
| int main(argc, argv)
 | |
| int argc;
 | |
| char *argv[];
 | |
| {
 | |
| char *prog;
 | |
| int opt_t;
 | |
| char *cfg = (char *)NULL;
 | |
| struct passwd *pwd;
 | |
| int s;
 | |
| 
 | |
|    strcpy(umsg, "Usage: ");
 | |
|    strcat(umsg, argv[0]);
 | |
|    strcat(umsg, " [-t|v] [config_file]\n");
 | |
| 
 | |
|    /* parse program name */
 | |
|    prog = strrchr(*argv, '/');
 | |
|    if(prog == (char *)NULL)
 | |
|    	prog = *argv;
 | |
|    else
 | |
|    	prog++;
 | |
|    argv++;
 | |
|    argc--;
 | |
| 
 | |
|    /* Any options */
 | |
|    if(argc)
 | |
|         if(argv[0][0] == '-') {
 | |
|              switch (argv[0][1]) {
 | |
|                   case 't' : opt_t = 1;
 | |
|                              argv++;
 | |
|                              argc--;
 | |
|                              break;
 | |
|                   case 'v' : fprintf(stderr, VERSION"\n"); 
 | |
|                              exit(EXIT_SUCCESS);
 | |
|                              break;
 | |
|                   default  : fprintf(stderr, VERSION"\n"); 
 | |
|                              fprintf(stderr, umsg); 
 | |
|                              exit(EXIT_FAILURE);
 | |
|              }
 | |
|         }
 | |
| 
 | |
|    /* Did they specify an alternate configuration file? */
 | |
|    if(argc) {
 | |
|    	cfg = *argv++;
 | |
|    	argc--;
 | |
|    }
 | |
| 
 | |
|    /* Read the configuration settings */
 | |
|    if(readconfig(cfg, opt_t)) {
 | |
|    	fprintf(stderr, "httpd: Error reading configuration file.\n");
 | |
|    	return(-1);
 | |
|    }
 | |
| 
 | |
|    /* Option t is to test configuration only */
 | |
|    if(opt_t)
 | |
| 	return(0);
 | |
| 
 | |
|    /* Open log file for append if it exists */
 | |
|    if(LogFile != NULL)
 | |
| 	if((stdlog = fopen(LogFile, "r")) != (FILE *)NULL) {
 | |
| 		fclose(stdlog);
 | |
| 		stdlog = fopen(LogFile, "a");
 | |
| 	}
 | |
| 
 | |
|    /* Open debug log file for append if it exists */
 | |
|    if(DbgFile != NULL)
 | |
| 	if((dbglog = fopen(DbgFile, "r")) != (FILE *)NULL) {
 | |
| 		fclose(dbglog);
 | |
| 		dbglog = fopen(DbgFile, "a");
 | |
|    }
 | |
| 
 | |
| #if 0
 | |
|    /* Get some network information */
 | |
|    GetNetInfo();
 | |
| #endif
 | |
| 
 | |
|    /* If user defined then prepare to secure as user given */
 | |
|    if(User != NULL)
 | |
| 	if((pwd = getpwnam(User)) == (struct passwd *)NULL) {
 | |
|    		fprintf(stderr, "httpd: unable to find user %s\n", User);
 | |
|   	 	return(-1);
 | |
| 	}
 | |
| 
 | |
|    /* If Chroot defined then secure even more by doing a chroot */
 | |
|    if(Chroot != NULL) {
 | |
| 	if(chroot(Chroot)) {
 | |
| 		fprintf(stderr, "httpd: unable to chroot\n");
 | |
| 		return(-1);
 | |
| 	}
 | |
| 	if(chdir("/")) {
 | |
|    		fprintf(stderr, "httpd: unable to chroot\n");
 | |
|    		return(-1);
 | |
| 	}
 | |
|    }
 | |
| 
 | |
|    /* If user defined then secure as user given */
 | |
|    if(User != NULL)
 | |
| 	if(setgid(pwd->pw_gid) || setuid(pwd->pw_uid)) {
 | |
|    		fprintf(stderr, "httpd: unable to set user\n");
 | |
|    		return(-1);
 | |
| 	}
 | |
| 
 | |
| #if DAEMON
 | |
|    /* Standalone? */
 | |
|    if (strncmp(prog, "in.", 3) != 0) {
 | |
|        /* Does not start with "in.", so not started from inetd/tcpd. */
 | |
|        /* XXX - Port name/number should be a config file option. */
 | |
|        daemonloop("http");
 | |
|    }
 | |
| #endif
 | |
| 
 | |
|    /* Get some network information */
 | |
|    GetNetInfo();
 | |
| 
 | |
|    /* log a connection */
 | |
|    if(dbglog != (FILE *)NULL) {
 | |
| 	fprintf(dbglog, "CONNECT: %d %s %s\n", getpid(),
 | |
| 		rmthostname, logdate((time_t *)NULL));
 | |
| 	fflush(dbglog);
 | |
|    }
 | |
| 
 | |
|    /* loop getting, processing and replying to requests */
 | |
|    while(!(s = getrequest(&request))) {
 | |
| 	if(processrequest(&request, &reply)) break;
 | |
| 	if(stdlog != (FILE *)NULL) {
 | |
| 		fprintf(stdlog, "%s %s %d %d %s\n",
 | |
| 			logdate((time_t *)NULL), rmthostname,
 | |
| 			request.method, reply.status, request.url);
 | |
| 		fflush(stdlog);
 | |
| 	}
 | |
| 	if(sendreply(&reply, &request)) break;
 | |
| 	if(!reply.keepopen) break;
 | |
|    }
 | |
|    if(s == 1 && stdlog != (FILE *)NULL) {
 | |
| 	fprintf(stdlog, "%s %s %d %d %s\n",
 | |
| 		logdate((time_t *)NULL), rmthostname,
 | |
| 		request.method, 999, request.url);
 | |
| 	fflush(stdlog);
 | |
|    }
 | |
| 
 | |
|    return(0);
 | |
| }
 | 
