nexmon – Blame information for rev 1
?pathlinks?
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 */ |