Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  1 #include "config.h"
  2 
  3 #include <stdio.h>
  4 #include <stdlib.h>
  5 #include <string.h>
  6 #include <unistd.h>
  7 #include <fcntl.h>
  8 #include <errno.h>
  9 #include <syslog.h>
 10 #include <sys/time.h>
 11 #include <sys/types.h>
 12 #include <sys/socket.h>
 13 #include <netinet/in.h>
 14 
 15 #include "httpd.h"
 16 
 17 /* ---------------------------------------------------------------------- */
 18 
 19 void
 20 read_request(struct REQUEST *req, int pipelined)
 21 {
 22     int             rc;
 23     char            *h;
 24 
 25  restart:
 26     rc = read(req->fd, req->hreq + req->hdata, MAX_HEADER - req->hdata);
 27     switch (rc) {
 28     case -1:
 29         if (errno == EAGAIN) {
 30             if (pipelined)
 31                 break; /* check if there is already a full request */
 32             else
 33                 return;
 34         }
 35         if (errno == EINTR)
 36             goto restart;
 37         xperror(LOG_INFO,"read",req->peerhost);
 38         /* fall through */
 39     case 0:
 40         req->state = STATE_CLOSE;
 41         return;
 42     default:
 43         req->hdata += rc;
 44         req->hreq[req->hdata] = 0;
 45     }
 46 
 47     /* check if this looks like a http request after
 48        the first few bytes... */
 49     if (req->hdata < 5)
 50         return;
 51     if (strncmp(req->hreq,"GET ",4)  != 0  &&
 52         strncmp(req->hreq,"PUT ",4)  != 0  &&
 53         strncmp(req->hreq,"HEAD ",5) != 0  &&
 54         strncmp(req->hreq,"POST ",5) != 0) {
 55         mkerror(req,400,0);
 56         return;
 57     }
 58     
 59     /* header complete ?? */
 60     if (NULL != (h = strstr(req->hreq,"\r\n\r\n")) ||
 61         NULL != (h = strstr(req->hreq,"\n\n"))) {
 62         if (*h == '\r') {
 63             h += 4;
 64             *(h-2) = 0;
 65         } else {
 66             h += 2;
 67             *(h-1) = 0;
 68         }
 69         req->lreq  = h - req->hreq;
 70         req->state = STATE_PARSE_HEADER;
 71         return;
 72     }
 73 
 74     if (req->hdata == MAX_HEADER) {
 75         /* oops: buffer full, but found no complete request ... */
 76         mkerror(req,400,0);
 77         return;
 78     }
 79     return;
 80 }
 81 
 82 /* ---------------------------------------------------------------------- */
 83 
 84 static int
 85 unhex(unsigned char c)
 86 {
 87     if (c < '@')
 88         return c - '';
 89     return (c & 0x0f) + 9;
 90 }
 91 
 92 static void
 93 unquote(unsigned char *dst, unsigned char *src)
 94 {
 95     int i,j,q,n=strlen(src);
 96 
 97     q=0;
 98     for (i=0, j=0; i<n; i++, j++) {
 99         if (src[i] == '?')
100             q = 1;
101         if (q && src[i] == '+') {
102             dst[j] = ' ';
103         } else if (src[i] == '%') {
104             dst[j] = (unhex(src[i+1]) << 4) | unhex(src[i+2]);
105             i += 2;
106         } else {
107             dst[j] = src[i];
108         }
109     }
110     dst[j] = 0;
111 }
112 
113 void
114 parse_request(struct REQUEST *req)
115 {
116     char filename[2048], proto[5], *h;
117     int  port;
118     
119     if (debug > 2)
120         fprintf(stderr,"%s\n",req->hreq);
121 
122     /* parse request. Hehe, scanf is powerfull :-) */
123     if (4 != sscanf(req->hreq, "%4[A-Z] %255[^ \t\r\n] HTTP/%d.%d",
124                     req->type,filename,&(req->major),&(req->minor))) {
125         mkerror(req,400,0);
126         return;
127     }
128     if (filename[0] == '/') {
129         strcpy(req->uri,filename);
130     } else {
131         port = 0;
132         *proto = 0;
133         if (4 != sscanf(filename,"%4[a-zA-Z]://%64[a-zA-Z0-9.-]:%d%255[^ \t\r\n]",
134                         proto,req->hostname,&port,req->uri) &&
135             3 != sscanf(filename,"%4[a-zA-Z]://%64[a-zA-Z0-9.-]%255[^ \t\r\n]",
136                         proto,req->hostname,req->uri)) {
137             mkerror(req,400,0);
138             return;
139         }
140         if (*proto != 0 && 0 != strcasecmp(proto,"http")) {
141             mkerror(req,400,0);
142             return;
143         }
144     }
145 
146     unquote(req->path,req->uri);    
147     if (debug)
148         fprintf(stderr,"%03d: %s \"%s\" HTTP/%d.%d\n",
149                 req->fd, req->type, req->path, req->major, req->minor);
150 
151     if (0 != strcmp(req->type,"GET") &&
152         0 != strcmp(req->type,"HEAD")) {
153         mkerror(req,501,0);
154         return;
155     }
156 
157     if (0 == strcmp(req->type,"HEAD")) {
158         req->head_only = 1;
159     }
160 
161     /* checks */
162     if (req->path[0] != '/') {
163         mkerror(req,400,0);
164         return;
165     }
166 
167     /* parse header lines */
168     req->keep_alive = req->minor;
169     for (h = req->hreq; h - req->hreq < req->lreq;) {
170         h = strchr(h,'\n');
171         if (NULL == h)
172             break;
173         h++;
174 
175         if (0 == strncasecmp(h,"Connection: ",12)) {
176             req->keep_alive = (0 == strncasecmp(h+12,"Keep-Alive",10));
177 
178         } else if (0 == strncasecmp(h,"Host: ",6)) {
179             sscanf(h+6,"%64[a-zA-Z0-9.-]",req->hostname);
180         }
181     }
182 
183     /* make sure we have a hostname */
184     if (req->hostname[0] == '\0' || canonicalhost)
185         strncpy(req->hostname,server_host,64);
186 
187     /* lowercase hostname */
188     for (h = req->hostname; *h != 0; h++) {
189         if (*h < 'A' || *h > 'Z')
190             continue;
191         *h += 32;
192     }
193 
194     /* handle request (more to come) */
195     buildpage(req);
196     return;
197 }
198 
  This page was automatically generated by the LXR engine.