1: /* sendsbr.c - routines to help WhatNow/Send along */ 2: 3: #include "../h/mh.h" 4: #include <setjmp.h> 5: #include <stdio.h> 6: #include <signal.h> 7: #include <sys/types.h> 8: #include <sys/stat.h> 9: 10: /* */ 11: 12: int debugsw = 0; /* global */ 13: int forwsw = 1; 14: int inplace = 0; 15: int pushsw = 0; 16: int unique = 0; 17: 18: char *altmsg = NULL; /* .. */ 19: char *annotext = NULL; 20: char *distfile = NULL; 21: 22: 23: static int armed = 0; 24: static jmp_buf env; 25: 26: 27: char *getusr (); 28: long lseek (); 29: 30: /* */ 31: 32: int sendsbr (vec, vecp, drft, st) 33: register char **vec, 34: *drft; 35: int vecp; 36: register struct stat *st; 37: { 38: int status; 39: 40: armed++; 41: switch (setjmp (env)) { 42: case OK: 43: status = sendaux (vec, vecp, drft, st) ? NOTOK : OK; 44: break; 45: 46: default: 47: status = DONE; 48: break; 49: } 50: armed = 0; 51: if (distfile) 52: (void) unlink (distfile); 53: 54: return status; 55: } 56: 57: /* */ 58: 59: int sendaux (vec, vecp, drft, st) 60: register char **vec, 61: *drft; 62: int vecp; 63: register struct stat *st; 64: { 65: int child_id, 66: i, 67: status, 68: fd, 69: fd2; 70: char backup[BUFSIZ], 71: buf[BUFSIZ], 72: file[BUFSIZ]; 73: 74: fd = pushsw ? tmp_fd () : NOTOK; 75: fd2 = NOTOK; 76: 77: if (pushsw && unique) { 78: if (rename (drft, strcpy (file, m_scratch (drft, invo_name))) 79: == NOTOK) 80: adios (file, "unable to rename %s to", drft); 81: drft = file; 82: } 83: vec[vecp++] = drft; 84: if (annotext) 85: if ((fd2 = tmp_fd ()) != NOTOK) { 86: vec[vecp++] = "-idanno"; 87: (void) sprintf (buf, "%d", fd2); 88: vec[vecp++] = buf; 89: } 90: else 91: admonish (NULLCP, "unable to create file for annotation list"); 92: if (distfile && distout (drft, distfile, backup) == NOTOK) 93: done (1); 94: vec[vecp] = NULL; 95: 96: for (i = 0; (child_id = vfork ()) == NOTOK && i < 5; i++) 97: sleep (5); 98: switch (child_id) { 99: case NOTOK: /* oops */ 100: adios ("fork", "unable to"); 101: 102: case OK: /* send it */ 103: if (fd != NOTOK) { 104: (void) dup2 (fd, fileno (stdout)); 105: (void) dup2 (fd, fileno (stderr)); 106: (void) close (fd); 107: } 108: execvp (postproc, vec); 109: fprintf (stderr, "unable to exec "); 110: perror (postproc); 111: _exit (-1); 112: 113: default: /* wait for it */ 114: if ((status = pidwait (child_id, NOTOK)) == 0) { 115: if (annotext && fd2 != NOTOK) 116: anno (fd2, st); 117: if (rename (drft, strcpy (buf, m_backup (drft))) == NOTOK) 118: advise (buf, "unable to rename %s to", drft); 119: } 120: else { 121: if (fd != NOTOK) { 122: alert (drft, fd); 123: (void) close (fd); 124: } 125: else 126: advise (NULLCP, "message not delivered to anyone"); 127: if (fd2 != NOTOK) 128: (void) close (fd2); 129: if (distfile) { 130: (void) unlink (drft); 131: if (rename (backup, drft) == NOTOK) 132: advise (drft, "unable to rename %s to", backup); 133: } 134: } 135: break; 136: } 137: 138: return status; 139: } 140: 141: /* */ 142: 143: static alert (file, out) 144: register char *file; 145: int out; 146: { 147: int child_id, 148: i, 149: in; 150: char buf[BUFSIZ]; 151: 152: for (i = 0; (child_id = fork ()) == NOTOK && i < 5; i++) 153: sleep (5); 154: switch (child_id) { 155: case NOTOK: /* oops */ 156: advise ("fork", "unable to"); 157: 158: case OK: /* send it */ 159: (void) signal (SIGHUP, SIG_IGN); 160: (void) signal (SIGINT, SIG_IGN); 161: (void) signal (SIGQUIT, SIG_IGN); 162: (void) signal (SIGTERM, SIG_IGN); 163: if (forwsw) 164: if ((in = open (file, 0)) == NOTOK) 165: admonish (file, "unable to re-open"); 166: else { 167: (void) lseek (out, 0L, 2); 168: (void) strcpy (buf, "\nMessage not delivered to anyone.\n"); 169: (void) write (out, buf, strlen (buf)); 170: (void) strcpy (buf, "\n------- Unsent Draft\n\n"); 171: (void) write (out, buf, strlen (buf)); 172: cpydgst (in, out, file, "temporary file"); 173: (void) close (in); 174: (void) strcpy (buf, "\n------- End of Unsent Draft\n"); 175: (void) write (out, buf, strlen (buf)); 176: if (rename (file, strcpy (buf, m_backup (file))) == NOTOK) 177: admonish (buf, "unable to rename %s to", file); 178: } 179: (void) lseek (out, 0L, 0); 180: (void) dup2 (out, fileno (stdin)); 181: (void) close (out); 182: (void) sprintf (buf, "send failed on %s", 183: forwsw ? "enclosed draft" : file); 184: 185: execlp (mailproc, r1bindex (mailproc, '/'), getusr (), 186: "-subject", buf, NULLCP); 187: fprintf (stderr, "unable to exec "); 188: perror (mailproc); 189: _exit (-1); 190: 191: default: /* no waiting... */ 192: break; 193: } 194: } 195: 196: /* */ 197: 198: static int tmp_fd () { 199: int fd; 200: char tmpfil[BUFSIZ]; 201: 202: (void) strcpy (tmpfil, m_tmpfil (invo_name)); 203: if ((fd = creat (tmpfil, 0600)) == NOTOK) 204: return NOTOK; 205: (void) close (fd); 206: 207: if ((fd = open (tmpfil, 2)) == NOTOK) 208: return NOTOK; 209: if (debugsw) 210: advise (NULLCP, "temporary file %s selected", tmpfil); 211: else 212: if (unlink (tmpfil) == NOTOK) 213: advise (tmpfil, "unable to remove"); 214: 215: return fd; 216: } 217: 218: /* */ 219: 220: static anno (fd, st) 221: int fd; 222: register struct stat *st; 223: { 224: int child_id; 225: int (*hstat) (), (*istat) (), (*qstat) (), (*tstat) (); 226: static char *cwd = NULL; 227: struct stat st2; 228: 229: if (altmsg && 230: (stat (altmsg, &st2) == NOTOK 231: || st -> st_mtime != st2.st_mtime 232: || st -> st_dev != st2.st_dev 233: || st -> st_ino != st2.st_ino)) { 234: if (debugsw) 235: admonish (NULLCP, "$mhaltmsg mismatch"); 236: return; 237: } 238: 239: child_id = debugsw ? NOTOK : fork (); 240: switch (child_id) { 241: case NOTOK: /* oops */ 242: if (!debugsw) 243: advise (NULLCP, 244: "unable to fork, so doing annotations by hand..."); 245: if (cwd == NULL) 246: cwd = getcpy (pwd ()); 247: 248: case OK: 249: hstat = signal (SIGHUP, SIG_IGN); 250: istat = signal (SIGINT, SIG_IGN); 251: qstat = signal (SIGQUIT, SIG_IGN); 252: tstat = signal (SIGTERM, SIG_IGN); 253: annoaux (fd); 254: if (child_id == OK) 255: _exit (0); 256: (void) signal (SIGHUP, hstat); 257: (void) signal (SIGINT, istat); 258: (void) signal (SIGQUIT, qstat); 259: (void) signal (SIGTERM, tstat); 260: (void) chdir (cwd); 261: break; 262: 263: default: /* no waiting... */ 264: (void) close (fd); 265: break; 266: } 267: } 268: 269: /* */ 270: 271: static annoaux (fd) 272: int fd; 273: { 274: int fd2, 275: fd3, 276: msgnum; 277: char *cp, 278: *folder, 279: *maildir, 280: buffer[BUFSIZ], 281: **ap; 282: FILE *fp; 283: struct msgs *mp; 284: 285: if ((folder = getenv ("mhfolder")) == NULL || *folder == NULL) { 286: if (debugsw) 287: admonish (NULLCP, "$mhfolder not set"); 288: return; 289: } 290: maildir = m_maildir (folder); 291: if (chdir (maildir) == NOTOK) { 292: if (debugsw) 293: admonish (maildir, "unable to change directory to"); 294: return; 295: } 296: if (!(mp = m_gmsg (folder))) { 297: if (debugsw) 298: admonish (NULLCP, "unable to read folder %s"); 299: return; 300: } 301: if (mp -> hghmsg == 0) { 302: if (debugsw) 303: admonish (NULLCP, "no messages in %s", folder); 304: goto oops; 305: } 306: 307: if ((cp = getenv ("mhmessages")) == NULL || *cp == NULL) { 308: if (debugsw) 309: admonish (NULLCP, "$mhmessages not set"); 310: goto oops; 311: } 312: if (!debugsw /* MOBY HACK... */ 313: && pushsw 314: && (fd3 = open ("/dev/null", 2)) != NOTOK 315: && (fd2 = dup (fileno (stderr))) != NOTOK) { 316: (void) dup2 (fd3, fileno (stderr)); 317: (void) close (fd3); 318: } 319: else 320: fd2 = NOTOK; 321: for (ap = brkstring (cp = getcpy (cp), " ", NULLCP); *ap; ap++) 322: (void) m_convert (mp, *ap); 323: free (cp); 324: if (fd2 != NOTOK) 325: (void) dup2 (fd2, fileno (stderr)); 326: if (mp -> numsel == 0) { 327: if (debugsw) 328: admonish (NULLCP, "no messages to annotate"); 329: goto oops; 330: } 331: 332: (void) lseek (fd, 0L, 0); 333: if ((fp = fdopen (fd, "r")) == NULL) { 334: if (debugsw) 335: admonish (NULLCP, "unable to fdopen annotation list"); 336: goto oops; 337: } 338: cp = NULL; 339: while (fgets (buffer, sizeof buffer, fp) != NULL) 340: cp = add (buffer, cp); 341: (void) fclose (fp); 342: 343: if (debugsw) 344: advise (NULLCP, "annotate%s with %s: \"%s\"", 345: inplace ? " inplace" : "", annotext, cp); 346: for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++) 347: if (mp -> msgstats[msgnum] & SELECTED) { 348: if (debugsw) 349: advise (NULLCP, "annotate message %d", msgnum); 350: (void) annotate (m_name (msgnum), annotext, cp, inplace); 351: } 352: 353: free (cp); 354: 355: oops: ; 356: m_fmsg (mp); 357: } 358: 359: /* */ 360: 361: void done (status) 362: int status; 363: { 364: if (armed) 365: longjmp (env, status ? status : NOTOK); 366: 367: exit (status); 368: }