]> diplodocus.org Git - nmh/blob - uip/vmhtest.c
Just reworded the bit about '%s' being safe not to quote (it's only safe not to
[nmh] / uip / vmhtest.c
1
2 /*
3 * vmhtest.c -- test out vmh protocol
4 *
5 * $Id$
6 */
7
8 #include <h/mh.h>
9 #include <h/vmhsbr.h>
10
11 static struct swit switches[] = {
12 #define READSW 0
13 { "vmhread fd", 7 },
14 #define WRITESW 1
15 { "vmhwrite fd", 8 },
16 #define VERSIONSW 2
17 { "version", 0 },
18 #define HELPSW 3
19 { "help", 0 },
20 { NULL, NULL }
21 };
22
23 #define NWIN 20
24 static int numwins = 0;
25 static int windows[NWIN + 1];
26
27
28 static int selcmds = 0;
29 #define selcmd() (selcmds++ % 2)
30
31 static int selwins = 0;
32 #define selwin() (selwins++ % 2 ? 3 : 1)
33
34
35 int
36 main (int argc, char **argv)
37 {
38 int fd1, fd2;
39 char *cp, buffer[BUFSIZ];
40 char **argp, **arguments;
41
42 #ifdef LOCALE
43 setlocale(LC_ALL, "");
44 #endif
45 invo_name = r1bindex (argv[0], '/');
46
47 /* foil search of user profile/context */
48 if (context_foil (NULL) == -1)
49 done (1);
50
51 arguments = getarguments (invo_name, argc, argv, 0);
52 argp = arguments;
53
54 while ((cp = *argp++))
55 if (*cp == '-')
56 switch (smatch (++cp, switches)) {
57 case AMBIGSW:
58 ambigsw (cp, switches);
59 done (1);
60 case UNKWNSW:
61 adios (NULL, "-%s unknown", cp);
62
63 case HELPSW:
64 snprintf (buffer, sizeof(buffer), "%s [switches]", invo_name);
65 print_help (buffer, switches, 0);
66 done (1);
67 case VERSIONSW:
68 print_version(invo_name);
69 done (1);
70
71 case READSW:
72 if (!(cp = *argp++) || *cp == '-')
73 adios (NULL, "missing argument to %s", argp[-2]);
74 if ((fd1 = atoi (cp)) < 1)
75 adios (NULL, "bad argument %s %s", argp[-2], cp);
76 continue;
77 case WRITESW:
78 if (!(cp = *argp++) || *cp == '-')
79 adios (NULL, "missing argument to %s", argp[-2]);
80 if ((fd2 = atoi (cp)) < 1)
81 adios (NULL, "bad argument %s %s", argp[-2], cp);
82 continue;
83 }
84 else
85 adios (NULL, "usage: %s [switches]", invo_name);
86
87 rcinit (fd1, fd2);
88 pINI ();
89 pLOOP ();
90
91 return done (0);
92 }
93
94
95 static int pINI () {
96 int i,
97 vrsn;
98 char *bp;
99 struct record rcs,
100 *rc = &rcs;
101
102 initrc (rc);
103
104 switch (peer2rc (rc)) {
105 case RC_INI:
106 bp = rc->rc_data;
107 while (isspace (*bp))
108 bp++;
109 if (sscanf (bp, "%d", &vrsn) != 1) {
110 bad_init: ;
111 fmt2peer (RC_ERR, "bad init \"%s\"", rc->rc_data);
112 done (1);
113 }
114 if (vrsn != RC_VRSN) {
115 fmt2peer (RC_ERR, "version %d unsupported", vrsn);
116 done (1);
117 }
118
119 while (*bp && !isspace (*bp))
120 bp++;
121 while (isspace (*bp))
122 bp++;
123 if (sscanf (bp, "%d", &numwins) != 1 || numwins <= 0)
124 goto bad_init;
125 if (numwins > NWIN)
126 numwins = NWIN;
127
128 for (i = 1; i <= numwins; i++) {
129 while (*bp && !isspace (*bp))
130 bp++;
131 while (isspace (*bp))
132 bp++;
133 if (sscanf (bp, "%d", &windows[i]) != 1 || windows[i] <= 0)
134 goto bad_init;
135 }
136 rc2peer (RC_ACK, 0, NULL);
137 return OK;
138
139 case RC_XXX:
140 adios (NULL, "%s", rc->rc_data);
141
142 default:
143 fmt2peer (RC_ERR, "pINI protocol screw-up");
144 done (1); /* NOTREACHED */
145 }
146 }
147
148
149 static int pLOOP () {
150 struct record rcs,
151 *rc = &rcs;
152
153 initrc (rc);
154
155 for (;;)
156 switch (peer2rc (rc)) {
157 case RC_QRY:
158 pQRY (rc->rc_data);
159 break;
160
161 case RC_CMD:
162 pCMD (rc->rc_data);
163 break;
164
165 case RC_FIN:
166 done (0);
167
168 case RC_XXX:
169 adios (NULL, "%s", rc->rc_data);
170
171 default:
172 fmt2peer (RC_ERR, "pLOOP protocol screw-up");
173 done (1);
174 }
175 }
176
177
178 static int pQRY (str)
179 char *str;
180 {
181 rc2peer (RC_EOF, 0, NULL);
182 return OK;
183 }
184
185
186 static int pCMD (str)
187 char *str;
188 {
189 if ((selcmd () ? pTTY (str) : pWIN (str)) == NOTOK)
190 return NOTOK;
191 rc2peer (RC_EOF, 0, NULL);
192 return OK;
193 }
194
195
196 static int pTTY (str)
197 char *str;
198 {
199 struct record rcs,
200 *rc = &rcs;
201
202 initrc (rc);
203
204 switch (rc2rc (RC_TTY, 0, NULL, rc)) {
205 case RC_ACK:
206 break;
207
208 case RC_ERR:
209 return NOTOK;
210
211 case RC_XXX:
212 adios (NULL, "%s", rc->rc_data);
213
214 default:
215 fmt2peer (RC_ERR, "pTTY protocol screw-up");
216 done (1);
217 }
218
219 system (str);
220
221 switch (rc2rc (RC_EOF, 0, NULL, rc)) {
222 case RC_ACK:
223 return OK;
224
225 case RC_XXX:
226 adios (NULL, "%s", rc->rc_data);/* NOTREACHED */
227
228 default:
229 fmt2peer (RC_ERR, "pTTY protocol screw-up");
230 done (1); /* NOTREACHED */
231 }
232 }
233
234
235 static int pWIN (str)
236 char *str;
237 {
238 int i,
239 pid,
240 pd[2];
241 char buffer[BUFSIZ];
242 struct record rcs,
243 *rc = &rcs;
244
245 initrc (rc);
246
247 snprintf (buffer, sizeof(buffer), "%d", selwin ());
248 switch (str2rc (RC_WIN, buffer, rc)) {
249 case RC_ACK:
250 break;
251
252 case RC_ERR:
253 return NOTOK;
254
255 case RC_XXX:
256 adios (NULL, "%s", rc->rc_data);
257
258 default:
259 fmt2peer (RC_ERR, "pWIN protocol screw-up");
260 done (1);
261 }
262
263 if (pipe (pd) == NOTOK) {
264 fmt2peer (RC_ERR, "no pipes");
265 return NOTOK;
266 }
267
268 switch (pid = vfork ()) {
269 case NOTOK:
270 fmt2peer (RC_ERR, "no forks");
271 return NOTOK;
272
273 case OK:
274 close (0);
275 open ("/dev/null", O_RDONLY);
276 dup2 (pd[1], 1);
277 dup2 (pd[1], 2);
278 close (pd[0]);
279 close (pd[1]);
280 execlp ("/bin/sh", "sh", "-c", str, NULL);
281 write (2, "no shell\n", strlen ("no shell\n"));
282 _exit (1);
283
284 default:
285 close (pd[1]);
286 while ((i = read (pd[0], buffer, sizeof buffer)) > 0)
287 switch (rc2rc (RC_DATA, i, buffer, rc)) {
288 case RC_ACK:
289 break;
290
291 case RC_ERR:
292 close (pd[0]);
293 pidwait (pid, OK);
294 return NOTOK;
295
296 case RC_XXX:
297 adios (NULL, "%s", rc->rc_data);
298
299 default:
300 fmt2peer (RC_ERR, "pWIN protocol screw-up");
301 done (1);
302 }
303 if (i == OK)
304 switch (rc2rc (RC_EOF, 0, NULL, rc)) {
305 case RC_ACK:
306 break;
307
308 case RC_XXX:
309 adios (NULL, "%s", rc->rc_data);
310
311 default:
312 fmt2peer (RC_ERR, "pWIN protocol screw-up");
313 done (1);
314 }
315 if (i == NOTOK)
316 fmt2peer (RC_ERR, "read from pipe lost");
317
318 close (pd[0]);
319 pidwait (pid, OK);
320 return (i != NOTOK ? OK : NOTOK);
321 }
322 }