1
0
Fork 0
mirror of git://git.code.sf.net/p/cdesktopenv/code synced 2025-03-09 15:50:02 +00:00
cde/cde/programs/dtprintinfo/util/Invoke.C
Marcin Cieslak 17a33f0430 Use KORNSHELL variable instead of /bin/ksh
This patch removes instances of hardcoded
invocation of /bin/ksh and allows to
replace it with, for, example,
/usr/local/bin/ksh93

Also "ksh93" is accepted whenever "ksh" is.

Tested using the following /bin/ksh:

----8<----
WHAT=`ps -o command= -p $PPID`
msg="Something tried to call /bin/ksh: $PPID: $WHAT"
print -u2 "$msg"
logger user.warn "$msg"
exit 99
----8<----
(Warning: first two lines are FreeBSD specific)

Scripts from Makefiles should now be executed either
with

$(KORNSHELL) korn-shell-script

or

$(SHELL) bourne-shell-script

therefore #!/bin/ksh has not been changed everywhere.

/usr/dt/bin/ scripts have been converted (e.g. Xsession)

Whenever possible Imake and CPP facilities have been used.

For C and C++ programs KORNSHELL needs to be defined to
"/path/to/your/ksh" (with quotes) so that it can make
a valid C constant.

Therefore, when adding KORNSHELL to Imakefile for C files,
you have to add

CXXEXTRA_DEFINES = -DKORNSHELL=\"$(KORNSHELL)\"

or similar (for example, see programs/dtprintinfo)

But for simple shell script substitution we usually change

 LOCAL_CPP_DEFINES = -DCDE_CONFIGURATION_TOP=$(CDE_CONFIGURATION_TOP) \
                     -DCDE_INSTALLATION_TOP=$(CDE_INSTALLATION_TOP) \
                     -DCDE_LOGFILES_TOP=$(CDE_LOGFILES_TOP)

to:

 LOCAL_CPP_DEFINES = -DCDE_CONFIGURATION_TOP=$(CDE_CONFIGURATION_TOP) \
                     -DCDE_INSTALLATION_TOP=$(CDE_INSTALLATION_TOP) \
                     -DCDE_LOGFILES_TOP=$(CDE_LOGFILES_TOP) \
                     -DKORNSHELL=$(KORNSHELL) \
                     -DXPROJECTROOT=X11ProjectRoot

since we don't want quotes for shell scripts.
2012-08-23 20:00:43 -06:00

363 lines
9.7 KiB
C

