813e6b74d402d9bd0603876a1d18a053df91498d
[mmh] / 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", 4 },
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     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 }