Changeset 97cdbaf5


Ignore:
Timestamp:
Mar 11, 2012, 10:57:35 PM (6 years ago)
Author:
David Benjamin <davidben@mit.edu>
Branches:
master, release-1.9
Children:
a03a409
Parents:
1f39ded
git-author:
David Benjamin <davidben@mit.edu> (01/23/12 00:38:29)
git-committer:
David Benjamin <davidben@mit.edu> (03/11/12 22:57:35)
Message:
Rewrite call_filter to use g_spawn_async_with_pipes

This simplifies the error-handling code. Also fixes a bug where file
descriptors get double-closed in call_filter. Also adds a unit test. The
separate prog argument is removed to avoid having to deal with
G_SPAWN_FILE_AND_ARGV_ZERO, and since we don't really use it anyway.
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • filterproc.c

    r1f39ded r97cdbaf5  
    33#include <poll.h>
    44
    5 int send_receive(int rfd, int wfd, const char *out, char **in)
     5/* Even in case of error, send_receive is responsible for closing wfd
     6 * (to EOF the child) and rfd (for consistency). */
     7static int send_receive(int rfd, int wfd, const char *out, char **in)
    68{
    79  GString *str = g_string_new("");
     
    2123  if(!out || !*out) {
    2224    /* Nothing to write. Close our end so the child doesn't hang waiting. */
    23     close(wfd);
     25    close(wfd); wfd = -1;
    2426    out = NULL;
    2527  }
     
    4648      }
    4749      if(!out || !*out || fds[1].revents & (POLLERR | POLLHUP)) {
    48         close(wfd);
     50        close(wfd); wfd = -1;
    4951        out = NULL;
    5052      }
     
    6264  }
    6365
     66  if (wfd >= 0) close(wfd);
     67  close(rfd);
    6468  *in = g_string_free(str, err < 0);
    6569  return err;
    6670}
    6771
    68 int call_filter(const char *prog, const char *const *argv, const char *in, char **out, int *status)
     72int call_filter(const char *const *argv, const char *in, char **out, int *status)
    6973{
    70   int err = 0;
    71   pid_t pid;
    72   int rfd[2];
    73   int wfd[2];
     74  int err;
     75  GPid child_pid;
     76  int child_stdin, child_stdout;
    7477
    75   if((err = pipe(rfd))) goto out;
    76   if((err = pipe(wfd))) goto out_close_rfd;
    77 
    78   pid = fork();
    79   if(pid < 0) {
    80     err = pid;
    81     goto out_close_all;
    82   }
    83   if(pid) {
    84     /* parent */
    85     close(rfd[1]);
    86     close(wfd[0]);
    87     err = send_receive(rfd[0], wfd[1], in, out);
    88     if(err == 0) {
    89       waitpid(pid, status, 0);
    90     }
    91   } else {
    92     /* child */
    93     close(rfd[0]);
    94     close(wfd[1]);
    95     dup2(rfd[1], 1);
    96     dup2(wfd[0], 0);
    97     close(rfd[1]);
    98     close(wfd[0]);
    99 
    100     if(execvp(prog, (char *const *)argv)) {
    101       _exit(-1);
    102     }
     78  if (!g_spawn_async_with_pipes(NULL, (char**)argv, NULL,
     79                                G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD,
     80                                NULL, NULL,
     81                                &child_pid, &child_stdin, &child_stdout, NULL,
     82                                NULL)) {
     83    return 1;
    10384  }
    10485
    105  out_close_all:
    106   close(wfd[0]);
    107   close(wfd[1]);
    108  out_close_rfd:
    109   close(rfd[0]);
    110   close(rfd[1]);
    111  out:
     86  err = send_receive(child_stdout, child_stdin, in, out);
     87  if (err == 0) {
     88    waitpid(child_pid, status, 0);
     89  }
    11290  return err;
    11391}
  • filterproc.h

    r06adc25 r97cdbaf5  
    22#define INC_BARNOWL_FILTER_PROC_H
    33
    4 int call_filter(const char *prog,
    5                 const char *const *argv,
     4int call_filter(const char *const *argv,
    65                const char *in,
    76                char **out, int *status);
  • functions.c

    rbd482c3 r97cdbaf5  
    405405
    406406  zcrypt = g_build_filename(owl_get_bindir(), "zcrypt", NULL);
    407   argv[0] = "zcrypt";
     407  argv[0] = zcrypt;
    408408  argv[1] = "-E";
    409409  argv[2] = "-c"; argv[3] = owl_zwrite_get_class(z);
     
    411411  argv[6] = NULL;
    412412
    413   rv = call_filter(zcrypt, argv, owl_zwrite_get_message(z), &cryptmsg, &status);
     413  rv = call_filter(argv, owl_zwrite_get_message(z), &cryptmsg, &status);
    414414
    415415  g_free(zcrypt);
  • message.c

    rbff1f22 r97cdbaf5  
    875875  if (owl_global_is_zcrypt(&g) && !strcasecmp(n->z_opcode, "crypt")) {
    876876    const char *argv[] = {
    877       "zcrypt",
     877      NULL,
    878878      "-D",
    879879      "-c", owl_message_get_class(m),
     
    887887
    888888    zcrypt = g_build_filename(owl_get_bindir(), "zcrypt", NULL);
    889 
    890     rv = call_filter(zcrypt, argv, owl_message_get_body(m), &out, &status);
     889    argv[0] = zcrypt;
     890
     891    rv = call_filter(argv, owl_message_get_body(m), &out, &status);
    891892    g_free(zcrypt);
    892893
  • tester.c

    ra74a044 r97cdbaf5  
    33#include "owl.h"
    44#undef WINDOW
     5#include "filterproc.h"
    56
    67#include <stdio.h>
     
    2324int owl_smartfilter_regtest(void);
    2425int owl_history_regtest(void);
     26int call_filter_regtest(void);
    2527
    2628extern void owl_perl_xs_init(pTHX);
     
    113115  numfailures += owl_smartfilter_regtest();
    114116  numfailures += owl_history_regtest();
     117  numfailures += call_filter_regtest();
    115118  if (numfailures) {
    116119      fprintf(stderr, "# *** WARNING: %d failures total\n", numfailures);
     
    981984  return numfailed;
    982985}
     986
     987int call_filter_regtest(void)
     988{
     989  int numfailed = 0;
     990  int ret;
     991  char *out = NULL;
     992  int status;
     993
     994  printf("# BEGIN testing call_filter\n");
     995
     996  const char *cat_argv[] = { "cat", NULL };
     997  ret = call_filter(cat_argv, "Mangos!", &out, &status);
     998  FAIL_UNLESS("call_filter cat", (ret == 0 &&
     999                                  status == 0 &&
     1000                                  strcmp(out, "Mangos!") == 0));
     1001  g_free(out); out = NULL;
     1002
     1003  ret = call_filter(cat_argv, "", &out, &status);
     1004  FAIL_UNLESS("call_filter cat", (ret == 0 &&
     1005                                  status == 0 &&
     1006                                  strcmp(out, "") == 0));
     1007  g_free(out); out = NULL;
     1008
     1009  ret = call_filter(cat_argv, NULL, &out, &status);
     1010  FAIL_UNLESS("call_filter cat", (ret == 0 &&
     1011                                  status == 0 &&
     1012                                  strcmp(out, "") == 0));
     1013  g_free(out); out = NULL;
     1014
     1015  printf("# END testing call_filter (%d failures)\n", numfailed);
     1016  return numfailed;
     1017}
  • zcrypt.c

    rc6332f5 r97cdbaf5  
    774774    NULL
    775775  };
    776   err = call_filter("gpg", argv, in, &out, &status);
     776  err = call_filter(argv, in, &out, &status);
    777777  if(err || status) {
    778778    g_free(out);
     
    857857  if(!in) return FALSE;
    858858
    859   err = call_filter("gpg", argv, in, &out, &status);
     859  err = call_filter(argv, in, &out, &status);
    860860  if(err || status) {
    861861    g_free(out);
Note: See TracChangeset for help on using the changeset viewer.