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