version 1.7.3.0
[socat.git] / xio-exec.c
blob1b1c8d5ff9526444060e1b0c943ac7ca6184ba91
1 /* source: xio-exec.c */
2 /* Copyright Gerhard Rieger 2001-2011 */
3 /* Published under the GNU General Public License V.2, see file COPYING */
5 /* this file contains the source for opening addresses of exec type */
7 #include "xiosysincludes.h"
8 #include "xioopen.h"
9 #include "nestlex.h"
11 #include "xio-progcall.h"
12 #include "xio-exec.h"
14 #if WITH_EXEC
16 static int xioopen_exec(int argc, const char *argv[], struct opt *opts,
17 int xioflags, /* XIO_RDONLY etc. */
18 xiofile_t *fd,
19 unsigned groups,
20 int dummy1, int dummy2, int dummy3
23 const struct addrdesc addr_exec = { "exec", 3, xioopen_exec, GROUP_FD|GROUP_FORK|GROUP_EXEC|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_TERMIOS|GROUP_FIFO|GROUP_PTY|GROUP_PARENT, 0, 0, 0 HELP(":<command-line>") };
25 const struct optdesc opt_dash = { "dash", "login", OPT_DASH, GROUP_EXEC, PH_PREEXEC, TYPE_BOOL, OFUNC_SPEC };
27 static int xioopen_exec(int argc, const char *argv[], struct opt *opts,
28 int xioflags, /* XIO_RDONLY, XIO_MAYCHILD etc. */
29 xiofile_t *fd,
30 unsigned groups,
31 int dummy1, int dummy2, int dummy3
32 ) {
33 int status;
34 bool dash = false;
35 int duptostderr;
37 if (argc != 2) {
38 Error3("\"%s:%s\": wrong number of parameters (%d instead of 1)", argv[0], argv[1], argc-1);
41 retropt_bool(opts, OPT_DASH, &dash);
43 status = _xioopen_foxec(xioflags, &fd->stream, groups, &opts, &duptostderr);
44 if (status < 0) return status;
45 if (status == 0) { /* child */
46 const char *ends[] = { " ", NULL };
47 const char *hquotes[] = { "'", NULL };
48 const char *squotes[] = { "\"", NULL };
49 const char *nests[] = {
50 "'", "'",
51 "(", ")",
52 "[", "]",
53 "{", "}",
54 NULL
55 } ;
56 char **pargv = NULL;
57 int pargc;
58 size_t len;
59 const char *strp;
60 char *token; /*! */
61 char *tokp;
62 char *path = NULL;
63 char *tmp;
64 int numleft;
66 /*! Close(something) */
67 /* parse command line */
68 Debug1("child: args = \"%s\"", argv[1]);
69 pargv = Malloc(8*sizeof(char *));
70 if (pargv == NULL) return STAT_RETRYLATER;
71 len = strlen(argv[1])+1;
72 strp = argv[1];
73 token = Malloc(len); /*! */
74 tokp = token;
75 if (nestlex(&strp, &tokp, &len, ends, hquotes, squotes, nests,
76 true, true, false) < 0) {
77 Error("internal: miscalculated string lengths");
79 *tokp++ = '\0';
80 pargv[0] = strrchr(tokp-1, '/');
81 if (pargv[0] == NULL) pargv[0] = token; else ++pargv[0];
82 pargc = 1;
83 while (*strp == ' ') {
84 while (*++strp == ' ') ;
85 if ((pargc & 0x07) == 0) {
86 pargv = Realloc(pargv, (pargc+8)*sizeof(char *));
87 if (pargv == NULL) return STAT_RETRYLATER;
89 pargv[pargc++] = tokp;
90 if (nestlex(&strp, &tokp, &len, ends, hquotes, squotes, nests,
91 true, true, false) < 0) {
92 Error("internal: miscalculated string lengths");
94 *tokp++ = '\0';
96 pargv[pargc] = NULL;
98 if ((tmp = Malloc(strlen(pargv[0])+2)) == NULL) {
99 return STAT_RETRYLATER;
101 if (dash) {
102 tmp[0] = '-';
103 strcpy(tmp+1, pargv[0]);
104 } else {
105 strcpy(tmp, pargv[0]);
107 pargv[0] = tmp;
109 if (setopt_path(opts, &path) < 0) {
110 /* this could be dangerous, so let us abort this child... */
111 Exit(1);
114 if ((numleft = leftopts(opts)) > 0) {
115 Error1("%d option(s) could not be used", numleft);
116 showleft(opts);
117 return STAT_NORETRY;
120 /* only now redirect stderr */
121 if (duptostderr >= 0) {
122 diag_dup();
123 Dup2(duptostderr, 2);
125 Notice1("execvp'ing \"%s\"", token);
126 Execvp(token, pargv);
127 /* here we come only if execvp() failed */
128 switch (pargc) {
129 case 1: Error3("execvp(\"%s\", \"%s\"): %s", token, pargv[0], strerror(errno)); break;
130 case 2: Error4("execvp(\"%s\", \"%s\", \"%s\"): %s", token, pargv[0], pargv[1], strerror(errno)); break;
131 case 3:
132 default:
133 Error5("execvp(\"%s\", \"%s\", \"%s\", \"%s\", ...): %s", token, pargv[0], pargv[1], pargv[2], strerror(errno)); break;
135 Exit(1); /* this child process */
138 /* parent */
139 return 0;
141 #endif /* WITH_EXEC */