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