mutt stable branch with some hacks
at jcs 217 lines 4.1 kB view raw
1/* 2 * Copyright (C) 1996-2000 Michael R. Elkins. 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 */ 18 19#if HAVE_CONFIG_H 20# include "config.h" 21#endif 22 23#include "mutt.h" 24#include "mutt_curses.h" 25#ifdef USE_IMAP 26# include "imap.h" 27#endif 28 29#include <unistd.h> 30#include <stdlib.h> 31#include <sys/wait.h> 32 33/* Invokes a command on a pipe and optionally connects its stdin and stdout 34 * to the specified handles. 35 */ 36pid_t 37mutt_create_filter_fd (const char *cmd, FILE **in, FILE **out, FILE **err, 38 int fdin, int fdout, int fderr) 39{ 40 int pin[2], pout[2], perr[2], thepid; 41 char columns[11]; 42 43 if (in) 44 { 45 *in = 0; 46 if (pipe (pin) == -1) 47 return (-1); 48 } 49 50 if (out) 51 { 52 *out = 0; 53 if (pipe (pout) == -1) 54 { 55 if (in) 56 { 57 close (pin[0]); 58 close (pin[1]); 59 } 60 return (-1); 61 } 62 } 63 64 if (err) 65 { 66 *err = 0; 67 if (pipe (perr) == -1) 68 { 69 if (in) 70 { 71 close (pin[0]); 72 close (pin[1]); 73 } 74 if (out) 75 { 76 close (pout[0]); 77 close (pout[1]); 78 } 79 return (-1); 80 } 81 } 82 83 mutt_block_signals_system (); 84 85 if ((thepid = fork ()) == 0) 86 { 87 mutt_unblock_signals_system (0); 88 89 if (in) 90 { 91 close (pin[1]); 92 dup2 (pin[0], 0); 93 close (pin[0]); 94 } 95 else if (fdin != -1) 96 { 97 dup2 (fdin, 0); 98 close (fdin); 99 } 100 101 if (out) 102 { 103 close (pout[0]); 104 dup2 (pout[1], 1); 105 close (pout[1]); 106 } 107 else if (fdout != -1) 108 { 109 dup2 (fdout, 1); 110 close (fdout); 111 } 112 113 if (err) 114 { 115 close (perr[0]); 116 dup2 (perr[1], 2); 117 close (perr[1]); 118 } 119 else if (fderr != -1) 120 { 121 dup2 (fderr, 2); 122 close (fderr); 123 } 124 125 if (MuttIndexWindow && (MuttIndexWindow->cols > 0)) 126 { 127 snprintf (columns, sizeof (columns), "%d", MuttIndexWindow->cols); 128 mutt_envlist_set ("COLUMNS", columns, 1); 129 } 130 131 execle (EXECSHELL, "sh", "-c", cmd, NULL, mutt_envlist ()); 132 _exit (127); 133 } 134 else if (thepid == -1) 135 { 136 mutt_unblock_signals_system (1); 137 138 if (in) 139 { 140 close (pin[0]); 141 close (pin[1]); 142 } 143 144 if (out) 145 { 146 close (pout[0]); 147 close (pout[1]); 148 } 149 150 if (err) 151 { 152 close (perr[0]); 153 close (perr[1]); 154 } 155 156 return (-1); 157 } 158 159 if (out) 160 { 161 close (pout[1]); 162 *out = fdopen (pout[0], "r"); 163 } 164 165 if (in) 166 { 167 close (pin[0]); 168 *in = fdopen (pin[1], "w"); 169 } 170 171 if (err) 172 { 173 close (perr[1]); 174 *err = fdopen (perr[0], "r"); 175 } 176 177 return (thepid); 178} 179 180pid_t mutt_create_filter (const char *s, FILE **in, FILE **out, FILE **err) 181{ 182 return (mutt_create_filter_fd (s, in, out, err, -1, -1, -1)); 183} 184 185int mutt_wait_filter (pid_t pid) 186{ 187 int rc; 188 189 waitpid (pid, &rc, 0); 190 mutt_unblock_signals_system (1); 191 rc = WIFEXITED (rc) ? WEXITSTATUS (rc) : -1; 192 193 return rc; 194} 195 196/* 197 * This is used for filters that are actually interactive commands 198 * with input piped in: e.g. in mutt_view_attachment(), a mailcap 199 * entry without copiousoutput _and_ without a %s. 200 * 201 * For those cases, we treat it like a blocking system command, and 202 * poll IMAP to keep connections open. 203 */ 204int mutt_wait_interactive_filter (pid_t pid) 205{ 206 int rc; 207 208#ifndef USE_IMAP 209 waitpid (pid, &rc, 0); 210#else 211 rc = imap_wait_keepalive (pid); 212#endif 213 mutt_unblock_signals_system (1); 214 rc = WIFEXITED (rc) ? WEXITSTATUS (rc) : -1; 215 216 return rc; 217}