2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 /* $TOG: Invoke.C /main/7 1997/07/30 15:42:39 samborn $ */
25 * (c) Copyright 1993, 1994 Hewlett-Packard Company *
26 * (c) Copyright 1993, 1994 International Business Machines Corp. *
27 * (c) Copyright 1993, 1994 Sun Microsystems, Inc. *
28 * (c) Copyright 1993, 1994 Novell, Inc. *
43 #include <strings.h> /* need to get bzero defined */
46 const BUFFER_SIZE = 512;
48 Invoke::Invoke(const char *command, // Command to Run
49 char **out_ptr, // ptr to output buffer ptr
50 char **err_ptr, // ptr to error buffer ptr
51 uid_t _uid) // run command as this UID
53 int m_stdout[2], m_stderr[2]; // progname file descriptors
54 pid_t c_pid; // child's pid
56 int out_num,err_num; // # of chars read
57 char *out_tmp, *err_tmp; // temp buffer ptrs
58 char *out_end,*err_end; // ptr to end of buffer
59 int outb_size,errb_size; // buffer size
60 int out_count, err_count; // # of buffers allocated
61 int trap_out,trap_err; // flags; if >0, trap output
62 fd_set rdmask; // for select system call
63 fd_set wrmask; // for select system call
64 fd_set exmask; // for select system call
67 struct sigaction action; // parameters of sigaction
68 struct sigaction oldsigint_act;
69 struct sigaction oldsigquit_act;
73 trap_out = (out_ptr != NULL);
74 trap_err = (err_ptr != NULL);
76 // initialize internal variables
77 out_num = err_num = 0;
79 // setup pipes if specified
84 if (pipe(m_stdout) < 0)
95 if (pipe(m_stderr) < 0)
104 Nfdsmsgs = m_stderr[0] + 1;
106 Nfdsmsgs = m_stdout[0] + 1;
110 // ignore these signals
111 memset(&action, '\0', sizeof (struct sigaction));
112 memset(&oldsigquit_act, '\0', sizeof (struct sigaction));
113 memset(&oldsigint_act, '\0', sizeof (struct sigaction));
115 #if defined(__OSF1__) || defined(__osf__)
116 action.sa_handler = (void (*)(int))SIG_IGN;
117 #elif defined(USL) || defined(__uxp__) || \
118 ( defined(sun) && OSMAJORVERSION == 5 && OSMINORVERSION <= 4)
119 action.sa_handler = (void (*)())SIG_IGN;
121 action.sa_handler = SIG_IGN;
124 sigaction(SIGINT, &action, &oldsigint_act);
125 sigaction(SIGQUIT, &action, &oldsigquit_act);
127 if ((c_pid = fork()) == 0)
128 { // ------------------------ child process --------------------------
130 if (_uid != (uid_t)-1)
134 { // duplicate stdout
142 { // duplicate stderr
150 execlp("/bin/ksh", "ksh", "-c", command, (char *) 0);
154 else if (c_pid == -1)
166 // -------------------------- parent process --------------------------
169 sigaction(SIGINT, &oldsigint_act, NULL);
170 sigaction(SIGQUIT, &oldsigquit_act, NULL);
172 // close the write side of the pipe for the parent
176 fcntl(m_stdout[0], F_SETFL, O_NDELAY);
182 fcntl(m_stderr[0], F_SETFL, O_NDELAY);
185 if (!trap_out && !trap_err)
187 // wait for the child to die
188 while ((w = wait(&status)) != c_pid && w != -1)
190 status = (status >> 8) & 0xFF;
194 // initialize buffer pointers
197 *out_ptr = (char *) malloc(BUFFER_SIZE);
198 if (*out_ptr == NULL)
208 out_end = *out_ptr + BUFFER_SIZE - 1;
210 outb_size = BUFFER_SIZE;
215 *err_ptr = (char *) malloc(BUFFER_SIZE);
216 if (*err_ptr == NULL)
226 *err_ptr = (char *) malloc(BUFFER_SIZE);
228 err_end = *err_ptr + BUFFER_SIZE - 1;
230 errb_size = BUFFER_SIZE;
233 while (trap_out || trap_err)
235 // reset the file descriptor masks
240 // set the bit masks for the descriptors to be checked
242 FD_SET(m_stdout[0], &rdmask);
244 FD_SET(m_stderr[0], &rdmask);
247 if (select(Nfdsmsgs,&rdmask,&wrmask,&exmask,(struct timeval *)NULL) == -1)
262 if (trap_out && FD_ISSET(m_stdout[0], &rdmask))
265 // read the child's stdout
266 if ((out_num = read(m_stdout[0], out_tmp, outb_size)) < 0)
283 else if (out_num == outb_size)
285 // filled up a buffer; allocate another one
287 *out_ptr = (char *)realloc(*out_ptr, (out_count * BUFFER_SIZE));
288 if (*out_ptr == NULL)
297 out_tmp = *out_ptr + ((out_count - 1) * BUFFER_SIZE);
298 out_end = out_tmp + BUFFER_SIZE - 1;
299 outb_size = BUFFER_SIZE;
301 else if (out_num > 0)
303 // read less than a full buffer; reset amount to read next
305 outb_size = out_end - out_tmp + 1;
306 outb_size = (outb_size > 0) ? outb_size : 0;
310 if (trap_err && FD_ISSET(m_stderr[0], &rdmask))
312 // read the child's stderr
313 if ((err_num = read(m_stderr[0], err_tmp, errb_size)) == -1)
331 else if (err_num == errb_size)
333 // filled up a buffer; allocate another one
335 *err_ptr = (char *)realloc(*err_ptr, (err_count * BUFFER_SIZE));
336 if (*err_ptr == NULL)
345 err_tmp = *err_ptr + ((err_count - 1) * BUFFER_SIZE);
346 err_end = err_tmp + BUFFER_SIZE - 1;
347 errb_size = BUFFER_SIZE;
349 else if (err_num > 0)
351 // read less than a full buffer; reset amount to read next
353 errb_size = err_end - err_tmp + 1;
354 errb_size = (errb_size > 0) ? errb_size : 0;
357 } // while trap_out or trap_err
359 while ((w = wait(&status)) != c_pid && w != -1);
360 status = (status >> 8) & 0xFF;