Changeset 34132f7


Ignore:
Timestamp:
Mar 11, 2012, 10:34:18 PM (12 years ago)
Author:
David Benjamin <davidben@mit.edu>
Branches:
release-1.8
Children:
6a08f16
Parents:
4a80a16
git-author:
David Benjamin <davidben@mit.edu> (01/23/12 00:38:29)
git-committer:
David Benjamin <davidben@mit.edu> (03/11/12 22:34:18)
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

    r4a80a16 r34132f7  
    1010#include <glib.h>
    1111
    12 int send_receive(int rfd, int wfd, const char *out, char **in)
     12/* Even in case of error, send_receive is responsible for closing wfd
     13 * (to EOF the child) and rfd (for consistency). */
     14static int send_receive(int rfd, int wfd, const char *out, char **in)
    1315{
    1416  GString *str = g_string_new("");
     
    2830  if(!out || !*out) {
    2931    /* Nothing to write. Close our end so the child doesn't hang waiting. */
    30     close(wfd);
     32    close(wfd); wfd = -1;
    3133    out = NULL;
    3234  }
     
    5355      }
    5456      if(!out || !*out || fds[1].revents & (POLLERR | POLLHUP)) {
    55         close(wfd);
     57        close(wfd); wfd = -1;
    5658        out = NULL;
    5759      }
     
    6971  }
    7072
     73  if (wfd >= 0) close(wfd);
     74  close(rfd);
    7175  *in = g_string_free(str, err < 0);
    7276  return err;
    7377}
    7478
    75 int call_filter(const char *prog, const char *const *argv, const char *in, char **out, int *status)
     79int call_filter(const char *const *argv, const char *in, char **out, int *status)
    7680{
    77   int err = 0;
    78   pid_t pid;
    79   int rfd[2];
    80   int wfd[2];
     81  int err;
     82  GPid child_pid;
     83  int child_stdin, child_stdout;
    8184
    82   if((err = pipe(rfd))) goto out;
    83   if((err = pipe(wfd))) goto out_close_rfd;
    84 
    85   pid = fork();
    86   if(pid < 0) {
    87     err = pid;
    88     goto out_close_all;
    89   }
    90   if(pid) {
    91     /* parent */
    92     close(rfd[1]);
    93     close(wfd[0]);
    94     err = send_receive(rfd[0], wfd[1], in, out);
    95     if(err == 0) {
    96       waitpid(pid, status, 0);
    97     }
    98   } else {
    99     /* child */
    100     close(rfd[0]);
    101     close(wfd[1]);
    102     dup2(rfd[1], 1);
    103     dup2(wfd[0], 0);
    104     close(rfd[1]);
    105     close(wfd[0]);
    106 
    107     if(execvp(prog, (char *const *)argv)) {
    108       _exit(-1);
    109     }
     85  if (!g_spawn_async_with_pipes(NULL, (char**)argv, NULL,
     86                                G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD,
     87                                NULL, NULL,
     88                                &child_pid, &child_stdin, &child_stdout, NULL,
     89                                NULL)) {
     90    return 1;
    11091  }
    11192
    112  out_close_all:
    113   close(wfd[0]);
    114   close(wfd[1]);
    115  out_close_rfd:
    116   close(rfd[0]);
    117   close(rfd[1]);
    118  out:
     93  err = send_receive(child_stdout, child_stdin, in, out);
     94  if (err == 0) {
     95    waitpid(child_pid, status, 0);
     96  }
    11997  return err;
    12098}
  • filterproc.h

    r06adc25 r34132f7  
    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

    r8e755c6 r34132f7  
    411411
    412412  zcrypt = g_build_filename(owl_get_bindir(), "zcrypt", NULL);
    413   argv[0] = "zcrypt";
     413  argv[0] = zcrypt;
    414414  argv[1] = "-E";
    415415  argv[2] = "-c"; argv[3] = owl_zwrite_get_class(z);
     
    417417  argv[6] = NULL;
    418418
    419   rv = call_filter(zcrypt, argv, owl_zwrite_get_message(z), &cryptmsg, &status);
     419  rv = call_filter(argv, owl_zwrite_get_message(z), &cryptmsg, &status);
    420420
    421421  g_free(zcrypt);
  • message.c

    rdde1b4d r34132f7  
    873873  if (owl_global_is_zcrypt(&g) && !strcasecmp(n->z_opcode, "crypt")) {
    874874    const char *argv[] = {
    875       "zcrypt",
     875      NULL,
    876876      "-D",
    877877      "-c", owl_message_get_class(m),
     
    885885
    886886    zcrypt = g_build_filename(owl_get_bindir(), "zcrypt", NULL);
    887 
    888     rv = call_filter(zcrypt, argv, owl_message_get_body(m), &out, &status);
     887    argv[0] = zcrypt;
     888
     889    rv = call_filter(argv, owl_message_get_body(m), &out, &status);
    889890    g_free(zcrypt);
    890891
  • tester.c

    r67e5ba36 r34132f7  
    33#include "owl.h"
    44#undef WINDOW
     5#include "filterproc.h"
    56
    67#include <unistd.h>
     
    2627int owl_smartfilter_regtest(void);
    2728int owl_history_regtest(void);
     29int call_filter_regtest(void);
    2830
    2931extern void owl_perl_xs_init(pTHX);
     
    116118  numfailures += owl_smartfilter_regtest();
    117119  numfailures += owl_history_regtest();
     120  numfailures += call_filter_regtest();
    118121  if (numfailures) {
    119122      fprintf(stderr, "# *** WARNING: %d failures total\n", numfailures);
     
    982985  return numfailed;
    983986}
     987
     988int call_filter_regtest(void)
     989{
     990  int numfailed = 0;
     991  int ret;
     992  char *out = NULL;
     993  int status;
     994
     995  printf("# BEGIN testing call_filter\n");
     996
     997  const char *cat_argv[] = { "cat", NULL };
     998  ret = call_filter(cat_argv, "Mangos!", &out, &status);
     999  FAIL_UNLESS("call_filter cat", (ret == 0 &&
     1000                                  status == 0 &&
     1001                                  strcmp(out, "Mangos!") == 0));
     1002  g_free(out); out = NULL;
     1003
     1004  ret = call_filter(cat_argv, "", &out, &status);
     1005  FAIL_UNLESS("call_filter cat", (ret == 0 &&
     1006                                  status == 0 &&
     1007                                  strcmp(out, "") == 0));
     1008  g_free(out); out = NULL;
     1009
     1010  ret = call_filter(cat_argv, NULL, &out, &status);
     1011  FAIL_UNLESS("call_filter cat", (ret == 0 &&
     1012                                  status == 0 &&
     1013                                  strcmp(out, "") == 0));
     1014  g_free(out); out = NULL;
     1015
     1016  printf("# END testing call_filter (%d failures)\n", numfailed);
     1017  return numfailed;
     1018}
  • zcrypt.c

    rc6332f5 r34132f7  
    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.