nexmon – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 /* source: xio-exec.c */
2 /* Copyright Gerhard Rieger */
3 /* Published under the GNU General Public License V.2, see file COPYING */
4  
5 /* this file contains the source for opening addresses of exec type */
6 /* this file contains the source for an inter address that just invokes a
7 program. The program should provide its data side on FDs 0 and 1, and its
8 protocol side on FDs 3 and 4. */
9  
10 #include "xiosysincludes.h"
11 #include "xioopen.h"
12 #include "nestlex.h"
13  
14 #include "xio-progcall.h"
15 #include "xio-exec.h"
16  
17 #if WITH_EXEC
18  
19 static int xioopen_exec1(int argc, const char *argv[], struct opt *opts,
20 int xioflags, /* XIO_RDONLY etc. */
21 xiofile_t *fd,
22 unsigned groups,
23 int inter, int form, int dummy3
24 );
25  
26 /* the endpoint variant: get stdin and/or stdout on "left" side. socat does not
27 provide a "right" side for script */
28 static const struct xioaddr_endpoint_desc xioendpoint_exec1 = { XIOADDR_ENDPOINT, "exec", 1, XIOBIT_ALL, GROUP_FD|GROUP_FORK|GROUP_EXEC|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_TERMIOS|GROUP_FIFO|GROUP_PTY|GROUP_PARENT, XIOSHUT_UNSPEC, XIOCLOSE_UNSPEC, xioopen_exec1, false, 0, 0 HELP(":<command-line>") };
29 /* the inter address variant: the bidirectional form has stdin and stdout on
30 its "left" side, and FDs 3 (for reading) and FD 4 (for writing) on its right
31 side. */
32 static const struct xioaddr_inter_desc xiointer_exec1_2rw = { XIOADDR_INTER, "exec", 1, XIOBIT_RDWR, GROUP_FD|GROUP_FORK|GROUP_EXEC|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_TERMIOS|GROUP_FIFO|GROUP_PTY|GROUP_PARENT, XIOSHUT_UNSPEC, XIOCLOSE_UNSPEC, xioopen_exec1, true, 2, 0, XIOBIT_RDWR HELP(":<command-line>") };
33 static const struct xioaddr_inter_desc xiointer_exec1_2ro = { XIOADDR_INTER, "exec", 1, XIOBIT_RDONLY, GROUP_FD|GROUP_FORK|GROUP_EXEC|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_TERMIOS|GROUP_FIFO|GROUP_PTY|GROUP_PARENT, XIOSHUT_UNSPEC, XIOCLOSE_UNSPEC, xioopen_exec1, true, 2, 0, XIOBIT_WRONLY HELP(":<command-line>") };
34 static const struct xioaddr_inter_desc xiointer_exec1_2wo = { XIOADDR_INTER, "exec", 1, XIOBIT_WRONLY, GROUP_FD|GROUP_FORK|GROUP_EXEC|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_TERMIOS|GROUP_FIFO|GROUP_PTY|GROUP_PARENT, XIOSHUT_UNSPEC, XIOCLOSE_UNSPEC, xioopen_exec1, true, 2, 0, XIOBIT_RDONLY HELP(":<command-line>") };
35 /* the unidirectional inter address variant: the "left" side reads from stdin,
36 and the right side reads from stdout. */
37 static const struct xioaddr_inter_desc xiointer_exec1_1wo = { XIOADDR_INTER, "exec1", 1, XIOBIT_WRONLY, GROUP_FD|GROUP_FORK|GROUP_EXEC|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_TERMIOS|GROUP_FIFO|GROUP_PTY|GROUP_PARENT, XIOSHUT_UNSPEC, XIOCLOSE_UNSPEC, xioopen_exec1, true, 1, 0, XIOBIT_RDONLY HELP(":<command-line>") };
38  
39 /* the general forms, designed for bidirectional transfer (stdio -- 3,4) */
40 const union xioaddr_desc *xioaddrs_exec[] = {
41 (union xioaddr_desc *)&xioendpoint_exec1,
42 (union xioaddr_desc *)&xiointer_exec1_2ro,
43 (union xioaddr_desc *)&xiointer_exec1_2wo,
44 (union xioaddr_desc *)&xiointer_exec1_2rw,
45 NULL };
46  
47 /* unidirectional inter address (stdin -- stdout) */
48 const union xioaddr_desc *xioaddrs_exec1[] = {
49 (union xioaddr_desc *)&xiointer_exec1_1wo,
50 NULL };
51  
52  
53 const struct optdesc opt_dash = { "dash", "login", OPT_DASH, GROUP_EXEC, PH_PREEXEC, TYPE_BOOL, OFUNC_SPEC };
54  
55  
56 /* the "1" in the function name means that it takes one parameter */
57 static int xioopen_exec1(int argc, const char *argv[], struct opt *opts,
58 int xioflags, /* XIO_RDONLY, XIO_MAYCHILD etc. */
59 xiofile_t *fd,
60 unsigned groups,
61 int inter, int form, int dummy3
62 ) {
63 int status;
64 bool dash = false;
65 int duptostderr;
66  
67 if (argc != 2) {
68 Error3("\"%s:%s\": wrong number of parameters (%d instead of 1)", argv[0], argv[1], argc-1);
69 }
70  
71 retropt_bool(opts, OPT_DASH, &dash);
72  
73 status = _xioopen_progcall(xioflags, &fd->stream, groups, &opts, &duptostderr, inter, form);
74 if (status < 0) return status;
75 if (status == 0) { /* child */
76 const char *ends[] = { " ", NULL };
77 const char *hquotes[] = { "'", NULL };
78 const char *squotes[] = { "\"", NULL };
79 const char *nests[] = {
80 "'", "'",
81 "(", ")",
82 "[", "]",
83 "{", "}",
84 NULL
85 } ;
86 char **pargv = NULL;
87 int pargc;
88 size_t len;
89 const char *strp;
90 char *token; /*! */
91 char *tokp;
92 char *path = NULL;
93 char *tmp;
94 int numleft;
95  
96 /*! Close(something) */
97 /* parse command line */
98 Debug1("child: args = \"%s\"", argv[1]);
99 pargv = Malloc(8*sizeof(char *));
100 if (pargv == NULL) return STAT_RETRYLATER;
101 len = strlen(argv[1])+1;
102 strp = argv[1];
103 token = Malloc(len); /*! */
104 tokp = token;
105 if (nestlex(&strp, &tokp, &len, ends, hquotes, squotes, nests,
106 false, true, true, false) < 0) {
107 Error("internal: miscalculated string lengths");
108 }
109 *tokp++ = '\0';
110 pargv[0] = strrchr(tokp-1, '/');
111 if (pargv[0] == NULL) pargv[0] = token; else ++pargv[0];
112 pargc = 1;
113 while (*strp == ' ') {
114 while (*++strp == ' ') ;
115 if ((pargc & 0x07) == 0) {
116 pargv = Realloc(pargv, (pargc+8)*sizeof(char *));
117 if (pargv == NULL) return STAT_RETRYLATER;
118 }
119 pargv[pargc++] = tokp;
120 if (nestlex(&strp, &tokp, &len, ends, hquotes, squotes, nests,
121 false, true, true, false) < 0) {
122 Error("internal: miscalculated string lengths");
123 }
124 *tokp++ = '\0';
125 }
126 pargv[pargc] = NULL;
127  
128 if ((tmp = Malloc(strlen(pargv[0])+2)) == NULL) {
129 return STAT_RETRYLATER;
130 }
131 if (dash) {
132 tmp[0] = '-';
133 strcpy(tmp+1, pargv[0]);
134 } else {
135 strcpy(tmp, pargv[0]);
136 }
137 pargv[0] = tmp;
138  
139 if (setopt_path(opts, &path) < 0) {
140 /* this could be dangerous, so let us abort this child... */
141 Exit(1);
142 }
143  
144 if ((numleft = leftopts(opts)) > 0) {
145 Error1("%d option(s) could not be used", numleft);
146 showleft(opts);
147 return STAT_NORETRY;
148 }
149  
150 /* only now redirect stderr */
151 if (duptostderr >= 0) {
152 diag_dup();
153 Dup2(duptostderr, 2);
154 }
155 Notice1("execvp'ing \"%s\"", token);
156 Execvp(token, pargv);
157 /* here we come only if execvp() failed */
158 switch (pargc) {
159 case 1: Error3("execvp(\"%s\", \"%s\"): %s", token, pargv[0], strerror(errno)); break;
160 case 2: Error4("execvp(\"%s\", \"%s\", \"%s\"): %s", token, pargv[0], pargv[1], strerror(errno)); break;
161 case 3:
162 default:
163 Error5("execvp(\"%s\", \"%s\", \"%s\", \"%s\", ...): %s", token, pargv[0], pargv[1], pargv[2], strerror(errno)); break;
164 }
165 Exit(1); /* this child process */
166 }
167  
168 /* parent */
169 return 0;
170 }
171  
172 #endif /* WITH_EXEC */