Annotation of embedaddon/axTLS/httpd/axhttpd.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * Copyright (c) Cameron Rich
        !             3:  * 
        !             4:  * All rights reserved.
        !             5:  * 
        !             6:  * Redistribution and use in source and binary forms, with or without 
        !             7:  * modification, are permitted provided that the following conditions are met:
        !             8:  *
        !             9:  * * Redistributions of source code must retain the above copyright notice, 
        !            10:  *   this list of conditions and the following disclaimer.
        !            11:  * * Redistributions in binary form must reproduce the above copyright notice, 
        !            12:  *   this list of conditions and the following disclaimer in the documentation 
        !            13:  *   and/or other materials provided with the distribution.
        !            14:  * * Neither the name of the axTLS project nor the names of its contributors 
        !            15:  *   may be used to endorse or promote products derived from this software 
        !            16:  *   without specific prior written permission.
        !            17:  *
        !            18:  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
        !            19:  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
        !            20:  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
        !            21:  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
        !            22:  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
        !            23:  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
        !            24:  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
        !            25:  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
        !            26:  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
        !            27:  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
        !            28:  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
        !            29:  */
        !            30: 
        !            31: #include <stdio.h>
        !            32: #include <string.h>
        !            33: #include <sys/types.h>
        !            34: #include <signal.h>
        !            35: #include <stdlib.h>
        !            36: #include <sys/stat.h>
        !            37: 
        !            38: #if !defined(WIN32)
        !            39: #include <pwd.h>
        !            40: #endif
        !            41: #include "axhttp.h"
        !            42: 
        !            43: struct serverstruct *servers;
        !            44: struct connstruct *usedconns;
        !            45: struct connstruct *freeconns;
        !            46: const char * const server_version = "axhttpd/"AXTLS_VERSION;
        !            47: static const char *webroot = CONFIG_HTTP_WEBROOT;
        !            48: 
        !            49: static void addtoservers(int sd);
        !            50: static int openlistener(char *address, int port);
        !            51: static void handlenewconnection(int listenfd, int is_ssl);
        !            52: static void addconnection(int sd, char *ip, int is_ssl);
        !            53: static void ax_chdir(void);
        !            54: 
        !            55: #if defined(CONFIG_HTTP_HAS_CGI)
        !            56: struct cgiextstruct *cgiexts;
        !            57: static void addcgiext(const char *tp);
        !            58: 
        !            59: #if !defined(WIN32)
        !            60: static void reaper(int sigtype) 
        !            61: {
        !            62:     while (wait3(NULL, WNOHANG, NULL) > 0)
        !            63:         continue;
        !            64: }
        !            65: #endif
        !            66: #endif
        !            67: 
        !            68: #ifdef CONFIG_HTTP_VERBOSE  /* should really be in debug mode or something */
        !            69: /* clean up memory for valgrind */
        !            70: static void sigint_cleanup(int sig)
        !            71: {
        !            72:     struct serverstruct *sp;
        !            73:     struct connstruct *tp;
        !            74: 
        !            75:     while (servers != NULL) 
        !            76:     {
        !            77:         if (servers->is_ssl)
        !            78:             ssl_ctx_free(servers->ssl_ctx);
        !            79: 
        !            80:         sp = servers->next;
        !            81:         free(servers);
        !            82:         servers = sp;
        !            83:     }
        !            84: 
        !            85:     while (freeconns != NULL)
        !            86:     {
        !            87:         tp = freeconns->next;
        !            88:         free(freeconns);
        !            89:         freeconns = tp;
        !            90:     }
        !            91: 
        !            92:     while (usedconns != NULL)
        !            93:     {
        !            94:         tp = usedconns->next;
        !            95:         free(usedconns);
        !            96:         usedconns = tp;
        !            97:     }
        !            98: 
        !            99: #if defined(CONFIG_HTTP_HAS_CGI)
        !           100:     while (cgiexts)
        !           101:     {
        !           102:         struct cgiextstruct *cp = cgiexts->next;
        !           103:         if (cp == NULL) /* last entry */
        !           104:             free(cgiexts->ext);
        !           105:         free(cgiexts);
        !           106:         cgiexts = cp;
        !           107:     }
        !           108: #endif
        !           109: 
        !           110:     exit(0);
        !           111: }
        !           112: 
        !           113: static void die(int sigtype) 
        !           114: {
        !           115:     exit(0);
        !           116: }
        !           117: #endif
        !           118: 
        !           119: int main(int argc, char *argv[]) 
        !           120: {
        !           121:     fd_set rfds, wfds;
        !           122:     struct connstruct *tp, *to;
        !           123:     struct serverstruct *sp;
        !           124:     int rnum, wnum, active;
        !           125:     int i = 1;
        !           126:     time_t currtime;
        !           127:     char *httpAddress = NULL;
        !           128:     int httpPort = CONFIG_HTTP_PORT;
        !           129:     char *httpsAddress = NULL;
        !           130:     int httpsPort = CONFIG_HTTP_HTTPS_PORT;
        !           131:     char *portStr;
        !           132: 
        !           133: #ifdef WIN32
        !           134:     WORD wVersionRequested = MAKEWORD(2, 2);
        !           135:     WSADATA wsaData;
        !           136:     WSAStartup(wVersionRequested,&wsaData);
        !           137: #else
        !           138:     signal(SIGPIPE, SIG_IGN);
        !           139: #if defined(CONFIG_HTTP_HAS_CGI)
        !           140:     signal(SIGCHLD, reaper);
        !           141: #endif
        !           142: #ifdef CONFIG_HTTP_VERBOSE
        !           143:     signal(SIGQUIT, die);
        !           144: #endif
        !           145: #endif
        !           146: 
        !           147: #ifdef CONFIG_HTTP_VERBOSE
        !           148:     signal(SIGTERM, die);
        !           149:     signal(SIGINT, sigint_cleanup);
        !           150: #endif
        !           151:     tdate_init();
        !           152: 
        !           153:     /* get some command-line parameters */
        !           154:     while (argv[i] != NULL)
        !           155:     {
        !           156:         if (strcmp(argv[i], "-p") == 0 && argv[i+1] != NULL)
        !           157:         {
        !           158:             if ((portStr = strchr(argv[i+1], ':')) != NULL)
        !           159:             {
        !           160:                 httpAddress = argv[i+1];
        !           161:                 *portStr = 0;
        !           162:                 httpPort = atoi(portStr + 1);
        !           163:             }
        !           164:             else
        !           165:                 httpPort = atoi(argv[i+1]);
        !           166: 
        !           167:             i += 2;
        !           168:             continue;
        !           169:         }
        !           170: 
        !           171:         if (strcmp(argv[i], "-s") == 0 && argv[i+1] != NULL)
        !           172:         {
        !           173:             if ((portStr = strchr(argv[i+1], ':')) != NULL)
        !           174:             {
        !           175:                 httpsAddress = argv[i+1];
        !           176:                 *portStr = 0;
        !           177:                 httpsPort = atoi(portStr + 1);
        !           178:             }
        !           179:             else
        !           180:                 httpsPort = atoi(argv[i+1]);
        !           181: 
        !           182:             i += 2;
        !           183:             continue;
        !           184:         }
        !           185: 
        !           186:         if (strcmp(argv[i], "-w") == 0 && argv[i+1] != NULL)
        !           187:         {
        !           188:             webroot = argv[i+1];
        !           189:             i += 2;
        !           190:             continue;
        !           191:         }
        !           192: 
        !           193:         printf("%s:\n"
        !           194:                "    [-p [address:]httpport]\n"
        !           195:                "    [-s [address:]httpsport]\n"
        !           196:                "    [-w webroot]\n", argv[0]);
        !           197:         exit(1);
        !           198:     }
        !           199: 
        !           200:     for (i = 0; i < INITIAL_CONNECTION_SLOTS; i++) 
        !           201:     {
        !           202:         tp = freeconns;
        !           203:         freeconns = (struct connstruct *)calloc(1, sizeof(struct connstruct));
        !           204:         freeconns->next = tp;
        !           205:     }
        !           206: 
        !           207:     if ((active = openlistener(httpAddress, httpPort)) == -1) 
        !           208:     {
        !           209: #ifdef CONFIG_HTTP_VERBOSE
        !           210:         fprintf(stderr, "ERR: Couldn't bind to port %d\n", httpPort);
        !           211: #endif
        !           212:         exit(1);
        !           213:     }
        !           214: 
        !           215:     addtoservers(active);
        !           216: 
        !           217:     if ((active = openlistener(httpsAddress, httpsPort)) == -1) 
        !           218:     {
        !           219: #ifdef CONFIG_HTTP_VERBOSE
        !           220:         fprintf(stderr, "ERR: Couldn't bind to port %d\n", httpsPort);
        !           221: #endif
        !           222:         exit(1);
        !           223:     }
        !           224: 
        !           225:     addtoservers(active);
        !           226:     servers->ssl_ctx = ssl_ctx_new(CONFIG_HTTP_DEFAULT_SSL_OPTIONS, 
        !           227:                                 CONFIG_HTTP_SESSION_CACHE_SIZE);
        !           228:     servers->is_ssl = 1;
        !           229: 
        !           230: #if defined(CONFIG_HTTP_HAS_CGI)
        !           231:     addcgiext(CONFIG_HTTP_CGI_EXTENSIONS);
        !           232: #endif
        !           233: 
        !           234: #if defined(CONFIG_HTTP_VERBOSE)
        !           235: #if defined(CONFIG_HTTP_HAS_CGI)
        !           236:     printf("addcgiext %s\n", CONFIG_HTTP_CGI_EXTENSIONS); 
        !           237: #endif
        !           238:     printf("%s: listening on ports %d (http) and %d (https)\n", 
        !           239:             server_version, httpPort, httpsPort);
        !           240:     TTY_FLUSH();
        !           241: #endif
        !           242: 
        !           243:     ax_chdir();
        !           244: 
        !           245: #ifdef CONFIG_HTTP_ENABLE_DIFFERENT_USER
        !           246:     {
        !           247:         struct passwd *pd = getpwnam(CONFIG_HTTP_USER);
        !           248: 
        !           249:         if (pd != NULL)
        !           250:         {
        !           251:             int res = setuid(pd->pw_uid);
        !           252:             res |= setgid(pd->pw_gid);
        !           253: 
        !           254: #if defined(CONFIG_HTTP_VERBOSE)
        !           255:             if (res == 0)
        !           256:             {
        !           257:                 printf("change to '%s' successful\n", CONFIG_HTTP_USER); 
        !           258:                 TTY_FLUSH();
        !           259:             }
        !           260: #endif
        !           261:         }
        !           262: 
        !           263:     }
        !           264: #endif
        !           265: 
        !           266: 
        !           267: #ifndef WIN32 
        !           268: #ifdef CONFIG_HTTP_IS_DAEMON
        !           269:     if (fork() > 0)  /* parent will die */
        !           270:         exit(0);
        !           271: 
        !           272:     setsid();
        !           273: #endif
        !           274: #endif
        !           275: 
        !           276:     /* main loop */
        !           277:     while (1)
        !           278:     {
        !           279:         struct timeval tv = { 10, 0 };
        !           280:         FD_ZERO(&rfds);
        !           281:         FD_ZERO(&wfds);
        !           282:         rnum = wnum = -1;
        !           283:         sp = servers;
        !           284: 
        !           285:         while (sp != NULL)  /* read each server port */
        !           286:         {
        !           287:             FD_SET(sp->sd, &rfds);
        !           288: 
        !           289:             if (sp->sd > rnum) 
        !           290:                 rnum = sp->sd;
        !           291:             sp = sp->next;
        !           292:         }
        !           293: 
        !           294:         /* Add the established sockets */
        !           295:         tp = usedconns;
        !           296:         currtime = time(NULL);
        !           297: 
        !           298:         while (tp != NULL) 
        !           299:         {
        !           300:             if (currtime > tp->timeout)     /* timed out? Kill it. */
        !           301:             {
        !           302:                 to = tp;
        !           303:                 tp = tp->next;
        !           304:                 removeconnection(to);
        !           305:                 continue;
        !           306:             }
        !           307: 
        !           308:             if (tp->state == STATE_WANT_TO_READ_HEAD) 
        !           309:             {
        !           310:                 FD_SET(tp->networkdesc, &rfds);
        !           311:                 if (tp->networkdesc > rnum) 
        !           312:                     rnum = tp->networkdesc;
        !           313:             }
        !           314: 
        !           315:             if (tp->state == STATE_WANT_TO_SEND_HEAD) 
        !           316:             {
        !           317:                 FD_SET(tp->networkdesc, &wfds);
        !           318:                 if (tp->networkdesc > wnum) 
        !           319:                     wnum = tp->networkdesc;
        !           320:             }
        !           321: 
        !           322:             if (tp->state == STATE_WANT_TO_READ_FILE) 
        !           323:             {
        !           324:                 FD_SET(tp->filedesc, &rfds);
        !           325:                 if (tp->filedesc > rnum) 
        !           326:                     rnum = tp->filedesc;
        !           327:             }
        !           328: 
        !           329:             if (tp->state == STATE_WANT_TO_SEND_FILE) 
        !           330:             {
        !           331:                 FD_SET(tp->networkdesc, &wfds);
        !           332:                 if (tp->networkdesc > wnum) 
        !           333:                     wnum = tp->networkdesc;
        !           334:             }
        !           335: 
        !           336: #if defined(CONFIG_HTTP_DIRECTORIES)
        !           337:             if (tp->state == STATE_DOING_DIR) 
        !           338:             {
        !           339:                 FD_SET(tp->networkdesc, &wfds);
        !           340:                 if (tp->networkdesc > wnum) 
        !           341:                     wnum = tp->networkdesc;
        !           342:             }
        !           343: #endif
        !           344:             tp = tp->next;
        !           345:         }
        !           346: 
        !           347:         active = select(wnum > rnum ? wnum+1 : rnum+1,
        !           348:                 rnum != -1 ? &rfds : NULL, 
        !           349:                 wnum != -1 ? &wfds : NULL,
        !           350:                 NULL, usedconns ? &tv : NULL);
        !           351: 
        !           352:         /* timeout? */
        !           353:         if (active == 0)
        !           354:             continue;
        !           355: 
        !           356:         /* New connection? */
        !           357:         sp = servers;
        !           358:         while (active > 0 && sp != NULL) 
        !           359:         {
        !           360:             if (FD_ISSET(sp->sd, &rfds)) 
        !           361:             {
        !           362:                 handlenewconnection(sp->sd, sp->is_ssl);
        !           363:                 active--;
        !           364:             }
        !           365: 
        !           366:             sp = sp->next;
        !           367:         }
        !           368: 
        !           369:         /* Handle the established sockets */
        !           370:         tp = usedconns;
        !           371: 
        !           372:         while (active > 0 && tp != NULL) 
        !           373:         {
        !           374:             to = tp;
        !           375:             tp = tp->next;
        !           376: 
        !           377:             if (to->state == STATE_WANT_TO_READ_HEAD &&
        !           378:                         FD_ISSET(to->networkdesc, &rfds)) 
        !           379:             {
        !           380:                 active--;
        !           381: #if defined(CONFIG_HTTP_HAS_CGI)
        !           382:                 if (to->post_state)
        !           383:                     read_post_data(to);
        !           384:                 else
        !           385: #endif
        !           386:                     procreadhead(to);
        !           387:             } 
        !           388: 
        !           389:             if (to->state == STATE_WANT_TO_SEND_HEAD &&
        !           390:                         FD_ISSET(to->networkdesc, &wfds)) 
        !           391:             {
        !           392:                 active--;
        !           393:                 procsendhead(to);
        !           394:             } 
        !           395: 
        !           396:             if (to->state == STATE_WANT_TO_READ_FILE && 
        !           397:                         FD_ISSET(to->filedesc, &rfds)) 
        !           398:             {
        !           399:                 active--;
        !           400:                 procreadfile(to);
        !           401:             } 
        !           402: 
        !           403:             if (to->state == STATE_WANT_TO_SEND_FILE && 
        !           404:                         FD_ISSET(to->networkdesc, &wfds)) 
        !           405:             {
        !           406:                 active--;
        !           407:                 procsendfile(to);
        !           408:             }
        !           409: 
        !           410: #if defined(CONFIG_HTTP_DIRECTORIES)
        !           411:             if (to->state == STATE_DOING_DIR &&
        !           412:                         FD_ISSET(to->networkdesc, &wfds)) 
        !           413:             {
        !           414:                 active--;
        !           415:                 procdodir(to);
        !           416:             }
        !           417: #endif
        !           418:         }
        !           419:     }
        !           420: 
        !           421:     return 0;
        !           422: }
        !           423: 
        !           424: #if defined(CONFIG_HTTP_HAS_CGI)
        !           425: static void addcgiext(const char *cgi_exts)
        !           426: {
        !           427:     char *cp = strdup(cgi_exts);
        !           428: 
        !           429:     /* extenstions are comma separated */
        !           430:     do 
        !           431:     {
        !           432:         struct cgiextstruct *ex = (struct cgiextstruct *)
        !           433:                             malloc(sizeof(struct cgiextstruct));
        !           434:         ex->ext = cp;
        !           435:         ex->next = cgiexts;
        !           436:         cgiexts = ex;
        !           437:         if ((cp = strchr(cp, ',')) != NULL)
        !           438:             *cp++ = 0;
        !           439:     } while (cp != NULL);
        !           440: }
        !           441: #endif
        !           442: 
        !           443: static void addtoservers(int sd) 
        !           444: {
        !           445:     struct serverstruct *tp = (struct serverstruct *)
        !           446:                             calloc(1, sizeof(struct serverstruct));
        !           447:     tp->next = servers;
        !           448:     tp->sd = sd;
        !           449:     servers = tp;
        !           450: }
        !           451: 
        !           452: #ifdef HAVE_IPV6
        !           453: static void handlenewconnection(int listenfd, int is_ssl) 
        !           454: {
        !           455:     struct sockaddr_in6 their_addr;
        !           456:     socklen_t tp = sizeof(their_addr);
        !           457:     char ipbuf[100];
        !           458:     int connfd = accept(listenfd, (struct sockaddr *)&their_addr, &tp);
        !           459: 
        !           460:     if (tp == sizeof(struct sockaddr_in6)) 
        !           461:         inet_ntop(AF_INET6, &their_addr.sin6_addr, ipbuf, sizeof(ipbuf));
        !           462:     else if (tp == sizeof(struct sockaddr_in)) 
        !           463:         inet_ntop(AF_INET, &(((struct sockaddr_in *)&their_addr)->sin_addr),
        !           464:                 ipbuf, sizeof(ipbuf));
        !           465:     else 
        !           466:         *ipbuf = '\0';
        !           467: 
        !           468:     if (connfd != -1) /* check for error condition */
        !           469:         addconnection(connfd, ipbuf, is_ssl);
        !           470: }
        !           471: 
        !           472: #else
        !           473: static void handlenewconnection(int listenfd, int is_ssl) 
        !           474: {
        !           475:     struct sockaddr_in their_addr;
        !           476:     socklen_t tp = sizeof(struct sockaddr_in);
        !           477:     int connfd = accept(listenfd, (struct sockaddr *)&their_addr, &tp);
        !           478:     addconnection(connfd, inet_ntoa(their_addr.sin_addr), is_ssl);
        !           479: }
        !           480: #endif
        !           481: 
        !           482: static int openlistener(char *address, int port) 
        !           483: {
        !           484:     int sd;
        !           485: #ifdef WIN32
        !           486:     char tp = 1;
        !           487: #else
        !           488:     int tp = 1;
        !           489: #endif
        !           490: #ifndef HAVE_IPV6
        !           491:     struct sockaddr_in my_addr;
        !           492: 
        !           493:     if ((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1) 
        !           494:         return -1;
        !           495: 
        !           496:     memset(&my_addr, 0, sizeof(my_addr));
        !           497:     my_addr.sin_family = AF_INET;
        !           498:     my_addr.sin_port = htons((short)port);
        !           499:     my_addr.sin_addr.s_addr = address == NULL ? 
        !           500:                         INADDR_ANY : inet_addr(address);
        !           501: #else
        !           502:     struct sockaddr_in6 my_addr;
        !           503: 
        !           504:     if ((sd = socket(AF_INET6, SOCK_STREAM, 0)) == -1) 
        !           505:         return -1;
        !           506: 
        !           507:     my_addr.sin6_family = AF_INET6;
        !           508:     my_addr.sin6_port = htons(port);
        !           509: 
        !           510:     if (address == NULL)
        !           511:         my_addr.sin6_addr = in6addr_any;
        !           512:     else 
        !           513:         inet_pton(AF_INET6, address, &my_addr.sin6_addr);
        !           514: #endif
        !           515: 
        !           516:     setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &tp, sizeof(tp));
        !           517:     if (bind(sd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1)
        !           518:     {
        !           519:         close(sd);
        !           520:         return -1;
        !           521:     }
        !           522: 
        !           523:     listen(sd, BACKLOG);
        !           524:     return sd;
        !           525: }
        !           526: 
        !           527: /* Wrapper function for strncpy() that guarantees
        !           528:    a null-terminated string. This is to avoid any possible
        !           529:    issues due to strncpy()'s behaviour.
        !           530:  */
        !           531: char *my_strncpy(char *dest, const char *src, size_t n) 
        !           532: {
        !           533:     strncpy(dest, src, n);
        !           534:     dest[n-1] = '\0';
        !           535:     return dest;
        !           536: }
        !           537: 
        !           538: int isdir(const char *tpbuf) 
        !           539: {
        !           540:     struct stat st;
        !           541:     char path[MAXREQUESTLENGTH];
        !           542:     strcpy(path, tpbuf);
        !           543: 
        !           544: #ifdef WIN32        /* win32 stat() can't handle trailing '\' */
        !           545:     if (path[strlen(path)-1] == '\\')
        !           546:         path[strlen(path)-1] = 0;
        !           547: #endif
        !           548: 
        !           549:     if (stat(path, &st) == -1) 
        !           550:         return 0;
        !           551: 
        !           552:     if ((st.st_mode & S_IFMT) == S_IFDIR) 
        !           553:         return 1;
        !           554: 
        !           555:     return 0;
        !           556: }
        !           557: 
        !           558: static void addconnection(int sd, char *ip, int is_ssl) 
        !           559: {
        !           560:     struct connstruct *tp;
        !           561: 
        !           562:     /* Get ourselves a connstruct */
        !           563:     if (freeconns == NULL) 
        !           564:         tp = (struct connstruct *)calloc(1, sizeof(struct connstruct));
        !           565:     else 
        !           566:     {
        !           567:         tp = freeconns;
        !           568:         freeconns = tp->next;
        !           569:     }
        !           570: 
        !           571:     /* Attach it to the used list */
        !           572:     tp->next = usedconns;
        !           573:     usedconns = tp;
        !           574:     tp->networkdesc = sd;
        !           575: 
        !           576:     if (is_ssl)
        !           577:         tp->ssl = ssl_server_new(servers->ssl_ctx, sd);
        !           578: 
        !           579:     tp->is_ssl = is_ssl;
        !           580:     tp->filedesc = -1;
        !           581: #if defined(CONFIG_HTTP_HAS_DIRECTORIES)
        !           582:     tp->dirp = NULL;
        !           583: #endif
        !           584:     *tp->actualfile = '\0';
        !           585:     *tp->filereq = '\0';
        !           586:     tp->state = STATE_WANT_TO_READ_HEAD;
        !           587:     tp->reqtype = TYPE_GET;
        !           588:     tp->close_when_done = 0;
        !           589:     tp->timeout = time(NULL) + CONFIG_HTTP_TIMEOUT;
        !           590: #if defined(CONFIG_HTTP_HAS_CGI)
        !           591:     strcpy(tp->remote_addr, ip);
        !           592: #endif
        !           593: }
        !           594: 
        !           595: void removeconnection(struct connstruct *cn) 
        !           596: {
        !           597:     struct connstruct *tp;
        !           598:     int shouldret = 0;
        !           599: 
        !           600:     tp = usedconns;
        !           601: 
        !           602:     if (tp == NULL || cn == NULL) 
        !           603:         shouldret = 1;
        !           604:     else if (tp == cn) 
        !           605:         usedconns = tp->next;
        !           606:     else 
        !           607:     {
        !           608:         while (tp != NULL) 
        !           609:         {
        !           610:             if (tp->next == cn) 
        !           611:             {
        !           612:                 tp->next = (tp->next)->next;
        !           613:                 shouldret = 0;
        !           614:                 break;
        !           615:             }
        !           616: 
        !           617:             tp = tp->next;
        !           618:             shouldret = 1;
        !           619:         }
        !           620:     }
        !           621: 
        !           622:     if (shouldret) 
        !           623:         return;
        !           624: 
        !           625:     /* If we did, add it to the free list */
        !           626:     cn->next = freeconns;
        !           627:     freeconns = cn;
        !           628: 
        !           629:     /* Close it all down */
        !           630:     if (cn->networkdesc != -1) 
        !           631:     {
        !           632:         if (cn->is_ssl) 
        !           633:         {
        !           634:             ssl_free(cn->ssl);
        !           635:             cn->ssl = NULL;
        !           636:         }
        !           637: 
        !           638: #ifndef WIN32
        !           639:         shutdown(cn->networkdesc, SHUT_WR);
        !           640: #endif
        !           641:         SOCKET_CLOSE(cn->networkdesc);
        !           642:     }
        !           643: 
        !           644:     if (cn->filedesc != -1) 
        !           645:         close(cn->filedesc);
        !           646: 
        !           647: #if defined(CONFIG_HTTP_HAS_DIRECTORIES)
        !           648:     if (cn->dirp != NULL) 
        !           649: #ifdef WIN32
        !           650:         FindClose(cn->dirp);
        !           651: #else
        !           652:         closedir(cn->dirp);
        !           653: #endif
        !           654: #endif
        !           655: }
        !           656: 
        !           657: /*
        !           658:  * Change directories one way or the other.
        !           659:  */
        !           660: 
        !           661: static void ax_chdir(void)
        !           662: {
        !           663:     if (chdir(webroot))
        !           664:     {
        !           665: #ifdef CONFIG_HTTP_VERBOSE
        !           666:         fprintf(stderr, "'%s' is not a directory\n", webroot);
        !           667: #endif
        !           668:         exit(1);
        !           669:     }
        !           670: }
        !           671: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>