reply.c

Go to the documentation of this file.
00001 /* reply.c
00002  *
00003  * This file is part of httpd.
00004  *
00005  * 02/17/1996                   Michael Temari <Michael@TemWare.Com>
00006  * 07/07/1996 Initial Release   Michael Temari <Michael@TemWare.Com>
00007  * 12/29/2002                   Michael Temari <Michael@TemWare.Com>
00008  *
00009  */
00010 #include <sys/types.h>
00011 #include <stdio.h>
00012 #include <string.h>
00013 #include <unistd.h>
00014 #include <errno.h>
00015 #include <signal.h>
00016 
00017 #include "http.h"
00018 #include "utility.h"
00019 #include "net.h"
00020 #include "config.h"
00021 
00022 #define SERVER  "Server: "VERSION
00023 
00024 _PROTOTYPE(static void GotAlarm, (int sig));
00025 _PROTOTYPE(static int sendout, (char *data));
00026 
00027 static void GotAlarm(sig)
00028 int sig;
00029 {
00030 }
00031 
00032 static int sendout(data)
00033 char *data;
00034 {
00035    if(strlen(data) > 0)
00036         write(1, data, strlen(data));
00037    write(1, "\r\n", 2);
00038    if(dbglog != (FILE *)NULL) {
00039         fprintf(dbglog, "REPLY: %s\n", data);
00040         fflush(dbglog);
00041    }
00042 
00043    return(0);
00044 }
00045 
00046 int sendreply(rp, rq)
00047 struct http_reply *rp;
00048 struct http_request *rq;
00049 {
00050 int s;
00051 int s2;
00052 int e;
00053 static char buffer[8192];
00054 
00055    if(rq->type != HTTP_REQUEST_TYPE_PROXY)
00056    /* We're receiving data from a */
00057    if(rq->method == HTTP_METHOD_POST ||
00058      (rq->method == HTTP_METHOD_PUT && rp->status == HTTP_STATUS_OK)) {
00059         if(rq->type != HTTP_REQUEST_TYPE_FULL)
00060                 return(0);
00061         if(rq->method == HTTP_METHOD_PUT)
00062                 rp->status = HTTP_STATUS_CREATED;
00063         else
00064                 rp->status = HTTP_STATUS_OK;
00065         while(rq->size != 0) {
00066                 s = read(0, buffer, (rq->size > sizeof(buffer)) ? sizeof(buffer) : rq->size);
00067                 if(s <= 0) {
00068                         rp->status = HTTP_STATUS_SERVER_ERROR;
00069                         strcpy(rp->statusmsg, strerror(errno));
00070                         close(rp->fd);
00071                         close(rp->ofd);
00072                         break;
00073                 }
00074                 rq->size -= s;
00075                 s2 = write(rp->ofd, buffer, s);
00076                 if(s2 != s) break;
00077         }
00078    }
00079 
00080    if(rp->status != HTTP_STATUS_OK && rp->status != HTTP_STATUS_CREATED &&
00081       rp->status != HTTP_STATUS_NOT_MODIFIED)
00082         rp->keepopen = 0;
00083 
00084    if(rp->status == HTTP_STATUS_NOT_MODIFIED) {
00085         sprintf(buffer, "<h2>Error %03d %s</h2>",
00086                 rp->status, rp->statusmsg);
00087         rp->size = strlen(buffer);
00088         rp->keepopen = rq->keepopen;
00089    }
00090 
00091    if(!rp->headers) {
00092 
00093    if((rq->type == HTTP_REQUEST_TYPE_PROXY && rp->status != HTTP_STATUS_OK) ||
00094        rq->type == HTTP_REQUEST_TYPE_FULL) {
00095         sprintf(buffer, "HTTP/%d.%d %03d %s",
00096                 rq->vmajor, rq->vminor, rp->status, rp->statusmsg);
00097         sendout(buffer);
00098         sendout(SERVER);
00099         if(rp->status == HTTP_STATUS_MOVED_PERM ||
00100            rp->status == HTTP_STATUS_MOVED_TEMP) {
00101 #if 1
00102                 sprintf(buffer, "Location: %s", rq->url);
00103 #else
00104                 sprintf(buffer, "Location: http://%s%s", myhostname, rq->url);
00105 #endif
00106                 sendout(buffer);
00107         }
00108         if(rp->keepopen)
00109                 sendout("Connection: Keep-Alive");
00110         else
00111                 sendout("Connection: Close");
00112         if(rp->status == HTTP_STATUS_UNAUTHORIZED && rp->auth != NULL) {
00113                 sprintf(buffer, "WWW-Authenticate: Basic realm=\"%s\"", rp->auth->desc);
00114                 sendout(buffer);
00115         }
00116         if(rp->status == HTTP_STATUS_PROXY_AUTH_REQRD && proxyauth != NULL) {
00117                 sprintf(buffer, "Proxy-Authenticate: Basic realm=\"%s\"", proxyauth->desc);
00118                 sendout(buffer);
00119         }
00120         if(rp->modtime != (time_t) -1) {
00121                 sprintf(buffer, "Last-Modified: %s", httpdate(&rp->modtime));
00122                 sendout(buffer);
00123         }
00124         if(rp->size != 0) {
00125                 sprintf(buffer, "Content-Length: %lu", rp->size);
00126                 sendout(buffer);
00127         }
00128         if(rp->status == HTTP_STATUS_OK) {
00129                 sprintf(buffer, "Content-Type: %s", rp->mtype);
00130                 sendout(buffer);
00131         } else
00132                 sendout("Content-Type: text/html");
00133         if(!rp->headers)
00134                 sendout("");
00135    } else
00136         if(rp->status != HTTP_STATUS_OK)
00137                 return(0);
00138    }
00139 
00140    if(rp->status != HTTP_STATUS_OK && rp->status != HTTP_STATUS_CREATED) {
00141         sprintf(buffer, "<h2>Error %03d %s</h2>",
00142                 rp->status, rp->statusmsg);
00143         sendout(buffer);
00144         return(0);
00145    }
00146 
00147    if(rq->type == HTTP_REQUEST_TYPE_PROXY) {
00148         proxy(rq, rp);
00149         return(0);
00150    }
00151 
00152    /* send out entity body */
00153    if(rq->method == HTTP_METHOD_GET || rq->method == HTTP_METHOD_POST) {
00154         errno = 0;
00155         while(1) {
00156                 alarm(0);
00157                 signal(SIGALRM, GotAlarm);
00158                 alarm(10);
00159                 s = read(rp->fd, buffer, sizeof(buffer));
00160                 e = errno;
00161                 alarm(0);
00162                 if(s > 0) {
00163                         s2 = write(1, buffer, s);
00164                         e = errno;
00165                         if(s2 != s) break;
00166                         continue;
00167                 }
00168                 if(s == 0) break;
00169                 if(s < 0 && e != EINTR) break;
00170                 signal(SIGALRM, GotAlarm);
00171                 alarm(2);
00172                 s = read(0, buffer, 1);
00173                 e = errno;
00174                 alarm(0);
00175                 if(s < 0 && e != EINTR) break;
00176         }
00177    }
00178 
00179    close(rp->fd);
00180    rp->fd = -1;
00181    if(rp->ofd != -1)
00182         close(rp->ofd);
00183    if(rp->pid != 0 && e != 0) {
00184         kill(-rp->pid, SIGHUP);
00185         rp->pid = 0;
00186    }
00187 
00188    return(0);
00189 }

Generated on Fri Apr 14 22:56:55 2006 for minix by  doxygen 1.4.6