0
|
1 /* msh.c - The MH shell (sigh) */
|
|
2 #ifndef lint
|
|
3 static char ident[] = "@(#)$Id$";
|
|
4 #endif /* lint */
|
|
5
|
|
6 /* TODO:
|
|
7 Keep more status information in maildrop map
|
|
8 */
|
|
9
|
|
10 #include "../h/mh.h"
|
|
11 #include "../h/dropsbr.h"
|
|
12 #include "../h/formatsbr.h"
|
|
13 #include "../h/scansbr.h"
|
|
14 #include "../zotnet/tws.h"
|
|
15 #include <stdio.h>
|
|
16 #include "../zotnet/mts.h"
|
|
17 #include <ctype.h>
|
|
18 #include <sys/types.h>
|
|
19 #include <sys/stat.h>
|
|
20 #ifndef SYS5
|
|
21 #include <sgtty.h>
|
|
22 #else /* SYS5 */
|
|
23 #include <termio.h>
|
|
24 #ifndef NOIOCTLH
|
|
25 #include <sys/ioctl.h>
|
|
26 #endif /* NOIOCTLH */
|
|
27 #endif /* SYS5 */
|
|
28 #include <pwd.h>
|
|
29 #include <setjmp.h>
|
|
30 #include <signal.h>
|
|
31 #include "../h/mshsbr.h"
|
|
32 #include "../h/vmhsbr.h"
|
|
33 #ifdef LOCALE
|
|
34 #include <locale.h>
|
|
35 #endif
|
|
36 #ifdef READLINE
|
|
37 #include <readline/readline.h>
|
|
38 #endif
|
|
39 #ifndef MIME
|
|
40 #define MIMEminc(a) (a)
|
|
41 #else
|
|
42 #define MIMEminc(a) 0
|
|
43 #endif
|
|
44
|
|
45 #define QUOTE '\\' /* sigh */
|
|
46
|
|
47
|
|
48 /* */
|
|
49
|
|
50 static struct swit switches[] = {
|
|
51 #define IDSW 0
|
|
52 "idstart number", -7, /* interface from bbc */
|
|
53 #define FDSW 1
|
|
54 "idstop number", -6, /* .. */
|
|
55 #define QDSW 2
|
|
56 "idquit number", -6, /* .. */
|
|
57 #define NMSW 3
|
|
58 "idname BBoard", -6, /* .. */
|
|
59
|
|
60 #define PRMPTSW 4
|
|
61 "prompt string", 0,
|
|
62
|
|
63 #define SCANSW 5
|
|
64 "scan", 0,
|
|
65 #define NSCANSW 6
|
|
66 "noscan", 0,
|
|
67
|
|
68 #define READSW 7
|
|
69 "vmhread fd", -7,
|
|
70 #define WRITESW 8
|
|
71 "vmhwrite fd", -8,
|
|
72
|
|
73 #define PREADSW 9
|
|
74 "popread fd", -7,
|
|
75 #define PWRITSW 10
|
|
76 "popwrite fd", -8,
|
|
77
|
|
78 #define TCURSW 11
|
|
79 "topcur", 0,
|
|
80 #define NTCURSW 12
|
|
81 "notopcur", 0,
|
|
82
|
|
83 #define HELPSW 13
|
|
84 "help", 4,
|
|
85
|
|
86 NULL, 0
|
|
87 };
|
|
88
|
|
89 /* */
|
|
90 /* FOLDER */
|
|
91 char *fmsh = NULL; /* folder instead of file */
|
|
92 int modified; /* command modified folder */
|
|
93 struct msgs *mp; /* used a lot */
|
|
94 static int nMsgs = 0;
|
|
95 struct Msg *Msgs = NULL; /* Msgs[0] not used */
|
|
96 static FILE *fp; /* input file */
|
|
97 static FILE *yp = NULL; /* temporary file */
|
|
98 static int mode; /* mode of file */
|
|
99 static int numfds = 0; /* number of files cached */
|
|
100 static int maxfds = 0; /* number of files cached to be cached */
|
|
101 static time_t mtime = (time_t) 0;/* mtime of file */
|
|
102
|
|
103
|
|
104 /* VMH */
|
|
105 #define ALARM ((unsigned int) 10)
|
|
106 #define ttyN(c) ttyNaux ((c), NULLCP)
|
|
107
|
|
108 static int vmh = 0;
|
|
109
|
|
110 static int vmhpid = OK;
|
|
111 static int vmhfd0;
|
|
112 static int vmhfd1;
|
|
113 static int vmhfd2;
|
|
114
|
|
115 static int vmhtty = NOTOK;
|
|
116
|
|
117 #define SCAN 1
|
|
118 #define STATUS 2
|
|
119 #define DISPLAY 3
|
|
120 #define NWIN DISPLAY
|
|
121
|
|
122 static int topcur = 0;
|
|
123
|
|
124 static int numwins = 0;
|
|
125 static int windows[NWIN + 1];
|
|
126
|
|
127 static jmp_buf peerenv;
|
|
128
|
|
129 void padios (), padvise ();
|
|
130 static TYPESIG alrmser ();
|
|
131
|
|
132
|
|
133 #if defined(BPOP) || defined(NNTP)
|
|
134 /* POP */
|
|
135
|
|
136 int pmsh = 0; /* BPOP enabled */
|
|
137
|
|
138 extern char response[];
|
|
139 #endif /* BPOP || NNTP */
|
|
140
|
|
141
|
|
142 /* PARENT */
|
|
143 static int pfd = NOTOK; /* fd parent is reading from */
|
|
144 static int ppid = 0; /* pid of parent */
|
|
145
|
|
146
|
|
147 /* COMMAND */
|
|
148 int interactive; /* running from a /dev/tty */
|
|
149 int redirected; /* re-directing output */
|
|
150 FILE *sp = NULL; /* original stdout */
|
|
151
|
|
152 char *cmd_name; /* command being run */
|
|
153
|
|
154 char myfilter[BUFSIZ]; /* path to mhl.forward */
|
|
155
|
|
156 static char *myprompt = "(%s) ";/* prompting string */
|
|
157
|
|
158
|
|
159 /* BBOARDS */
|
|
160 static int gap; /* gap in BBoard-ID:s */
|
|
161
|
|
162 static char *myname = NULL; /* BBoard name */
|
|
163
|
|
164 char *BBoard_ID = "BBoard-ID";/* BBoard-ID constant */
|
|
165
|
|
166 /* SIGNALS */
|
|
167 TYPESIG (*istat) (); /* original SIGINT */
|
|
168 static TYPESIG (*pstat) (); /* current SIGPIPE */
|
|
169 TYPESIG (*qstat) (); /* original SIGQUIT */
|
|
170 #ifdef SIGTSTP
|
|
171 static TYPESIG (*tstat) (); /* original SIGTSTP */
|
|
172 #endif /* SIGTSTP */
|
|
173 int interrupted; /* SIGINT detected */
|
|
174 int broken_pipe; /* SIGPIPE detected */
|
|
175 int told_to_quit; /* SIGQUIT detected */
|
|
176
|
|
177 #if defined(BSD42) || defined(SVR4)
|
|
178 int should_intr; /* signal handler should interrupt call */
|
|
179 jmp_buf sigenv; /* the environment pointer */
|
|
180 #endif /* BSD42 || SVR4 */
|
|
181
|
|
182 static TYPESIG intrser (), pipeser (), quitser ();
|
|
183
|
|
184
|
|
185 #ifndef __STDC__
|
|
186 #ifdef SYS5
|
|
187 struct passwd *getpwnam ();
|
|
188 #endif /* SYS5 */
|
|
189 #endif
|
|
190
|
|
191 static int read_map(), read_file(), check_folder(), getargs(), parse();
|
|
192 static int getcmds(), init_io(), initaux_io(), finaux_io(), peerwait();
|
|
193 static int pINI(), pQRY(), pQRY1(), pQRY2(), pCMD(), pFIN();
|
|
194 static int ttyR(), ttyNaux(), winN(), winR(), winX();
|
|
195 static msh(), m_gMsgs(), scanrange(), scanstring(), quit();
|
|
196 static fin_io(), m_init();
|
|
197 #if defined(BPOP) || defined(NNTP)
|
|
198 static int read_pop();
|
|
199 #endif
|
|
200 /* */
|
|
201
|
|
202 /* ARGSUSED */
|
|
203
|
|
204 main (argc, argv)
|
|
205 int argc;
|
|
206 char **argv;
|
|
207 {
|
|
208 int id = 0,
|
|
209 scansw = 0,
|
|
210 vmh1 = 0,
|
|
211 vmh2 = 0;
|
|
212 #if defined(BPOP) || defined(NNTP)
|
|
213 int pmsh1 = 0,
|
|
214 pmsh2 = 0;
|
|
215 #endif /* BPOP || NNTP */
|
|
216 char *cp,
|
|
217 *file = NULL,
|
|
218 *folder = NULL,
|
|
219 **ap,
|
|
220 **argp,
|
|
221 buf[80],
|
|
222 *arguments[MAXARGS];
|
|
223
|
|
224 #ifdef LOCALE
|
|
225 setlocale(LC_ALL, "");
|
|
226 #endif
|
|
227 #ifdef JAPAN
|
|
228 ml_init();
|
|
229 #endif /* JAPAN */
|
|
230 invo_name = r1bindex (argv[0], '/');
|
|
231 mts_init (invo_name);
|
|
232 if ((cp = m_find (invo_name)) != NULL) {
|
|
233 ap = brkstring (cp = getcpy (cp), " ", "\n");
|
|
234 ap = copyip (ap, arguments);
|
|
235 }
|
|
236 else
|
|
237 ap = arguments;
|
|
238 (void) copyip (argv + 1, ap);
|
|
239 argp = arguments;
|
|
240
|
|
241 /* */
|
|
242
|
|
243 while (cp = *argp++) {
|
|
244 if (*cp == '-')
|
|
245 switch (smatch (++cp, switches)) {
|
|
246 case AMBIGSW:
|
|
247 ambigsw (cp, switches);
|
|
248 done (1);
|
|
249 case UNKWNSW:
|
|
250 adios (NULLCP, "-%s unknown", cp);
|
|
251 case HELPSW:
|
|
252 (void) sprintf (buf, "%s [switches] file", invo_name);
|
|
253 help (buf, switches);
|
|
254 done (1);
|
|
255
|
|
256 case IDSW:
|
|
257 if (!(cp = *argp++) || *cp == '-')
|
|
258 adios (NULLCP, "missing argument to %s", argp[-2]);
|
|
259 if ((id = atoi (cp)) < 1)
|
|
260 adios (NULLCP, "bad argument %s %s", argp[-2], cp);
|
|
261 continue;
|
|
262 case FDSW:
|
|
263 if (!(cp = *argp++) || *cp == '-')
|
|
264 adios (NULLCP, "missing argument to %s", argp[-2]);
|
|
265 if ((pfd = atoi (cp)) <= 1)
|
|
266 adios (NULLCP, "bad argument %s %s", argp[-2], cp);
|
|
267 continue;
|
|
268 case QDSW:
|
|
269 if (!(cp = *argp++) || *cp == '-')
|
|
270 adios (NULLCP, "missing argument to %s", argp[-2]);
|
|
271 if ((ppid = atoi (cp)) <= 1)
|
|
272 adios (NULLCP, "bad argument %s %s", argp[-2], cp);
|
|
273 continue;
|
|
274 case NMSW:
|
|
275 if (!(myname = *argp++) || *myname == '-')
|
|
276 adios (NULLCP, "missing argument to %s", argp[-2]);
|
|
277 continue;
|
|
278
|
|
279 case SCANSW:
|
|
280 scansw++;
|
|
281 continue;
|
|
282 case NSCANSW:
|
|
283 scansw = 0;
|
|
284 continue;
|
|
285
|
|
286 case PRMPTSW:
|
|
287 if (!(myprompt = *argp++) || *myprompt == '-')
|
|
288 adios (NULLCP, "missing argument to %s", argp[-2]);
|
|
289 continue;
|
|
290
|
|
291 case READSW:
|
|
292 if (!(cp = *argp++) || *cp == '-')
|
|
293 adios (NULLCP, "missing argument to %s", argp[-2]);
|
|
294 if ((vmh1 = atoi (cp)) < 1)
|
|
295 adios (NULLCP, "bad argument %s %s", argp[-2], cp);
|
|
296 continue;
|
|
297 case WRITESW:
|
|
298 if (!(cp = *argp++) || *cp == '-')
|
|
299 adios (NULLCP, "missing argument to %s", argp[-2]);
|
|
300 if ((vmh2 = atoi (cp)) < 1)
|
|
301 adios (NULLCP, "bad argument %s %s", argp[-2], cp);
|
|
302 continue;
|
|
303
|
|
304 case PREADSW:
|
|
305 if (!(cp = *argp++) || *cp == '-')
|
|
306 adios (NULLCP, "missing argument to %s", argp[-2]);
|
|
307 #if defined(BPOP) || defined(NNTP)
|
|
308 if ((pmsh1 = atoi (cp)) < 1)
|
|
309 adios (NULLCP, "bad argument %s %s", argp[-2], cp);
|
|
310 #endif /* BPOP || NNTP */
|
|
311 continue;
|
|
312 case PWRITSW:
|
|
313 if (!(cp = *argp++) || *cp == '-')
|
|
314 adios (NULLCP, "missing argument to %s", argp[-2]);
|
|
315 #if defined(BPOP) || defined(NNTP)
|
|
316 if ((pmsh2 = atoi (cp)) < 1)
|
|
317 adios (NULLCP, "bad argument %s %s", argp[-2], cp);
|
|
318 #endif /* BPOP || NNTP */
|
|
319 continue;
|
|
320
|
|
321 case TCURSW:
|
|
322 topcur++;
|
|
323 continue;
|
|
324 case NTCURSW:
|
|
325 topcur = 0;
|
|
326 continue;
|
|
327 }
|
|
328 if (*cp == '+' || *cp == '@') {
|
|
329 if (folder)
|
|
330 adios (NULLCP, "only one folder at a time!");
|
|
331 else
|
|
332 folder = path (cp + 1, *cp == '+' ? TFOLDER : TSUBCWF);
|
|
333 }
|
|
334 else
|
|
335 if (file)
|
|
336 adios (NULLCP, "only one file at a time!");
|
|
337 else
|
|
338 file = cp;
|
|
339 }
|
|
340
|
|
341 /* */
|
|
342
|
|
343 if (!file && !folder)
|
|
344 file = "./msgbox";
|
|
345 if (file && folder)
|
|
346 adios (NULLCP, "use a file or a folder, not both");
|
|
347 (void) strcpy (myfilter, libpath (mhlforward));
|
|
348 #ifdef FIOCLEX
|
|
349 if (pfd > 1)
|
|
350 (void) ioctl (pfd, FIOCLEX, NULLCP);
|
|
351 #endif /* FIOCLEX */
|
|
352
|
|
353 #if defined(BSD42) || defined(SVR4)
|
|
354 should_intr = 0;
|
|
355 #endif /* BSD42 || SVR4 */
|
|
356 setsigx (istat, SIGINT, intrser);
|
|
357 setsigx (qstat, SIGQUIT, quitser);
|
|
358
|
|
359 (void) sc_width (); /* MAGIC... */
|
|
360
|
|
361 if (vmh = vmh1 && vmh2) {
|
|
362 (void) rcinit (vmh1, vmh2);
|
|
363 (void) pINI ();
|
|
364 (void) signal (SIGINT, SIG_IGN);
|
|
365 (void) signal (SIGQUIT, SIG_IGN);
|
|
366 #ifdef SIGTSTP
|
|
367 tstat = signal (SIGTSTP, SIG_IGN);
|
|
368 #endif /* SIGTSTP */
|
|
369 }
|
|
370
|
|
371 #if defined(BPOP) || defined(NNTP)
|
|
372 if (pmsh = pmsh1 && pmsh2) {
|
|
373 cp = getenv ("MHPOPDEBUG");
|
|
374 #ifdef NNTP
|
|
375 if (pop_set (pmsh1, pmsh2, cp && *cp, myname) == NOTOK)
|
|
376 #else /* NNTP */
|
|
377 if (pop_set (pmsh1, pmsh2, cp && *cp) == NOTOK)
|
|
378 #endif /* NNTP */
|
|
379 padios (NULLCP, "%s", response);
|
|
380 if (folder)
|
|
381 file = folder, folder = NULL;
|
|
382 }
|
|
383 #endif /* BPOP || NNTP */
|
|
384
|
|
385 if (folder)
|
|
386 fsetup (folder);
|
|
387 else
|
|
388 setup (file);
|
|
389 readids (id);
|
|
390 display_info (id > 0 ? scansw : 0);
|
|
391
|
|
392 msh (id > 0 ? scansw : 0);
|
|
393
|
|
394 m_reset ();
|
|
395
|
|
396 done (0);
|
|
397 }
|
|
398
|
|
399 /* */
|
|
400
|
|
401 static struct swit mshcmds[] = {
|
|
402 #define ADVCMD 0
|
|
403 "advance", -7,
|
|
404 #define ALICMD 1
|
|
405 "ali", 0,
|
|
406 #define EXPLCMD 2
|
|
407 "burst", 0,
|
|
408 #define COMPCMD 3
|
|
409 "comp", 0,
|
|
410 #define DISTCMD 4
|
|
411 "dist", 0,
|
|
412 #define EXITCMD 5
|
|
413 "exit", 0,
|
|
414 #define FOLDCMD 6
|
|
415 "folder", 0,
|
|
416 #define FORWCMD 7
|
|
417 "forw", 0,
|
|
418 #define HELPCMD 8
|
|
419 "help", 0,
|
|
420 #define INCMD 9
|
|
421 "inc", 0,
|
|
422 #define MARKCMD 10
|
|
423 "mark", 0,
|
|
424 #define MAILCMD 11
|
|
425 "mhmail", 0,
|
|
426 #define MHNCMD 12
|
|
427 "mhn", MIMEminc(-3),
|
|
428 #define MSGKCMD 13
|
|
429 "msgchk", 0,
|
|
430 #define NEXTCMD 14
|
|
431 "next", 0,
|
|
432 #define PACKCMD 15
|
|
433 "packf", 0,
|
|
434 #define PICKCMD 16
|
|
435 "pick", 0,
|
|
436 #define PREVCMD 17
|
|
437 "prev", 0,
|
|
438 #define QUITCMD 18
|
|
439 "quit", 0,
|
|
440 #define FILECMD 19
|
|
441 "refile", 0,
|
|
442 #define REPLCMD 20
|
|
443 "repl", 0,
|
|
444 #define RMMCMD 21
|
|
445 "rmm", 0,
|
|
446 #define SCANCMD 22
|
|
447 "scan", 0,
|
|
448 #define SENDCMD 23
|
|
449 "send", 0,
|
|
450 #define SHOWCMD 24
|
|
451 "show", 0,
|
|
452 #define SORTCMD 25
|
|
453 "sortm", 0,
|
|
454 #define WHATCMD 26
|
|
455 "whatnow", 0,
|
|
456 #define WHOMCMD 27
|
|
457 "whom", 0,
|
|
458
|
|
459 NULL, 0
|
|
460 };
|
|
461
|
|
462 /* */
|
|
463
|
|
464 static msh (scansw)
|
|
465 int scansw;
|
|
466 {
|
|
467 int i;
|
|
468 register char *cp,
|
|
469 **ap;
|
|
470 char prompt[BUFSIZ],
|
|
471 *vec[MAXARGS];
|
|
472 struct Cmd typein;
|
|
473 register struct Cmd *cmdp;
|
|
474 static int once_only = ADVCMD;
|
|
475
|
|
476 (void) sprintf (prompt, myprompt, invo_name);
|
|
477 cmdp = &typein;
|
|
478
|
|
479 #ifdef READLINE
|
|
480 (void) initialize_readline();
|
|
481 #endif
|
|
482 for (;;) {
|
|
483 if (yp) {
|
|
484 (void) fclose (yp);
|
|
485 yp = NULL;
|
|
486 }
|
|
487 if (vmh) {
|
|
488 if ((i = getcmds (mshcmds, cmdp, scansw)) == EOF) {
|
|
489 (void) rcdone ();
|
|
490 return;
|
|
491 }
|
|
492 }
|
|
493 else {
|
|
494 (void) check_folder (scansw);
|
|
495 if ((i = getargs (prompt, mshcmds, cmdp)) == EOF) {
|
|
496 (void) putchar ('\n');
|
|
497 return;
|
|
498 }
|
|
499 }
|
|
500 cmd_name = mshcmds[i].sw;
|
|
501
|
|
502 switch (i) {
|
|
503 case QUITCMD:
|
|
504 quit ();
|
|
505 return;
|
|
506
|
|
507 case ADVCMD:
|
|
508 if (once_only == ADVCMD)
|
|
509 once_only = i = SHOWCMD;
|
|
510 else
|
|
511 i = mp -> curmsg != mp -> hghmsg ? NEXTCMD : EXITCMD;
|
|
512 cmd_name = mshcmds[i].sw;
|
|
513 /* and fall... */
|
|
514
|
|
515 case EXITCMD:
|
|
516 case EXPLCMD:
|
|
517 case FOLDCMD:
|
|
518 case FORWCMD: /* sigh */
|
|
519 case MARKCMD:
|
|
520 case NEXTCMD:
|
|
521 case PACKCMD:
|
|
522 case PICKCMD:
|
|
523 case PREVCMD:
|
|
524 case RMMCMD:
|
|
525 case SHOWCMD:
|
|
526 case SCANCMD:
|
|
527 case SORTCMD:
|
|
528 if ((cp = m_find (cmd_name)) != NULL) {
|
|
529 ap = brkstring (cp = getcpy (cp), " ", "\n");
|
|
530 ap = copyip (ap, vec);
|
|
531 }
|
|
532 else
|
|
533 ap = vec;
|
|
534 break;
|
|
535
|
|
536 default:
|
|
537 cp = NULL;
|
|
538 ap = vec;
|
|
539 break;
|
|
540 }
|
|
541 (void) copyip (cmdp -> args + 1, ap);
|
|
542
|
|
543 m_init ();
|
|
544
|
|
545 if (!vmh && init_io (cmdp, vmh) == NOTOK) {
|
|
546 if (cp != NULL)
|
|
547 free (cp);
|
|
548 continue;
|
|
549 }
|
|
550 modified = 0;
|
|
551 redirected = vmh || cmdp -> direction != STDIO;
|
|
552
|
|
553 switch (i) {
|
|
554 case ALICMD:
|
|
555 case COMPCMD:
|
|
556 case INCMD:
|
|
557 case MAILCMD:
|
|
558 case MSGKCMD:
|
|
559 case SENDCMD:
|
|
560 case WHATCMD:
|
|
561 case WHOMCMD:
|
|
562 if (!vmh || ttyN (cmdp) != NOTOK)
|
|
563 forkcmd (vec, cmd_name);
|
|
564 break;
|
|
565
|
|
566 case DISTCMD:
|
|
567 if (!vmh || ttyN (cmdp) != NOTOK)
|
|
568 distcmd (vec);
|
|
569 break;
|
|
570
|
|
571 case EXPLCMD:
|
|
572 if (!vmh || winN (cmdp, DISPLAY, 1) != NOTOK)
|
|
573 explcmd (vec);
|
|
574 break;
|
|
575
|
|
576 case FILECMD:
|
|
577 if (!vmh
|
|
578 || (filehak (vec) == OK ? ttyN (cmdp)
|
|
579 : winN (cmdp, DISPLAY, 1)) != NOTOK)
|
|
580 filecmd (vec);
|
|
581 break;
|
|
582
|
|
583 case FOLDCMD:
|
|
584 if (!vmh || winN (cmdp, DISPLAY, 1) != NOTOK)
|
|
585 foldcmd (vec);
|
|
586 break;
|
|
587
|
|
588 case FORWCMD:
|
|
589 if (!vmh || ttyN (cmdp) != NOTOK)
|
|
590 forwcmd (vec);
|
|
591 break;
|
|
592
|
|
593 case HELPCMD:
|
|
594 if (!vmh || winN (cmdp, DISPLAY, 1) != NOTOK)
|
|
595 helpcmd (vec);
|
|
596 break;
|
|
597
|
|
598 case EXITCMD:
|
|
599 case MARKCMD:
|
|
600 if (!vmh || winN (cmdp, DISPLAY, 1) != NOTOK)
|
|
601 markcmd (vec);
|
|
602 break;
|
|
603
|
|
604 case MHNCMD:
|
|
605 #ifdef MIME
|
|
606 if (!vmh || ttyN (cmdp) != NOTOK)
|
|
607 mhncmd (vec);
|
|
608 #endif
|
|
609 break;
|
|
610
|
|
611 case NEXTCMD:
|
|
612 case PREVCMD:
|
|
613 case SHOWCMD:
|
|
614 if (!vmh || winN (cmdp, DISPLAY, 1) != NOTOK)
|
|
615 showcmd (vec);
|
|
616 break;
|
|
617
|
|
618 case PACKCMD:
|
|
619 if (!vmh
|
|
620 || (packhak (vec) == OK ? ttyN (cmdp)
|
|
621 : winN (cmdp, DISPLAY, 1)) != NOTOK)
|
|
622 packcmd (vec);
|
|
623 break;
|
|
624
|
|
625 case PICKCMD:
|
|
626 if (!vmh || winN (cmdp, DISPLAY, 1) != NOTOK)
|
|
627 pickcmd (vec);
|
|
628 break;
|
|
629
|
|
630 case REPLCMD:
|
|
631 if (!vmh || ttyN (cmdp) != NOTOK)
|
|
632 replcmd (vec);
|
|
633 break;
|
|
634
|
|
635 case RMMCMD:
|
|
636 if (!vmh || winN (cmdp, DISPLAY, 1) != NOTOK)
|
|
637 rmmcmd (vec);
|
|
638 break;
|
|
639
|
|
640 case SCANCMD:
|
|
641 if (!vmh || winN (cmdp, DISPLAY, 1) != NOTOK)
|
|
642 scancmd (vec);
|
|
643 break;
|
|
644
|
|
645 case SORTCMD:
|
|
646 if (!vmh || winN (cmdp, DISPLAY, 1) != NOTOK)
|
|
647 sortcmd (vec);
|
|
648 break;
|
|
649
|
|
650 default:
|
|
651 padios (NULLCP, "no dispatch for %s", cmd_name);
|
|
652 }
|
|
653
|
|
654 if (vmh) {
|
|
655 if (vmhtty != NOTOK)
|
|
656 (void) ttyR (cmdp);
|
|
657 if (vmhpid > OK)
|
|
658 (void) winR (cmdp);
|
|
659 }
|
|
660 else
|
|
661 fin_io (cmdp, vmh);
|
|
662 if (cp != NULL)
|
|
663 free (cp);
|
|
664 if (i == EXITCMD) {
|
|
665 quit ();
|
|
666 return;
|
|
667 }
|
|
668 }
|
|
669 }
|
|
670
|
|
671 /* */
|
|
672
|
|
673 fsetup (folder)
|
|
674 char *folder;
|
|
675 {
|
|
676 register int msgnum;
|
|
677 char *maildir;
|
|
678 struct stat st;
|
|
679
|
|
680 maildir = m_maildir (folder);
|
|
681 if (chdir (maildir) == NOTOK)
|
|
682 padios (maildir, "unable to change directory to");
|
|
683 if (!(mp = m_gmsg (folder)))
|
|
684 padios (NULLCP, "unable to read folder %s", folder);
|
|
685 if (mp -> hghmsg == 0)
|
|
686 padios (NULLCP, "no messages in %s", folder);
|
|
687
|
|
688 mode = m_gmprot ();
|
|
689 mtime = stat (mp -> foldpath, &st) != NOTOK ? st.st_mtime : 0;
|
|
690
|
|
691 m_gMsgs (mp -> hghmsg);
|
|
692
|
|
693 for (msgnum = mp -> lowmsg; msgnum <= mp -> hghmsg; msgnum++) {
|
|
694 Msgs[msgnum].m_bboard_id = 0;
|
|
695 Msgs[msgnum].m_top = NOTOK;
|
|
696 Msgs[msgnum].m_start = Msgs[msgnum].m_stop = 0L;
|
|
697 Msgs[msgnum].m_scanl = NULL;
|
|
698 }
|
|
699
|
|
700 m_init ();
|
|
701
|
|
702 fmsh = getcpy (folder);
|
|
703
|
|
704 #if !defined(BSD42) && !defined(linux) && defined(_NFILE)
|
|
705 maxfds = _NFILE / 2;
|
|
706 #else /* BSD42 || linux */
|
|
707 maxfds = getdtablesize () / 2;
|
|
708 #endif /* BSD42 || linux */
|
|
709 if ((maxfds -= 2) < 1)
|
|
710 maxfds = 1;
|
|
711 }
|
|
712
|
|
713 /* */
|
|
714
|
|
715 setup (file)
|
|
716 char *file;
|
|
717 {
|
|
718 int i,
|
|
719 msgp;
|
|
720 #if defined(BPOP) || defined(NNTP)
|
|
721 char tmpfil[BUFSIZ];
|
|
722 #endif /* BPOP || NNTP */
|
|
723 struct stat st;
|
|
724
|
|
725 #if defined(BPOP) || defined(NNTP)
|
|
726 if (pmsh) {
|
|
727 (void) strcpy (tmpfil, m_tmpfil (invo_name));
|
|
728 if ((fp = fopen (tmpfil, "w+")) == NULL)
|
|
729 padios (tmpfil, "unable to create");
|
|
730 (void) unlink (tmpfil);
|
|
731 }
|
|
732 else
|
|
733 #endif /* BPOP || NNTP */
|
|
734 if ((fp = fopen (file, "r")) == NULL)
|
|
735 padios (file, "unable to read");
|
|
736 #ifdef FIOCLEX
|
|
737 (void) ioctl (fileno (fp), FIOCLEX, NULLCP);
|
|
738 #endif /* FIOCLEX */
|
|
739 if (fstat (fileno (fp), &st) != NOTOK) {
|
|
740 mode = (int) (st.st_mode & 0777), mtime = st.st_mtime;
|
|
741 msgp = read_map (file, (long) st.st_size);
|
|
742 }
|
|
743 else {
|
|
744 mode = m_gmprot (), mtime = 0;
|
|
745 msgp = 0;
|
|
746 }
|
|
747
|
|
748 if ((msgp = read_file (msgp ? Msgs[msgp].m_stop : 0L, msgp + 1)) < 1)
|
|
749 padios (NULLCP, "no messages in %s", myname ? myname : file);
|
|
750
|
|
751 mp = (struct msgs *) calloc ((unsigned) 1, MHSIZE (mp, 1, msgp + 1));
|
|
752 if (mp == NULL)
|
|
753 padios (NULLCP, "unable to allocate folder storage");
|
|
754
|
|
755 mp -> hghmsg = msgp;
|
|
756 mp -> nummsg = msgp;
|
|
757 mp -> lowmsg = 1;
|
|
758 mp -> curmsg = 0;
|
|
759
|
|
760 mp -> foldpath = getcpy (myname ? myname : file);
|
|
761 mp -> msgflags = 0;
|
|
762 #if defined(BPOP) || defined(NNTP)
|
|
763 if (pmsh)
|
|
764 mp -> msgflags |= READONLY;
|
|
765 else {
|
|
766 #endif /* BPOP || NNTP */
|
|
767 (void) stat (file, &st);
|
|
768 if (st.st_uid != getuid () || access (file, 02) == NOTOK)
|
|
769 mp -> msgflags |= READONLY;
|
|
770 #if defined(BPOP) || defined(NNTP)
|
|
771 }
|
|
772 #endif /* BPOP || NNTP */
|
|
773 mp -> lowoff = 1;
|
|
774 mp -> hghoff = mp -> hghmsg + 1;
|
|
775
|
|
776 #ifdef MTR
|
|
777 mp -> msgstats = (short *)
|
|
778 calloc ((unsigned) 1, MHSIZEX (mp, mp -> lowmsg, mp -> hghmsg));
|
|
779 if (mp -> msgstats == NULL)
|
|
780 padios (NULLCP, "unable to allocate messages storage");
|
|
781 mp -> msgstats = (mp -> msgbase = mp -> msgstats) - mp -> lowoff;
|
|
782 if (mp -> msgstats < (short *)0)
|
|
783 padios (NULLCP, "setup() botch -- you lose big");
|
|
784 #endif /* MTR */
|
|
785 #if defined(BPOP) || defined(NNTP)
|
|
786 if (pmsh) {
|
|
787 #ifndef NNTP
|
|
788 for (i = mp -> lowmsg; i <= mp -> hghmsg; i++) {
|
|
789 Msgs[i].m_top = i;
|
|
790 mp -> msgstats[i] = EXISTS | VIRTUAL;
|
|
791 }
|
|
792 #else /* NNTP */
|
|
793 for (i = mp -> lowmsg; i <= mp -> hghmsg; i++) {
|
|
794 if (Msgs[i].m_top) /* set in read_pop() */
|
|
795 mp -> msgstats[i] = EXISTS | VIRTUAL;
|
|
796 }
|
|
797 #endif /* NNTP */
|
|
798 }
|
|
799 else
|
|
800 #endif /* BPOP || NNTP */
|
|
801 for (i = mp -> lowmsg; i <= mp -> hghmsg; i++)
|
|
802 mp -> msgstats[i] = EXISTS;
|
|
803 m_init ();
|
|
804
|
|
805 mp -> msgattrs[0] = getcpy ("unseen");
|
|
806 mp -> msgattrs[1] = NULL;
|
|
807
|
|
808 m_unknown (fp); /* the MAGIC invocation */
|
|
809 if (fmsh) {
|
|
810 free (fmsh);
|
|
811 fmsh = NULL;
|
|
812 }
|
|
813 }
|
|
814
|
|
815 /* */
|
|
816
|
|
817 static int read_map (file, size)
|
|
818 char *file;
|
|
819 long size;
|
|
820 {
|
|
821 register int i,
|
|
822 msgp;
|
|
823 register struct drop *dp,
|
|
824 *mp;
|
|
825 struct drop *rp;
|
|
826
|
|
827 #if defined(BPOP) || defined(NNTP)
|
|
828 if (pmsh)
|
|
829 return read_pop ();
|
|
830 #endif /* BPOP || NNTP */
|
|
831
|
|
832 if ((i = map_read (file, size, &rp, 1)) == 0)
|
|
833 return 0;
|
|
834
|
|
835 m_gMsgs (i);
|
|
836
|
|
837 msgp = 1;
|
|
838 for (dp = rp + 1; i-- > 0; msgp++, dp++) {
|
|
839 mp = &Msgs[msgp].m_drop;
|
|
840 mp -> d_id = dp -> d_id;
|
|
841 mp -> d_size = dp -> d_size;
|
|
842 mp -> d_start = dp -> d_start;
|
|
843 mp -> d_stop = dp -> d_stop;
|
|
844 Msgs[msgp].m_scanl = NULL;
|
|
845 }
|
|
846 free ((char *) rp);
|
|
847
|
|
848 return (msgp - 1);
|
|
849 }
|
|
850
|
|
851 /* */
|
|
852
|
|
853 static int read_file (pos, msgp)
|
|
854 register long pos;
|
|
855 register int msgp;
|
|
856 {
|
|
857 register int i;
|
|
858 register struct drop *dp,
|
|
859 *mp;
|
|
860 struct drop *rp;
|
|
861
|
|
862 #if defined(BPOP) || defined(NNTP)
|
|
863 if (pmsh)
|
|
864 return (msgp - 1);
|
|
865 #endif /* BPOP || NNTP */
|
|
866
|
|
867 if ((i = mbx_read (fp, pos, &rp, 1)) <= 0)
|
|
868 return (msgp - 1);
|
|
869
|
|
870 m_gMsgs ((msgp - 1) + i);
|
|
871
|
|
872 for (dp = rp; i-- > 0; msgp++, dp++) {
|
|
873 mp = &Msgs[msgp].m_drop;
|
|
874 mp -> d_id = 0;
|
|
875 mp -> d_size = dp -> d_size;
|
|
876 mp -> d_start = dp -> d_start;
|
|
877 mp -> d_stop = dp -> d_stop;
|
|
878 Msgs[msgp].m_scanl = NULL;
|
|
879 }
|
|
880 free ((char *) rp);
|
|
881
|
|
882 return (msgp - 1);
|
|
883 }
|
|
884
|
|
885 /* */
|
|
886
|
|
887 #if defined(BPOP) || defined(NNTP)
|
|
888 #ifdef NNTP
|
|
889 static int pop_base = 0;
|
|
890
|
|
891 static int pop_statmsg (s)
|
|
892 register char *s;
|
|
893 {
|
|
894 register int i, n;
|
|
895
|
|
896 n = (i = atoi (s)) - pop_base; /* s="nnn header-line..." */
|
|
897 Msgs[n].m_top = Msgs[n].m_bboard_id = i;
|
|
898 }
|
|
899
|
|
900 #endif /* NNTP */
|
|
901 static int read_pop () {
|
|
902 int nmsgs,
|
|
903 nbytes;
|
|
904
|
|
905 if (pop_stat (&nmsgs, &nbytes) == NOTOK)
|
|
906 padios (NULLCP, "%s", response);
|
|
907
|
|
908 m_gMsgs (nmsgs);
|
|
909
|
|
910 #ifdef NNTP /* this makes read_pop() do some real work... */
|
|
911 pop_base = nbytes - 1; /* nmsgs=last-first+1, nbytes=first */
|
|
912 pop_exists (pop_statmsg);
|
|
913 #endif /* NNTP */
|
|
914 return nmsgs;
|
|
915 }
|
|
916
|
|
917
|
|
918 static int pop_action (s)
|
|
919 register char *s;
|
|
920 {
|
|
921 fprintf (yp, "%s\n", s);
|
|
922 }
|
|
923 #endif /* BPOP || NNTP */
|
|
924
|
|
925 /* */
|
|
926
|
|
927 static m_gMsgs (n)
|
|
928 int n;
|
|
929 {
|
|
930 int nmsgs;
|
|
931
|
|
932 if (Msgs == NULL) {
|
|
933 nMsgs = n + MAXFOLDER / 2;
|
|
934 Msgs = (struct Msg *) calloc ((unsigned) (nMsgs + 2), sizeof *Msgs);
|
|
935 if (Msgs == NULL)
|
|
936 padios (NULLCP, "unable to allocate Msgs structure");
|
|
937 return;
|
|
938 }
|
|
939
|
|
940 if (nMsgs >= n)
|
|
941 return;
|
|
942
|
|
943 nmsgs = nMsgs + n + MAXFOLDER / 2;
|
|
944 Msgs = (struct Msg *) realloc ((char *) Msgs,
|
|
945 (unsigned) (nmsgs + 2) * sizeof *Msgs);
|
|
946 if (Msgs == NULL)
|
|
947 padios (NULLCP, "unable to reallocate Msgs structure");
|
|
948 bzero ((char *) (Msgs + nMsgs + 2),
|
|
949 (unsigned) ((nmsgs - nMsgs) * sizeof *Msgs));
|
|
950
|
|
951 nMsgs = nmsgs;
|
|
952 }
|
|
953
|
|
954 /* */
|
|
955
|
|
956 FILE *msh_ready (msgnum, full)
|
|
957 register int msgnum;
|
|
958 int full;
|
|
959 {
|
|
960 register int msgp;
|
|
961 int fd;
|
|
962 long pos1,
|
|
963 pos2;
|
|
964 char *cp,
|
|
965 tmpfil[BUFSIZ];
|
|
966
|
|
967 if (yp) {
|
|
968 (void) fclose (yp);
|
|
969 yp = NULL;
|
|
970 }
|
|
971
|
|
972 if (fmsh) {
|
|
973 if ((fd = Msgs[msgnum].m_top) == NOTOK) {
|
|
974 if (numfds >= maxfds)
|
|
975 for (msgp = mp -> lowmsg; msgp <= mp -> hghmsg; msgp++)
|
|
976 if (Msgs[msgp].m_top != NOTOK) {
|
|
977 (void) close (Msgs[msgp].m_top);
|
|
978 Msgs[msgp].m_top = NOTOK;
|
|
979 numfds--;
|
|
980 break;
|
|
981 }
|
|
982
|
|
983 if ((fd = open (cp = m_name (msgnum), 0)) == NOTOK)
|
|
984 padios (cp, "unable to open message");
|
|
985 Msgs[msgnum].m_top = fd;
|
|
986 numfds++;
|
|
987 }
|
|
988
|
|
989 if ((fd = dup (fd)) == NOTOK)
|
|
990 padios ("cached message", "unable to dup");
|
|
991 if ((yp = fdopen (fd, "r")) == NULL)
|
|
992 padios (NULLCP, "unable to fdopen cached message");
|
|
993 (void) fseek (yp, 0L, 0);
|
|
994 return yp;
|
|
995 }
|
|
996
|
|
997 #if defined(BPOP) || defined(NNTP)
|
|
998 if (pmsh && (mp -> msgstats[msgnum] & VIRTUAL)) {
|
|
999 if (Msgs[msgnum].m_top == 0)
|
|
1000 padios (NULLCP, "msh_ready (%d, %d) botch", msgnum, full);
|
|
1001 if (!full) {
|
|
1002 (void) strcpy (tmpfil, m_tmpfil (invo_name));
|
|
1003 if ((yp = fopen (tmpfil, "w+")) == NULL)
|
|
1004 padios (tmpfil, "unable to create");
|
|
1005 (void) unlink (tmpfil);
|
|
1006
|
|
1007 if (pop_top (Msgs[msgnum].m_top, 4, pop_action) == NOTOK)
|
|
1008 #ifndef NNTP
|
|
1009 padios (NULLCP, "%s", response);
|
|
1010 #else /* NNTP */
|
|
1011 {
|
|
1012 if (strncmp(response, "423 ", 4) == 0)
|
|
1013 /* 423 no such article number in this group */
|
|
1014 fprintf (yp, "Expired:\n\n"); /* dummy */
|
|
1015 else
|
|
1016 padios (NULLCP, "%s", response);
|
|
1017 }
|
|
1018 #endif /* NNTP */
|
|
1019
|
|
1020 m_eomsbr ((int (*)()) 0); /* XXX */
|
|
1021 msg_style = MS_DEFAULT; /* .. */
|
|
1022 (void) fseek (yp, 0L, 0);
|
|
1023 return yp;
|
|
1024 }
|
|
1025
|
|
1026 (void) fseek (fp, 0L, 2);
|
|
1027 (void) fwrite (mmdlm1, 1, strlen (mmdlm1), fp);
|
|
1028 if (fflush (fp))
|
|
1029 padios ("temporary file", "write error on");
|
|
1030 (void) fseek (fp, 0L, 2);
|
|
1031 pos1 = ftell (fp);
|
|
1032
|
|
1033 yp = fp;
|
|
1034 if (pop_retr (Msgs[msgnum].m_top, pop_action) == NOTOK)
|
|
1035 #ifndef NNTP
|
|
1036 padios (NULLCP, "%s", response);
|
|
1037 #else /* NNTP */
|
|
1038 {
|
|
1039 if (strncmp(response, "423 ", 4) == 0)
|
|
1040 /* 423 no such article number in this group */
|
|
1041 fprintf (yp, "Expired:\n\n"); /* dummy */
|
|
1042 else
|
|
1043 padios (NULLCP, "%s", response);
|
|
1044 }
|
|
1045 #endif /* NNTP */
|
|
1046 yp = NULL;
|
|
1047
|
|
1048 (void) fseek (fp, 0L, 2);
|
|
1049 pos2 = ftell (fp);
|
|
1050 (void) fwrite (mmdlm2, 1, strlen (mmdlm2), fp);
|
|
1051 if (fflush (fp))
|
|
1052 padios ("temporary file", "write error on");
|
|
1053
|
|
1054 Msgs[msgnum].m_start = pos1;
|
|
1055 Msgs[msgnum].m_stop = pos2;
|
|
1056
|
|
1057 mp -> msgstats[msgnum] &= ~VIRTUAL;
|
|
1058 }
|
|
1059 #endif /* BPOP || NNTP */
|
|
1060
|
|
1061 m_eomsbr ((int (*)()) 0); /* XXX */
|
|
1062 (void) fseek (fp, Msgs[msgnum].m_start, 0);
|
|
1063 return fp;
|
|
1064 }
|
|
1065
|
|
1066 /* */
|
|
1067
|
|
1068 static int check_folder (scansw)
|
|
1069 int scansw;
|
|
1070 {
|
|
1071 int flags,
|
|
1072 i,
|
|
1073 low,
|
|
1074 hgh,
|
|
1075 msgp;
|
|
1076 struct stat st;
|
|
1077
|
|
1078 #if defined(BPOP) || defined(NNTP)
|
|
1079 if (pmsh)
|
|
1080 return 0;
|
|
1081 #endif /* BPOP || NNTP */
|
|
1082
|
|
1083 if (fmsh) {
|
|
1084 if (stat (mp -> foldpath, &st) == NOTOK)
|
|
1085 padios (mp -> foldpath, "unable to stat");
|
|
1086 if (mtime == st.st_mtime)
|
|
1087 return 0;
|
|
1088 mtime = st.st_mtime;
|
|
1089
|
|
1090 low = mp -> hghmsg + 1;
|
|
1091 m_fmsg (mp);
|
|
1092
|
|
1093 if (!(mp = m_gmsg (fmsh)))
|
|
1094 padios (NULLCP, "unable to re-read folder %s", fmsh);
|
|
1095
|
|
1096 hgh = mp -> hghmsg;
|
|
1097
|
|
1098 for (msgp = mp -> lowmsg; msgp <= mp -> hghmsg; msgp++) {
|
|
1099 if (Msgs[msgp].m_top != NOTOK) {
|
|
1100 (void) close (Msgs[msgp].m_top);
|
|
1101 Msgs[msgp].m_top = NOTOK;
|
|
1102 numfds--;
|
|
1103 }
|
|
1104 if (Msgs[msgp].m_scanl) {
|
|
1105 free (Msgs[msgp].m_scanl);
|
|
1106 Msgs[msgp].m_scanl = NULL;
|
|
1107 }
|
|
1108 }
|
|
1109
|
|
1110 m_init ();
|
|
1111
|
|
1112 if (modified || low > hgh)
|
|
1113 return 1;
|
|
1114 goto check_vmh;
|
|
1115 }
|
|
1116 if (fstat (fileno (fp), &st) == NOTOK)
|
|
1117 padios (mp -> foldpath, "unable to fstat");
|
|
1118 if (mtime == st.st_mtime)
|
|
1119 return 0;
|
|
1120 mode = (int) (st.st_mode & 0777);
|
|
1121 mtime = st.st_mtime;
|
|
1122
|
|
1123 if ((msgp = read_file (Msgs[mp -> hghmsg].m_stop, mp -> hghmsg + 1)) < 1)
|
|
1124 padios (NULLCP, "no messages in %s", mp -> foldpath); /* XXX */
|
|
1125 if (msgp <= mp -> hghmsg)
|
|
1126 return 0; /* XXX */
|
|
1127
|
|
1128 if ((mp = m_remsg (mp, 0, msgp)) == NULL)
|
|
1129 padios (NULLCP, "unable to allocate folder storage");
|
|
1130
|
|
1131 low = mp -> hghmsg + 1, hgh = msgp;
|
|
1132 flags = scansw ? m_seqflag (mp, "unseen") : 0;
|
|
1133 for (i = mp -> hghmsg + 1; i <= msgp; i++) {
|
|
1134 mp -> msgstats[i] = EXISTS | flags;
|
|
1135 mp -> nummsg++;
|
|
1136 }
|
|
1137 mp -> hghmsg = msgp;
|
|
1138 m_init ();
|
|
1139
|
|
1140 check_vmh: ;
|
|
1141 if (vmh)
|
|
1142 return 1;
|
|
1143
|
|
1144 advise (NULLCP, "new messages have arrived!\007");
|
|
1145 if (scansw)
|
|
1146 scanrange (low, hgh);
|
|
1147
|
|
1148 return 1;
|
|
1149 }
|
|
1150
|
|
1151 /* */
|
|
1152
|
|
1153 static scanrange (low, hgh)
|
|
1154 int low,
|
|
1155 hgh;
|
|
1156 {
|
|
1157 char buffer[BUFSIZ];
|
|
1158
|
|
1159 (void) sprintf (buffer, "%d-%d", low, hgh);
|
|
1160 scanstring (buffer);
|
|
1161 }
|
|
1162
|
|
1163
|
|
1164 static scanstring (arg)
|
|
1165 char *arg;
|
|
1166 {
|
|
1167 char *cp,
|
|
1168 **ap,
|
|
1169 *vec[MAXARGS];
|
|
1170
|
|
1171 if ((cp = m_find (cmd_name = "scan")) != NULL) {
|
|
1172 ap = brkstring (cp = getcpy (cp), " ", "\n");
|
|
1173 ap = copyip (ap, vec);
|
|
1174 }
|
|
1175 else
|
|
1176 ap = vec;
|
|
1177 *ap++ = arg;
|
|
1178 *ap = NULL;
|
|
1179 m_init ();
|
|
1180 scancmd (vec);
|
|
1181 if (cp != NULL)
|
|
1182 free (cp);
|
|
1183 }
|
|
1184
|
|
1185 /* */
|
|
1186
|
|
1187 readids (id)
|
|
1188 int id;
|
|
1189 {
|
|
1190 register int cur,
|
|
1191 flags,
|
|
1192 i,
|
|
1193 msgnum;
|
|
1194
|
|
1195 if (mp -> curmsg == 0)
|
|
1196 m_setcur (mp, mp -> lowmsg);
|
|
1197 if (id <= 0 || (flags = m_seqflag (mp, "unseen")) == 0)
|
|
1198 return;
|
|
1199
|
|
1200 for (msgnum = mp -> hghmsg; msgnum >= mp -> lowmsg; msgnum--)
|
|
1201 mp -> msgstats[msgnum] |= flags;
|
|
1202
|
|
1203 if (id != 1) {
|
|
1204 cur = mp -> curmsg;
|
|
1205
|
|
1206 for (msgnum = mp -> hghmsg; msgnum >= mp -> lowmsg; msgnum--)
|
|
1207 if (mp -> msgstats[msgnum] & EXISTS) /* FIX */
|
|
1208 if ((i = readid (msgnum)) > 0 && i < id) {
|
|
1209 cur = msgnum + 1;
|
|
1210 mp -> msgstats[msgnum] &= ~flags;
|
|
1211 break;
|
|
1212 }
|
|
1213 for (i = mp -> lowmsg; i < msgnum; i++)
|
|
1214 mp -> msgstats[i] &= ~flags;
|
|
1215
|
|
1216 if (cur > mp -> hghmsg)
|
|
1217 cur = mp -> hghmsg;
|
|
1218
|
|
1219 m_setcur (mp, cur);
|
|
1220 }
|
|
1221
|
|
1222 if ((gap = 1 < id && id < (i = readid (mp -> lowmsg)) ? id : 0) && !vmh)
|
|
1223 advise (NULLCP, "gap in ID:s, last seen %d, lowest present %d\n",
|
|
1224 id - 1, i);
|
|
1225 }
|
|
1226
|
|
1227 /* */
|
|
1228
|
|
1229 int readid (msgnum)
|
|
1230 int msgnum;
|
|
1231 {
|
|
1232 int i,
|
|
1233 state;
|
|
1234 #if defined(BPOP) || defined(NNTP)
|
|
1235 int arg1,
|
|
1236 arg2,
|
|
1237 arg3;
|
|
1238 #endif /* BPOP || NNTP */
|
|
1239 char *bp,
|
|
1240 buf[BUFSIZ],
|
|
1241 name[NAMESZ];
|
|
1242 register FILE *zp;
|
|
1243
|
|
1244 if (Msgs[msgnum].m_bboard_id)
|
|
1245 return Msgs[msgnum].m_bboard_id;
|
|
1246 #if defined(BPOP) || defined(NNTP)
|
|
1247 if (pmsh) {
|
|
1248 if (Msgs[msgnum].m_top == 0)
|
|
1249 padios (NULLCP, "readid (%d) botch", msgnum);
|
|
1250 if (pop_list (Msgs[msgnum].m_top, (int *) 0, &arg1, &arg2, &arg3) == OK
|
|
1251 && arg3 > 0)
|
|
1252 return (Msgs[msgnum].m_bboard_id = arg3);
|
|
1253 }
|
|
1254 #endif /* BPOP || NNTP */
|
|
1255
|
|
1256 zp = msh_ready (msgnum, 0);
|
|
1257 for (state = FLD;;)
|
|
1258 switch (state = m_getfld (state, name, buf, sizeof buf, zp)) {
|
|
1259 case FLD:
|
|
1260 case FLDEOF:
|
|
1261 case FLDPLUS:
|
|
1262 if (uleq (name, BBoard_ID)) {
|
|
1263 bp = getcpy (buf);
|
|
1264 while (state == FLDPLUS) {
|
|
1265 state = m_getfld (state, name, buf, sizeof buf, zp);
|
|
1266 bp = add (buf, bp);
|
|
1267 }
|
|
1268 i = atoi (bp);
|
|
1269 free (bp);
|
|
1270 if (i > 0)
|
|
1271 return (Msgs[msgnum].m_bboard_id = i);
|
|
1272 else
|
|
1273 continue;
|
|
1274 }
|
|
1275 while (state == FLDPLUS)
|
|
1276 state = m_getfld (state, name, buf, sizeof buf, zp);
|
|
1277 if (state != FLDEOF)
|
|
1278 continue;
|
|
1279
|
|
1280 default:
|
|
1281 return 0;
|
|
1282 }
|
|
1283 }
|
|
1284
|
|
1285 /* */
|
|
1286
|
|
1287 display_info (scansw)
|
|
1288 int scansw;
|
|
1289 {
|
|
1290 int flags,
|
|
1291 sd;
|
|
1292
|
|
1293 interactive = isatty (fileno (stdout));
|
|
1294 if (sp == NULL) {
|
|
1295 if ((sd = dup (fileno (stdout))) == NOTOK)
|
|
1296 padios ("standard output", "unable to dup");
|
|
1297 #ifndef BSD42 /* XXX */
|
|
1298 #ifdef FIOCLEX
|
|
1299 (void) ioctl (sd, FIOCLEX, NULL);
|
|
1300 #endif /* FIOCLEX */
|
|
1301 #endif /* not BSD42 */
|
|
1302 if ((sp = fdopen (sd, "w")) == NULL)
|
|
1303 padios ("standard output", "unable to fdopen");
|
|
1304 }
|
|
1305
|
|
1306 (void) m_putenv ("mhfolder", mp -> foldpath);
|
|
1307 if (vmh)
|
|
1308 return;
|
|
1309
|
|
1310 if (myname) {
|
|
1311 printf ("Reading ");
|
|
1312 if (SOprintf ("%s", myname))
|
|
1313 printf ("%s", myname);
|
|
1314 printf (", currently at message %d of %d\n",
|
|
1315 mp -> curmsg, mp -> hghmsg);
|
|
1316 }
|
|
1317 else {
|
|
1318 printf ("Reading ");
|
|
1319 if (fmsh)
|
|
1320 printf ("+%s", fmsh);
|
|
1321 else
|
|
1322 printf ("%s", mp -> foldpath);
|
|
1323 printf (", currently at message %d of %d\n",
|
|
1324 mp -> curmsg, mp -> hghmsg);
|
|
1325 }
|
|
1326
|
|
1327 if ((flags = m_seqflag (mp, "unseen"))
|
|
1328 && scansw
|
|
1329 && (mp -> msgstats[mp -> hghmsg] & flags))
|
|
1330 scanstring ("unseen");
|
|
1331 }
|
|
1332
|
|
1333 /* */
|
|
1334
|
|
1335 static write_ids () {
|
|
1336 int i = 0,
|
|
1337 flags,
|
|
1338 msgnum;
|
|
1339 char buffer[80];
|
|
1340
|
|
1341 if (pfd <= 1)
|
|
1342 return;
|
|
1343
|
|
1344 if (flags = m_seqflag (mp, "unseen"))
|
|
1345 for (msgnum = mp -> hghmsg; msgnum >= mp -> lowmsg; msgnum--)
|
|
1346 if (!(mp -> msgstats[msgnum] & flags)) {
|
|
1347 if (Msgs[msgnum].m_bboard_id == 0)
|
|
1348 (void) readid (msgnum);
|
|
1349 if ((i = Msgs[msgnum].m_bboard_id) > 0)
|
|
1350 break;
|
|
1351 }
|
|
1352
|
|
1353 (void) sprintf (buffer, "%d %d\n", i, Msgs[mp -> hghmsg].m_bboard_id);
|
|
1354 (void) write (pfd, buffer, sizeof buffer);
|
|
1355 (void) close (pfd);
|
|
1356 pfd = NOTOK;
|
|
1357 }
|
|
1358
|
|
1359 /* */
|
|
1360
|
|
1361 static quit () {
|
|
1362 int i,
|
|
1363 md,
|
|
1364 msgnum;
|
|
1365 char *cp,
|
|
1366 tmpfil[BUFSIZ],
|
|
1367 map1[BUFSIZ],
|
|
1368 map2[BUFSIZ];
|
|
1369 struct stat st;
|
|
1370 FILE *dp;
|
|
1371
|
|
1372 if (!(mp -> msgflags & MODIFIED) || mp -> msgflags & READONLY || fmsh) {
|
|
1373 if (vmh)
|
|
1374 (void) rc2peer (RC_FIN, 0, NULLCP);
|
|
1375 return;
|
|
1376 }
|
|
1377
|
|
1378 if (vmh)
|
|
1379 (void) ttyNaux (NULLCMD, "FAST");
|
|
1380 cp = NULL;
|
|
1381 if ((dp = lkfopen (mp -> foldpath, "r")) == NULL) {
|
|
1382 advise (mp -> foldpath, "unable to lock");
|
|
1383 if (vmh) {
|
|
1384 (void) ttyR (NULLCMD);
|
|
1385 (void) pFIN ();
|
|
1386 }
|
|
1387 return;
|
|
1388 }
|
|
1389 if (fstat (fileno (dp), &st) == NOTOK) {
|
|
1390 advise (mp -> foldpath, "unable to stat");
|
|
1391 goto release;
|
|
1392 }
|
|
1393 if (mtime != st.st_mtime) {
|
|
1394 advise (NULLCP, "new messages have arrived, no update");
|
|
1395 goto release;
|
|
1396 }
|
|
1397 mode = (int) (st.st_mode & 0777);
|
|
1398
|
|
1399 if (mp -> nummsg == 0) {
|
|
1400 cp = concat ("Zero file \"", mp -> foldpath, "\"? ", NULLCP);
|
|
1401 if (getanswer (cp)) {
|
|
1402 if ((i = creat (mp -> foldpath, mode)) != NOTOK)
|
|
1403 (void) close (i);
|
|
1404 else
|
|
1405 advise (mp -> foldpath, "error zero'ing");
|
|
1406 (void) unlink (map_name (mp -> foldpath));/* XXX */
|
|
1407 }
|
|
1408 goto release;
|
|
1409 }
|
|
1410
|
|
1411 cp = concat ("Update file \"", mp -> foldpath, "\"? ", NULLCP);
|
|
1412 if (!getanswer (cp))
|
|
1413 goto release;
|
|
1414 (void) strcpy (tmpfil, m_backup (mp -> foldpath));
|
|
1415 if ((md = mbx_open (tmpfil, st.st_uid, st.st_gid, mode)) == NOTOK) {
|
|
1416 advise (tmpfil, "unable to open");
|
|
1417 goto release;
|
|
1418 }
|
|
1419
|
|
1420 for (msgnum = mp -> lowmsg; msgnum <= mp -> hghmsg; msgnum++)
|
|
1421 if (mp -> msgstats[msgnum] & EXISTS
|
|
1422 && pack (tmpfil, md, msgnum) == NOTOK) {
|
|
1423 (void) mbx_close (tmpfil, md);
|
|
1424 (void) unlink (tmpfil);
|
|
1425 (void) unlink (map_name (tmpfil));
|
|
1426 goto release;
|
|
1427 }
|
|
1428 (void) mbx_close (tmpfil, md);
|
|
1429
|
|
1430 if (rename (tmpfil, mp -> foldpath) == NOTOK)
|
|
1431 admonish (mp -> foldpath, "unable to rename %s to", tmpfil);
|
|
1432 else {
|
|
1433 (void) strcpy (map1, map_name (tmpfil));
|
|
1434 (void) strcpy (map2, map_name (mp -> foldpath));
|
|
1435
|
|
1436 if (rename (map1, map2) == NOTOK) {
|
|
1437 admonish (map2, "unable to rename %s to", map1);
|
|
1438 (void) unlink (map1);
|
|
1439 (void) unlink (map2);
|
|
1440 }
|
|
1441 }
|
|
1442
|
|
1443 release: ;
|
|
1444 if (cp)
|
|
1445 free (cp);
|
|
1446 (void) lkfclose (dp, mp -> foldpath);
|
|
1447 if (vmh) {
|
|
1448 (void) ttyR (NULLCMD);
|
|
1449 (void) pFIN ();
|
|
1450 }
|
|
1451 }
|
|
1452
|
|
1453 /* */
|
|
1454
|
|
1455 #ifdef READLINE
|
|
1456 char *
|
|
1457 command_comp(text, state)
|
|
1458 char *text;
|
|
1459 int state;
|
|
1460 {
|
|
1461 static int list_index, len;
|
|
1462 char *name;
|
|
1463
|
|
1464 if (!state) {
|
|
1465 list_index = 0;
|
|
1466 len = strlen(text);
|
|
1467 }
|
|
1468 while ((name = mshcmds[list_index].sw) != NULLCP) {
|
|
1469 if (mshcmds[list_index++].minchars < 0)
|
|
1470 continue;
|
|
1471 if (strncmp(name, text, len) == 0)
|
|
1472 return getcpy(name);
|
|
1473 }
|
|
1474 return NULLCP;
|
|
1475 }
|
|
1476
|
|
1477 #ifdef SYS5DIR
|
|
1478 #include <dirent.h>
|
|
1479 #else
|
|
1480 #include <direct.h>
|
|
1481 #endif
|
|
1482
|
|
1483 char *
|
|
1484 folder_comp(text, state)
|
|
1485 char *text;
|
|
1486 int state;
|
|
1487 {
|
|
1488 static DIR *dp;
|
|
1489 static char *dirname = NULLCP;
|
|
1490 static char *filename = NULLCP;
|
|
1491 static char *foldername = NULLCP;
|
|
1492 static char *subdir = NULLCP;
|
|
1493 static int len;
|
|
1494 #ifdef SYS5DIR
|
|
1495 struct dirent *entry = (struct dirent *)0;
|
|
1496 #else
|
|
1497 struct direct *entry = (struct direct *)0;
|
|
1498 #endif
|
|
1499 char *p;
|
|
1500
|
|
1501 if (!state) {
|
|
1502 foldername = getcpy(text);
|
|
1503 if ((p = rindex(text, '/')) != NULL) {
|
|
1504 foldername[p-text+1] = '\0';
|
|
1505 filename = getcpy(p+1);
|
|
1506 dirname = m_mailpath(path(foldername+1,
|
|
1507 *text == '+' ? TFOLDER : TSUBCWF));
|
|
1508 } else {
|
|
1509 foldername[1] = '\0';
|
|
1510 filename = getcpy(text+1);
|
|
1511 dirname = m_mailpath(*text == '+' ? "" : path("./", TSUBCWF));
|
|
1512 }
|
|
1513 dp = opendir(dirname);
|
|
1514 len = strlen(filename);
|
|
1515 subdir = NULLCP;
|
|
1516 }
|
|
1517 if (subdir && *subdir) {
|
|
1518 p = subdir;
|
|
1519 subdir = NULLCP;
|
|
1520 return p;
|
|
1521 }
|
|
1522 while (dp && (entry = readdir(dp))) {
|
|
1523 if ((len == 0
|
|
1524 && (entry->d_name[0] != '.' ||
|
|
1525 (entry->d_name[1] &&
|
|
1526 (entry->d_name[1] != '.' || entry->d_name[2]))))
|
|
1527 ||
|
|
1528 (len != 0
|
|
1529 && strncmp(filename, entry->d_name, len) == 0)) {
|
|
1530 struct stat st;
|
|
1531 if (lstat(add(entry->d_name, add("/", add(dirname, NULLCP))), &st)
|
|
1532 != NOTOK
|
|
1533 && (st.st_mode & S_IFDIR)) {
|
|
1534 if (st.st_nlink > 2)
|
|
1535 subdir = add("/", add(entry->d_name,
|
|
1536 add(foldername, NULLCP)));
|
|
1537 break;
|
|
1538 }
|
|
1539 }
|
|
1540 }
|
|
1541 if (entry)
|
|
1542 return add(entry->d_name, add(foldername, NULLCP));
|
|
1543
|
|
1544 if (dp) {
|
|
1545 closedir(dp);
|
|
1546 dp = (DIR *)0;
|
|
1547 }
|
|
1548 if (dirname) {
|
|
1549 free(dirname);
|
|
1550 dirname = NULLCP;
|
|
1551 }
|
|
1552 if (filename) {
|
|
1553 free(filename);
|
|
1554 filename = NULLCP;
|
|
1555 }
|
|
1556 if (foldername) {
|
|
1557 free(foldername);
|
|
1558 foldername = NULLCP;
|
|
1559 }
|
|
1560 if (subdir) {
|
|
1561 free(subdir);
|
|
1562 subdir = NULLCP;
|
|
1563 }
|
|
1564 return NULLCP;
|
|
1565 }
|
|
1566
|
|
1567 char **
|
|
1568 msh_completion(text, start, end)
|
|
1569 char *text;
|
|
1570 int start, end;
|
|
1571 {
|
|
1572 char **matches = NULLVP;
|
|
1573
|
|
1574 if (start == 0)
|
|
1575 matches = completion_matches(text, command_comp);
|
|
1576 else if (text[0] == '+' || text[0] == '@')
|
|
1577 matches = completion_matches(text, folder_comp);
|
|
1578
|
|
1579 return matches;
|
|
1580 }
|
|
1581
|
|
1582 initialize_readline()
|
|
1583 {
|
|
1584 rl_readline_name = invo_name;
|
|
1585 rl_basic_word_break_characters = " \t\n\"\\'`$><=;|&{(";
|
|
1586 rl_attempted_completion_function = (CPPFunction *)msh_completion;
|
|
1587 }
|
|
1588 #endif /* READLINE */
|
|
1589
|
|
1590 static int getargs (prompt, sw, cmdp)
|
|
1591 char *prompt;
|
|
1592 struct swit *sw;
|
|
1593 struct Cmd *cmdp;
|
|
1594 {
|
|
1595 int i;
|
|
1596 char *cp;
|
|
1597 static char buffer[BUFSIZ];
|
|
1598
|
|
1599 told_to_quit = 0;
|
|
1600 for (;;) {
|
|
1601 interrupted = 0;
|
|
1602 #if defined(BSD42) || defined(SVR4)
|
|
1603 switch (setjmp (sigenv)) {
|
|
1604 case OK:
|
|
1605 should_intr = 1;
|
|
1606 break;
|
|
1607
|
|
1608 default:
|
|
1609 should_intr = 0;
|
|
1610 if (interrupted && !told_to_quit) {
|
|
1611 (void) putchar ('\n');
|
|
1612 continue;
|
|
1613 }
|
|
1614 if (ppid > 0)
|
|
1615 (void) kill (ppid, SIGEMT);
|
|
1616 return EOF;
|
|
1617 }
|
|
1618 #endif /* BSD42 || SVR4 */
|
|
1619 #ifdef READLINE
|
|
1620 if (!(cp = readline(interactive ? prompt : ""))) {
|
|
1621 #if !defined(BSD42) && !defined(SVR4)
|
|
1622 if (ppid > 0)
|
|
1623 (void) kill (ppid, SIGEMT);
|
|
1624 return EOF;
|
|
1625 #else /* BSD42 || SVR4 */
|
|
1626 longjmp (sigenv, DONE);
|
|
1627 #endif /* BSD42 || SVR4 */
|
|
1628 }
|
|
1629 if (!*cp)
|
|
1630 continue;
|
|
1631 add_history(cp);
|
|
1632 strncpy(buffer, cp, sizeof buffer - 2);
|
|
1633 buffer[sizeof buffer - 2] = '\0';
|
|
1634 free(cp);
|
|
1635 #else /* READLINE */
|
|
1636 if (interactive) {
|
|
1637 printf ("%s", prompt);
|
|
1638 (void) fflush (stdout);
|
|
1639 }
|
|
1640 for (cp = buffer; (i = getchar ()) != '\n';) {
|
|
1641 #if !defined(BSD42) && !defined(SVR4)
|
|
1642 if (interrupted && !told_to_quit) {
|
|
1643 buffer[0] = '\0';
|
|
1644 (void) putchar ('\n');
|
|
1645 break;
|
|
1646 }
|
|
1647 if (told_to_quit || i == EOF) {
|
|
1648 if (ppid > 0)
|
|
1649 (void) kill (ppid, SIGEMT);
|
|
1650 return EOF;
|
|
1651 }
|
|
1652 #else /* BSD42 || SVR4 */
|
|
1653 if (i == EOF)
|
|
1654 longjmp (sigenv, DONE);
|
|
1655 #endif /* BSD42 || SVR4 */
|
|
1656 if (cp < &buffer[sizeof buffer - 2])
|
|
1657 *cp++ = i;
|
|
1658 }
|
|
1659 *cp = 0;
|
|
1660
|
|
1661 if (buffer[0] == 0)
|
|
1662 continue;
|
|
1663 #endif /* READLINE */
|
|
1664 if (buffer[0] == '?') {
|
|
1665 printf ("commands:\n");
|
|
1666 printsw (ALL, sw, "");
|
|
1667 printf ("type CTRL-D or use ``quit'' to leave %s\n",
|
|
1668 invo_name);
|
|
1669 continue;
|
|
1670 }
|
|
1671
|
|
1672 if (parse (buffer, cmdp) == NOTOK)
|
|
1673 continue;
|
|
1674
|
|
1675 switch (i = smatch (cmdp -> args[0], sw)) {
|
|
1676 case AMBIGSW:
|
|
1677 ambigsw (cmdp -> args[0], sw);
|
|
1678 continue;
|
|
1679 case UNKWNSW:
|
|
1680 printf ("say what: ``%s'' -- type ? (or help) for help\n",
|
|
1681 cmdp -> args[0]);
|
|
1682 continue;
|
|
1683 default:
|
|
1684 #if defined(BSD42) || defined(SVR4)
|
|
1685 should_intr = 0;
|
|
1686 #endif /* BSD42 || SVR4 */
|
|
1687 return i;
|
|
1688 }
|
|
1689 }
|
|
1690 }
|
|
1691
|
|
1692 /* */
|
|
1693
|
|
1694 static int getcmds (sw, cmdp, scansw)
|
|
1695 struct swit *sw;
|
|
1696 struct Cmd *cmdp;
|
|
1697 int scansw;
|
|
1698 {
|
|
1699 int i;
|
|
1700 struct record rcs,
|
|
1701 *rc = &rcs;
|
|
1702
|
|
1703 initrc (rc);
|
|
1704
|
|
1705 for (;;)
|
|
1706 switch (peer2rc (rc)) {
|
|
1707 case RC_QRY:
|
|
1708 (void) pQRY (rc -> rc_data, scansw);
|
|
1709 break;
|
|
1710
|
|
1711 case RC_CMD:
|
|
1712 if ((i = pCMD (rc -> rc_data, sw, cmdp)) != NOTOK)
|
|
1713 return i;
|
|
1714 break;
|
|
1715
|
|
1716 case RC_FIN:
|
|
1717 if (ppid > 0)
|
|
1718 (void) kill (ppid, SIGEMT);
|
|
1719 return EOF;
|
|
1720
|
|
1721 case RC_XXX:
|
|
1722 padios (NULLCP, "%s", rc -> rc_data);
|
|
1723
|
|
1724 default:
|
|
1725 (void) fmt2peer (RC_ERR, "pLOOP protocol screw-up");
|
|
1726 done (1);
|
|
1727 }
|
|
1728 }
|
|
1729
|
|
1730 /* */
|
|
1731
|
|
1732 static int parse (buffer, cmdp)
|
|
1733 char *buffer;
|
|
1734 struct Cmd *cmdp;
|
|
1735 {
|
|
1736 int argp = 0;
|
|
1737 char c,
|
|
1738 *cp,
|
|
1739 *pp;
|
|
1740
|
|
1741 cmdp -> line[0] = 0;
|
|
1742 pp = cmdp -> args[argp++] = cmdp -> line;
|
|
1743 cmdp -> redirect = NULL;
|
|
1744 cmdp -> direction = STDIO;
|
|
1745 cmdp -> stream = NULL;
|
|
1746
|
|
1747 for (cp = buffer; c = *cp; cp++)
|
|
1748 if (!isspace ((unsigned char) c))
|
|
1749 break;
|
|
1750 if (c == 0) {
|
|
1751 if (vmh)
|
|
1752 (void) fmt2peer (RC_EOF, "null command");
|
|
1753 return NOTOK;
|
|
1754 }
|
|
1755
|
|
1756 while (c = *cp++) {
|
|
1757 if (isspace ((unsigned char) c)) {
|
|
1758 while (isspace ((unsigned char) c))
|
|
1759 c = *cp++;
|
|
1760 if (c == 0)
|
|
1761 break;
|
|
1762 *pp++ = 0;
|
|
1763 cmdp -> args[argp++] = pp;
|
|
1764 *pp = 0;
|
|
1765 }
|
|
1766
|
|
1767 switch (c) {
|
|
1768 case '"':
|
|
1769 for (;;) {
|
|
1770 switch (c = *cp++) {
|
|
1771 case 0:
|
|
1772 padvise (NULLCP, "unmatched \"");
|
|
1773 return NOTOK;
|
|
1774 case '"':
|
|
1775 break;
|
|
1776 case QUOTE:
|
|
1777 if ((c = *cp++) == 0)
|
|
1778 goto no_quoting;
|
|
1779 default:
|
|
1780 *pp++ = c;
|
|
1781 continue;
|
|
1782 }
|
|
1783 break;
|
|
1784 }
|
|
1785 continue;
|
|
1786
|
|
1787 case QUOTE:
|
|
1788 if ((c = *cp++) == 0) {
|
|
1789 no_quoting: ;
|
|
1790 padvise (NULLCP, "the newline character can not be quoted");
|
|
1791 return NOTOK;
|
|
1792 }
|
|
1793
|
|
1794 default: ;
|
|
1795 *pp++ = c;
|
|
1796 continue;
|
|
1797
|
|
1798 case '>':
|
|
1799 case '|':
|
|
1800 if (pp == cmdp -> line) {
|
|
1801 padvise (NULLCP, "invalid null command");
|
|
1802 return NOTOK;
|
|
1803 }
|
|
1804 if (*cmdp -> args[argp - 1] == 0)
|
|
1805 argp--;
|
|
1806 cmdp -> direction = c == '>' ? CRTIO : PIPIO;
|
|
1807 if (cmdp -> direction == CRTIO && (c = *cp) == '>') {
|
|
1808 cmdp -> direction = APPIO;
|
|
1809 cp++;
|
|
1810 }
|
|
1811 cmdp -> redirect = pp + 1;/* sigh */
|
|
1812 for (; c = *cp; cp++)
|
|
1813 if (!isspace ((unsigned char) c))
|
|
1814 break;
|
|
1815 if (c == 0) {
|
|
1816 padvise (NULLCP, cmdp -> direction != PIPIO
|
|
1817 ? "missing name for redirect"
|
|
1818 : "invalid null command");
|
|
1819 return NOTOK;
|
|
1820 }
|
|
1821 (void) strcpy (cmdp -> redirect, cp);
|
|
1822 if (cmdp -> direction != PIPIO) {
|
|
1823 for (; *cp; cp++)
|
|
1824 if (isspace ((unsigned char) *cp)) {
|
|
1825 padvise (NULLCP, "bad name for redirect");
|
|
1826 return NOTOK;
|
|
1827 }
|
|
1828 if (expand (cmdp -> redirect) == NOTOK)
|
|
1829 return NOTOK;
|
|
1830 }
|
|
1831 break;
|
|
1832 }
|
|
1833 break;
|
|
1834 }
|
|
1835
|
|
1836 *pp++ = 0;
|
|
1837 cmdp -> args[argp] = NULL;
|
|
1838
|
|
1839 return OK;
|
|
1840 }
|
|
1841
|
|
1842 /* */
|
|
1843
|
|
1844 int expand (redirect)
|
|
1845 char *redirect;
|
|
1846 {
|
|
1847 char *cp,
|
|
1848 *pp;
|
|
1849 char path[BUFSIZ];
|
|
1850 struct passwd *pw;
|
|
1851
|
|
1852 if (*redirect != '~')
|
|
1853 return OK;
|
|
1854
|
|
1855 if (cp = index (pp = redirect + 1, '/'))
|
|
1856 *cp++ = 0;
|
|
1857 if (*pp == 0)
|
|
1858 pp = mypath;
|
|
1859 else
|
|
1860 if (pw = getpwnam (pp))
|
|
1861 pp = pw -> pw_dir;
|
|
1862 else {
|
|
1863 padvise (NULLCP, "unknown user: %s", pp);
|
|
1864 return NOTOK;
|
|
1865 }
|
|
1866
|
|
1867 (void) sprintf (path, "%s/%s", pp, cp ? cp : "");
|
|
1868 (void) strcpy (redirect, path);
|
|
1869 return OK;
|
|
1870 }
|
|
1871
|
|
1872 /* */
|
|
1873
|
|
1874 static int init_io (cmdp, vio)
|
|
1875 register struct Cmd *cmdp;
|
|
1876 int vio;
|
|
1877 {
|
|
1878 int io,
|
|
1879 result;
|
|
1880
|
|
1881 io = vmh;
|
|
1882
|
|
1883 vmh = vio;
|
|
1884 result = initaux_io (cmdp);
|
|
1885 vmh = io;
|
|
1886
|
|
1887 return result;
|
|
1888 }
|
|
1889
|
|
1890
|
|
1891 static int initaux_io (cmdp)
|
|
1892 register struct Cmd *cmdp;
|
|
1893 {
|
|
1894 char *mode;
|
|
1895
|
|
1896 switch (cmdp -> direction) {
|
|
1897 case STDIO:
|
|
1898 return OK;
|
|
1899
|
|
1900 case CRTIO:
|
|
1901 case APPIO:
|
|
1902 mode = cmdp -> direction == CRTIO ? "write" : "append";
|
|
1903 if ((cmdp -> stream = fopen (cmdp -> redirect, mode)) == NULL) {
|
|
1904 padvise (cmdp -> redirect, "unable to %s ", mode);
|
|
1905 cmdp -> direction = STDIO;
|
|
1906 return NOTOK;
|
|
1907 }
|
|
1908 break;
|
|
1909
|
|
1910 case PIPIO:
|
|
1911 if ((cmdp -> stream = popen (cmdp -> redirect, "w")) == NULL) {
|
|
1912 padvise (cmdp -> redirect, "unable to pipe");
|
|
1913 cmdp -> direction = STDIO;
|
|
1914 return NOTOK;
|
|
1915 }
|
|
1916 (void) signal (SIGPIPE, pipeser);
|
|
1917 broken_pipe = 0;
|
|
1918 break;
|
|
1919
|
|
1920 default:
|
|
1921 padios (NULLCP, "unknown redirection for command");
|
|
1922 }
|
|
1923
|
|
1924 (void) fflush (stdout);
|
|
1925 if (dup2 (fileno (cmdp -> stream), fileno (stdout)) == NOTOK)
|
|
1926 padios ("standard output", "unable to dup2");
|
|
1927 clearerr (stdout);
|
|
1928
|
|
1929 return OK;
|
|
1930 }
|
|
1931
|
|
1932 /* */
|
|
1933
|
|
1934 static fin_io (cmdp, vio)
|
|
1935 register struct Cmd *cmdp;
|
|
1936 int vio;
|
|
1937 {
|
|
1938 int io;
|
|
1939
|
|
1940 io = vmh;
|
|
1941
|
|
1942 vmh = vio;
|
|
1943 finaux_io (cmdp);
|
|
1944 vmh = io;
|
|
1945 }
|
|
1946
|
|
1947
|
|
1948 static int finaux_io (cmdp)
|
|
1949 register struct Cmd *cmdp;
|
|
1950 {
|
|
1951 switch (cmdp -> direction) {
|
|
1952 case STDIO:
|
|
1953 return;
|
|
1954
|
|
1955 case CRTIO:
|
|
1956 case APPIO:
|
|
1957 (void) fflush (stdout);
|
|
1958 (void) close (fileno (stdout));
|
|
1959 if (ferror (stdout))
|
|
1960 padvise (NULLCP, "problems writing %s", cmdp -> redirect);
|
|
1961 (void) fclose (cmdp -> stream);
|
|
1962 break;
|
|
1963
|
|
1964 case PIPIO:
|
|
1965 (void) fflush (stdout);
|
|
1966 (void) close (fileno (stdout));
|
|
1967 (void) pclose (cmdp -> stream);
|
|
1968 (void) signal (SIGPIPE, SIG_DFL);
|
|
1969 break;
|
|
1970
|
|
1971 default:
|
|
1972 padios (NULLCP, "unknown redirection for command");
|
|
1973 }
|
|
1974
|
|
1975 if (dup2 (fileno (sp), fileno (stdout)) == NOTOK)
|
|
1976 padios ("standard output", "unable to dup2");
|
|
1977 clearerr (stdout);
|
|
1978
|
|
1979 cmdp -> direction = STDIO;
|
|
1980 }
|
|
1981
|
|
1982 /* */
|
|
1983
|
|
1984 static m_init () {
|
|
1985 int msgnum;
|
|
1986
|
|
1987 for (msgnum = mp -> lowmsg; msgnum <= mp -> hghmsg; msgnum++)
|
|
1988 mp -> msgstats[msgnum] &= ~SELECTED;
|
|
1989 mp -> lowsel = mp -> hghsel = mp -> numsel = 0;
|
|
1990 }
|
|
1991
|
|
1992
|
|
1993 m_reset () {
|
|
1994 write_ids ();
|
|
1995 m_fmsg (mp);
|
|
1996 myname = NULL;
|
|
1997 #if defined(BPOP) || defined(NNTP)
|
|
1998 if (pmsh) {
|
|
1999 (void) pop_done ();
|
|
2000 pmsh = 0;
|
|
2001 }
|
|
2002 #endif /* BPOP || NNTP */
|
|
2003 }
|
|
2004
|
|
2005 /* */
|
|
2006
|
|
2007 void m_setcur (mp, msgnum)
|
|
2008 register struct msgs *mp;
|
|
2009 register int msgnum;
|
|
2010 {
|
|
2011 if (mp -> curmsg == msgnum)
|
|
2012 return;
|
|
2013
|
|
2014 if (mp -> curmsg && Msgs[mp -> curmsg].m_scanl) {
|
|
2015 free (Msgs[mp -> curmsg].m_scanl);
|
|
2016 Msgs[mp -> curmsg].m_scanl = NULL;
|
|
2017 }
|
|
2018 if (Msgs[msgnum].m_scanl) {
|
|
2019 free (Msgs[msgnum].m_scanl);
|
|
2020 Msgs[msgnum].m_scanl = NULL;
|
|
2021 }
|
|
2022
|
|
2023 mp -> curmsg = msgnum;
|
|
2024 }
|
|
2025
|
|
2026 /* */
|
|
2027
|
|
2028 /* ARGSUSED */
|
|
2029
|
|
2030 static TYPESIG intrser (i)
|
|
2031 int i;
|
|
2032 {
|
|
2033 #ifndef BSD42
|
|
2034 (void) signal (SIGINT, intrser);
|
|
2035 #endif /* not BSD42 */
|
|
2036
|
|
2037 discard (stdout);
|
|
2038
|
|
2039 interrupted++;
|
|
2040 #if defined(BSD42) || defined(SVR4)
|
|
2041 if (should_intr)
|
|
2042 longjmp (sigenv, NOTOK);
|
|
2043 #endif /* BSD42 || SVR4 */
|
|
2044 }
|
|
2045
|
|
2046
|
|
2047 /* ARGSUSED */
|
|
2048
|
|
2049 static TYPESIG pipeser (i)
|
|
2050 int i;
|
|
2051 {
|
|
2052 #ifndef BSD42
|
|
2053 (void) signal (SIGPIPE, pipeser);
|
|
2054 #endif /* not BSD42 */
|
|
2055
|
|
2056 if (broken_pipe++ == 0)
|
|
2057 fprintf (stderr, "broken pipe\n");
|
|
2058 told_to_quit++;
|
|
2059 interrupted++;
|
|
2060 #if defined(BSD42) || defined(SVR4)
|
|
2061 if (should_intr)
|
|
2062 longjmp (sigenv, NOTOK);
|
|
2063 #endif /* BSD42 || SVR4 */
|
|
2064 }
|
|
2065
|
|
2066
|
|
2067 /* ARGSUSED */
|
|
2068
|
|
2069 static TYPESIG quitser (i)
|
|
2070 int i;
|
|
2071 {
|
|
2072 #ifndef BSD42
|
|
2073 (void) signal (SIGQUIT, quitser);
|
|
2074 #endif /* BSD42 */
|
|
2075
|
|
2076 told_to_quit++;
|
|
2077 interrupted++;
|
|
2078 #if defined(BSD42) || defined(SVR4)
|
|
2079 if (should_intr)
|
|
2080 longjmp (sigenv, NOTOK);
|
|
2081 #endif /* BSD42 || SVR4 */
|
|
2082 }
|
|
2083
|
|
2084 /* */
|
|
2085
|
|
2086 static int pINI () {
|
|
2087 int i,
|
|
2088 vrsn;
|
|
2089 char *bp;
|
|
2090 struct record rcs,
|
|
2091 *rc = &rcs;
|
|
2092
|
|
2093 initrc (rc);
|
|
2094
|
|
2095 switch (peer2rc (rc)) {
|
|
2096 case RC_INI:
|
|
2097 bp = rc -> rc_data;
|
|
2098 while (isspace (*bp))
|
|
2099 bp++;
|
|
2100 if (sscanf (bp, "%d", &vrsn) != 1) {
|
|
2101 bad_init: ;
|
|
2102 (void) fmt2peer (RC_ERR, "bad init \"%s\"", rc -> rc_data);
|
|
2103 done (1);
|
|
2104 }
|
|
2105 if (vrsn != RC_VRSN) {
|
|
2106 (void) fmt2peer (RC_ERR, "version %d unsupported", vrsn);
|
|
2107 done (1);
|
|
2108 }
|
|
2109
|
|
2110 while (*bp && !isspace (*bp))
|
|
2111 bp++;
|
|
2112 while (isspace (*bp))
|
|
2113 bp++;
|
|
2114 if (sscanf (bp, "%d", &numwins) != 1 || numwins <= 0)
|
|
2115 goto bad_init;
|
|
2116 if (numwins > NWIN)
|
|
2117 numwins = NWIN;
|
|
2118
|
|
2119 for (i = 1; i <= numwins; i++) {
|
|
2120 while (*bp && !isspace (*bp))
|
|
2121 bp++;
|
|
2122 while (isspace (*bp))
|
|
2123 bp++;
|
|
2124 if (sscanf (bp, "%d", &windows[i]) != 1 || windows[i] <= 0)
|
|
2125 goto bad_init;
|
|
2126 }
|
|
2127 (void) rc2peer (RC_ACK, 0, NULLCP);
|
|
2128 return OK;
|
|
2129
|
|
2130 case RC_XXX:
|
|
2131 padios (NULLCP, "%s", rc -> rc_data);
|
|
2132
|
|
2133 default:
|
|
2134 (void) fmt2peer (RC_ERR, "pINI protocol screw-up");
|
|
2135 done (1); /* NOTREACHED */
|
|
2136 }
|
|
2137 }
|
|
2138
|
|
2139 /* */
|
|
2140
|
|
2141 /* ARGSUSED */
|
|
2142
|
|
2143 static int pQRY (str, scansw)
|
|
2144 char *str;
|
|
2145 int scansw;
|
|
2146 {
|
|
2147 if (pQRY1 (scansw) == NOTOK || pQRY2 () == NOTOK)
|
|
2148 return NOTOK;
|
|
2149
|
|
2150 (void) rc2peer (RC_EOF, 0, NULLCP);
|
|
2151 return OK;
|
|
2152 }
|
|
2153
|
|
2154 /* */
|
|
2155
|
|
2156 static int pQRY1 (scansw)
|
|
2157 int scansw;
|
|
2158 {
|
|
2159 int oldhgh;
|
|
2160 static int lastlow = 0,
|
|
2161 lastcur = 0,
|
|
2162 lasthgh = 0,
|
|
2163 lastnum = 0;
|
|
2164
|
|
2165 oldhgh = mp -> hghmsg;
|
|
2166 if (check_folder (scansw) && oldhgh < mp -> hghmsg) {
|
|
2167 switch (winX (STATUS)) {
|
|
2168 case NOTOK:
|
|
2169 return NOTOK;
|
|
2170
|
|
2171 case OK:
|
|
2172 printf ("new messages have arrived!");
|
|
2173 (void) fflush (stdout);
|
|
2174 (void) fflush (stderr);
|
|
2175 _exit (0); /* NOTREACHED */
|
|
2176
|
|
2177 default:
|
|
2178 lastlow = lastcur = lasthgh = lastnum = 0;
|
|
2179 break;
|
|
2180 }
|
|
2181
|
|
2182 switch (winX (DISPLAY)) {
|
|
2183 case NOTOK:
|
|
2184 return NOTOK;
|
|
2185
|
|
2186 case OK:
|
|
2187 scanrange (oldhgh + 1, mp -> hghmsg);
|
|
2188 (void) fflush (stdout);
|
|
2189 (void) fflush (stderr);
|
|
2190 _exit (0); /* NOTREACHED */
|
|
2191
|
|
2192 default:
|
|
2193 break;
|
|
2194 }
|
|
2195 return OK;
|
|
2196 }
|
|
2197
|
|
2198 if (gap)
|
|
2199 switch (winX (STATUS)) {
|
|
2200 case NOTOK:
|
|
2201 return NOTOK;
|
|
2202
|
|
2203 case OK:
|
|
2204 printf ("%s: gap in ID:s, last seen %d, lowest present %d\n",
|
|
2205 myname ? myname : fmsh ? fmsh : mp -> foldpath, gap - 1,
|
|
2206 readid (mp -> lowmsg));
|
|
2207 (void) fflush (stdout);
|
|
2208 (void) fflush (stderr);
|
|
2209 _exit (0); /* NOTREACHED */
|
|
2210
|
|
2211 default:
|
|
2212 gap = 0;
|
|
2213 return OK;
|
|
2214 }
|
|
2215
|
|
2216 if (mp -> lowmsg != lastlow
|
|
2217 || mp -> curmsg != lastcur
|
|
2218 || mp -> hghmsg != lasthgh
|
|
2219 || mp -> nummsg != lastnum)
|
|
2220 switch (winX (STATUS)) {
|
|
2221 case NOTOK:
|
|
2222 return NOTOK;
|
|
2223
|
|
2224 case OK:
|
|
2225 foldcmd (NULLVP);
|
|
2226 (void) fflush (stdout);
|
|
2227 (void) fflush (stderr);
|
|
2228 _exit (0); /* NOTREACHED */
|
|
2229
|
|
2230 default:
|
|
2231 lastlow = mp -> lowmsg;
|
|
2232 lastcur = mp -> curmsg;
|
|
2233 lasthgh = mp -> hghmsg;
|
|
2234 lastnum = mp -> nummsg;
|
|
2235 return OK;
|
|
2236 }
|
|
2237
|
|
2238 return OK;
|
|
2239 }
|
|
2240
|
|
2241 /* */
|
|
2242
|
|
2243 static int pQRY2 () {
|
|
2244 int i,
|
|
2245 j,
|
|
2246 k,
|
|
2247 msgnum,
|
|
2248 n;
|
|
2249 static int cur = 0,
|
|
2250 num = 0,
|
|
2251 lo = 0,
|
|
2252 hi = 0;
|
|
2253
|
|
2254 if (mp -> nummsg == 0 && mp -> nummsg != num)
|
|
2255 switch (winX (SCAN)) {
|
|
2256 case NOTOK:
|
|
2257 return NOTOK;
|
|
2258
|
|
2259 case OK:
|
|
2260 printf ("empty!");
|
|
2261 (void) fflush (stdout);
|
|
2262 (void) fflush (stderr);
|
|
2263 _exit (0); /* NOTREACHED */
|
|
2264
|
|
2265 default:
|
|
2266 num = mp -> nummsg;
|
|
2267 return OK;
|
|
2268 }
|
|
2269 num = mp -> nummsg;
|
|
2270
|
|
2271 i = 0;
|
|
2272 j = (k = windows[SCAN]) / 2;
|
|
2273 for (msgnum = mp -> curmsg; msgnum <= mp -> hghmsg; msgnum++)
|
|
2274 if (mp -> msgstats[msgnum] & EXISTS)
|
|
2275 i++;
|
|
2276 if (i-- > 0)
|
|
2277 if (topcur)
|
|
2278 k = i >= k ? 1 : k - i;
|
|
2279 else
|
|
2280 k -= i > j ? j : i;
|
|
2281
|
|
2282 i = j = 0;
|
|
2283 n = 1;
|
|
2284 for (msgnum = mp -> curmsg; msgnum >= mp -> lowmsg; msgnum--)
|
|
2285 if (mp -> msgstats[msgnum] & EXISTS) {
|
|
2286 i = msgnum;
|
|
2287 if (j == 0)
|
|
2288 j = msgnum;
|
|
2289 if (n++ >= k)
|
|
2290 break;
|
|
2291 }
|
|
2292 for (msgnum = mp -> curmsg + 1; msgnum <= mp -> hghmsg; msgnum++)
|
|
2293 if (mp -> msgstats[msgnum] & EXISTS) {
|
|
2294 if (i == 0)
|
|
2295 i = msgnum;
|
|
2296 j = msgnum;
|
|
2297 if (n++ >= windows[SCAN])
|
|
2298 break;
|
|
2299 }
|
|
2300 if (!topcur
|
|
2301 && lo > 0
|
|
2302 && hi > 0
|
|
2303 && mp -> msgstats[lo] & EXISTS
|
|
2304 && mp -> msgstats[hi] & EXISTS
|
|
2305 && (lo < mp -> curmsg
|
|
2306 || (lo == mp -> curmsg && lo == mp -> lowmsg))
|
|
2307 && (mp -> curmsg < hi
|
|
2308 || (hi == mp -> curmsg && hi == mp -> hghmsg))
|
|
2309 && hi - lo == j - i)
|
|
2310 i = lo, j = hi;
|
|
2311
|
|
2312 if (mp -> curmsg != cur || modified)
|
|
2313 switch (winN (NULLCMD, SCAN, 0)) {
|
|
2314 case NOTOK:
|
|
2315 return NOTOK;
|
|
2316
|
|
2317 case OK:
|
|
2318 return OK;
|
|
2319
|
|
2320 default:
|
|
2321 scanrange (lo = i, hi = j);
|
|
2322 cur = mp -> curmsg;
|
|
2323 (void) winR (NULLCMD);
|
|
2324 return OK;
|
|
2325 }
|
|
2326
|
|
2327 return OK;
|
|
2328 }
|
|
2329
|
|
2330 /* */
|
|
2331
|
|
2332 static int pCMD (str, sw, cmdp)
|
|
2333 char *str;
|
|
2334 struct swit *sw;
|
|
2335 struct Cmd *cmdp;
|
|
2336 {
|
|
2337 int i;
|
|
2338
|
|
2339 if (*str == '?')
|
|
2340 switch (winX (DISPLAY)) {
|
|
2341 case NOTOK:
|
|
2342 return NOTOK;
|
|
2343
|
|
2344 case OK:
|
|
2345 printf ("commands:\n");
|
|
2346 printsw (ALL, sw, "");
|
|
2347 printf ("type ``quit'' to leave %s\n", invo_name);
|
|
2348 (void) fflush (stdout);
|
|
2349 (void) fflush (stderr);
|
|
2350 _exit (0); /* NOTREACHED */
|
|
2351
|
|
2352 default:
|
|
2353 (void) rc2peer (RC_EOF, 0, NULLCP);
|
|
2354 return NOTOK;
|
|
2355 }
|
|
2356
|
|
2357 if (parse (str, cmdp) == NOTOK)
|
|
2358 return NOTOK;
|
|
2359
|
|
2360 switch (i = smatch (cmdp -> args[0], sw)) {
|
|
2361 case AMBIGSW:
|
|
2362 switch (winX (DISPLAY)) {
|
|
2363 case NOTOK:
|
|
2364 return NOTOK;
|
|
2365
|
|
2366 case OK:
|
|
2367 ambigsw (cmdp -> args[0], sw);
|
|
2368 (void) fflush (stdout);
|
|
2369 (void) fflush (stderr);
|
|
2370 _exit (0); /* NOTREACHED */
|
|
2371
|
|
2372 default:
|
|
2373 (void) rc2peer (RC_EOF, 0, NULLCP);
|
|
2374 return NOTOK;
|
|
2375 }
|
|
2376
|
|
2377 case UNKWNSW:
|
|
2378 (void) fmt2peer (RC_ERR,
|
|
2379 "say what: ``%s'' -- type ? (or help) for help",
|
|
2380 cmdp -> args[0]);
|
|
2381 return NOTOK;
|
|
2382
|
|
2383 default:
|
|
2384 return i;
|
|
2385 }
|
|
2386 }
|
|
2387
|
|
2388 /* */
|
|
2389
|
|
2390 static int pFIN () {
|
|
2391 int status;
|
|
2392
|
|
2393 switch (setjmp (peerenv)) {
|
|
2394 case OK:
|
|
2395 (void) signal (SIGALRM, alrmser);
|
|
2396 (void) alarm (ALARM);
|
|
2397
|
|
2398 status = peerwait ();
|
|
2399
|
|
2400 (void) alarm (0);
|
|
2401 return status;
|
|
2402
|
|
2403 default:
|
|
2404 return NOTOK;
|
|
2405 }
|
|
2406 }
|
|
2407
|
|
2408
|
|
2409 static int peerwait () {
|
|
2410 struct record rcs,
|
|
2411 *rc = &rcs;
|
|
2412
|
|
2413 initrc (rc);
|
|
2414
|
|
2415 switch (peer2rc (rc)) {
|
|
2416 case RC_QRY:
|
|
2417 case RC_CMD:
|
|
2418 (void) rc2peer (RC_FIN, 0, NULLCP);
|
|
2419 return OK;
|
|
2420
|
|
2421 case RC_XXX:
|
|
2422 advise (NULLCP, "%s", rc -> rc_data);
|
|
2423 return NOTOK;
|
|
2424
|
|
2425 default:
|
|
2426 (void) fmt2peer (RC_FIN, "pLOOP protocol screw-up");
|
|
2427 return NOTOK;
|
|
2428 }
|
|
2429 }
|
|
2430
|
|
2431
|
|
2432 /* ARGSUSED */
|
|
2433
|
|
2434 static TYPESIG alrmser (i)
|
|
2435 int i;
|
|
2436 {
|
|
2437 longjmp (peerenv, DONE);
|
|
2438 }
|
|
2439
|
|
2440 /* */
|
|
2441
|
|
2442 static int ttyNaux (cmdp, s)
|
|
2443 register struct Cmd *cmdp;
|
|
2444 char *s;
|
|
2445 {
|
|
2446 struct record rcs,
|
|
2447 *rc = &rcs;
|
|
2448
|
|
2449 initrc (rc);
|
|
2450
|
|
2451 if (cmdp && init_io (cmdp, vmh) == NOTOK)
|
|
2452 return NOTOK;
|
|
2453
|
|
2454 if (!fmsh)
|
|
2455 (void) fseek (fp, 0L, 0);/* XXX: fseek() too tricky for our own good */
|
|
2456
|
|
2457 vmhtty = NOTOK;
|
|
2458 switch (rc2rc (RC_TTY, s ? strlen (s) : 0, s, rc)) {
|
|
2459 case RC_ACK:
|
|
2460 vmhtty = OK; /* fall */
|
|
2461 case RC_ERR:
|
|
2462 break;
|
|
2463
|
|
2464 case RC_XXX:
|
|
2465 padios (NULLCP, "%s", rc -> rc_data);/* NOTREACHED */
|
|
2466
|
|
2467 default:
|
|
2468 (void) fmt2peer (RC_ERR, "pTTY protocol screw-up");
|
|
2469 done (1); /* NOTREACHED */
|
|
2470 }
|
|
2471
|
|
2472 #ifdef SIGTSTP
|
|
2473 (void) signal (SIGTSTP, tstat);
|
|
2474 #endif /* SIGTSTP */
|
|
2475 return vmhtty;
|
|
2476 }
|
|
2477
|
|
2478 /* */
|
|
2479
|
|
2480 static int ttyR (cmdp)
|
|
2481 register struct Cmd *cmdp;
|
|
2482 {
|
|
2483 struct record rcs,
|
|
2484 *rc = &rcs;
|
|
2485
|
|
2486 #ifdef SIGTSTP
|
|
2487 (void) signal (SIGTSTP, SIG_IGN);
|
|
2488 #endif /* SIGTSTP */
|
|
2489
|
|
2490 if (vmhtty != OK)
|
|
2491 return NOTOK;
|
|
2492
|
|
2493 initrc (rc);
|
|
2494
|
|
2495 if (cmdp)
|
|
2496 fin_io (cmdp, 0);
|
|
2497
|
|
2498 vmhtty = NOTOK;
|
|
2499 switch (rc2rc (RC_EOF, 0, NULLCP, rc)) {
|
|
2500 case RC_ACK:
|
|
2501 (void) rc2peer (RC_EOF, 0, NULLCP);
|
|
2502 return OK;
|
|
2503
|
|
2504 case RC_XXX:
|
|
2505 padios (NULLCP, "%s", rc -> rc_data);/* NOTREACHED */
|
|
2506
|
|
2507 default:
|
|
2508 (void) fmt2peer (RC_ERR, "pTTY protocol screw-up");
|
|
2509 done (1); /* NOTREACHED */
|
|
2510 }
|
|
2511 }
|
|
2512
|
|
2513 /* */
|
|
2514
|
|
2515 static int winN (cmdp, n, eof)
|
|
2516 register struct Cmd *cmdp;
|
|
2517 int n,
|
|
2518 eof;
|
|
2519 {
|
|
2520 int i,
|
|
2521 pd[2];
|
|
2522 char buffer[BUFSIZ];
|
|
2523 struct record rcs,
|
|
2524 *rc = &rcs;
|
|
2525
|
|
2526 if (vmhpid == NOTOK)
|
|
2527 return OK;
|
|
2528
|
|
2529 initrc (rc);
|
|
2530
|
|
2531 if (!fmsh)
|
|
2532 (void) fseek (fp, 0L, 0);/* XXX: fseek() too tricky for our own good */
|
|
2533
|
|
2534 vmhpid = OK;
|
|
2535
|
|
2536 (void) sprintf (buffer, "%d", n);
|
|
2537 switch (str2rc (RC_WIN, buffer, rc)) {
|
|
2538 case RC_ACK:
|
|
2539 break;
|
|
2540
|
|
2541 case RC_ERR:
|
|
2542 return NOTOK;
|
|
2543
|
|
2544 case RC_XXX:
|
|
2545 padios (NULLCP, "%s", rc -> rc_data);
|
|
2546
|
|
2547 default:
|
|
2548 (void) fmt2peer (RC_ERR, "pWIN protocol screw-up");
|
|
2549 done (1);
|
|
2550 }
|
|
2551
|
|
2552 if (pipe (pd) == NOTOK) {
|
|
2553 (void) err2peer (RC_ERR, "pipe", "unable to");
|
|
2554 return NOTOK;
|
|
2555 }
|
|
2556
|
|
2557 switch (vmhpid = fork ()) {
|
|
2558 case NOTOK:
|
|
2559 (void) err2peer (RC_ERR, "fork", "unable to");
|
|
2560 (void) close (pd[0]);
|
|
2561 (void) close (pd[1]);
|
|
2562 return NOTOK;
|
|
2563
|
|
2564 case OK:
|
|
2565 (void) close (pd[1]);
|
|
2566 (void) signal (SIGPIPE, SIG_IGN);
|
|
2567 while ((i = read (pd[0], buffer, sizeof buffer)) > 0)
|
|
2568 switch (rc2rc (RC_DATA, i, buffer, rc)) {
|
|
2569 case RC_ACK:
|
|
2570 break;
|
|
2571
|
|
2572 case RC_ERR:
|
|
2573 _exit (1);
|
|
2574
|
|
2575 case RC_XXX:
|
|
2576 advise (NULLCP, "%s", rc -> rc_data);
|
|
2577 _exit (2);
|
|
2578
|
|
2579 default:
|
|
2580 (void) fmt2peer (RC_ERR, "pWIN protocol screw-up");
|
|
2581 _exit (2);
|
|
2582 }
|
|
2583 if (i == OK)
|
|
2584 switch (rc2rc (RC_EOF, 0, NULLCP, rc)) {
|
|
2585 case RC_ACK:
|
|
2586 if (eof)
|
|
2587 (void) rc2peer (RC_EOF, 0, NULLCP);
|
|
2588 i = 0;
|
|
2589 break;
|
|
2590
|
|
2591 case RC_XXX:
|
|
2592 advise (NULLCP, "%s", rc -> rc_data);
|
|
2593 i = 2;
|
|
2594 break;
|
|
2595
|
|
2596 default:
|
|
2597 (void) fmt2peer (RC_ERR, "pWIN protocol screw-up");
|
|
2598 i = 2;
|
|
2599 break;
|
|
2600 }
|
|
2601 if (i == NOTOK)
|
|
2602 (void) err2peer (RC_ERR, "pipe", "error reading from");
|
|
2603 (void) close (pd[0]);
|
|
2604 _exit (i != NOTOK ? i : 1);
|
|
2605
|
|
2606 default:
|
|
2607 if ((vmhfd0 = dup (fileno (stdin))) == NOTOK)
|
|
2608 padios ("standard input", "unable to dup");
|
|
2609 if ((vmhfd1 = dup (fileno (stdout))) == NOTOK)
|
|
2610 padios ("standard output", "unable to dup");
|
|
2611 if ((vmhfd2 = dup (fileno (stderr))) == NOTOK)
|
|
2612 padios ("diagnostic output", "unable to dup");
|
|
2613
|
|
2614 (void) close (0);
|
|
2615 if ((i = open ("/dev/null", 0)) != NOTOK && i != fileno (stdin)) {
|
|
2616 (void) dup2 (i, fileno (stdin));
|
|
2617 (void) close (i);
|
|
2618 }
|
|
2619
|
|
2620 (void) fflush (stdout);
|
|
2621 if (dup2 (pd[1], fileno (stdout)) == NOTOK)
|
|
2622 padios ("standard output", "unable to dup2");
|
|
2623 clearerr (stdout);
|
|
2624
|
|
2625 (void) fflush (stderr);
|
|
2626 if (dup2 (pd[1], fileno (stderr)) == NOTOK)
|
|
2627 padios ("diagnostic output", "unable to dup2");
|
|
2628 clearerr (stderr);
|
|
2629
|
|
2630 if (cmdp && init_io (cmdp, 0) == NOTOK)
|
|
2631 return NOTOK;
|
|
2632 pstat = signal (SIGPIPE, pipeser);
|
|
2633 broken_pipe = 1;
|
|
2634
|
|
2635 (void) close (pd[0]);
|
|
2636 (void) close (pd[1]);
|
|
2637
|
|
2638 return vmhpid;
|
|
2639 }
|
|
2640 }
|
|
2641
|
|
2642 /* */
|
|
2643
|
|
2644 static int winR (cmdp)
|
|
2645 register struct Cmd *cmdp;
|
|
2646 {
|
|
2647 int status;
|
|
2648
|
|
2649 if (vmhpid <= OK)
|
|
2650 return NOTOK;
|
|
2651
|
|
2652 if (cmdp)
|
|
2653 fin_io (cmdp, 0);
|
|
2654
|
|
2655 if (dup2 (vmhfd0, fileno (stdin)) == NOTOK)
|
|
2656 padios ("standard input", "unable to dup2");
|
|
2657 clearerr (stdin);
|
|
2658 (void) close (vmhfd0);
|
|
2659
|
|
2660 (void) fflush (stdout);
|
|
2661 if (dup2 (vmhfd1, fileno (stdout)) == NOTOK)
|
|
2662 padios ("standard output", "unable to dup2");
|
|
2663 clearerr (stdout);
|
|
2664 (void) close (vmhfd1);
|
|
2665
|
|
2666 (void) fflush (stderr);
|
|
2667 if (dup2 (vmhfd2, fileno (stderr)) == NOTOK)
|
|
2668 padios ("diagnostic output", "unable to dup2");
|
|
2669 clearerr (stderr);
|
|
2670 (void) close (vmhfd2);
|
|
2671
|
|
2672 (void) signal (SIGPIPE, pstat);
|
|
2673
|
|
2674 if ((status = pidwait (vmhpid, OK)) == 2)
|
|
2675 done (1);
|
|
2676
|
|
2677 vmhpid = OK;
|
|
2678 return (status == 0 ? OK : NOTOK);
|
|
2679 }
|
|
2680
|
|
2681 /* */
|
|
2682
|
|
2683 static int winX (n)
|
|
2684 int n;
|
|
2685 {
|
|
2686 int i,
|
|
2687 pid,
|
|
2688 pd[2];
|
|
2689 char buffer[BUFSIZ];
|
|
2690 struct record rcs,
|
|
2691 *rc = &rcs;
|
|
2692
|
|
2693 initrc (rc);
|
|
2694
|
|
2695 if (!fmsh)
|
|
2696 (void) fseek (fp, 0L, 0);/* XXX: fseek() too tricky for our own good */
|
|
2697
|
|
2698 (void) sprintf (buffer, "%d", n);
|
|
2699 switch (str2rc (RC_WIN, buffer, rc)) {
|
|
2700 case RC_ACK:
|
|
2701 break;
|
|
2702
|
|
2703 case RC_ERR:
|
|
2704 return NOTOK;
|
|
2705
|
|
2706 case RC_XXX:
|
|
2707 padios (NULLCP, "%s", rc -> rc_data);
|
|
2708
|
|
2709 default:
|
|
2710 (void) fmt2peer (RC_ERR, "pWIN protocol screw-up");
|
|
2711 done (1);
|
|
2712 }
|
|
2713
|
|
2714 if (pipe (pd) == NOTOK) {
|
|
2715 (void) err2peer (RC_ERR, "pipe", "unable to");
|
|
2716 return NOTOK;
|
|
2717 }
|
|
2718
|
|
2719 switch (pid = fork ()) {
|
|
2720 case NOTOK:
|
|
2721 (void) err2peer (RC_ERR, "fork", "unable to");
|
|
2722 (void) close (pd[0]);
|
|
2723 (void) close (pd[1]);
|
|
2724 return NOTOK;
|
|
2725
|
|
2726 case OK:
|
|
2727 (void) close (fileno (stdin));
|
|
2728 if ((i = open ("/dev/null", 0)) != NOTOK && i != fileno (stdin)) {
|
|
2729 (void) dup2 (i, fileno (stdin));
|
|
2730 (void) close (i);
|
|
2731 }
|
|
2732 (void) dup2 (pd[1], fileno (stdout));
|
|
2733 (void) dup2 (pd[1], fileno (stderr));
|
|
2734 (void) close (pd[0]);
|
|
2735 (void) close (pd[1]);
|
|
2736 vmhpid = NOTOK;
|
|
2737 return OK;
|
|
2738
|
|
2739 default:
|
|
2740 (void) close (pd[1]);
|
|
2741 while ((i = read (pd[0], buffer, sizeof buffer)) > 0)
|
|
2742 switch (rc2rc (RC_DATA, i, buffer, rc)) {
|
|
2743 case RC_ACK:
|
|
2744 break;
|
|
2745
|
|
2746 case RC_ERR:
|
|
2747 (void) close (pd[0]);
|
|
2748 (void) pidwait (pid, OK);
|
|
2749 return NOTOK;
|
|
2750
|
|
2751 case RC_XXX:
|
|
2752 padios (NULLCP, "%s", rc -> rc_data);
|
|
2753
|
|
2754 default:
|
|
2755 (void) fmt2peer (RC_ERR, "pWIN protocol screw-up");
|
|
2756 done (1);
|
|
2757 }
|
|
2758 if (i == OK)
|
|
2759 switch (rc2rc (RC_EOF, 0, NULLCP, rc)) {
|
|
2760 case RC_ACK:
|
|
2761 break;
|
|
2762
|
|
2763 case RC_XXX:
|
|
2764 padios (NULLCP, "%s", rc -> rc_data);
|
|
2765
|
|
2766 default:
|
|
2767 (void) fmt2peer (RC_ERR, "pWIN protocol screw-up");
|
|
2768 done (1);
|
|
2769 }
|
|
2770 if (i == NOTOK)
|
|
2771 (void) err2peer (RC_ERR, "pipe", "error reading from");
|
|
2772
|
|
2773 (void) close (pd[0]);
|
|
2774 (void) pidwait (pid, OK);
|
|
2775 return (i != NOTOK ? pid : NOTOK);
|
|
2776 }
|
|
2777 }
|
|
2778
|
|
2779 /* */
|
|
2780
|
|
2781 /* VARARGS2 */
|
|
2782
|
|
2783 void padios (what, fmt, a, b, c, d, e, f)
|
|
2784 char *what,
|
|
2785 *fmt,
|
|
2786 *a,
|
|
2787 *b,
|
|
2788 *c,
|
|
2789 *d,
|
|
2790 *e,
|
|
2791 *f;
|
|
2792 {
|
|
2793 if (vmh) {
|
|
2794 (void) err2peer (RC_FIN, what, fmt, a, b, c, d, e, f);
|
|
2795 (void) rcdone ();
|
|
2796 }
|
|
2797 else
|
|
2798 advise (what, fmt, a, b, c, d, e, f);
|
|
2799
|
|
2800 done (1);
|
|
2801 }
|
|
2802
|
|
2803
|
|
2804 /* VARARGS2 */
|
|
2805
|
|
2806 void padvise (what, fmt, a, b, c, d, e, f)
|
|
2807 char *what,
|
|
2808 *fmt,
|
|
2809 *a,
|
|
2810 *b,
|
|
2811 *c,
|
|
2812 *d,
|
|
2813 *e,
|
|
2814 *f;
|
|
2815 {
|
|
2816 if (vmh)
|
|
2817 (void) err2peer (RC_ERR, what, fmt, a, b, c, d, e, f);
|
|
2818 else
|
|
2819 advise (what, fmt, a, b, c, d, e, f);
|
|
2820 }
|