Mercurial > hg > Applications > mh
comparison uip/msh.c @ 0:bce86c4163a3
Initial revision
author | kono |
---|---|
date | Mon, 18 Apr 2005 23:46:02 +0900 |
parents | |
children | 441a2190cfae |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:bce86c4163a3 |
---|---|
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 } |