/*
* CDE - Common Desktop Environment
*
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
*
* These libraries and programs are free software; you can
* redistribute them and/or modify them under the terms of the GNU
* Lesser General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* These libraries and programs are distributed in the hope that
* they will be useful, but WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with these librararies and programs; if not, write
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
* Floor, Boston, MA 02110-1301 USA
*/
/* $TOG: Invoke.C /main/7 1997/07/30 15:42:39 samborn $ */
/* *
* (c) Copyright 1993, 1994 Hewlett-Packard Company *
* (c) Copyright 1993, 1994 International Business Machines Corp. *
* (c) Copyright 1993, 1994 Sun Microsystems, Inc. *
* (c) Copyright 1993, 1994 Novell, Inc. *
*/
#include "Invoke.h"
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <fcntl.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <string.h>
#include <errno.h>
#if !defined(CSRG_BASED)
#include <values.h>
#endif
#ifdef _AIX
#include <strings.h> /* need to get bzero defined */
#endif /* _AIX */
const int BUFFER_SIZE = 512;
Invoke::Invoke(const char *command, // Command to Run
char **out_ptr, // ptr to output buffer ptr
char **err_ptr, // ptr to error buffer ptr
uid_t _uid) // run command as this UID
{
int m_stdout[2], m_stderr[2]; // progname file descriptors
pid_t c_pid; // child's pid
pid_t w; // temp vars
int out_num,err_num; // # of chars read
char *out_tmp, *err_tmp; // temp buffer ptrs
char *out_end,*err_end; // ptr to end of buffer
int outb_size,errb_size; // buffer size
int out_count, err_count; // # of buffers allocated
int trap_out,trap_err; // flags; if >0, trap output
fd_set rdmask; // for select system call
fd_set wrmask; // for select system call
fd_set exmask; // for select system call
int Nfdsmsgs;
struct sigaction action; // parameters of sigaction
struct sigaction oldsigint_act;
struct sigaction oldsigquit_act;
status = 0;
trap_out = (out_ptr != NULL);
trap_err = (err_ptr != NULL);
// initialize internal variables
out_num = err_num = 0;
// setup pipes if specified
if (trap_out)
{
*out_ptr = 0;
if (pipe(m_stdout) < 0)
{
status = -1;
return;
}
}
if (trap_err)
{
*err_ptr = 0;
if (pipe(m_stderr) < 0)
{
if (trap_out)
close(m_stdout[0]);
status = -1;
return;
}
}
if (trap_err)
Nfdsmsgs = m_stderr[0] + 1;
else if (trap_out)
Nfdsmsgs = m_stdout[0] + 1;
else
Nfdsmsgs = 0;
// ignore these signals
memset(&action, '\0', sizeof (struct sigaction));
memset(&oldsigquit_act, '\0', sizeof (struct sigaction));
memset(&oldsigint_act, '\0', sizeof (struct sigaction));
#if defined(__OSF1__) || defined(__osf__)
action.sa_handler = (void (*)(int))SIG_IGN;
#elif defined(USL) || defined(__uxp__) || \
( defined(sun) && OSMAJORVERSION == 5 && OSMINORVERSION <= 4)
action.sa_handler = (void (*)())SIG_IGN;
#else
action.sa_handler = SIG_IGN;
#endif
sigaction(SIGINT, &action, &oldsigint_act);
sigaction(SIGQUIT, &action, &oldsigquit_act);
if ((c_pid = fork()) == 0)
{ // ------------------------ child process --------------------------
if (_uid != (uid_t)-1)
setuid(_uid);
if (trap_out)
{ // duplicate stdout
close(m_stdout[0]);
close(1);
dup(m_stdout[1]);
close(m_stdout[1]);
}
if (trap_err)
{ // duplicate stderr
close(m_stderr[0]);
close(2);
dup(m_stderr[1]);
close(m_stderr[1]);
}
// start the program
execlp(KORNSHELL, "ksh", "-c", command, (char *) 0);
exit(-1);
}
else if (c_pid == -1)
{
if (trap_err)
close(m_stderr[0]);
if (trap_out)
close(m_stdout[0]);
status = -1;
return;
}
// -------------------------- parent process --------------------------
// restore signals
sigaction(SIGINT, &oldsigint_act, NULL);
sigaction(SIGQUIT, &oldsigquit_act, NULL);
// close the write side of the pipe for the parent
if (trap_out)
{
close(m_stdout[1]);
fcntl(m_stdout[0], F_SETFL, O_NDELAY);
}
if (trap_err)
{
close(m_stderr[1]);
fcntl(m_stderr[0], F_SETFL, O_NDELAY);
}
if (!trap_out && !trap_err)
{ // no piped output
// wait for the child to die
while ((w = wait(&status)) != c_pid && w != -1)
;
status = (status >> 8) & 0xFF;
return;
}
// initialize buffer pointers
if (trap_out)
{
*out_ptr = (char *) malloc(BUFFER_SIZE);
if (*out_ptr == NULL)
{
close(m_stdout[0]);
if (trap_err)
close(m_stderr[0]);
status = -1;
return;
}
out_tmp = *out_ptr;
out_end = *out_ptr + BUFFER_SIZE - 1;
out_count = 1;
outb_size = BUFFER_SIZE;
}
if (trap_err)
{
*err_ptr = (char *) malloc(BUFFER_SIZE);
if (*err_ptr == NULL)
{
close(m_stderr[0]);
if (trap_out)
close(m_stdout[0]);
status = -1;
return;
}
*err_ptr = (char *) malloc(BUFFER_SIZE);
err_tmp = *err_ptr;
err_end = *err_ptr + BUFFER_SIZE - 1;
err_count = 1;
errb_size = BUFFER_SIZE;
}
while (trap_out || trap_err)
{
// reset the file descriptor masks
FD_ZERO(&rdmask);
FD_ZERO(&wrmask);
FD_ZERO(&exmask);
// set the bit masks for the descriptors to be checked
if (trap_out)
FD_SET(m_stdout[0], &rdmask);
if (trap_err)
FD_SET(m_stderr[0], &rdmask);
// check the status
if (select(Nfdsmsgs,&rdmask,&wrmask,&exmask,(struct timeval *)NULL) == -1)
{
if (errno == EINTR)
continue;
else
{
if (trap_out)
close(m_stdout[0]);
if (trap_err)
close(m_stderr[0]);
status = -1;
return;
}
}
if (trap_out && FD_ISSET(m_stdout[0], &rdmask))
{
// read the child's stdout
if ((out_num = read(m_stdout[0], out_tmp, outb_size)) < 0)
{
close(m_stdout[0]);
if (trap_err)
close(m_stderr[0]);
status = -1;
return;
}
if (out_num == 0)
{
// no more to read
trap_out = 0;
close(m_stdout[0]);
*out_tmp = '\0';
}
else if (out_num == outb_size)
{
// filled up a buffer; allocate another one
out_count++;
*out_ptr = (char *)realloc(*out_ptr, (out_count * BUFFER_SIZE));
if (*out_ptr == NULL)
{
close(m_stdout[0]);
if (trap_err)
close(m_stderr[0]);
status = -1;
return;
}
out_tmp = *out_ptr + ((out_count - 1) * BUFFER_SIZE);
out_end = out_tmp + BUFFER_SIZE - 1;
outb_size = BUFFER_SIZE;
}
else if (out_num > 0)
{
// read less than a full buffer; reset amount to read next
out_tmp += out_num;
outb_size = out_end - out_tmp + 1;
outb_size = (outb_size > 0) ? outb_size : 0;
}
} // if trap_out
if (trap_err && FD_ISSET(m_stderr[0], &rdmask))
{
// read the child's stderr
if ((err_num = read(m_stderr[0], err_tmp, errb_size)) == -1)
{
if (trap_out)
close(m_stdout[0]);
close(m_stderr[0]);
status = -1;
return;
}
if (err_num == 0)
{
// no more to read
trap_err = 0;
close(m_stderr[0]);
*err_tmp = '\0';
}
else if (err_num == errb_size)
{
// filled up a buffer; allocate another one
err_count++;
*err_ptr = (char *)realloc(*err_ptr, (err_count * BUFFER_SIZE));
if (*err_ptr == NULL)
{
close(m_stderr[0]);
if (trap_out)
close(m_stdout[0]);
status = -1;
return;
}
err_tmp = *err_ptr + ((err_count - 1) * BUFFER_SIZE);
err_end = err_tmp + BUFFER_SIZE - 1;
errb_size = BUFFER_SIZE;
}
else if (err_num > 0)
{
// read less than a full buffer; reset amount to read next
err_tmp += err_num;
errb_size = err_end - err_tmp + 1;
errb_size = (errb_size > 0) ? errb_size : 0;
}
} // if trap_err
} // while trap_out or trap_err
while ((w = wait(&status)) != c_pid && w != -1);
status = (status >> 8) & 0xFF;
}