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 libraries 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. *
41 #if !defined(CSRG_BASED)
45 #include <strings.h> /* need to get bzero defined */
48 const int BUFFER_SIZE = 512;
50 Invoke::Invoke(const char *command, // Command to Run
51 char **out_ptr, // ptr to output buffer ptr
52 char **err_ptr, // ptr to error buffer ptr
53 uid_t _uid) // run command as this UID
55 int m_stdout[2], m_stderr[2]; // progname file descriptors
56 pid_t c_pid; // child's pid
58 int out_num,err_num; // # of chars read
59 char *out_tmp, *err_tmp; // temp buffer ptrs
60 char *out_end,*err_end; // ptr to end of buffer
61 int outb_size,errb_size; // buffer size
62 int out_count, err_count; // # of buffers allocated
63 int trap_out,trap_err; // flags; if >0, trap output
64 fd_set rdmask; // for select system call
65 fd_set wrmask; // for select system call
66 fd_set exmask; // for select system call
69 struct sigaction action; // parameters of sigaction
70 struct sigaction oldsigint_act;
71 struct sigaction oldsigquit_act;
75 trap_out = (out_ptr != NULL);
76 trap_err = (err_ptr != NULL);
78 // initialize internal variables
79 out_num = err_num = 0;
81 // setup pipes if specified
86 if (pipe(m_stdout) < 0)
97 if (pipe(m_stderr) < 0)
106 Nfdsmsgs = m_stderr[0] + 1;
108 Nfdsmsgs = m_stdout[0] + 1;
112 // ignore these signals
113 memset(&action, '\0', sizeof (struct sigaction));
114 memset(&oldsigquit_act, '\0', sizeof (struct sigaction));
115 memset(&oldsigint_act, '\0', sizeof (struct sigaction));
117 #if defined(__OSF1__) || defined(__osf__)
118 action.sa_handler = (void (*)(int))SIG_IGN;
119 #elif defined(USL) || defined(__uxp__) || \
120 ( defined(sun) && OSMAJORVERSION == 5 && OSMINORVERSION <= 4)
121 action.sa_handler = (void (*)())SIG_IGN;
123 action.sa_handler = SIG_IGN;
126 sigaction(SIGINT, &action, &oldsigint_act);
127 sigaction(SIGQUIT, &action, &oldsigquit_act);
129 if ((c_pid = fork()) == 0)
130 { // ------------------------ child process --------------------------
132 if (_uid != (uid_t)-1)
136 { // duplicate stdout
144 { // duplicate stderr
152 execlp(KORNSHELL, "ksh", "-c", command, (char *) 0);
156 else if (c_pid == -1)
168 // -------------------------- parent process --------------------------
171 sigaction(SIGINT, &oldsigint_act, NULL);
172 sigaction(SIGQUIT, &oldsigquit_act, NULL);
174 // close the write side of the pipe for the parent
178 fcntl(m_stdout[0], F_SETFL, O_NDELAY);
184 fcntl(m_stderr[0], F_SETFL, O_NDELAY);
187 if (!trap_out && !trap_err)
189 // wait for the child to die
190 while ((w = wait(&status)) != c_pid && w != -1)
192 status = (status >> 8) & 0xFF;
196 // initialize buffer pointers
199 *out_ptr = (char *) malloc(BUFFER_SIZE);
200 if (*out_ptr == NULL)
210 out_end = *out_ptr + BUFFER_SIZE - 1;
212 outb_size = BUFFER_SIZE;
217 *err_ptr = (char *) malloc(BUFFER_SIZE);
218 if (*err_ptr == NULL)
228 *err_ptr = (char *) malloc(BUFFER_SIZE);
230 err_end = *err_ptr + BUFFER_SIZE - 1;
232 errb_size = BUFFER_SIZE;
235 while (trap_out || trap_err)
237 // reset the file descriptor masks
242 // set the bit masks for the descriptors to be checked
244 FD_SET(m_stdout[0], &rdmask);
246 FD_SET(m_stderr[0], &rdmask);
249 if (select(Nfdsmsgs,&rdmask,&wrmask,&exmask,(struct timeval *)NULL) == -1)
264 if (trap_out && FD_ISSET(m_stdout[0], &rdmask))
267 // read the child's stdout
268 if ((out_num = read(m_stdout[0], out_tmp, outb_size)) < 0)
285 else if (out_num == outb_size)
287 // filled up a buffer; allocate another one
289 *out_ptr = (char *)realloc(*out_ptr, (out_count * BUFFER_SIZE));
290 if (*out_ptr == NULL)
299 out_tmp = *out_ptr + ((out_count - 1) * BUFFER_SIZE);
300 out_end = out_tmp + BUFFER_SIZE - 1;
301 outb_size = BUFFER_SIZE;
303 else if (out_num > 0)
305 // read less than a full buffer; reset amount to read next
307 outb_size = out_end - out_tmp + 1;
308 outb_size = (outb_size > 0) ? outb_size : 0;
312 if (trap_err && FD_ISSET(m_stderr[0], &rdmask))
314 // read the child's stderr
315 if ((err_num = read(m_stderr[0], err_tmp, errb_size)) == -1)
333 else if (err_num == errb_size)
335 // filled up a buffer; allocate another one
337 *err_ptr = (char *)realloc(*err_ptr, (err_count * BUFFER_SIZE));
338 if (*err_ptr == NULL)
347 err_tmp = *err_ptr + ((err_count - 1) * BUFFER_SIZE);
348 err_end = err_tmp + BUFFER_SIZE - 1;
349 errb_size = BUFFER_SIZE;
351 else if (err_num > 0)
353 // read less than a full buffer; reset amount to read next
355 errb_size = err_end - err_tmp + 1;
356 errb_size = (errb_size > 0) ? errb_size : 0;
359 } // while trap_out or trap_err
361 while ((w = wait(&status)) != c_pid && w != -1);
362 status = (status >> 8) & 0xFF;