1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
|
/* source: xio-shell.c */
/* Copyright Gerhard Rieger and contributors (see file CHANGES) */
/* Published under the GNU General Public License V.2, see file COPYING */
/* this file contains the source for opening addresses of shell type */
#include "xiosysincludes.h"
#include "xioopen.h"
#include "xio-progcall.h"
#include "xio-shell.h"
#if WITH_SHELL
static int xioopen_shell(int arg, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, const struct addrdesc *addrdesc);
const struct addrdesc xioaddr_shell = { "SHELL", 3, xioopen_shell, GROUP_FD|GROUP_FORK|GROUP_EXEC|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_TERMIOS|GROUP_FIFO|GROUP_PTY|GROUP_PARENT|GROUP_SHELL, 1, 0, 0 HELP("[:<shell-command>]") };
const struct optdesc opt_shell = { "shell", NULL, OPT_SHELL, GROUP_SHELL, PH_PREEXEC, TYPE_STRING, OFUNC_SPEC, 0, 0 };
static int xioopen_shell(
int argc,
const char *argv[],
struct opt *opts,
int xioflags,
xiofile_t *xfd,
const struct addrdesc *addrdesc)
{
struct single *sfd = &xfd->stream;
int status;
char *path = NULL;
int duptostderr;
int result;
char *shellpath = NULL;
const char *shellname;
const char *string = argv[1];
if (argc < 1 || argc > 2) {
xio_syntax(argv[0], 1, argc-1, addrdesc->syntax);
return STAT_NORETRY;
}
shellpath = getenv("SHELL");
retropt_string(opts, OPT_SHELL, &shellpath);
if (shellpath == NULL) {
Error("SHELL variable undefined");
errno = EINVAL;
return -1;
}
shellname = strrchr(shellpath, '/');
if (shellname == NULL) {
Error1("SHELL \"%s\" variable does not specify a path (has no '/')", shellpath);
errno = EINVAL;
return -1;
}
++shellname;
status = _xioopen_foxec(xioflags, sfd, addrdesc->groups, &opts, &duptostderr);
if (status < 0) return status;
if (status == 0) { /* child */
int numleft;
if (setopt_path(opts, &path) < 0) {
/* this could be dangerous, so let us abort this child... */
Exit(1);
}
if ((numleft = leftopts(opts)) > 0) {
Error1("%d option(s) could not be used", numleft);
showleft(opts);
return STAT_NORETRY;
}
/* only now redirect stderr */
if (duptostderr >= 0) {
diag_dup();
Dup2(duptostderr, 2);
}
Setenv("SHELL", shellpath, 1);
if (string != NULL) {
Info1("executing shell command \"%s\"", string);
Debug3("execl(\"%s\", \"%s\", \"-c\", \"%s\", NULL)",
shellpath, shellname, string);
result = execl(shellpath, shellname, "-c", string, (char *)NULL);
} else {
Info("executing interactive shell");
Debug2("execl(\"%s\", \"%s\", NULL)",
shellpath, shellname);
result = execl(shellpath, shellname, (char *)NULL);
}
if (result != 0) {
Warn2("execl(\"%s\") returned with status %d", string, result);
Warn1("execl(): %s", strerror(errno));
}
Exit(0); /* this child process */
}
/* parent */
return 0;
}
#endif /* WITH_SHELL */
|