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(sun) && OSMAJORVERSION == 5 && OSMINORVERSION <= 4)
118 action.sa_handler = (void (*)())SIG_IGN;
120 action.sa_handler = SIG_IGN;
123 sigaction(SIGINT, &action, &oldsigint_act);
124 sigaction(SIGQUIT, &action, &oldsigquit_act);
126 if ((c_pid = fork()) == 0)
127 { // ------------------------ child process --------------------------
129 if (_uid != (uid_t)-1)
133 { // duplicate stdout
141 { // duplicate stderr
149 execlp(KORNSHELL, "ksh", "-c", command, (char *) 0);
153 else if (c_pid == -1)
165 // -------------------------- parent process --------------------------
168 sigaction(SIGINT, &oldsigint_act, NULL);
169 sigaction(SIGQUIT, &oldsigquit_act, NULL);
171 // close the write side of the pipe for the parent
175 fcntl(m_stdout[0], F_SETFL, O_NDELAY);
181 fcntl(m_stderr[0], F_SETFL, O_NDELAY);
184 if (!trap_out && !trap_err)
186 // wait for the child to die
187 while ((w = wait(&status)) != c_pid && w != -1)
189 status = (status >> 8) & 0xFF;
193 // initialize buffer pointers
196 *out_ptr = (char *) malloc(BUFFER_SIZE);
197 if (*out_ptr == NULL)
207 out_end = *out_ptr + BUFFER_SIZE - 1;
209 outb_size = BUFFER_SIZE;
214 *err_ptr = (char *) malloc(BUFFER_SIZE);
215 if (*err_ptr == NULL)
225 *err_ptr = (char *) malloc(BUFFER_SIZE);
227 err_end = *err_ptr + BUFFER_SIZE - 1;
229 errb_size = BUFFER_SIZE;
232 while (trap_out || trap_err)
234 // reset the file descriptor masks
239 // set the bit masks for the descriptors to be checked
241 FD_SET(m_stdout[0], &rdmask);
243 FD_SET(m_stderr[0], &rdmask);
246 if (select(Nfdsmsgs,&rdmask,&wrmask,&exmask,(struct timeval *)NULL) == -1)
261 if (trap_out && FD_ISSET(m_stdout[0], &rdmask))
264 // read the child's stdout
265 if ((out_num = read(m_stdout[0], out_tmp, outb_size)) < 0)
282 else if (out_num == outb_size)
284 // filled up a buffer; allocate another one
286 *out_ptr = (char *)realloc(*out_ptr, (out_count * BUFFER_SIZE));
287 if (*out_ptr == NULL)
296 out_tmp = *out_ptr + ((out_count - 1) * BUFFER_SIZE);
297 out_end = out_tmp + BUFFER_SIZE - 1;
298 outb_size = BUFFER_SIZE;
300 else if (out_num > 0)
302 // read less than a full buffer; reset amount to read next
304 outb_size = out_end - out_tmp + 1;
305 outb_size = (outb_size > 0) ? outb_size : 0;
309 if (trap_err && FD_ISSET(m_stderr[0], &rdmask))
311 // read the child's stderr
312 if ((err_num = read(m_stderr[0], err_tmp, errb_size)) == -1)
330 else if (err_num == errb_size)
332 // filled up a buffer; allocate another one
334 *err_ptr = (char *)realloc(*err_ptr, (err_count * BUFFER_SIZE));
335 if (*err_ptr == NULL)
344 err_tmp = *err_ptr + ((err_count - 1) * BUFFER_SIZE);
345 err_end = err_tmp + BUFFER_SIZE - 1;
346 errb_size = BUFFER_SIZE;
348 else if (err_num > 0)
350 // read less than a full buffer; reset amount to read next
352 errb_size = err_end - err_tmp + 1;
353 errb_size = (errb_size > 0) ? errb_size : 0;
356 } // while trap_out or trap_err
358 while ((w = wait(&status)) != c_pid && w != -1);
359 status = (status >> 8) & 0xFF;