webserver.c

00001 /*
00002  * $Id: webserver.c 5147 2007-05-08 15:36:22Z ajc $
00003  */
00012 #include "webcit.h"
00013 #include "webserver.h"
00014 
00015 #if HAVE_BACKTRACE
00016 #include <execinfo.h>
00017 #endif
00018 
00019 #ifndef HAVE_SNPRINTF
00020 int vsnprintf(char *buf, size_t max, const char *fmt, va_list argp);
00021 #endif
00022 
00023 int verbosity = 9;              
00024 int msock;                          
00025 int is_https = 0;               
00026 int follow_xff = 0;             
00027 int home_specified = 0; 
00028 extern void *context_loop(int);
00029 extern void *housekeeping_loop(void);
00030 extern pthread_mutex_t SessionListMutex;
00031 extern pthread_key_t MyConKey;
00032 
00033 char socket_dir[PATH_MAX];      
00034 static const char editor_absolut_dir[PATH_MAX]=EDITORDIR; 
00035 static char static_dir[PATH_MAX]; 
00036 static char static_local_dir[PATH_MAX]; 
00037 char  *static_dirs[]={ 
00038         (char*)static_dir,                  
00039         (char*)static_local_dir,            
00040         (char*)editor_absolut_dir           
00041 };
00042 
00048 char *static_content_dirs[] = {
00049         "static",                     
00050         "static.local",               
00051         "tiny_mce"                    
00052 };
00053 
00054 int ndirs=3;
00055 
00056 
00057 char *server_cookie = NULL; 
00059 int http_port = PORT_NUM;       
00061 char *ctdlhost = DEFAULT_HOST; 
00062 char *ctdlport = DEFAULT_PORT; 
00063 int setup_wizard = 0;          
00064 char wizard_filename[PATH_MAX];
00065 int running_as_daemon = 0;     
00075 int ig_tcp_server(char *ip_addr, int port_number, int queue_len)
00076 {
00077         struct sockaddr_in sin;
00078         int s, i;
00079 
00080         memset(&sin, 0, sizeof(sin));
00081         sin.sin_family = AF_INET;
00082         if (ip_addr == NULL) {
00083                 sin.sin_addr.s_addr = INADDR_ANY;
00084         } else {
00085                 sin.sin_addr.s_addr = inet_addr(ip_addr);
00086         }
00087 
00088         if (sin.sin_addr.s_addr == INADDR_NONE) {
00089                 sin.sin_addr.s_addr = INADDR_ANY;
00090         }
00091 
00092         if (port_number == 0) {
00093                 lprintf(1, "Cannot start: no port number specified.\n");
00094                 exit(WC_EXIT_BIND);
00095         }
00096         sin.sin_port = htons((u_short) port_number);
00097 
00098         s = socket(PF_INET, SOCK_STREAM, (getprotobyname("tcp")->p_proto));
00099         if (s < 0) {
00100                 lprintf(1, "Can't create a socket: %s\n", strerror(errno));
00101                 exit(WC_EXIT_BIND);
00102         }
00104         i = 1;
00105         setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i));
00106 
00107         if (bind(s, (struct sockaddr *) &sin, sizeof(sin)) < 0) {
00108                 lprintf(1, "Can't bind: %s\n", strerror(errno));
00109                 exit(WC_EXIT_BIND);
00110         }
00111         if (listen(s, queue_len) < 0) {
00112                 lprintf(1, "Can't listen: %s\n", strerror(errno));
00113                 exit(WC_EXIT_BIND);
00114         }
00115         return (s);
00116 }
00117 
00118 
00119 
00125 int ig_uds_server(char *sockpath, int queue_len)
00126 {
00127         struct sockaddr_un addr;
00128         int s;
00129         int i;
00130         int actual_queue_len;
00131 
00132         actual_queue_len = queue_len;
00133         if (actual_queue_len < 5) actual_queue_len = 5;
00134 
00135         i = unlink(sockpath);
00136         if (i != 0) if (errno != ENOENT) {
00137                 lprintf(1, "citserver: can't unlink %s: %s\n",
00138                         sockpath, strerror(errno));
00139                 exit(WC_EXIT_BIND);
00140         }
00141 
00142         memset(&addr, 0, sizeof(addr));
00143         addr.sun_family = AF_UNIX;
00144         safestrncpy(addr.sun_path, sockpath, sizeof addr.sun_path);
00145 
00146         s = socket(AF_UNIX, SOCK_STREAM, 0);
00147         if (s < 0) {
00148                 lprintf(1, "citserver: Can't create a socket: %s\n",
00149                         strerror(errno));
00150                 exit(WC_EXIT_BIND);
00151         }
00152 
00153         if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
00154                 lprintf(1, "citserver: Can't bind: %s\n",
00155                         strerror(errno));
00156                 exit(WC_EXIT_BIND);
00157         }
00158 
00159         if (listen(s, actual_queue_len) < 0) {
00160                 lprintf(1, "citserver: Can't listen: %s\n",
00161                         strerror(errno));
00162                 exit(WC_EXIT_BIND);
00163         }
00164 
00165         chmod(sockpath, 0777);
00166         return(s);
00167 }
00168 
00169 
00170 
00171 
00183 int client_read_to(int sock, char *buf, int bytes, int timeout)
00184 {
00185         int len, rlen;
00186         fd_set rfds;
00187         struct timeval tv;
00188         int retval;
00189 
00190 
00191 #ifdef HAVE_OPENSSL
00192         if (is_https) {
00193                 return (client_read_ssl(buf, bytes, timeout));
00194         }
00195 #endif
00196 
00197         len = 0;
00198         while (len < bytes) {
00199                 FD_ZERO(&rfds);
00200                 FD_SET(sock, &rfds);
00201                 tv.tv_sec = timeout;
00202                 tv.tv_usec = 0;
00203 
00204                 retval = select((sock) + 1, &rfds, NULL, NULL, &tv);
00205                 if (FD_ISSET(sock, &rfds) == 0) {
00206                         return (0);
00207                 }
00208 
00209                 rlen = read(sock, &buf[len], bytes - len);
00210 
00211                 if (rlen < 1) {
00212                         lprintf(2, "client_read() failed: %s\n",
00213                                 strerror(errno));
00214                         return (-1);
00215                 }
00216                 len = len + rlen;
00217         }
00218 
00219 #ifdef HTTP_TRACING
00220         write(2, "\033[32m", 5);
00221         write(2, buf, bytes);
00222         write(2, "\033[30m", 5);
00223 #endif
00224         return (1);
00225 }
00226 
00232 ssize_t client_write(const void *buf, size_t count)
00233 {
00234         char *newptr;
00235         size_t newalloc;
00236 
00237         if (WC->burst != NULL) {
00238                 if ((WC->burst_len + count) >= WC->burst_alloc) {
00239                         newalloc = (WC->burst_alloc * 2);
00240                         if ((WC->burst_len + count) >= newalloc) {
00241                                 newalloc += count;
00242                         }
00243                         newptr = realloc(WC->burst, newalloc);
00244                         if (newptr != NULL) {
00245                                 WC->burst = newptr;
00246                                 WC->burst_alloc = newalloc;
00247                         }
00248                 }
00249                 if ((WC->burst_len + count) < WC->burst_alloc) {
00250                         memcpy(&WC->burst[WC->burst_len], buf, count);
00251                         WC->burst_len += count;
00252                         return (count);
00253                 }
00254                 else {
00255                         return(-1);
00256                 }
00257         }
00258 #ifdef HAVE_OPENSSL
00259         if (is_https) {
00260                 client_write_ssl((char *) buf, count);
00261                 return (count);
00262         }
00263 #endif
00264 #ifdef HTTP_TRACING
00265         write(2, "\033[34m", 5);
00266         write(2, buf, count);
00267         write(2, "\033[30m", 5);
00268 #endif
00269         return (write(WC->http_sock, buf, count));
00270 }
00271 
00275 void begin_burst(void)
00276 {
00277         if (WC->burst != NULL) {
00278                 free(WC->burst);
00279                 WC->burst = NULL;
00280         }
00281         WC->burst_len = 0;
00282         WC->burst_alloc = 32768;
00283         WC->burst = malloc(WC->burst_alloc);
00284 }
00285 
00286 
00291 #ifdef HAVE_ZLIB
00292 #define DEF_MEM_LEVEL 8 
00293 #define OS_CODE 0x03    
00294 int ZEXPORT compress_gzip(Bytef * dest,         
00295                                                   uLongf * destLen,     
00296                                                   const Bytef * source, 
00297                                                   uLong sourceLen,      
00298                                                   int level)            
00299 {
00300         const int gz_magic[2] = { 0x1f, 0x8b }; 
00303         sprintf((char *) dest, "%c%c%c%c%c%c%c%c%c%c",
00304                 gz_magic[0], gz_magic[1], Z_DEFLATED,
00305                 0 /*flags */ , 0, 0, 0, 0 /*time */ , 0  ,
00306                 OS_CODE);
00307 
00308         /* normal deflate */
00309         z_stream stream;
00310         int err;
00311         stream.next_in = (Bytef *) source;
00312         stream.avail_in = (uInt) sourceLen;
00313         stream.next_out = dest + 10L;   // after header
00314         stream.avail_out = (uInt) * destLen;
00315         if ((uLong) stream.avail_out != *destLen)
00316                 return Z_BUF_ERROR;
00317 
00318         stream.zalloc = (alloc_func) 0;
00319         stream.zfree = (free_func) 0;
00320         stream.opaque = (voidpf) 0;
00321 
00322         err = deflateInit2(&stream, level, Z_DEFLATED, -MAX_WBITS,
00323                            DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY);
00324         if (err != Z_OK)
00325                 return err;
00326 
00327         err = deflate(&stream, Z_FINISH);
00328         if (err != Z_STREAM_END) {
00329                 deflateEnd(&stream);
00330                 return err == Z_OK ? Z_BUF_ERROR : err;
00331         }
00332         *destLen = stream.total_out + 10L;
00333 
00334         /* write CRC and Length */
00335         uLong crc = crc32(0L, source, sourceLen);
00336         int n;
00337         for (n = 0; n < 4; ++n, ++*destLen) {
00338                 dest[*destLen] = (int) (crc & 0xff);
00339                 crc >>= 8;
00340         }
00341         uLong len = stream.total_in;
00342         for (n = 0; n < 4; ++n, ++*destLen) {
00343                 dest[*destLen] = (int) (len & 0xff);
00344                 len >>= 8;
00345         }
00346         err = deflateEnd(&stream);
00347         return err;
00348 }
00349 #endif
00350 
00354 void end_burst(void)
00355 {
00356         size_t the_len;
00357         char *the_data;
00358 
00359         if (WC->burst == NULL)
00360                 return;
00361 
00362         the_len = WC->burst_len;
00363         the_data = WC->burst;
00364 
00365         WC->burst_len = 0;
00366         WC->burst_alloc = 0;
00367         WC->burst = NULL;
00368 
00369 #ifdef HAVE_ZLIB
00370         /* Handle gzip compression */
00371         if (WC->gzip_ok) {
00372                 char *compressed_data = NULL;
00373                 uLongf compressed_len;
00374 
00375                 compressed_len = (uLongf) ((the_len * 101) / 100) + 100;
00376                 compressed_data = malloc(compressed_len);
00377 
00378                 if (compress_gzip((Bytef *) compressed_data,
00379                                   &compressed_len,
00380                                   (Bytef *) the_data,
00381                                   (uLongf) the_len, Z_BEST_SPEED) == Z_OK) {
00382                         wprintf("Content-encoding: gzip\r\n");
00383                         free(the_data);
00384                         the_data = compressed_data;
00385                         the_len = compressed_len;
00386                 } else {
00387                         free(compressed_data);
00388                 }
00389         }
00390 #endif                          /* HAVE_ZLIB */
00391 
00392         wprintf("Content-length: %d\r\n\r\n", the_len);
00393         client_write(the_data, the_len);
00394         free(the_data);
00395         return;
00396 }
00397 
00398 
00399 
00408 int client_read(int sock, char *buf, int bytes)
00409 {
00410         return (client_read_to(sock, buf, bytes, SLEEPING));
00411 }
00412 
00413 
00423 int client_getln(int sock, char *buf, int bufsiz)
00424 {
00425         int i, retval;
00426 
00428         for (i = 0;; i++) {
00429                 retval = client_read(sock, &buf[i], 1);
00430                 if (retval != 1 || buf[i] == '\n' || i == (bufsiz-1))
00431                         break;
00432                 if ( (!isspace(buf[i])) && (!isprint(buf[i])) ) {
00434                         return(-1);
00435                 }
00436         }
00437 
00439         if (i == (bufsiz-1))
00440                 while (buf[i] != '\n' && retval == 1)
00441                         retval = client_read(sock, &buf[i], 1);
00442 
00446         buf[i] = 0;
00447         while ((strlen(buf) > 0) && (!isprint(buf[strlen(buf) - 1]))) {
00448                 buf[strlen(buf) - 1] = 0;
00449         }
00450         return (retval);
00451 }
00452 
00457 pid_t current_child;
00458 void graceful_shutdown(int signum) {
00459         kill(current_child, signum);
00460         exit(0);
00461 }
00462 
00463 
00470 /*
00471  * Start running as a daemon.
00472  */
00473 void start_daemon(char *pid_file) 
00474 {
00475         int status = 0;
00476         pid_t child = 0;
00477         FILE *fp;
00478         int do_restart = 0;
00479 
00480         current_child = 0;
00481 
00482         /* Close stdin/stdout/stderr and replace them with /dev/null.
00483          * We don't just call close() because we don't want these fd's
00484          * to be reused for other files.
00485          */
00486         chdir("/");
00487 
00488         signal(SIGHUP, SIG_IGN);
00489         signal(SIGINT, SIG_IGN);
00490         signal(SIGQUIT, SIG_IGN);
00491 
00492         child = fork();
00493         if (child != 0) {
00494                 exit(0);
00495         }
00496 
00497         setsid();
00498         umask(0);
00499         freopen("/dev/null", "r", stdin);
00500         freopen("/dev/null", "w", stdout);
00501         freopen("/dev/null", "w", stderr);
00502 
00503         do {
00504                 current_child = fork();
00505 
00506         
00507                 if (current_child < 0) {
00508                         perror("fork");
00509                         exit(errno);
00510                 }
00511         
00512                 else if (current_child == 0) {
00513                         signal(SIGTERM, graceful_shutdown);
00514                         return; /* continue starting citadel. */
00515                 }
00516         
00517                 else {
00518                         signal(SIGTERM, SIG_IGN);
00519                         if (pid_file) {
00520                                 fp = fopen(pid_file, "w");
00521                                 if (fp != NULL) {
00522                                         fprintf(fp, "%d\n", current_child);
00523                                         fclose(fp);
00524                                 }
00525                         }
00526                         waitpid(current_child, &status, 0);
00527                 }
00528 
00529                 do_restart = 0;
00530 
00531                 /* Did the main process exit with an actual exit code? */
00532                 if (WIFEXITED(status)) {
00533 
00534                         /* Exit code 0 means the watcher should exit */
00535                         if (WEXITSTATUS(status) == 0) {
00536                                 do_restart = 0;
00537                         }
00538 
00539                         /* Exit code 101-109 means the watcher should exit */
00540                         else if ( (WEXITSTATUS(status) >= 101) && (WEXITSTATUS(status) <= 109) ) {
00541                                 do_restart = 0;
00542                         }
00543 
00544                         /* Any other exit code means we should restart. */
00545                         else {
00546                                 do_restart = 1;
00547                         }
00548                 }
00549 
00550                 /* Any other type of termination (signals, etc.) should also restart. */
00551                 else {
00552                         do_restart = 1;
00553                 }
00554 
00555         } while (do_restart);
00556 
00557         if (pid_file) {
00558                 unlink(pid_file);
00559         }
00560         exit(WEXITSTATUS(status));
00561 }
00562 
00566 void spawn_another_worker_thread()
00567 {
00568         pthread_t SessThread;   
00569         pthread_attr_t attr;    
00570         int ret;
00571 
00572         lprintf(3, "Creating a new thread\n");
00573 
00575         pthread_attr_init(&attr);
00576         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
00577 
00583         if ((ret = pthread_attr_setstacksize(&attr, 1024 * 1024))) {
00584                 lprintf(1, "pthread_attr_setstacksize: %s\n",
00585                         strerror(ret));
00586                 pthread_attr_destroy(&attr);
00587         }
00588 
00590         if (pthread_create(&SessThread, &attr,
00591                            (void *(*)(void *)) worker_entry, NULL)
00592             != 0) {
00593                 lprintf(1, "Can't create thread: %s\n", strerror(errno));
00594         }
00595 
00597         pthread_attr_destroy(&attr);
00598 }
00599 
00605 int main(int argc, char **argv)
00606 {
00607         pthread_t SessThread;   
00608         pthread_attr_t attr;    
00609         int a, i;                       
00610         char tracefile[PATH_MAX];
00611         char ip_addr[256];
00612         char dirbuffer[PATH_MAX]="";
00613         int relh=0;
00614         int home=0;
00615         int home_specified=0;
00616         char relhome[PATH_MAX]="";
00617         char webcitdir[PATH_MAX] = DATADIR;
00618         char *pidfile = NULL;
00619         char *hdir;
00620         const char *basedir;
00621 #ifdef ENABLE_NLS
00622         char *locale = NULL;
00623         char *mo = NULL;
00624 #endif /* ENABLE_NLS */
00625         char uds_listen_path[PATH_MAX]; 
00627         strcpy(uds_listen_path, "");
00628 
00630 #ifdef HAVE_OPENSSL
00631         while ((a = getopt(argc, argv, "h:i:p:t:x:dD:cfs")) != EOF)
00632 #else
00633         while ((a = getopt(argc, argv, "h:i:p:t:x:dD:cf")) != EOF)
00634 #endif
00635                 switch (a) {
00636                 case 'h':
00637                         hdir = strdup(optarg);
00638                         relh=hdir[0]!='/';
00639                         if (!relh) safestrncpy(webcitdir, hdir,
00640                                                                    sizeof webcitdir);
00641                         else
00642                                 safestrncpy(relhome, relhome,
00643                                                         sizeof relhome);
00644                         /* free(hdir); TODO: SHOULD WE DO THIS? */
00645                         home_specified = 1;
00646                         home=1;
00647                         break;
00648                 case 'd':
00649                         running_as_daemon = 1;
00650                         break;
00651                 case 'D':
00652                         pidfile = strdup(optarg);
00653                         running_as_daemon = 1;
00654                         break;
00655                 case 'i':
00656                         safestrncpy(ip_addr, optarg, sizeof ip_addr);
00657                         break;
00658                 case 'p':
00659                         http_port = atoi(optarg);
00660                         if (http_port == 0) {
00661                                 safestrncpy(uds_listen_path, optarg, sizeof uds_listen_path);
00662                         }
00663                         break;
00664                 case 't':
00665                         safestrncpy(tracefile, optarg, sizeof tracefile);
00666                         freopen(tracefile, "w", stdout);
00667                         freopen(tracefile, "w", stderr);
00668                         freopen(tracefile, "r", stdin);
00669                         break;
00670                 case 'x':
00671                         verbosity = atoi(optarg);
00672                         break;
00673                 case 'f':
00674                         follow_xff = 1;
00675                         break;
00676                 case 'c':
00677                         server_cookie = malloc(256);
00678                         if (server_cookie != NULL) {
00679                                 safestrncpy(server_cookie,
00680                                        "Set-cookie: wcserver=",
00681                                         256);
00682                                 if (gethostname
00683                                     (&server_cookie[strlen(server_cookie)],
00684                                      200) != 0) {
00685                                         lprintf(2, "gethostname: %s\n",
00686                                                 strerror(errno));
00687                                         free(server_cookie);
00688                                 }
00689                         }
00690                         break;
00691                 case 's':
00692                         is_https = 1;
00693                         break;
00694                 default:
00695                         fprintf(stderr, "usage: webserver "
00696                                 "[-i ip_addr] [-p http_port] "
00697                                 "[-t tracefile] [-c] [-f] "
00698                                 "[-d] "
00699 #ifdef HAVE_OPENSSL
00700                                 "[-s] "
00701 #endif
00702                                 "[remotehost [remoteport]]\n");
00703                         return 1;
00704                 }
00705 
00706         if (optind < argc) {
00707                 ctdlhost = argv[optind];
00708                 if (++optind < argc)
00709                         ctdlport = argv[optind];
00710         }
00711 
00712         /* daemonize, if we were asked to */
00713         if (running_as_daemon) {
00714                 start_daemon(pidfile);
00715         }
00716 
00718         lprintf(1, SERVER "\n");
00719         lprintf(1, "Copyright (C) 1996-2007 by the Citadel development team.\n"
00720                 "This software is distributed under the terms of the "
00721                 "GNU General Public License.\n\n"
00722         );
00723 
00724 
00726 #ifdef ENABLE_NLS
00727         initialize_locales();
00728         locale = setlocale(LC_ALL, "");
00729         mo = malloc(strlen(webcitdir) + 20);
00730         lprintf(9, "Message catalog directory: %s\n", bindtextdomain("webcit", LOCALEDIR"/locale"));
00731         free(mo);
00732         lprintf(9, "Text domain: %s\n", textdomain("webcit"));
00733         lprintf(9, "Text domain Charset: %s\n", bind_textdomain_codeset("webcit","UTF8"));
00734 #endif
00735 
00736 
00737         /* calculate all our path on a central place */
00738     /* where to keep our config */
00739         
00740 #define COMPUTE_DIRECTORY(SUBDIR) memcpy(dirbuffer,SUBDIR, sizeof dirbuffer);\
00741         snprintf(SUBDIR,sizeof SUBDIR,  "%s%s%s%s%s%s%s", \
00742                          (home&!relh)?webcitdir:basedir, \
00743              ((basedir!=webcitdir)&(home&!relh))?basedir:"/", \
00744              ((basedir!=webcitdir)&(home&!relh))?"/":"", \
00745                          relhome, \
00746              (relhome[0]!='\0')?"/":"",\
00747                          dirbuffer,\
00748                          (dirbuffer[0]!='\0')?"/":"");
00749         basedir=RUNDIR;
00750         COMPUTE_DIRECTORY(socket_dir);
00751         basedir=DATADIR "/static";
00752         COMPUTE_DIRECTORY(static_dir);
00753         basedir=DATADIR "/static.local";
00754         COMPUTE_DIRECTORY(static_local_dir);
00756         lprintf(9, "Changing directory to %s\n", socket_dir);
00757         if (chdir(webcitdir) != 0) {
00758                 perror("chdir");
00759         }
00760         initialize_viewdefs();
00761         initialize_axdefs();
00762 
00768         if (pthread_key_create(&MyConKey, NULL) != 0) {
00769                 lprintf(1, "Can't create TSD key: %s\n", strerror(errno));
00770         }
00771 
00778 #ifdef HAVE_OPENSSL
00779         if (pthread_key_create(&ThreadSSL, NULL) != 0) {
00780                 lprintf(1, "Can't create TSD key: %s\n", strerror(errno));
00781         }
00782 #endif
00783 
00790         if (strlen(uds_listen_path) > 0) {
00791                 lprintf(2, "Attempting to create listener socket at %s...\n", uds_listen_path);
00792                 msock = ig_uds_server(uds_listen_path, LISTEN_QUEUE_LENGTH);
00793         }
00794         else {
00795                 lprintf(2, "Attempting to bind to port %d...\n", http_port);
00796                 msock = ig_tcp_server(ip_addr, http_port, LISTEN_QUEUE_LENGTH);
00797         }
00798 
00799         lprintf(2, "Listening on socket %d\n", msock);
00800         signal(SIGPIPE, SIG_IGN);
00801 
00802         pthread_mutex_init(&SessionListMutex, NULL);
00803 
00807         pthread_attr_init(&attr);
00808         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
00809         pthread_create(&SessThread, &attr,
00810                        (void *(*)(void *)) housekeeping_loop, NULL);
00811 
00812 
00816 #ifdef HAVE_OPENSSL
00817         if (is_https) {
00818                 init_ssl();
00819         }
00820 #endif
00821 
00823         for (i = 0; i < (MIN_WORKER_THREADS); ++i) {
00824                 spawn_another_worker_thread();
00825         }
00826 
00827         /* now the original thread becomes another worker */
00828         worker_entry();
00829         return 0;
00830 }
00831 
00832 
00836 void worker_entry(void)
00837 {
00838         int ssock;
00839         int i = 0;
00840         int time_to_die = 0;
00841         int fail_this_transaction = 0;
00842 
00843         do {
00845                 fail_this_transaction = 0;
00846                 ssock = accept(msock, NULL, 0);
00847                 if (ssock < 0) {
00848                         lprintf(2, "accept() failed: %s\n",
00849                                 strerror(errno));
00850                 } else {
00852                         i = 1;
00853                         setsockopt(ssock, SOL_SOCKET, SO_REUSEADDR,
00854                                    &i, sizeof(i));
00855 
00857 #ifdef HAVE_OPENSSL
00858                         if (is_https) {
00859                                 if (starttls(ssock) != 0) {
00860                                         fail_this_transaction = 1;
00861                                         close(ssock);
00862                                 }
00863                         }
00864 #endif
00865 
00866                         if (fail_this_transaction == 0) {
00867 
00869                                 context_loop(ssock);
00870 
00872 #ifdef HAVE_OPENSSL
00873                                 if (is_https) {
00874                                         endtls();
00875                                 }
00876 #endif
00877 
00879                                 lingering_close(ssock);
00880                         }
00881 
00882                 }
00883 
00884         } while (!time_to_die);
00885 
00886         pthread_exit(NULL);
00887 }
00888 
00896 int lprintf(int loglevel, const char *format, ...)
00897 {
00898         va_list ap;
00899 
00900         if (loglevel <= verbosity) {
00901                 va_start(ap, format);
00902                 vfprintf(stderr, format, ap);
00903                 va_end(ap);
00904                 fflush(stderr);
00905         }
00906         return 1;
00907 }
00908 
00909 
00913 void wc_backtrace(void)
00914 {
00915 #ifdef HAVE_BACKTRACE
00916         void *stack_frames[50];
00917         size_t size, i;
00918         char **strings;
00919 
00920 
00921         size = backtrace(stack_frames, sizeof(stack_frames) / sizeof(void*));
00922         strings = backtrace_symbols(stack_frames, size);
00923         for (i = 0; i < size; i++) {
00924                 if (strings != NULL)
00925                         lprintf(1, "%s\n", strings[i]);
00926                 else
00927                         lprintf(1, "%p\n", stack_frames[i]);
00928         }
00929         free(strings);
00930 #endif
00931 }
00932 

Generated on Wed Jun 20 23:13:11 2007 for webcit by  doxygen 1.5.2