Back to index

courier  0.68.2
fork.c
Go to the documentation of this file.
00001 /*
00002 ** Copyright 2001-2006 Double Precision, Inc.  See COPYING for
00003 ** distribution information.
00004 */
00005 
00006 
00007 #include      "config.h"
00008 #include      <stdio.h>
00009 #include      <stdlib.h>
00010 #include      <string.h>
00011 #include      <unistd.h>
00012 #include      <signal.h>
00013 #include      <errno.h>
00014 #include      <sys/types.h>
00015 #include      <sys/stat.h>
00016 #include      <sys/time.h>
00017 #if HAVE_SYS_WAIT_H
00018 #include      <sys/wait.h>
00019 #endif
00020 #ifndef WEXITSTATUS
00021 #define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
00022 #endif
00023 #ifndef WIFEXITED
00024 #define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
00025 #endif
00026 
00027 #include      "gpg.h"
00028 #include      "gpglib.h"
00029 
00030 extern int libmail_gpg_stdin, libmail_gpg_stdout, libmail_gpg_stderr;
00031 extern pid_t libmail_gpg_pid;
00032 
00033 
00034 /*
00035 ** Helper function: for and run pgp, with the given file descriptors and
00036 ** options.
00037 */
00038 
00039 pid_t libmail_gpg_fork(int *libmail_gpg_stdin, int *libmail_gpg_stdout,
00040                      int *libmail_gpg_stderr,
00041                      const char *gpgdir,
00042                      char **argvec)
00043 {
00044        int pipein[2], pipeout[2], pipeerr[2];
00045        pid_t p;
00046        char *s;
00047 
00048        if (libmail_gpg_stdin && pipe(pipein) < 0)
00049               return (-1);
00050 
00051        if (libmail_gpg_stdout && pipe(pipeout) < 0)
00052        {
00053               if (libmail_gpg_stdin)
00054               {
00055                      close(pipein[0]);
00056                      close(pipein[1]);
00057               }
00058               return (-1);
00059        }
00060 
00061        if (libmail_gpg_stderr && pipe(pipeerr) < 0)
00062        {
00063               if (libmail_gpg_stdout)
00064               {
00065                      close(pipeout[0]);
00066                      close(pipeout[1]);
00067               }
00068 
00069               if (libmail_gpg_stdin)
00070               {
00071                      close(pipein[0]);
00072                      close(pipein[1]);
00073               }
00074               return (-1);
00075        }
00076 
00077        signal(SIGCHLD, SIG_DFL);
00078        p=libmail_gpg_pid=fork();
00079        if (p < 0)
00080        {
00081               if (libmail_gpg_stderr)
00082               {
00083                      close(pipeerr[0]);
00084                      close(pipeerr[1]);
00085               }
00086 
00087               if (libmail_gpg_stdout)
00088               {
00089                      close(pipeout[0]);
00090                      close(pipeout[1]);
00091               }
00092               if (libmail_gpg_stdin)
00093               {
00094                      close(pipein[0]);
00095                      close(pipein[1]);
00096               }
00097 
00098               return (-1);
00099        }
00100 
00101        if (p)
00102        {
00103               signal(SIGPIPE, SIG_IGN);
00104 
00105               if (libmail_gpg_stderr)
00106               {
00107                      close(pipeerr[1]);
00108                      *libmail_gpg_stderr=pipeerr[0];
00109               }
00110 
00111               if (libmail_gpg_stdout)
00112               {
00113                      close(pipeout[1]);
00114                      *libmail_gpg_stdout=pipeout[0];
00115               }
00116 
00117               if (libmail_gpg_stdin)
00118               {
00119                      close(pipein[0]);
00120                      *libmail_gpg_stdin=pipein[1];
00121               }
00122               return (0);
00123        }
00124 
00125        if (libmail_gpg_stderr)
00126        {
00127               dup2(pipeerr[1], 2);
00128               close(pipeerr[0]);
00129               close(pipeerr[1]);
00130        }
00131        else if (libmail_gpg_stdout)
00132        {
00133               dup2(pipeout[1], 2);
00134        }
00135 
00136        if (libmail_gpg_stdout)
00137        {
00138               dup2(pipeout[1], 1);
00139               close(pipeout[0]);
00140               close(pipeout[1]);
00141        }
00142 
00143        if (libmail_gpg_stdin)
00144        {
00145               dup2(pipein[0], 0);
00146               close(pipein[0]);
00147               close(pipein[1]);
00148        }
00149 
00150        if (gpgdir)
00151        {
00152               s=malloc(sizeof("GNUPGHOME=")+strlen(gpgdir));
00153               if (!s)
00154               {
00155                      perror("malloc");
00156                      exit(1);
00157               }
00158               strcat(strcpy(s, "GNUPGHOME="), gpgdir);
00159               if (putenv(s) < 0)
00160               {
00161                      perror("putenv");
00162                      exit(1);
00163               }
00164        }
00165 
00166        {
00167               const char *gpg=getenv("GPG");
00168               if (!gpg || !*gpg)
00169                      gpg=GPG;
00170 
00171               execv(gpg, argvec);
00172               perror(gpg);
00173        }
00174        _exit(1);
00175        return (0);
00176 }
00177 
00178 int libmail_gpg_write(const char *p, size_t cnt,
00179                     int (*stdout_func)(const char *, size_t, void *),
00180                     int (*stderr_func)(const char *, size_t, void *),
00181                     int (*timeout_func)(void *),
00182                     unsigned timeout,
00183                     void *voidarg)
00184 {
00185        char buf[BUFSIZ];
00186 
00187        fd_set fdr, fdw;
00188        struct timeval tv;
00189 
00190        if (!timeout_func)
00191               timeout=0;
00192        while (cnt)
00193        {
00194               int maxfd=0;
00195               int n;
00196 
00197               FD_ZERO(&fdr);
00198               FD_ZERO(&fdw);
00199 
00200               FD_SET(libmail_gpg_stdin, &fdw);
00201 
00202               if (libmail_gpg_stdout >= 0)
00203               {
00204                      FD_SET(libmail_gpg_stdout, &fdr);
00205                      if (libmail_gpg_stdout > maxfd)
00206                             maxfd=libmail_gpg_stdout;
00207               }
00208 
00209               if (libmail_gpg_stderr >= 0)
00210               {
00211                      FD_SET(libmail_gpg_stderr, &fdr);
00212                      if (libmail_gpg_stderr > maxfd)
00213                             maxfd=libmail_gpg_stderr;
00214               }
00215 
00216               tv.tv_usec=0;
00217               tv.tv_sec=timeout;
00218               n=select(maxfd+1, &fdr, &fdw, NULL, timeout ? &tv:NULL);
00219               if (n == 0)
00220               {
00221                      n=(*timeout_func)(voidarg);
00222                      if (n)
00223                             return(n);
00224                      continue;
00225               }
00226               if (n < 0)
00227                      continue;
00228 
00229               if (FD_ISSET(libmail_gpg_stdin, &fdw))
00230               {
00231                      int n=write(libmail_gpg_stdin, p, cnt);
00232 
00233                      if (n <= 0)
00234                             return (-1);
00235 
00236                      p += n;
00237                      cnt -= n;
00238               }
00239 
00240               if (libmail_gpg_stdout >= 0 &&
00241                   FD_ISSET(libmail_gpg_stdout, &fdr))
00242               {
00243                      int n=read(libmail_gpg_stdout, buf, sizeof(buf));
00244 
00245                      if (n <= 0)
00246                      {
00247                             close(libmail_gpg_stdout);
00248                             libmail_gpg_stdout= -1;
00249                      }
00250                      else if (stdout_func &&
00251                              (n=(*stdout_func)(buf, n, voidarg)) != 0)
00252                             return (n);
00253               }
00254 
00255               if (libmail_gpg_stderr >= 0 &&
00256                   FD_ISSET(libmail_gpg_stderr, &fdr))
00257               {
00258                      int n=read(libmail_gpg_stderr, buf, sizeof(buf));
00259 
00260                      if (n <= 0)
00261                      {
00262                             close(libmail_gpg_stderr);
00263                             libmail_gpg_stderr= -1;
00264                      }
00265                      else if (stderr_func &&
00266                              (n=(*stderr_func)(buf, n, voidarg)) != 0)
00267                             return (n);
00268               }
00269        }
00270        return (0);
00271 }
00272 
00273 int libmail_gpg_read(int (*stdout_func)(const char *, size_t, void *),
00274                    int (*stderr_func)(const char *, size_t, void *),
00275                    int (*timeout_func)(void *),
00276                    unsigned timeout,
00277                    void *voidarg)
00278 {
00279        char buf[BUFSIZ];
00280 
00281        fd_set fdr;
00282        struct timeval tv;
00283 
00284        if (libmail_gpg_stdin >= 0)
00285        {
00286               close(libmail_gpg_stdin);
00287               libmail_gpg_stdin= -1;
00288        }
00289 
00290        if (!timeout_func)
00291               timeout=0;
00292 
00293        while ( libmail_gpg_stdout >= 0 || libmail_gpg_stderr >= 0)
00294        {
00295               int maxfd=0;
00296               int n;
00297 
00298               FD_ZERO(&fdr);
00299 
00300               if (libmail_gpg_stdout >= 0)
00301               {
00302                      FD_SET(libmail_gpg_stdout, &fdr);
00303                      if (libmail_gpg_stdout > maxfd)
00304                             maxfd=libmail_gpg_stdout;
00305               }
00306 
00307               if (libmail_gpg_stderr >= 0)
00308               {
00309                      FD_SET(libmail_gpg_stderr, &fdr);
00310                      if (libmail_gpg_stderr > maxfd)
00311                             maxfd=libmail_gpg_stderr;
00312               }
00313 
00314               tv.tv_usec=0;
00315               tv.tv_sec=timeout;
00316               n=select(maxfd+1, &fdr, NULL, NULL, timeout ? &tv:NULL);
00317 
00318               if (n == 0)
00319               {
00320                      n=(*timeout_func)(voidarg);
00321                      if (n)
00322                             return(n);
00323                      continue;
00324               }
00325               if (n < 0)
00326                      continue;
00327 
00328               if (libmail_gpg_stdout >= 0 &&
00329                   FD_ISSET(libmail_gpg_stdout, &fdr))
00330               {
00331                      int n=read(libmail_gpg_stdout, buf, sizeof(buf));
00332 
00333                      if (n <= 0)
00334                      {
00335                             close(libmail_gpg_stdout);
00336                             libmail_gpg_stdout= -1;
00337                      }
00338                      else if (stdout_func &&
00339                              (n=(*stdout_func)(buf, n, voidarg)) != 0)
00340                             return (n);
00341               }
00342 
00343               if (libmail_gpg_stderr >= 0 &&
00344                   FD_ISSET(libmail_gpg_stderr, &fdr))
00345               {
00346                      int n=read(libmail_gpg_stderr, buf, sizeof(buf));
00347 
00348                      if (n <= 0)
00349                      {
00350                             close(libmail_gpg_stderr);
00351                             libmail_gpg_stderr= -1;
00352                      }
00353                      else if (stderr_func &&
00354                              (n=(*stderr_func)(buf, n, voidarg)) != 0)
00355                             return (n);
00356               }
00357        }
00358        return (0);
00359 }