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