Version 1.8.0.0
[socat.git] / xio-shell.c
blob8a41e21b08f10fa56be389926cbb19c9725ecf72
1 /* source: xio-shell.c */
2 /* Copyright Gerhard Rieger and contributors (see file CHANGES) */
3 /* Published under the GNU General Public License V.2, see file COPYING */
5 /* this file contains the source for opening addresses of shell type */
7 #include "xiosysincludes.h"
8 #include "xioopen.h"
10 #include "xio-progcall.h"
11 #include "xio-shell.h"
14 #if WITH_SHELL
16 static int xioopen_shell(int arg, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, const struct addrdesc *addrdesc);
18 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>") };
20 const struct optdesc opt_shell = { "shell", NULL, OPT_SHELL, GROUP_SHELL, PH_PREEXEC, TYPE_STRING, OFUNC_SPEC, 0, 0 };
22 static int xioopen_shell(
23 int argc,
24 const char *argv[],
25 struct opt *opts,
26 int xioflags,
27 xiofile_t *xfd,
28 const struct addrdesc *addrdesc)
30 struct single *sfd = &xfd->stream;
31 int status;
32 char *path = NULL;
33 int duptostderr;
34 int result;
35 char *shellpath = NULL;
36 const char *shellname;
37 const char *string = argv[1];
39 if (argc != 2) {
40 xio_syntax(argv[0], 1, argc-1, addrdesc->syntax);
41 return STAT_NORETRY;
44 shellpath = getenv("SHELL");
45 retropt_string(opts, OPT_SHELL, &shellpath);
46 if (shellpath == NULL) {
47 Error("SHELL variable undefined");
48 errno = EINVAL;
49 return -1;
51 shellname = strrchr(shellpath, '/');
52 if (shellname == NULL) {
53 Error1("SHELL \"%s\" variable does not specify a path (has no '/')", shellpath);
54 errno = EINVAL;
55 return -1;
57 ++shellname;
59 status = _xioopen_foxec(xioflags, sfd, addrdesc->groups, &opts, &duptostderr);
60 if (status < 0) return status;
61 if (status == 0) { /* child */
62 int numleft;
64 if (setopt_path(opts, &path) < 0) {
65 /* this could be dangerous, so let us abort this child... */
66 Exit(1);
69 if ((numleft = leftopts(opts)) > 0) {
70 Error1("%d option(s) could not be used", numleft);
71 showleft(opts);
72 return STAT_NORETRY;
75 /* only now redirect stderr */
76 if (duptostderr >= 0) {
77 diag_dup();
78 Dup2(duptostderr, 2);
81 Setenv("SHELL", shellpath, 1);
83 Info1("executing shell command \"%s\"", string);
84 Debug3("execl(\"%s\", \"%s\", \"-c\", \"%s\", NULL",
85 shellpath, shellname, string);
86 result = execl(shellpath, shellname, "-c", string, (char *)NULL);
87 if (result != 0) {
88 Warn2("execl(\"%s\") returned with status %d", string, result);
89 Warn1("execl(): %s", strerror(errno));
91 Exit(0); /* this child process */
94 /* parent */
95 return 0;
98 #endif /* WITH_SHELL */