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 <errno.h>
  8 #include <signal.h>
  9 #include <syslog.h>
 10 #include <fcntl.h>
 11 #include <pwd.h>
 12 #include <grp.h>
 13 #include <time.h>
 14 #include <sys/ioctl.h>
 15 #include <sys/time.h>
 16 #include <sys/types.h>
 17 #include <sys/wait.h>
 18 #include <sys/signal.h>
 19 #include <sys/utsname.h>
 20 #include <sys/socket.h>
 21 #include <sys/un.h>
 22 #include <netinet/in.h>
 23 #include <arpa/inet.h>
 24 #include <netdb.h>
 25 #ifdef __linux__
 26 # include "videodev.h"
 27 #endif
 28 
 29 #include "httpd.h"
 30 #include "devices.h"
 31 #include "vbi-data.h"
 32 
 33 /* ---------------------------------------------------------------------- */
 34 /* public variables - server configuration                                */
 35 
 36 char    *server_name   = "alevtd/2.0";
 37 
 38 int     debug          = 0;
 39 int     dontdetach     = 0;
 40 int     timeout        = 60;
 41 int     keepalive_time = 5;
 42 int     tcp_port       = 0;
 43 int     ascii_art      = 0;
 44 char    *listen_ip     = NULL;
 45 char    *listen_port   = "5654";
 46 int     canonicalhost  = 0;
 47 char    server_host[256];
 48 char    user[17];
 49 char    group[17];
 50 char    *logfile       = NULL;
 51 FILE    *logfd         = NULL;
 52 int     flushlog       = 0;
 53 int     usesyslog      = 0;
 54 int     have_tty       = 1;
 55 int     max_conn       = 32;
 56 int     cachereset     = 0;
 57 
 58 time_t  now,start;
 59 int     slisten;
 60 
 61 struct vbi_state *vbi;
 62 
 63 /* ---------------------------------------------------------------------- */
 64 
 65 static int termsig,got_sighup,got_sigusr1;
 66 
 67 static void catchsig(int sig)
 68 {
 69     if (SIGTERM == sig || SIGINT == sig)
 70         termsig = sig;
 71     if (SIGHUP == sig)
 72         got_sighup = 1;
 73     if (SIGUSR1 == sig)
 74         got_sigusr1 = 1;
 75 }
 76 
 77 /* ---------------------------------------------------------------------- */
 78 
 79 static void
 80 usage(char *name)
 81 {
 82     char           *h;
 83     struct passwd  *pw;
 84     struct group   *gr;
 85 
 86     h = strrchr(name,'/');
 87     fprintf(stderr,
 88             "alevt http daemon.\n"
 89             "\n"
 90             "usage: %s [ options ]\n"
 91             "\n"
 92             "Options:\n"
 93             "  -h       print this text\n"
 94             "  -v dev   vbi device                          [%s]\n"
 95             "  -d       enable debug output                 [%s]\n"
 96             "  -F       do not fork into background         [%s]\n"
 97             "  -s       enable syslog (start/stop/errors)   [%s]\n"
 98             "  -t sec   set network timeout                 [%i]\n"
 99             "  -c n     set max. allowed connections        [%i]\n"
100             "  -p port  use tcp-port >port<                 [%s]\n"
101             "  -n host  server hostname is >host<           [%s]\n"
102             "  -N host  same as above + UseCanonicalName\n"
103             "  -i ip    bind to IP-address >ip<             [%s]\n"
104             "  -l log   write access log to file >log<      [%s]\n"
105             "  -L log   same as above + flush every line\n"
106 #if 0
107             "  -r       poll tv frequency and clear cache\n"
108             "           on station changes                  [%s]\n"
109             "  -a       use ascii art for block graphics    [%s]\n"
110 #endif
111             "",
112             h ? h+1 : name,
113             ng_dev.vbi,
114             debug     ?  "on" : "off",
115             dontdetach ?  "on" : "off",
116             usesyslog ?  "on" : "off",
117             timeout, max_conn,
118             listen_port,
119             server_host,
120             listen_ip ? listen_ip : "any",
121             logfile ? logfile : "none");
122 #if 0
123             logfile ? logfile : "none",
124             cachereset ? "on" : "off",
125             ascii_art  ? "on" : "off");
126 #endif
127     if (getuid() == 0) {
128         pw = getpwuid(0);
129         gr = getgrgid(getgid());
130         fprintf(stderr,
131                 "  -u user  run as user >user<                  [%s]\n"
132                 "  -g group run as group >group<                [%s]\n",
133                 pw ? pw->pw_name : "???",
134                 gr ? gr->gr_name : "???");
135     }
136     exit(1);
137 }
138 
139 static void
140 fix_ug(void)
141 {
142     struct passwd  *pw = NULL;
143     struct group   *gr = NULL;
144     
145     /* root is allowed to use any uid/gid,
146      * others will get their real uid/gid */
147     if (0 == getuid() && strlen(user) > 0) {
148         if (NULL == (pw = getpwnam(user)))
149             pw = getpwuid(atoi(user));
150     } else {
151         pw = getpwuid(getuid());
152     }
153     if (0 == getuid() && strlen(group) > 0) {
154         if (NULL == (gr = getgrnam(group)))
155             gr = getgrgid(atoi(group));
156     } else {
157         gr = getgrgid(getgid());
158     }
159 
160     if (NULL == pw) {
161         xerror(LOG_ERR,"user unknown",NULL);
162         exit(1);
163     }
164     if (NULL == gr) {
165         xerror(LOG_ERR,"group unknown",NULL);
166         exit(1);
167     }
168 
169     /* set group */
170     if (getegid() != gr->gr_gid || getgid() != gr->gr_gid)
171         setgid(gr->gr_gid);
172     if (getegid() != gr->gr_gid || getgid() != gr->gr_gid) {
173         xerror(LOG_ERR,"setgid failed",NULL);
174         exit(1);
175     }
176     strncpy(group,gr->gr_name,16);
177 
178     /* set user */
179     if (geteuid() != pw->pw_uid || getuid() != pw->pw_uid)
180         setuid(pw->pw_uid);
181     if (geteuid() != pw->pw_uid || getuid() != pw->pw_uid) {
182         xerror(LOG_ERR,"setuid failed",NULL);
183         exit(1);
184     }
185     strncpy(user,pw->pw_name,16);
186 }
187 
188 /* ---------------------------------------------------------------------- */
189 
190 static void
191 access_log(struct REQUEST *req, time_t now)
192 {
193     char timestamp[32];
194 
195     /* common log format: host ident authuser date request status bytes */
196     strftime(timestamp,31,"[%d/%b/%Y:%H:%M:%S +0000]",gmtime(&now));
197     if (0 == req->status)
198         req->status = 400; /* bad request */
199     if (400 == req->status) {
200         fprintf(logfd,"%s - - %s \"-\" 400 %d\n",
201                 req->peerhost,
202                 timestamp,
203                 req->bc);
204     } else {
205         fprintf(logfd,"%s - - %s \"%s %s HTTP/%d.%d\" %d %d\n",
206                 req->peerhost,
207                 timestamp,
208                 req->type,
209                 req->uri,
210                 req->major,
211                 req->minor,
212                 req->status,
213                 req->bc);
214     }
215     if (flushlog)
216         fflush(logfd);
217 }
218 
219 /*
220  * loglevel usage
221  *   ERR    : fatal errors (which are followed by exit(1))
222  *   WARNING: this should'nt happen error (oom, ...)
223  *   NOTICE : start/stop of the daemon
224  *   INFO   : "normal" errors (canceled downloads, timeouts,
225  *            stuff what happens all the time)
226  */
227 
228 static void
229 syslog_init(void)
230 {
231     openlog("alevtd",LOG_PID, LOG_DAEMON);
232 }
233 
234 static void
235 syslog_start(void)
236 {
237     syslog(LOG_NOTICE,
238            "started (listen on %s:%d, user=%s, group=%s)\n",
239            listen_ip,tcp_port,user,group);
240 }
241 
242 static void
243 syslog_stop(void)
244 {
245     if (termsig)
246         syslog(LOG_NOTICE,"stopped on signal %d\n",termsig);
247     else
248         syslog(LOG_NOTICE,"stopped\n");
249     closelog();
250 }
251 
252 void
253 xperror(int loglevel, char *txt, char *peerhost)
254 {
255     if (LOG_INFO == loglevel && usesyslog < 2 && !debug)
256         return;
257     if (have_tty) {
258         if (NULL == peerhost)
259             perror(txt);
260         else
261             fprintf(stderr,"%s: %s (peer=%s)\n",txt,strerror(errno),
262                     peerhost);
263     }
264     if (usesyslog) {
265         if (NULL == peerhost)
266             syslog(loglevel,"%s: %s\n",txt,strerror(errno));
267         else
268             syslog(loglevel,"%s: %s (peer=%s)\n",txt,strerror(errno),
269                    peerhost);
270     }
271 }
272 
273 void
274 xerror(int loglevel, char *txt, char *peerhost)
275 {
276     if (LOG_INFO == loglevel && usesyslog < 2 && !debug)
277         return;
278     if (have_tty) {
279         if (NULL == peerhost)
280             fprintf(stderr,"%s\n",txt);
281         else
282             fprintf(stderr,"%s (peer=%s)\n",txt,peerhost);
283     }
284     if (usesyslog) {
285         if (NULL == peerhost)
286             syslog(loglevel,"%s\n",txt);
287         else
288             syslog(loglevel,"%s (peer=%s)\n",txt,peerhost);
289     }   
290 }
291 
292 static void
293 dummy_handler(vbi_event *ev, void *unused)
294 {
295     return;
296 }
297 
298 /* ---------------------------------------------------------------------- */
299 /* main loop                                                              */
300 
301 static void*
302 mainloop(void)
303 {
304     struct REQUEST *conns = NULL;
305     int curr_conn = 0;
306 
307     struct REQUEST      *req,*prev,*tmp;
308     struct timeval      tv;
309     int                 max,length;
310     fd_set              rd,wr;
311 
312     for (;!termsig;) {
313         if (got_sighup) {
314             if (NULL != logfile && 0 != strcmp(logfile,"-")) {
315                 if (debug)
316                     fprintf(stderr,"got SIGHUP, reopen logfile %s\n",logfile);
317                 if (logfd)
318                     fclose(logfd);
319                 if (NULL == (logfd = fopen(logfile,"a")))
320                     xperror(LOG_WARNING,"reopen access log",NULL);
321             }
322             got_sighup = 0;
323         }
324 #if 0
325         if (got_sigusr1) {
326             if (debug)
327                 fprintf(stderr,"got SIGUSR1, reset cached vbi pages\n");
328             vbi->cache->op->reset(vbi->cache);
329             got_sigusr1 = 0;
330         }
331 #endif
332 
333         FD_ZERO(&rd);
334         FD_ZERO(&wr);
335         FD_SET(vbi->fd,&rd);
336         max = vbi->fd;
337         /* add listening socket */
338         if (curr_conn < max_conn) {
339             FD_SET(slisten,&rd);
340             max = slisten;
341         }
342         /* add connection sockets */
343         for (req = conns; req != NULL; req = req->next) {
344             switch (req->state) {
345             case STATE_KEEPALIVE:
346             case STATE_READ_HEADER:
347                 FD_SET(req->fd,&rd);
348                 if (req->fd > max)
349                     max = req->fd;
350                 break;
351             case STATE_WRITE_HEADER:
352             case STATE_WRITE_BODY:
353                 FD_SET(req->fd,&wr);
354                 if (req->fd > max)
355                     max = req->fd;
356                 break;
357             }
358         }
359         /* go! */
360         tv.tv_sec  = keepalive_time;
361         tv.tv_usec = 0;
362         if (-1 == select(max+1,&rd,&wr,NULL,(curr_conn > 0) ? &tv : NULL)) {
363             if (debug)
364                 perror("select");
365             continue;
366         }
367         now = time(NULL);
368 
369         /* vbi data? */
370         if (FD_ISSET(vbi->fd,&rd)) {
371 #if 0 /* def __linux__ */
372             if (cachereset) {
373                 ioctl(vbi->fd, VIDIOCGFREQ, &freq);
374                 if (lastfreq != freq) {
375                     lastfreq = freq;
376                     vbi->cache->op->reset( vbi->cache) ;
377                     if (debug)
378                         fprintf(stderr, "frequency change: cache cleared.\n");
379                 }
380             }
381 #endif
382             vbi_hasdata(vbi);
383         }
384 
385         /* new connection ? */
386         if (FD_ISSET(slisten,&rd)) {
387             req = malloc(sizeof(struct REQUEST));
388             if (NULL == req) {
389                 /* oom: let the request sit in the listen queue */
390                 if (debug)
391                     fprintf(stderr,"oom\n");
392             } else {
393                 memset(req,0,sizeof(struct REQUEST));
394                 if (-1 == (req->fd = accept(slisten,NULL,NULL))) {
395                     if (EAGAIN != errno)
396                         xperror(LOG_WARNING,"accept",NULL);
397                     free(req);
398                 } else {
399                     fcntl(req->fd,F_SETFL,O_NONBLOCK);
400                     req->state = STATE_READ_HEADER;
401                     req->ping = now;
402                     req->next = conns;
403                     conns = req;
404                     curr_conn++;
405                     if (debug)
406                         fprintf(stderr,"%03d: new request (%d)\n",req->fd,curr_conn);
407                     length = sizeof(req->peer);
408                     if (-1 == getpeername(req->fd,(struct sockaddr*)&(req->peer),&length)) {
409                         xperror(LOG_WARNING,"getpeername",NULL);
410                         req->state = STATE_CLOSE;
411                     }
412                     getnameinfo((struct sockaddr*)&req->peer,length,
413                                 req->peerhost,64,req->peerserv,8,
414                                 NI_NUMERICHOST | NI_NUMERICSERV);
415                     if (debug)
416                         fprintf(stderr,"%03d: connect from (%s)\n",
417                                 req->fd,req->peerhost);
418                 }
419             }
420         }
421 
422         /* check active connections */
423         for (req = conns, prev = NULL; req != NULL;) {
424             /* I/O */
425             if (FD_ISSET(req->fd,&rd)) {
426                 if (req->state == STATE_KEEPALIVE)
427                     req->state = STATE_READ_HEADER;
428                 read_request(req,0);
429                 req->ping = now;
430             }
431             if (FD_ISSET(req->fd,&wr)) {
432                 write_request(req);
433                 req->ping = now;
434             }
435 
436             /* check timeouts */
437             if (req->state == STATE_KEEPALIVE) {
438                 if (now > req->ping + keepalive_time) {
439                     if (debug)
440                         fprintf(stderr,"%03d: keepalive timeout\n",req->fd);
441                     req->state = STATE_CLOSE;
442                 }
443             } else {
444                 if (now > req->ping + timeout) {
445                     if (req->state == STATE_READ_HEADER) {
446                         mkerror(req,408,0);
447                     } else {
448                         xerror(LOG_INFO,"network timeout",req->peerhost);
449                         req->state = STATE_CLOSE;
450                     }
451                 }
452             }
453 
454             /* header parsing */
455 header_parsing:
456             if (req->state == STATE_PARSE_HEADER) {
457                 parse_request(req);
458                 if (req->state == STATE_WRITE_HEADER)
459                     write_request(req);
460             }
461 
462             /* handle finished requests */
463             if (req->state == STATE_FINISHED && !req->keep_alive)
464                 req->state = STATE_CLOSE;
465             if (req->state == STATE_FINISHED) {
466                 if (logfd)
467                     access_log(req,now);
468                 /* cleanup */
469                 if (req->free_the_mallocs)
470                     free(req->body);
471                 req->free_the_mallocs = 0;
472                 req->body      = NULL;
473                 req->written   = 0;
474                 req->head_only = 0;
475 
476                 if (req->hdata == req->lreq) {
477                     /* ok, wait for the next one ... */
478                     if (debug)
479                         fprintf(stderr,"%03d: keepalive wait\n",req->fd);
480                     req->state = STATE_KEEPALIVE;
481                     req->hdata = 0;
482                     req->lreq  = 0;
483                 } else {
484                     /* there is a pipelined request in the queue ... */
485                     if (debug)
486                         fprintf(stderr,"%03d: keepalive pipeline\n",req->fd);
487                     req->state = STATE_READ_HEADER;
488                     memmove(req->hreq,req->hreq+req->lreq,
489                             req->hdata-req->lreq);
490                     req->hdata -= req->lreq;
491                     req->lreq  =  0;
492                     read_request(req,1);
493                     goto header_parsing;
494                 }
495             }
496 
497             /* connections to close */
498             if (req->state == STATE_CLOSE) {
499                 if (logfd)
500                     access_log(req,now);
501                 /* cleanup */
502                 close(req->fd);
503                 curr_conn--;
504                 if (debug)
505                     fprintf(stderr,"%03d: done (%d)\n",req->fd,curr_conn);
506                 /* unlink from list */
507                 tmp = req;
508                 if (prev == NULL) {
509                     conns = req->next;
510                     req = conns;
511                 } else {
512                     prev->next = req->next;
513                     req = req->next;
514                 }
515                 /* free memory  */
516                 if (tmp->free_the_mallocs)
517                     free(tmp->body);
518                 free(tmp);
519             } else {
520                 prev = req;
521                 req = req->next;
522             }
523         }
524     }
525     return NULL;
526 }
527 
528 /* ---------------------------------------------------------------------- */
529 
530 int
531 main(int argc, char *argv[])
532 {
533     struct sigaction         act,old;
534     struct addrinfo          ask,*res;
535 #ifdef HAVE_SOCKADDR_STORAGE
536     struct sockaddr_storage ss;
537 #else
538     struct sockaddr ss;
539 #endif
540     int                      c, opt, rc, ss_len, v4, v6, simulate;
541     char host[INET6_ADDRSTRLEN+1];
542     char serv[16];
543 
544     ng_device_init();
545     gethostname(server_host,255);
546     memset(&ask,0,sizeof(ask));
547     ask.ai_flags = AI_CANONNAME;
548     if (0 == (rc = getaddrinfo(server_host, NULL, &ask, &res))) {
549         if (res->ai_canonname)
550             strcpy(server_host,res->ai_canonname);
551     }
552     
553     /* parse options */
554     v4 = 1; v6 = 1; simulate = 0;
555     for (;;) {
556         if (-1 == (c = getopt(argc,argv,"hasdFr46S"
557                               "p:N:n:i:t:c:u:g:l:L:v:")))
558             break;
559         switch (c) {
560         case 'h':
561             usage(argv[0]);
562             break;
563         case '4':
564             v4 = 1;
565             v6 = 0;
566             break;
567         case '6':
568             v4 = 0;
569             v6 = 1;
570             break;
571         case 'a':
572             ascii_art++;
573             break;
574         case 's':
575             usesyslog++;
576             break;
577         case 'S':
578             simulate++;
579             break;
580         case 'd':
581             debug++;
582             break;
583         case 'F':
584             dontdetach++;
585             break;
586         case 'r':
587             cachereset++;
588             break;
589         case 'N':
590             canonicalhost = 1;
591             /* fall through */
592         case 'n':
593             strncpy(server_host,optarg,sizeof(server_host)-1);
594             break;
595         case 'i':
596             listen_ip = optarg;
597             break;
598         case 'p':
599             listen_port = optarg;
600             break;
601         case 't':
602             timeout = atoi(optarg);
603             break;
604         case 'c':
605             max_conn = atoi(optarg);
606             break;
607         case 'u':
608             strncpy(user,optarg,16);
609             break;
610         case 'g':
611             strncpy(group,optarg,16);
612             break;
613         case 'L':
614             flushlog = 1;
615             /* fall through */
616         case 'l':
617             logfile = optarg;
618             break;
619         case 'v':
620             ng_dev.vbi = optarg;
621             break;
622         default:
623             exit(1);
624         }
625     }
626     if (usesyslog)
627         syslog_init();
628 
629     /* open vbi device */
630     vbi = vbi_open(ng_dev.vbi,debug,simulate);
631     if (NULL == vbi) {
632         xperror(LOG_ERR,"cannot open vbi device",NULL);
633         exit(1);
634     }
635     if (debug)
636         vbi_event_handler_add(vbi->dec,~0,vbi_dump_event,vbi);
637     else
638         vbi_event_handler_add(vbi->dec,~0,dummy_handler,vbi);
639 
640     /* bind to socket */
641     slisten = -1;
642     memset(&ask,0,sizeof(ask));
643     ask.ai_flags = AI_PASSIVE;
644     if (listen_ip)
645         ask.ai_flags |= AI_CANONNAME;
646     ask.ai_socktype = SOCK_STREAM;
647 
648     /* try ipv6 first ... */
649     if (-1 == slisten  &&  v6) {
650         ask.ai_family = PF_INET6;
651         if (0 != (rc = getaddrinfo(listen_ip, listen_port, &ask, &res))) {
652             if (debug)
653                 fprintf(stderr,"getaddrinfo (ipv6): %s\n",gai_strerror(rc));
654         } else {
655             if (-1 == (slisten = socket(res->ai_family, res->ai_socktype,
656                                         res->ai_protocol)) && debug)
657                 xperror(LOG_ERR,"socket (ipv6)",NULL);
658         }
659     }
660     
661     /* ... failing that try ipv4 */
662     if (-1 == slisten  &&  v4) {
663         ask.ai_family = PF_INET;
664         if (0 != (rc = getaddrinfo(listen_ip, listen_port, &ask, &res))) {
665             fprintf(stderr,"getaddrinfo (ipv4): %s\n",gai_strerror(rc));
666         } else {
667             if (-1 == (slisten = socket(res->ai_family, res->ai_socktype,
668                                         res->ai_protocol)))
669                 xperror(LOG_ERR,"socket (ipv4)",NULL);
670         }
671     }
672 
673     if (-1 == slisten)
674         exit(1);
675 
676     memcpy(&ss,res->ai_addr,res->ai_addrlen);
677     ss_len = res->ai_addrlen;
678     if (res->ai_canonname)
679         strcpy(server_host,res->ai_canonname);
680     if (0 != (rc = getnameinfo((struct sockaddr*)&ss,ss_len,
681                                host,INET6_ADDRSTRLEN,serv,15,
682                                NI_NUMERICHOST | NI_NUMERICSERV))) {
683         fprintf(stderr,"getnameinfo: %s\n",gai_strerror(rc));
684         exit(1);
685     }
686 
687     tcp_port = atoi(serv);
688     opt = 1;
689     setsockopt(slisten,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));
690     fcntl(slisten,F_SETFL,O_NONBLOCK);
691 
692     if (-1 == bind(slisten, (struct sockaddr*) &ss, ss_len)) {
693         xperror(LOG_ERR,"bind",NULL);
694         exit(1);
695     }
696     if (-1 == listen(slisten, 2*max_conn)) {
697         xperror(LOG_ERR,"listen",NULL);
698         exit(1);
699     }
700 
701     /* change user/group - also does chroot */
702     fix_ug();
703 
704     if (logfile) {
705         if (0 == strcmp(logfile,"-")) {
706             logfd = stdout;
707         } else {
708             if (NULL == (logfd = fopen(logfile,"a")))
709                 xperror(LOG_WARNING,"open access log",NULL);
710         }
711     }
712 
713     if (debug) {
714         fprintf(stderr,
715                 "alevt http server started\n"
716                 "  ipv6  : %s\n"
717                 "  node  : %s\n"
718                 "  ipaddr: %s\n"
719                 "  port  : %d\n"
720                 "  user  : %s\n"
721                 "  group : %s\n",
722                 res->ai_family == PF_INET6 ? "yes" : "no",
723                 server_host,host,tcp_port,user,group);
724     }
725 
726     /* run as daemon - detach from terminal */
727     if ((!debug) && (!dontdetach)) {
728         switch (fork()) {
729         case -1:
730             xperror(LOG_ERR,"fork",NULL);
731             exit(1);
732         case 0:
733             close(0); close(1); close(2); setsid();
734             have_tty = 0;
735             break;
736         default:
737             exit(0);
738         }
739     }
740     if (usesyslog) {
741         syslog_start();
742         atexit(syslog_stop);
743     }
744 
745     /* setup signal handler */
746     memset(&act,0,sizeof(act));
747     sigemptyset(&act.sa_mask);
748     act.sa_handler = SIG_IGN;
749     sigaction(SIGPIPE,&act,&old);
750     act.sa_handler = catchsig;
751     sigaction(SIGHUP,&act,&old);
752     sigaction(SIGUSR1,&act,&old);
753     sigaction(SIGTERM,&act,&old);
754     if (debug)
755         sigaction(SIGINT,&act,&old);
756 
757     /* go! */
758     start = time(NULL);
759     mainloop();
760     
761     if (logfd)
762         fclose(logfd);
763     if (debug)
764         fprintf(stderr,"bye...\n");
765     exit(0);
766 }
767 
  This page was automatically generated by the LXR engine.