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