1: /* rcvdist.c - a rcvmail program to distribute messages */ 2: 3: #include "../h/mh.h" 4: #include "../h/formatsbr.h" 5: #include "../h/rcvmail.h" 6: #include "../zotnet/tws.h" 7: #include <stdio.h> 8: 9: /* */ 10: 11: static struct swit switches[] = { 12: #define FORMSW 0 13: "form formfile", 4, 14: 15: #define HELPSW 1 16: "help", 4, 17: 18: NULL, NULL 19: }; 20: 21: /* */ 22: 23: static char backup[BUFSIZ] = ""; 24: static char drft[BUFSIZ] = ""; 25: static char tmpfil[BUFSIZ] = ""; 26: 27: /* */ 28: 29: /* ARGSUSED */ 30: 31: main (argc, argv) 32: int argc; 33: char **argv; 34: { 35: int i, 36: child_id, 37: vecp = 1; 38: char *addrs = NULL, 39: *cp, 40: *form = NULL, 41: buf[100], 42: **ap, 43: **argp, 44: *arguments[MAXARGS], 45: *vec[MAXARGS]; 46: register FILE * fp; 47: 48: invo_name = r1bindex (argv[0], '/'); 49: mts_init (invo_name); 50: if ((cp = m_find (invo_name)) != NULL) { 51: ap = brkstring (cp = getcpy (cp), " ", "\n"); 52: ap = copyip (ap, arguments); 53: } 54: else 55: ap = arguments; 56: (void) copyip (argv + 1, ap); 57: argp = arguments; 58: 59: /* */ 60: 61: while (cp = *argp++) { 62: if (*cp == '-') 63: switch (smatch (++cp, switches)) { 64: case AMBIGSW: 65: ambigsw (cp, switches); 66: done (1); 67: case UNKWNSW: 68: vec[vecp++] = --cp; 69: continue; 70: case HELPSW: 71: (void) sprintf (buf, 72: "%s [switches] [switches for postproc] address ...", 73: invo_name); 74: help (buf, switches); 75: done (1); 76: 77: case FORMSW: 78: if (!(form = *argp++) || *form == '-') 79: adios (NULLCP, "missing argument to %s", argp[-2]); 80: continue; 81: } 82: addrs = addrs ? add (cp, add (", ", addrs)) : getcpy (cp); 83: } 84: 85: /* */ 86: 87: if (addrs == NULL) 88: adios (NULLCP, "usage: %s [switches] [switches for postproc] address ...", 89: invo_name); 90: 91: (void) umask (~m_gmprot ()); 92: (void) strcpy (tmpfil, m_tmpfil (invo_name)); 93: if ((fp = fopen (tmpfil, "w+")) == NULL) 94: adios (tmpfil, "unable to create"); 95: (void) cpydata (fileno (stdin), fileno (fp), "message", tmpfil); 96: (void) fseek (fp, 0L, 0); 97: (void) strcpy (drft, m_tmpfil (invo_name)); 98: rcvdistout (fp, form, addrs); 99: (void) fclose (fp); 100: 101: if (distout (drft, tmpfil, backup) == NOTOK) 102: done (1); 103: 104: vec[0] = r1bindex (postproc, '/'); 105: vec[vecp++] = "-dist"; 106: vec[vecp++] = drft; 107: vec[vecp] = NULL; 108: 109: for (i = 0; (child_id = fork ()) == NOTOK && i < 5; i++) 110: sleep (5); 111: switch (child_id) { 112: case NOTOK: 113: admonish (NULLCP, "unable to fork");/* fall */ 114: case OK: 115: execvp (postproc, vec); 116: fprintf (stderr, "unable to exec "); 117: perror (postproc); 118: _exit (1); 119: 120: default: 121: done (pidXwait (child_id, postproc)); 122: } 123: /* NOTREACHED */ 124: } 125: 126: /* */ 127: 128: /* very similar to routine in replsbr.c */ 129: 130: #define SBUFSIZ 256 131: 132: static int outputlinelen = OUTPUTLINELEN; 133: 134: static struct format *fmt; 135: 136: static int ncomps = 0; 137: static char **compbuffers = 0; 138: static struct comp **used_buf = 0; 139: 140: static int dat[4]; 141: 142: 143: static rcvdistout (inb, form, addrs) 144: register FILE *inb; 145: char *form, 146: *addrs; 147: { 148: register int char_read = 0, 149: format_len, 150: i, 151: state; 152: register char *tmpbuf, 153: **nxtbuf; 154: char *cp, 155: *scanl, 156: name[NAMESZ]; 157: register struct comp *cptr, 158: **savecomp; 159: FILE *out; 160: 161: if ((out = fopen (drft, "w")) == NULL) 162: adios (drft, "unable to create"); 163: 164: cp = new_fs (form ? form : rcvdistcomps, NULLCP, NULLCP); 165: format_len = strlen (cp); 166: ncomps = fmt_compile (cp, &fmt) + 1; 167: nxtbuf = compbuffers = (char **) calloc ((unsigned) ncomps, 168: sizeof (char *)); 169: if (nxtbuf == NULL) 170: adios (NULLCP, "unable to allocate component buffers"); 171: used_buf = (struct comp **) calloc ((unsigned) (ncomps + 1), 172: sizeof (struct comp *)); 173: if (used_buf == NULL) 174: adios (NULLCP, "unable to allocate component buffer stack"); 175: used_buf += ncomps + 1; 176: *--used_buf = 0; 177: for (i = ncomps; i--;) 178: if ((*nxtbuf++ = malloc (SBUFSIZ)) == NULL) 179: adios (NULLCP, "unable to allocate component buffer"); 180: 181: nxtbuf = compbuffers; 182: savecomp = used_buf; 183: tmpbuf = *nxtbuf++; 184: 185: FINDCOMP (cptr, "addresses"); 186: if (cptr) 187: cptr -> c_text = addrs; 188: 189: for (state = FLD;;) { 190: switch (state = m_getfld (state, name, tmpbuf, SBUFSIZ, inb)) { 191: case FLD: 192: case FLDPLUS: 193: if (cptr = wantcomp[CHASH (name)]) 194: do { 195: if (uleq (name, cptr -> c_name)) { 196: char_read += msg_count; 197: if (!cptr -> c_text) { 198: cptr -> c_text = tmpbuf; 199: *--savecomp = cptr; 200: tmpbuf = *nxtbuf++; 201: } 202: else { 203: i = strlen (cp = cptr -> c_text) - 1; 204: if (cp[i] == '\n') 205: if (cptr -> c_flags) { 206: cp[i] = NULL; 207: cp = add (",\n\t", cp); 208: } 209: else 210: cp = add ("\t", cp); 211: cptr -> c_text = add (tmpbuf, cp); 212: } 213: break; 214: } 215: } 216: while (cptr = cptr -> c_next); 217: 218: while (state == FLDPLUS) { 219: state = m_getfld (state, name, tmpbuf, SBUFSIZ, inb); 220: cptr -> c_text = add (tmpbuf, cptr -> c_text); 221: char_read += msg_count; 222: } 223: break; 224: 225: case LENERR: 226: case FMTERR: 227: case BODY: 228: case FILEEOF: 229: goto finished; 230: 231: default: 232: adios (NULLCP, "m_getfld() returned %d", state); 233: } 234: } 235: finished: ; 236: 237: i = format_len + char_read + 256; 238: scanl = malloc ((unsigned) i + 2); 239: dat[0] = dat[1] = dat[2] = 0; 240: dat[3] = outputlinelen; 241: (void) fmtscan (fmt, scanl, i, dat); 242: fputs (scanl, out); 243: 244: if (ferror (out)) 245: adios (drft, "error writing"); 246: (void) fclose (out); 247: 248: free (scanl); 249: while (cptr = *savecomp++) 250: free (cptr -> c_text); 251: free (tmpbuf); 252: free ((char *) compbuffers); 253: free ((char *) used_buf); 254: } 255: 256: /* */ 257: 258: void done (status) 259: register int status; 260: { 261: if (backup[0]) 262: (void) unlink (backup); 263: if (drft[0]) 264: (void) unlink (drft); 265: if (tmpfil[0]) 266: (void) unlink (tmpfil); 267: 268: exit (status ? RCV_MBX : RCV_MOK); 269: }