|
|
1.1 root 1: /* whatnowsbr.c - the WhatNow shell */
2:
3: #include "../h/mh.h"
4: #include <stdio.h>
5: #include <sys/types.h>
6: #include <sys/stat.h>
7:
8: static int editfile(), copyf(), editfile(), copyf(), whomfile();
9: static void sendfile(), sendfile(), sendit();
10:
11: /* */
12:
13: static struct swit whatnowswitches[] = {
14: #define DFOLDSW 0
15: "draftfolder +folder", 0,
16: #define DMSGSW 1
17: "draftmessage msg", 0,
18: #define NDFLDSW 2
19: "nodraftfolder", 0,
20:
21: #define EDITRSW 3
22: "editor editor", 0,
23: #define NEDITSW 4
24: "noedit", 0,
25:
26: #define PRMPTSW 5
27: "prompt string", 4,
28:
29: #define HELPSW 6
30: "help", 4,
31:
32: NULL, NULL
33: };
34:
35: /* */
36:
37: static struct swit aleqs[] = {
38: #define DISPSW 0
39: "display [<switches>]", 0,
40: #define EDITSW 1
41: "edit [<editor> <switches>]", 0,
42: #define LISTSW 2
43: "list [<switches>]", 0,
44: #define PUSHSW 3
45: "push [<switches>]", 0,
46: #define QUITSW 4
47: "quit [-delete]", 0,
48: #define REFILEOPT 5
49: "refile [<switches>] +folder", 0,
50: #define SENDSW 6
51: "send [<switches>]", 0,
52: #define WHOMSW 7
53: "whom [<switches>]", 0,
54:
55: NULL, NULL
56: };
57:
58: /* */
59:
60: static char *myprompt = "\nWhat now? ";
61:
62: /* */
63:
64: /* ARGSUSED */
65:
66: WhatNow(argc, argv)
67: int argc;
68: char **argv;
69: {
70: int isdf = 0,
71: nedit = 0,
72: use = 0;
73: char *cp,
74: *dfolder = NULL,
75: *dmsg = NULL,
76: *ed = NULL,
77: *drft = NULL,
78: *msgnam = NULL,
79: buf[100],
80: prompt[BUFSIZ],
81: **ap,
82: **argp,
83: *arguments[MAXARGS];
84: struct stat st;
85:
86: invo_name = r1bindex (argv[0], '/');
87: if ((cp = m_find (invo_name)) != NULL) {
88: ap = brkstring (cp = getcpy (cp), " ", "\n");
89: ap = copyip (ap, arguments);
90: }
91: else
92: ap = arguments;
93: (void) copyip (argv + 1, ap);
94: argp = arguments;
95:
96: /* */
97:
98: while (cp = *argp++) {
99: if (*cp == '-')
100: switch (smatch (++cp, whatnowswitches)) {
101: case AMBIGSW:
102: ambigsw (cp, whatnowswitches);
103: done (1);
104: case UNKWNSW:
105: adios (NULLCP, "-%s unknown", cp);
106: case HELPSW:
107: (void) sprintf (buf, "%s [switches] [file]", invo_name);
108: help (buf, whatnowswitches);
109: done (1);
110:
111: case DFOLDSW:
112: if (dfolder)
113: adios (NULLCP, "only one draft folder at a time!");
114: if (!(cp = *argp++) || *cp == '-')
115: adios (NULLCP, "missing argument to %s", argp[-2]);
116: dfolder = path (*cp == '+' || *cp == '@' ? cp + 1 : cp,
117: *cp != '@' ? TFOLDER : TSUBCWF);
118: continue;
119: case DMSGSW:
120: if (dmsg)
121: adios (NULLCP, "only one draft message at a time!");
122: if (!(dmsg = *argp++) || *dmsg == '-')
123: adios (NULLCP, "missing argument to %s", argp[-2]);
124: continue;
125: case NDFLDSW:
126: dfolder = NULL;
127: isdf = NOTOK;
128: continue;
129:
130: case EDITRSW:
131: if (!(ed = *argp++) || *ed == '-')
132: adios (NULLCP, "missing argument to %s", argp[-2]);
133: nedit = 0;
134: continue;
135: case NEDITSW:
136: nedit++;
137: continue;
138:
139: case PRMPTSW:
140: if (!(myprompt = *argp++) || *myprompt == '-')
141: adios (NULLCP, "missing argument to %s", argp[-2]);
142: continue;
143: }
144: if (drft)
145: adios (NULLCP, "only one draft at a time!");
146: else
147: drft = cp;
148: }
149:
150: /* */
151:
152: if (drft == NULL && (drft = getenv ("mhdraft")) == NULL || *drft == NULL)
153: drft = getcpy (m_draft (dfolder, dmsg, 1, &isdf));
154: msgnam = (cp = getenv ("mhaltmsg")) && *cp ? getcpy (cp) : NULLCP;
155: if (ed == NULL && ((ed = getenv ("mheditor")) == NULL || *ed == NULL))
156: ed = NULL, nedit++;
157: if ((cp = getenv ("mhuse")) && *cp)
158: use = atoi (cp);
159: if (!nedit
160: && editfile (&ed, NULLVP, drft, use, NULLMP, msgnam, NULLCP) < 0)
161: done (1);
162:
163: /* */
164:
165: (void) sprintf (prompt, myprompt, invo_name);
166: for (;;) {
167: if (!(argp = getans (prompt, aleqs))) {
168: (void) unlink (LINK);
169: done (1);
170: }
171: switch (smatch (*argp, aleqs)) {
172: case DISPSW:
173: if (msgnam)
174: (void) showfile (++argp, msgnam);
175: else
176: advise (NULLCP, "no alternate message to display");
177: break;
178:
179: case EDITSW:
180: if (*++argp)
181: ed = *argp++;
182: if (editfile (&ed, argp, drft, NOUSE, NULLMP, msgnam, NULLCP)
183: == NOTOK)
184: done (1);
185: break;
186:
187: case LISTSW:
188: (void) showfile (++argp, drft);
189: break;
190:
191: case WHOMSW:
192: (void) whomfile (++argp, drft);
193: break;
194:
195: case QUITSW:
196: if (*++argp && (*argp[0] == 'd' ||
197: ((*argp)[0] == '-' && (*argp)[1] == 'd'))) {
198: if (unlink (drft) == NOTOK)
199: adios (drft, "unable to unlink");
200: }
201: else
202: if (stat (drft, &st) != NOTOK)
203: advise (NULLCP, "draft left on %s", drft);
204: done (1);
205:
206: case PUSHSW:
207: sendfile (++argp, drft, 1);
208: done (1);
209:
210: case SENDSW:
211: sendfile (++argp, drft, 0);
212: break;
213:
214: case REFILEOPT:
215: if (refile (++argp, drft) == 0)
216: done (0);
217: break;
218:
219: default:
220: advise (NULLCP, "say what?");
221: break;
222: }
223: }
224: }
225:
226: /* EDIT */
227:
228: static int reedit = 0;
229: static char *edsave = NULL;
230:
231:
232: /* ARGSUSED */
233:
234: static int
235: editfile(ed, arg, file, use, mp, altmsg, cwd)
236: register struct msgs *mp;
237: register char **ed, **arg, *file, *altmsg, *cwd;
238: register int use;
239: {
240: int pid,
241: status;
242: register int vecp;
243: register char *cp;
244: char altpath[BUFSIZ],
245: linkpath[BUFSIZ],
246: *vec[MAXARGS];
247: struct stat st;
248: #ifdef BSD42
249: int slinked;
250: #endif BSD42
251:
252: if (!reedit) { /* set initial editor */
253: if (*ed == NULL && (*ed = m_find ("editor")) == NULL)
254: *ed = sysed;
255: }
256: else
257: if (!*ed) { /* no explicit editor */
258: *ed = edsave;
259: if ((cp = r1bindex (*ed, '/')) == NULL)
260: cp = *ed;
261: cp = concat (cp, "-next", NULLCP);
262: if ((cp = m_find (cp)) != NULL)
263: *ed = cp;
264: }
265:
266: if (altmsg) {
267: if (mp == NULL || *altmsg == '/' || cwd == NULL)
268: (void) strcpy (altpath, altmsg);
269: else
270: (void) sprintf (altpath, "%s/%s", mp -> foldpath, altmsg);
271: if (cwd == NULL)
272: (void) strcpy (linkpath, LINK);
273: else
274: (void) sprintf (linkpath, "%s/%s", cwd, LINK);
275: }
276:
277: if (altmsg) {
278: (void) unlink (linkpath);
279: #ifdef BSD42
280: #ifndef VAXVMS
281: if (link (altpath, linkpath) == NOTOK) {
282: #endif
283: (void) symlink (altpath, linkpath);
284: slinked = 1;
285: #ifndef VAXVMS
286: }
287: else
288: slinked = 0;
289: #endif
290: #else not BSD42
291: (void) link (altpath, linkpath);
292: #endif not BSD42
293: }
294:
295: m_update ();
296: (void) fflush (stdout);
297:
298: switch (pid = vfork ()) {
299: case NOTOK:
300: advise ("fork", "unable to");
301: status = NOTOK;
302: break;
303:
304: case OK:
305: if (cwd)
306: (void) chdir (cwd);
307: if (altmsg) {
308: if (mp)
309: (void) putenv ("mhfolder", mp -> foldpath);
310: (void) putenv ("editalt", altpath);
311: }
312:
313: vecp = 0;
314: vec[vecp++] = r1bindex (*ed, '/');
315: if (arg)
316: while (*arg)
317: vec[vecp++] = *arg++;
318: vec[vecp++] = file;
319: vec[vecp] = NULL;
320:
321: execvp (*ed, vec);
322: fprintf (stderr, "unable to exec ");
323: perror (*ed);
324: _exit (-1);
325:
326: default:
327: if (status = pidwait (pid, NOTOK)) {
328: if (((status & 0xff00) != 0xff00)
329: && (!reedit || (status & 0x00ff)))
330: if (!use && (status & 0xff00)) {
331: (void) unlink (file);
332: advise (NULLCP, "problems with edit--%s deleted", file);
333: }
334: else
335: advise (NULLCP, "problems with edit--%s preserved",
336: file);
337: status = -2;
338: break;
339: }
340:
341: reedit++;
342: #ifdef BSD42
343: if (altmsg
344: && mp
345: && (!mp -> msgflags & READONLY)
346: && (slinked
347: ? lstat (linkpath, &st) != NOTOK
348: && (st.st_mode & S_IFMT) == S_IFREG
349: && copyf (linkpath, altpath) == NOTOK
350: : stat (linkpath, &st) != NOTOK
351: && st.st_nlink == 1
352: && (unlink (altpath) == NOTOK
353: || link (linkpath, altpath) == NOTOK)))
354: advise (linkpath, "unable to update %s from", altmsg);
355: #else not BSD42
356: if (altmsg
357: && mp
358: && (!mp -> msgflags & READONLY)
359: && stat (linkpath, &st) != NOTOK
360: && st.st_nlink == 1
361: && (unlink (altpath) == NOTOK
362: || link (linkpath, altpath) == NOTOK))
363: advise (linkpath, "unable to update %s from", altmsg);
364: #endif not BSD42
365: }
366:
367: edsave = getcpy (*ed);
368: *ed = NULL;
369: if (altmsg)
370: (void) unlink (linkpath);
371:
372: return status;
373: }
374:
375: /* */
376:
377: #ifdef BSD42
378: static int
379: copyf(ifile, ofile)
380: register char *ifile, *ofile;
381: {
382: register int i;
383: int in,
384: out;
385: char buffer[BUFSIZ];
386:
387: if ((in = open (ifile, 0)) == NOTOK)
388: return NOTOK;
389: if ((out = open (ofile, 1)) == NOTOK || ftruncate (out, 0) == NOTOK) {
390: if (out != NOTOK) {
391: admonish (ofile, "unable to truncate");
392: (void) close (out);
393: }
394: (void) close (in);
395: return NOTOK;
396: }
397:
398: while ((i = read (in, buffer, sizeof buffer)) > OK)
399: if (write (out, buffer, i) != i) {
400: advise (ofile, "may have damaged");
401: i = NOTOK;
402: break;
403: }
404:
405: (void) close (in);
406: (void) close (out);
407:
408: return i;
409: }
410: #endif BSD42
411:
412: /* SEND */
413:
414: static void
415: sendfile(arg, file, pushsw)
416: register char **arg, *file;
417: int pushsw;
418: {
419: register int child_id,
420: i,
421: vecp;
422: char *cp,
423: *sp,
424: *vec[MAXARGS];
425:
426: if (strcmp (sp = r1bindex (sendproc, '/'), "send") == 0) {
427: cp = invo_name;
428: sendit (invo_name = sp, arg, file, pushsw);
429: invo_name = cp;
430: return;
431: }
432:
433: m_update ();
434: (void) fflush (stdout);
435:
436: for (i = 0; (child_id = vfork ()) == NOTOK && i < 5; i++)
437: sleep (5);
438: switch (child_id) {
439: case NOTOK:
440: advise (NULLCP, "unable to fork, so sending directly...");
441: case OK:
442: vecp = 0;
443: vec[vecp++] = invo_name;
444: if (pushsw)
445: vec[vecp++] = "-push";
446: if (arg)
447: while (*arg)
448: vec[vecp++] = *arg++;
449: vec[vecp++] = file;
450: vec[vecp] = NULL;
451:
452: execvp (sendproc, vec);
453: fprintf (stderr, "unable to exec ");
454: perror (sendproc);
455: _exit (-1);
456:
457: default:
458: if (pidwait (child_id, OK) == 0)
459: done (0);
460: return;
461: }
462: }
463:
464: /* */
465:
466: static struct swit sendswitches[] = {
467: #define ALIASW 0
468: "alias aliasfile", 0,
469:
470: #define DEBUGSW 1
471: "debug", -5,
472:
473: #define ENCRSW 2
474: "encrypt",
475: #ifndef TMA
476: -7,
477: #else TMA
478: 0,
479: #endif TMA
480: #define NENCRSW 3
481: "noencrypt",
482: #ifndef TMA
483: -9,
484: #else TMA
485: 0,
486: #endif TMA
487:
488: #define FILTSW 4
489: "filter filterfile", 0,
490: #define NFILTSW 5
491: "nofilter", 0,
492:
493: #define FRMTSW 6
494: "format", 0,
495: #define NFRMTSW 7
496: "noformat", 0,
497:
498: #define FORWSW 8
499: "forward", 0,
500: #define NFORWSW 9
501: "noforward", 0,
502:
503: #define MSGDSW 10
504: "msgid", 0,
505: #define NMSGDSW 11
506: "nomsgid", 0,
507:
508: #define SPSHSW 12
509: "push", 0,
510: #define NSPSHSW 13
511: "nopush", 0,
512:
513: #define UNIQSW 14
514: "unique", -6,
515: #define NUNIQSW 15
516: "nounique", -8,
517:
518: #define VERBSW 16
519: "verbose", 0,
520: #define NVERBSW 17
521: "noverbose", 0,
522:
523: #define WATCSW 18
524: "watch", 0,
525: #define NWATCSW 19
526: "nowatch", 0,
527:
528: #define WIDTHSW 20
529: "width columns", 0,
530:
531: #define SHELPSW 21
532: "help", 4,
533:
534: #define MAILSW 22
535: "mail", -4,
536: #define SAMLSW 23
537: "saml", -4,
538: #define SSNDSW 24
539: "send", -4,
540: #define SOMLSW 25
541: "soml", -4,
542:
543: #define CLIESW 26
544: "client host", -6,
545: #define SERVSW 27
546: "server host", -6,
547: #define SNOOPSW 28
548: "snoop", -5,
549:
550: #define SDRFSW 29
551: "draftfolder +folder", -6,
552: #define SDRMSW 30
553: "draftmessage msg", -6,
554: #define SNDRFSW 31
555: "nodraftfolder", -3,
556:
557: NULL, NULL
558: };
559:
560: /* */
561:
562: extern int debugsw; /* from sendsbr.c */
563: extern int forwsw;
564: extern int inplace;
565: extern int pushsw;
566: extern int unique;
567:
568: extern char *altmsg; /* .. */
569: extern char *annotext;
570: extern char *distfile;
571:
572: /* */
573:
574: static void
575: sendit(sp, arg, file, pushed)
576: register char *sp, **arg, *file;
577: int pushed;
578: {
579: int distsw = 0,
580: vecp = 1;
581: char *cp,
582: buf[100],
583: **ap,
584: **argp,
585: *arguments[MAXARGS],
586: *vec[MAXARGS];
587: struct stat st;
588: #ifdef UCI
589: FILE *fp;
590: #endif UCI
591:
592: if (arg)
593: (void) copyip (arg, vec);
594: if ((cp = m_find (sp)) != NULL) {
595: ap = brkstring (cp = getcpy (cp), " ", "\n");
596: ap = copyip (ap, arguments);
597: }
598: else
599: ap = arguments;
600: if (arg)
601: (void) copyip (vec, ap);
602: argp = arguments;
603:
604: debugsw = 0, forwsw = 1, inplace = 0, unique = 0;
605: altmsg = annotext = distfile = NULL;
606: vec[vecp++] = "-library";
607: vec[vecp++] = getcpy (m_maildir (""));
608:
609: /* */
610:
611: while (cp = *argp++) {
612: if (*cp == '-')
613: switch (smatch (++cp, sendswitches)) {
614: case AMBIGSW:
615: ambigsw (cp, sendswitches);
616: return;
617: case UNKWNSW:
618: advise (NULLCP, "-%s unknown\n", cp);
619: return;
620: case SHELPSW:
621: (void) sprintf (buf, "%s [switches]", sp);
622: help (buf, sendswitches);
623: return;
624:
625: case SPSHSW:
626: pushed++;
627: continue;
628: case NSPSHSW:
629: pushed = 0;
630: continue;
631:
632: case UNIQSW:
633: unique++;
634: continue;
635: case NUNIQSW:
636: unique = 0;
637: continue;
638: case FORWSW:
639: forwsw++;
640: continue;
641: case NFORWSW:
642: forwsw = 0;
643: continue;
644:
645: case DEBUGSW:
646: debugsw++; /* fall */
647: case NFILTSW:
648: case FRMTSW:
649: case NFRMTSW:
650: case MSGDSW:
651: case NMSGDSW:
652: case VERBSW:
653: case NVERBSW:
654: case WATCSW:
655: case NWATCSW:
656: case MAILSW:
657: case SAMLSW:
658: case SSNDSW:
659: case SOMLSW:
660: case ENCRSW:
661: case NENCRSW:
662: case SNOOPSW:
663: vec[vecp++] = --cp;
664: continue;
665:
666: case ALIASW:
667: case FILTSW:
668: case WIDTHSW:
669: case CLIESW:
670: case SERVSW:
671: vec[vecp++] = --cp;
672: if (!(cp = *argp++) || *cp == '-') {
673: advise (NULLCP, "missing argument to %s", argp[-2]);
674: return;
675: }
676: vec[vecp++] = cp;
677: continue;
678:
679: case SDRFSW:
680: case SDRMSW:
681: if (!(cp = *argp++) || *cp == '-') {
682: advise (NULLCP, "missing argument to %s", argp[-2]);
683: return;
684: }
685: case SNDRFSW:
686: continue;
687: }
688: advise (NULLCP, "usage: %s [switches]", sp);
689: return;
690: }
691:
692: /* */
693:
694: #ifdef TMA
695: if ((cp = getenv ("KDS")) == NULL || *cp == NULL)
696: if ((cp = m_find ("kdsproc")) && *cp)
697: (void) putenv ("KDS", cp);
698: if ((cp = getenv ("TMADB")) == NULL || *cp == NULL)
699: if ((cp = m_find ("tmadb")) && *cp)
700: (void) putenv ("TMADB", m_maildir (cp));
701: #endif TMA
702:
703: if ((cp = getenv ("SIGNATURE")) == NULL || *cp == NULL)
704: if ((cp = m_find ("signature")) && *cp)
705: (void) putenv ("SIGNATURE", cp);
706: #ifdef UCI
707: else {
708: (void) sprintf (buf, "%s/.signature", mypath);
709: if ((fp = fopen (buf, "r")) != NULL
710: && fgets (buf, sizeof buf, fp) != NULL) {
711: (void) fclose (fp);
712: if (cp = index (buf, '\n'))
713: *cp = NULL;
714: (void) putenv ("SIGNATURE", buf);
715: }
716: }
717: #endif UCI
718:
719: if ((annotext = getenv ("mhannotate")) == NULL || *annotext == NULL)
720: annotext = NULL;
721: if ((altmsg = getenv ("mhaltmsg")) == NULL || *altmsg == NULL)
722: altmsg = NULL;
723: if (annotext && ((cp = getenv ("mhinplace")) != NULL && *cp != NULL))
724: inplace = atoi (cp);
725:
726: if ((cp = getenv ("mhdist"))
727: && *cp
728: && (distsw = atoi (cp))
729: && altmsg) {
730: vec[vecp++] = "-dist";
731: distfile = getcpy (m_scratch (altmsg, invo_name));
732: if (link (altmsg, distfile) == NOTOK)
733: adios (distfile, "unable to link %s to", altmsg);
734: }
735: else
736: distfile = NULL;
737:
738: if (altmsg == NULL || stat (altmsg, &st) == NOTOK)
739: st.st_mtime = 0, st.st_dev = 0, st.st_ino = 0;
740: if (pushsw = pushed)
741: push ();
742:
743: vec[0] = r1bindex (postproc, '/');
744: closefds (3);
745:
746: if (sendsbr (vec, vecp, file, &st) == OK)
747: done (0);
748: }
749:
750: /* WHOM */
751:
752: static int
753: whomfile(arg, file)
754: register char **arg, *file;
755: {
756: int pid;
757: register int vecp;
758: char *vec[MAXARGS];
759:
760: m_update ();
761: (void) fflush (stdout);
762:
763: switch (pid = vfork ()) {
764: case NOTOK:
765: advise ("fork", "unable to");
766: return 1;
767:
768: case OK:
769: vecp = 0;
770: vec[vecp++] = r1bindex (whomproc, '/');
771: vec[vecp++] = file;
772: if (arg)
773: while (*arg)
774: vec[vecp++] = *arg++;
775: vec[vecp] = NULL;
776:
777: execvp (whomproc, vec);
778: fprintf (stderr, "unable to exec ");
779: perror (whomproc);
780: _exit (-1); /* NOTREACHED */
781:
782: default:
783: return (pidwait (pid, NOTOK) & 0377 ? 1 : 0);
784: }
785: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.