Back to index

courier  0.68.2
ldapaliasd.c
Go to the documentation of this file.
00001 /*
00002 ** Copyright 2000-2009 Double Precision, Inc.
00003 ** See COPYING for distribution information.
00004 */
00005 
00006 #if HAVE_CONFIG_H
00007 #include "config.h"
00008 #endif
00009 #include <stdio.h>
00010 #include <stdlib.h>
00011 #include <ctype.h>
00012 #include <string.h>
00013 #include <errno.h>
00014 #include <signal.h>
00015 #include <fcntl.h>
00016 #include <sys/types.h>
00017 #include      "numlib/numlib.h"
00018 #if TIME_WITH_SYS_TIME
00019 #include        <sys/time.h>
00020 #include        <time.h>
00021 #else
00022 #if HAVE_SYS_TIME_H
00023 #include        <sys/time.h>
00024 #else
00025 #include        <time.h>
00026 #endif
00027 #endif
00028 #if HAVE_SYS_STAT_H
00029 #include <sys/stat.h>
00030 #endif
00031 #if HAVE_SYS_WAIT_H
00032 #include <sys/wait.h>
00033 #endif
00034 #if HAVE_UNISTD_H
00035 #include <unistd.h>
00036 #endif
00037 #if HAVE_LBER_H
00038 #include <lber.h>
00039 #endif
00040 #if HAVE_LBER_H
00041 #include <lber.h>
00042 #endif
00043 #if HAVE_LDAP_H
00044 #include <ldap.h>
00045 #if LDAP_VENDOR_VERSION > 20000
00046 #define OPENLDAPV2
00047 #endif
00048 #endif
00049 #if HAVE_SYSLOG_H
00050 #include <syslog.h>
00051 #else
00052 #define syslog(a,b)
00053 #endif
00054 #include <sys/socket.h>
00055 #include <sys/un.h>
00056 
00057 #include      <courierauth.h>
00058 #include      "courier.h"
00059 #include      "liblock/config.h"
00060 #include      "liblock/liblock.h"
00061 #include      "ldapaliasdrc.h"
00062 #include      "sysconfdir.h"
00063 #include      "localstatedir.h"
00064 
00065 
00066 static LDAP *my_ldap_fp=0;
00067 static const char *basedn;
00068 static const char *mailfield;
00069 static const char *maildropfield;
00070 static const char *sourcefield;
00071 static const char *vdomain;
00072 static const char *vuser;
00073 static int timeout_n;
00074 
00075 
00076 /*
00077 ** There's a memory leak in OpenLDAP 1.2.11, presumably in earlier versions
00078 ** too.  See http://www.OpenLDAP.org/its/index.cgi?findid=864 for more
00079 ** information.  To work around the bug, the first time a connection fails
00080 ** we stop trying for 60 seconds.  After 60 seconds we kill the process,
00081 ** and let the parent process restart it.
00082 **
00083 ** We'll control this behavior via LDAP_MEMORY_LEAK.  Set it to ZERO to turn
00084 ** off this behavior (whenever OpenLDAP gets fixed).
00085 */
00086 
00087 static time_t ldapfailflag=0;
00088 
00089 static void ldapconnfailure()
00090 {
00091        const char *p=getenv("LDAP_MEMORY_LEAK");
00092 
00093        if (!p) p="1";
00094 
00095        if (atoi(p) && !ldapfailflag)
00096        {
00097               time(&ldapfailflag);
00098               ldapfailflag += 60;
00099        }
00100 }
00101 
00102 static int ldapconncheck()
00103 {
00104        time_t t;
00105 
00106        if (!ldapfailflag)
00107               return (0);
00108 
00109        time(&t);
00110 
00111        if (t >= ldapfailflag)
00112               exit(0);
00113        return (1);
00114 }
00115 
00116 static void ldapclose()
00117 {
00118        if (my_ldap_fp)
00119        {
00120               ldap_unbind_ext(my_ldap_fp, NULL, NULL);
00121               my_ldap_fp=0;
00122        }
00123 }
00124 
00125 static int ldaperror(int rc)
00126 {
00127 #ifdef OPENLDAPV2
00128        if (rc && !LDAP_NAME_ERROR(rc))
00129 #else
00130        if (rc && !NAME_ERROR(rc))
00131 #endif
00132        {
00133               /* If there was a protocol error, close the connection */
00134               ldapclose();
00135               ldapconnfailure();
00136        }
00137        return (rc);
00138 }
00139 
00140 static LDAP *ldapconnect()
00141 {
00142        LDAP   *p;
00143 
00144        const char *url_s=ldapaliasd_config("LDAP_URI");
00145 
00146        if (!*url_s)
00147        {
00148 #if    HAVE_SYSLOG_H
00149               syslog(LOG_DAEMON|LOG_CRIT,
00150                      "Cannot read LDAP_URI from %s",
00151                      LDAPALIASDCONFIGFILE);
00152 #endif
00153               return (0);
00154        }
00155 
00156        if (ldapconncheck())
00157               return (NULL);
00158 
00159        if (ldap_initialize(&p, url_s) != LDAP_SUCCESS)
00160        {
00161 #if    HAVE_SYSLOG_H
00162               syslog(LOG_DAEMON|LOG_CRIT,
00163                      "Cannot connect to %s: %s",
00164                      url_s, strerror(errno));
00165 #endif
00166               ldapconnfailure();
00167        }
00168        return (p);
00169 }
00170 
00171 static int ldapopen()
00172 {
00173        int     ldrc;
00174        const char *binddn_s=ldapaliasd_config("LDAP_BINDDN");
00175        const char *bindpw_s=ldapaliasd_config("LDAP_BINDPW");
00176        struct berval cred;
00177 
00178        basedn=ldapaliasd_config("LDAP_BASEDN");
00179 
00180        if ((timeout_n=atoi(ldapaliasd_config("LDAP_TIMEOUT"))) <= 0)
00181        {
00182 #if    HAVE_SYSLOG_H
00183               syslog(LOG_DAEMON|LOG_CRIT,
00184                      "Cannot read LDAP_TIMEOUT from %s",
00185                      LDAPALIASDCONFIGFILE);
00186 #endif
00187               return (-1);
00188        }
00189 
00190 
00191        my_ldap_fp=ldapconnect();
00192 
00193        if (!my_ldap_fp)
00194        {
00195               return (-1);
00196        }
00197 
00198        if (!*binddn_s)
00199        {
00200 #if 0
00201 #if    HAVE_SYSLOG_H
00202               syslog(LOG_DAEMON|LOG_CRIT,
00203                      "Cannot read LDAP_BINDDN from %s",
00204                      LDAPALIASDCONFIGFILE);
00205 #endif
00206 #endif
00207               return (0);
00208        }
00209 
00210        cred.bv_len=strlen(bindpw_s ? bindpw_s:"");
00211        cred.bv_val=bindpw_s ? (char *)bindpw_s:"";
00212 
00213 
00214        if (ldaperror(ldrc = ldap_sasl_bind_s(my_ldap_fp, binddn_s, NULL,
00215                                          &cred, NULL, NULL, NULL))
00216            != LDAP_SUCCESS)
00217        {
00218               const char *s=ldap_err2string(ldrc);
00219 
00220 #if    HAVE_SYSLOG_H
00221               syslog(LOG_DAEMON|LOG_CRIT,
00222                      "ldap_simple_bind_s failed: %s", s);
00223 #endif
00224               ldapclose();
00225               ldapconnfailure();
00226               return (-1);
00227        }
00228        return (0);
00229 }
00230 
00231 static LDAPMessage *search_attr_retry(const char *filter, const char *attr)
00232 {
00233        char *attrlist[2];
00234        struct timeval timeout;
00235        LDAPMessage *result;
00236 
00237        attrlist[0]=(char *)attr;
00238        attrlist[1]=0;
00239 
00240        timeout.tv_sec=timeout_n;
00241        timeout.tv_usec=0;
00242 
00243        if (ldaperror(ldap_search_ext_s(my_ldap_fp, (char *)basedn,
00244                                    LDAP_SCOPE_SUBTREE,
00245                                    (char *)filter, attrlist,
00246                                    0,
00247                                    NULL, NULL, &timeout,
00248                                    1000000,
00249                                    &result))
00250            != LDAP_SUCCESS)
00251               return (NULL);
00252        return (result);
00253 }
00254 
00255 static LDAPMessage *search_attr(const char *filter, const char *attr)
00256 {
00257        LDAPMessage *result=search_attr_retry(filter, attr);
00258 
00259        if (result == NULL && my_ldap_fp == NULL && ldapopen() == 0)
00260               result=search_attr_retry(filter, attr);
00261 
00262        return result;
00263 }
00264 
00265 static int search_maildrop2(const char *mail, const char *source, FILE *outfp);
00266 
00267 static int search_maildrop(const char *mail, const char *source, FILE *outfp)
00268 {
00269        int rc;
00270        char *escaped=courier_auth_ldap_escape(mail);
00271 
00272        if (!escaped)
00273        {
00274               syslog(LOG_DAEMON|LOG_CRIT, "malloc failed: %m");
00275               return(0);
00276        }
00277 
00278        rc=search_maildrop2(escaped, source, outfp);
00279        free(escaped);
00280        return rc;
00281 }
00282 
00283 static int search_maildrop2(const char *mail, const char *source, FILE *outfp)
00284 {
00285        char *filter;
00286        char *p;
00287        LDAPMessage *result;
00288        int rc=1;
00289 
00290        if (my_ldap_fp == 0)
00291        {
00292               if (ldapopen())
00293                      return(0);
00294        }
00295 
00296        filter=malloc(strlen(mail)+(source ? strlen(source):0)+
00297                     (sourcefield ? strlen(sourcefield):0)+
00298                     strlen(mailfield)+80);
00299        if (!filter)
00300        {
00301               syslog(LOG_DAEMON|LOG_CRIT, "malloc failed: %m");
00302               return (0);
00303        }
00304 
00305        strcpy(filter, "(&(");
00306        strcat(filter, mailfield);
00307        strcat(filter, "=");
00308 
00309        p=filter+strlen(filter);
00310        while (*mail)
00311        {
00312               if (*mail != '\\' && *mail != '(' && *mail != ')')
00313                      *p++=*mail;
00314               ++mail;
00315        }
00316        strcpy(p, ")");
00317 
00318        if (source)
00319        {
00320               strcat(filter,"(");
00321               strcat(filter, sourcefield);
00322               strcat(filter, "=");
00323               p=filter+strlen(filter);
00324               while (*source)
00325               {
00326                      if (*source != '\\' && *source != '('
00327                          && *source != ')')
00328                             *p++= *source;
00329                      ++source;
00330               }
00331               strcpy(p, ")");
00332        }
00333        else if (*sourcefield) {
00334               strcat(filter, "(!(");
00335               strcat(filter, sourcefield);
00336               strcat(filter, "=*))");
00337        }
00338        strcat(filter, ")");
00339 
00340        result=search_attr(filter, maildropfield);
00341        free(filter);
00342 
00343        if (!result)
00344               return (0);   /* Protocol error. */
00345 
00346        if (ldap_count_entries(my_ldap_fp, result) == 1)
00347        {
00348               LDAPMessage *entry;
00349               struct berval **values;
00350 
00351               if ((entry=ldap_first_entry(my_ldap_fp, result)) != NULL &&
00352                   (values=ldap_get_values_len(my_ldap_fp, entry,
00353                                           (char *)
00354                                           maildropfield)) != NULL)
00355               {
00356                      int n=ldap_count_values_len(values);
00357                      int i;
00358 
00359                      for (i=0; i<n; i++)
00360                      {
00361                             int rc;
00362 
00363                             fprintf(outfp, "maildrop: ");
00364                             if ((rc=fwrite(values[i]->bv_val,
00365                                           values[i]->bv_len,
00366                                           1, outfp)) < 0)
00367                                    break;
00368                             fprintf(outfp, "\n");
00369                             rc=0;
00370                      }
00371                      ldap_value_free_len(values);
00372               }
00373        }
00374        ldap_msgfree(result);
00375 
00376        if (rc == 0)
00377               fprintf(outfp, ".\n");
00378        return (rc);
00379 }
00380 
00381 static int search_virtual(const char *mail, const char *source, FILE *outfp)
00382 {
00383        char *filter;
00384        char *p;
00385        LDAPMessage *result;
00386        int rc=1;
00387        const char *domain;
00388 
00389        if (*vdomain == 0 || *vuser == 0)
00390               return (1);
00391 
00392        domain=strrchr(mail, '@');
00393 
00394        if (domain == 0)
00395               return (1);
00396 
00397        if (my_ldap_fp == 0)
00398        {
00399               if (ldapopen())
00400                      return(0);
00401        }
00402 
00403        filter=malloc(strlen(mail)+(source ? strlen(source):0)+
00404                     (sourcefield ? strlen(sourcefield):0)+
00405                     strlen(vdomain)+80);
00406        if (!filter)
00407        {
00408               syslog(LOG_DAEMON|LOG_CRIT, "malloc failed: %m");
00409               return (0);
00410        }
00411 
00412        strcpy(filter, "(&(");
00413        strcat(filter, vdomain);
00414        strcat(filter, "=");
00415 
00416        p=filter+strlen(filter);
00417        ++domain;     /* Skip past '@' */
00418        while (*domain)
00419        {
00420               if (*domain != '\\' && *domain != '(' && *domain != ')')
00421                      *p++=*domain;
00422               ++domain;
00423        }
00424        strcpy(p, ")");
00425 
00426        if (source)
00427        {
00428               strcat(filter,"(");
00429               strcat(filter, sourcefield);
00430               strcat(filter, "=");
00431               p=filter+strlen(filter);
00432               while (*source)
00433               {
00434                      if (*source != '\\' && *source != '('
00435                          && *source != ')')
00436                             *p++= *source;
00437                      ++source;
00438               }
00439               strcpy(p, ")");
00440        }
00441        else if (*sourcefield) {
00442               strcat(filter, "(!(");
00443               strcat(filter, sourcefield);
00444               strcat(filter, "=*))");
00445        }
00446        strcat(filter, ")");
00447 
00448        result=search_attr(filter, vuser);
00449 
00450        if (!result)
00451        {
00452               free(filter);
00453               return (0);   /* Protocol error. */
00454        }
00455 
00456        strcpy(filter, mail);
00457        *strrchr(filter, '@')=0;
00458 
00459        if (ldap_count_entries(my_ldap_fp, result) == 1)
00460        {
00461               LDAPMessage *entry;
00462               struct berval **values;
00463 
00464               if ((entry=ldap_first_entry(my_ldap_fp, result)) != NULL &&
00465                   (values=ldap_get_values_len(my_ldap_fp, entry,
00466                                           (char *)
00467                                           vuser)) != NULL)
00468               {
00469                      int n=ldap_count_values_len(values);
00470                      int i;
00471 
00472                      for (i=0; i<n; i++)
00473                      {
00474                             int rc;
00475 
00476                             fprintf(outfp, "maildrop: ");
00477                             if ((rc=fwrite(values[i]->bv_val,
00478                                           values[i]->bv_len,
00479                                           1, outfp)) < 0)
00480                                    break;
00481 
00482                             fprintf(outfp, "-%s\n", filter);
00483                             rc=0;
00484                      }
00485                      ldap_value_free_len(values);
00486               }
00487        }
00488        ldap_msgfree(result);
00489        free(filter);
00490 
00491        if (rc == 0)
00492               fprintf(outfp, ".\n");
00493        return (rc);
00494 }
00495 
00496 static void search_source(char *source, FILE *outfp)
00497 {
00498        char *query;
00499 
00500        for (query=source; *query; query++)
00501        {
00502               if (isspace((int)(unsigned char)*query))
00503               {
00504                      *query++=0;
00505                      while (*query && isspace((int)(unsigned char)*query))
00506                             ++query;
00507                      break;
00508               }
00509        }
00510 
00511        if (!*query)
00512               return;
00513 
00514        if (sourcefield && *sourcefield &&
00515            search_maildrop(query, source, outfp) == 0)
00516               return;
00517 
00518        if (sourcefield && *sourcefield &&
00519            search_virtual(query, source, outfp) == 0)
00520               return;
00521 
00522        if (search_maildrop(query, NULL, outfp) &&
00523            search_virtual(query, NULL, outfp))
00524               fprintf(outfp, ".\n");
00525 }
00526 
00527 static int mksocket()
00528 {
00529        int     fd=socket(PF_UNIX, SOCK_STREAM, 0);
00530        struct  sockaddr_un skun;
00531 
00532         if (fd < 0)     return (-1);
00533         skun.sun_family=AF_UNIX;
00534         strcpy(skun.sun_path, SOCKETFILE);
00535         strcat(skun.sun_path, ".tmp");
00536         unlink(skun.sun_path);
00537 
00538         if (bind(fd, (const struct sockaddr *)&skun, sizeof(skun)) ||
00539            listen(fd, SOMAXCONN) ||
00540            chmod(skun.sun_path, 0770) ||
00541            rename(skun.sun_path, SOCKETFILE) ||
00542            fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
00543         {
00544                 close(fd);
00545                 return (-1);
00546         }
00547         return (fd);
00548 }
00549 
00550 static int pipe_tochild;
00551 static int pipe_fromchildren;
00552 
00553 static void child(int fd)
00554 {
00555        int afd;
00556 
00557        sourcefield=ldapaliasd_config("LDAP_SOURCE");
00558        mailfield=ldapaliasd_config("LDAP_MAIL");
00559        maildropfield=ldapaliasd_config("LDAP_MAILDROP");
00560        if (!*mailfield)
00561               mailfield="mail";
00562        if (!*maildropfield)
00563               maildropfield="maildrop";
00564 
00565        vdomain=ldapaliasd_config("LDAP_VDOMAIN");
00566        vuser=ldapaliasd_config("LDAP_VUSER");
00567 
00568        for (;;)
00569        {
00570               struct sockaddr saddr;
00571               socklen_t     saddr_len;
00572               FILE   *fp;
00573               char   buf[BUFSIZ];
00574               char   *p;
00575               fd_set  fds;
00576               struct timeval tv;
00577 
00578               FD_ZERO(&fds);
00579               FD_SET(fd, &fds);
00580               FD_SET(pipe_tochild, &fds);
00581 
00582               tv.tv_sec=300;
00583               tv.tv_usec=0;
00584 
00585               if (select((fd > pipe_tochild ? fd:pipe_tochild)+1,
00586                         &fds, 0, 0, &tv) < 0)
00587               {
00588                         syslog(LOG_CRIT, "select() failed: %m");
00589                      return;
00590               }
00591 
00592               if (FD_ISSET(pipe_tochild, &fds))
00593                      return;
00594               if (!FD_ISSET(fd, &fds))
00595               {
00596                      ldapclose();
00597                      continue;
00598               }
00599 
00600                 saddr_len=sizeof(saddr);
00601                 if ((afd=accept(fd, &saddr, &saddr_len)) < 0)
00602                         continue;
00603                 if (fcntl(afd, F_SETFL, 0) < 0)
00604                 {
00605                         syslog(LOG_CRIT, "fcntl() failed: %m");
00606                      close(afd);
00607                      continue;
00608               }
00609 
00610               fp=fdopen(afd, "r+");
00611               if (!fp)
00612               {
00613                         syslog(LOG_CRIT, "fdopen() failed: %m");
00614                      close(afd);
00615                      continue;
00616               }
00617 
00618               if (fgets(buf, sizeof(buf), fp) == NULL)
00619               {
00620                      fclose(fp);
00621                      continue;
00622               }
00623               if ((p=strchr(buf, '\n')) != 0)
00624                      *p=0;
00625               search_source(buf, fp);
00626               fclose(fp);
00627        }
00628 }
00629 
00630 static int sigterm_received;
00631 static int sighup_received;
00632 static int sigchild_received;
00633 
00634 static RETSIGTYPE sigalarm(int signum)
00635 {
00636        signal(SIGALRM, sigalarm);
00637        alarm(2);
00638 
00639 #if     RETSIGTYPE != void
00640         return (0);
00641 #endif
00642 }
00643 
00644 static RETSIGTYPE sigterm(int signum)
00645 {
00646        sigterm_received=1;
00647 
00648 #if     RETSIGTYPE != void
00649         return (0);
00650 #endif
00651 }
00652 
00653 static RETSIGTYPE sighup(int signum)
00654 {
00655        sighup_received=1;
00656 
00657        signal(SIGHUP, sighup);
00658 
00659 #if     RETSIGTYPE != void
00660         return (0);
00661 #endif
00662 }
00663 
00664 static RETSIGTYPE sigchild(int signum)
00665 {
00666        sigchild_received=1;
00667        alarm(1);
00668 
00669 #if     RETSIGTYPE != void
00670         return (0);
00671 #endif
00672 }
00673 
00674 static void loop(int fd)
00675 {
00676        int afd;
00677 
00678        int pipea[2];
00679        int pipeb[2];
00680 
00681        if (pipe(pipea) < 0)
00682        {
00683               syslog(LOG_CRIT, "pipe() failed: %m");
00684               sleep(5);
00685        }
00686 
00687        if (pipe(pipeb) < 0)
00688        {
00689               close(pipea[0]);
00690               close(pipea[1]);
00691               syslog(LOG_CRIT, "pipe() failed: %m");
00692               sleep(5);
00693               return;
00694        }
00695 
00696        afd=atoi(ldapaliasd_config("LDAP_NUMPROCS"));
00697 
00698        if (afd <= 0)
00699               afd=5;
00700 
00701        signal(SIGALRM, sigalarm);
00702        signal(SIGCHLD, sigchild);
00703 
00704        while (afd)
00705        {
00706               pid_t p=fork();
00707 
00708               if (p < 0)
00709               {
00710                      char buf;
00711 
00712                      syslog(LOG_CRIT, "pipe() failed: %m");
00713                      close(pipea[0]);
00714                      close(pipea[1]);
00715                      close(pipeb[1]);
00716 
00717                      if (read(pipeb[0], &buf, 1) < 0)
00718                             ; /* suppress gcc warning */
00719 
00720                      close(pipeb[0]);
00721                      sleep (5);
00722                      return;
00723               }
00724 
00725               if (p == 0)
00726               {
00727                      alarm(0);
00728                      signal(SIGCHLD, SIG_DFL);
00729                      signal(SIGTERM, SIG_DFL);
00730                      signal(SIGHUP, SIG_DFL);
00731                      signal(SIGALRM, SIG_DFL);
00732                      pipe_tochild=pipea[0];
00733                      close(pipea[1]);
00734                      pipe_fromchildren=pipeb[1];
00735                      close(pipeb[0]);
00736                      child(fd);
00737                      exit(0);
00738               }
00739               --afd;
00740        }
00741 
00742        sighup_received=0;
00743        sigterm_received=0;
00744        sigchild_received=0;
00745        pipe_tochild=pipea[1];
00746        close(pipea[0]);
00747        pipe_fromchildren=pipeb[0];
00748        close(pipeb[1]);
00749 
00750        signal(SIGTERM, sigterm);
00751        signal(SIGHUP, sighup);
00752 
00753        while (!sighup_received && !sigterm_received &&
00754               !sigchild_received)
00755        {
00756               sigset_t ss;
00757 
00758               sigemptyset(&ss);
00759               sigaddset(&ss, SIGUSR1);
00760 
00761               sigsuspend(&ss);
00762        }
00763 
00764        /* should be sigpause(0), but Solaris is broken */
00765 
00766        alarm(0);
00767        signal(SIGALRM, SIG_DFL);
00768        signal(SIGTERM, SIG_DFL);
00769        signal(SIGHUP, SIG_IGN);
00770 
00771 #if 0
00772 #if USE_NOCLDWAIT
00773 
00774        {
00775               struct sigaction sa;
00776 
00777               memset(&sa, 0, sizeof(sa));
00778               sa.sa_handler=SIG_IGN;
00779               sa.sa_flags=SA_NOCLDWAIT;
00780               sigaction(SIGCHLD, &sa, NULL);
00781        }
00782 #else
00783        signal(SIGCHLD, SIG_IGN);
00784 #endif
00785 #else
00786        signal(SIGCHLD, SIG_DFL);
00787 #endif
00788 
00789        close(pipe_tochild);
00790 
00791        if (sighup_received)
00792               syslog(LOG_DAEMON|LOG_INFO,
00793                      "Terminating child processes after a SIGHUP");
00794        if (sigterm_received)
00795               syslog(LOG_DAEMON|LOG_INFO,
00796                      "Terminating child processes after a SIGTERM");
00797        if (sigchild_received)
00798               syslog(LOG_DAEMON|LOG_CRIT,
00799                      "Terminating child processes after a SIGCHILD");
00800        {
00801               char c;
00802               int waitstat;
00803 
00804               if (read(pipe_fromchildren, &c, 1) < 0)
00805                      ; /* suppress gcc warning */
00806 
00807               close(pipe_fromchildren);
00808               while (wait(&waitstat) >= 0)
00809                      ;
00810        }
00811        if (sighup_received)
00812               syslog(LOG_DAEMON|LOG_INFO,
00813                      "Terminated child processes after a SIGHUP");
00814        if (sigterm_received)
00815               syslog(LOG_DAEMON|LOG_INFO,
00816                      "Terminated child processes after a SIGTERM");
00817        if (sigchild_received)
00818               syslog(LOG_DAEMON|LOG_CRIT,
00819                      "Terminated child processes after a SIGCHILD");
00820        if (sigterm_received)
00821               exit(0);
00822        ldapaliasd_configchanged();
00823 }
00824 
00825 static void start()
00826 {
00827        int lockfd;
00828        int sockfd;
00829 
00830        lockfd=ll_daemon_start(LOCKFILE);
00831 
00832        if (lockfd < 0)
00833        {
00834               perror("ll_daemon_start");
00835               exit(1);
00836        }
00837 
00838        if (atoi(ldapaliasd_config("LDAP_ALIAS")) <= 0)
00839        {
00840               ll_daemon_started(PIDFILE, lockfd);
00841               /* Consider this a good start */
00842               exit(0);
00843        }
00844 
00845        if ((sockfd=mksocket()) < 0)
00846        {
00847               perror("socket");
00848               exit(1);
00849        }
00850 
00851        signal(SIGPIPE, SIG_IGN);
00852        ll_daemon_started(PIDFILE, lockfd);
00853        ll_daemon_resetio();
00854 
00855 
00856        for (;;)
00857        {
00858               if (atoi(ldapaliasd_config("LDAP_ALIAS")) <= 0)
00859                      exit(0);
00860               loop(sockfd);
00861        }
00862 }
00863 
00864 static void stop()
00865 {
00866        ll_daemon_stop(LOCKFILE, PIDFILE);
00867 }
00868 
00869 static void restart()
00870 {
00871        ll_daemon_restart(LOCKFILE, PIDFILE);
00872 }
00873 
00874 static const char *readline(FILE *fp)
00875 {
00876        static char buf[BUFSIZ];
00877        char *p;
00878 
00879        if (fgets(buf, sizeof(buf), fp) == NULL)
00880        {
00881               fclose(fp);
00882               return (NULL);
00883        }
00884        if ((p=strchr(buf, '\n')) != 0)
00885               *p=0;
00886        return (buf);
00887 }
00888 
00889 static void check(const char *source, const char *query)
00890 {
00891        FILE *fp=ldapaliasd_connect();
00892        int found=0;
00893        const char *p;
00894 
00895        if (!fp)
00896        {
00897               fprintf(stderr, "connect failed\n");
00898               exit(1);
00899        }
00900 
00901        fprintf(fp, "%s %s\n", source, query);
00902        fflush(fp);
00903 
00904        while ((p=readline(fp)) != NULL)
00905        {
00906               if (strcmp(p, ".") == 0)
00907               {
00908                      if (!found)
00909                      {
00910                             fprintf(stderr, "%s: not found\n", query);
00911                             exit (1);
00912                      }
00913                      exit (0);
00914               }
00915               printf("%s\n", p);
00916               found=1;
00917        }
00918 
00919        fprintf(stderr, "Error.\n");
00920        exit (1);
00921 }
00922 
00923 int main(int argc, char **argv)
00924 {
00925        if (chdir(COURIER_HOME) < 0)
00926        {
00927               perror(COURIER_HOME);
00928               exit(1);
00929        }
00930 
00931        libmail_changeuidgid(MAILUID, MAILGID);
00932        
00933 #if HAVE_SYSLOG_H
00934        openlog("courierldapaliasd", LOG_PID, LOG_MAIL);
00935 #endif
00936 
00937        if (argc > 1)
00938        {
00939               if (strcmp(argv[1], "start") == 0)
00940               {
00941                      start();
00942                      return (0);
00943               }
00944 
00945               if (strcmp(argv[1], "stop") == 0)
00946               {
00947                      stop();
00948                      return (0);
00949               }
00950 
00951               if (strcmp(argv[1], "restart") == 0)
00952               {
00953                      restart();
00954                      return (0);
00955               }
00956 
00957               if (strcmp(argv[1], "query") == 0 && argc > 3)
00958               {
00959                      check(argv[2], argv[3]);
00960                      return (0);
00961               }
00962        }
00963 
00964        fprintf(stderr, "Usage: %s [start|stop|restart]\n", argv[0]);
00965        return (1);
00966 }