1: /* 2: * unbatchnews: extract news in batched format and process it one article 3: * at a time. The format looks like 4: * #! rnews 1234 5: * article containing 1234 characters 6: * #! rnews 4321 7: * article containing 4321 characters 8: * 9: * or 10: * 11: * #! command [args] 12: * calls LIBDIR/command [args] to process the news 13: */ 14: 15: #ifdef SCCSID 16: static char *SccsId = "@(#)unbatch.c 6.3 5/17/86"; 17: #endif /* SCCSID */ 18: 19: #define MAXARGS 20 20: 21: #ifdef BSD4_2 22: #define fork vfork 23: #endif /* BSD4_2 */ 24: 25: #include <stdio.h> 26: #include <ctype.h> 27: #ifdef USG 28: #include <fcntl.h> 29: #endif /* USG */ 30: 31: char buf[BUFSIZ]; 32: char sibuf[BUFSIZ]; 33: 34: main() 35: { 36: register int c; 37: register FILE *pfn; 38: register long size; 39: char *filename; 40: int pid, wpid, exstat; 41: char *mktemp(), *gets(); 42: long atol(); 43: 44: filename = mktemp("/tmp/unbnewsXXXXXX"); 45: setbuf(stdin, (char *)NULL); /* only for the first line */ 46: if (gets(buf) == NULL) { 47: (void) unlink(filename); 48: exit(0); 49: } 50: if (strncmp(buf, "#! rnews ", 9) != 0) { 51: docmd(buf); 52: /* should not return */ 53: logerr("unbatch: docmd returned!"); 54: exit(1); 55: } 56: 57: setbuf(stdin, sibuf); /* buffer the rest of the file */ 58: 59: do { 60: while (strncmp(buf, "#! rnews ", 9) 61: && strncmp(buf, "! rnews ", 8)) { /* kludge for bug */ 62: register char *cp; 63: for (cp = buf; *cp != '\0'; ++cp) 64: if (!isascii(*cp) || 65: (!isprint(*cp) && !isspace(*cp))) 66: *cp = '?'; 67: logerr("out of sync, skipping %s", buf); 68: if (gets(buf) == NULL) 69: exit(0); 70: } 71: size = atol(buf + (buf[0] == '#' ? 9 : 8)); 72: if(size <= 0) { 73: logerr("nonsense size %ld", size); 74: continue; 75: } 76: #ifdef VMS 77: vmsdelete(filename); 78: #endif /* VMS */ 79: pfn = fopen(filename, "w"); 80: while(--size >= 0 && (c = getc(stdin)) != EOF) 81: putc(c, pfn); 82: (void) fclose(pfn); 83: 84: /* 85: * If we got a truncated batch, don't process the 86: * last article; it will probably be received again. 87: */ 88: if (size > 0) 89: break; 90: 91: /* 92: * rnews < filename 93: */ 94: while ((pid = fork()) == -1) { 95: logerr("fork failed, waiting...\n"); 96: sleep(53); 97: } 98: if (pid == 0) { 99: (void) close(0); 100: (void) open(filename, 0); 101: #ifdef IHCC 102: (void) sprintf(buf, "%s/%s/rnews", logdir(HOME), LIBDIR); 103: #else 104: (void) sprintf(buf, "%s/rnews", BINDIR); 105: #endif 106: execlp(buf, "rnews", (char *)0); 107: perror("rnews"); 108: exit(1); 109: } 110: while ((wpid = wait(&exstat)) >= 0 && wpid != pid) 111: ; 112: } while (gets(buf) != NULL); 113: (void) unlink(filename); 114: exit(0); 115: } 116: 117: docmd(p) 118: register char *p; 119: { 120: char *args[MAXARGS]; 121: register char **ap = args; 122: char path[BUFSIZ]; 123: char *rindex(), *cp; 124: 125: while (*p && !isspace(*p)) /* skip leading #! crud */ 126: p++; 127: 128: while (isspace(*p)) 129: p++; 130: 131: while (*p != '\0') { 132: *ap++ = p; 133: if (ap >= &args[MAXARGS]) { 134: logerr("unbatch: Too many args to %s", args[0]); 135: exit(2); 136: } 137: while (*p && !isspace(*p)) 138: p++; 139: if (*p) 140: *p++ = '\0'; 141: while (isspace(*p)) 142: p++; 143: } 144: *ap = (char *)0; 145: 146: if (ap == args) { 147: logerr("unbatch: no command to execute"); 148: exit(2); 149: } 150: 151: /* strip off any leading pathname in case someone gets tricky */ 152: cp = rindex(args[0], '/'); 153: if (cp++ == NULL) 154: cp = args[0]; 155: 156: sprintf(path, "%s/%s", LIBDIR, cp); 157: 158: /* 159: * "path" is absolute, no searching is needed, we use 160: * 'execvp' solely so that sh scripts will be handled 161: */ 162: (void) execvp(path, args); 163: perror(path); 164: exit(2); 165: } 166: 167: /* 168: * Log the given message, with printf strings and parameters allowed, 169: * on the log file, if it can be written. 170: */ 171: /* VARARGS1 */ 172: logerr(fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9) 173: char *fmt; 174: { 175: FILE *logfile; 176: char lfname[BUFSIZ]; /* the log file */ 177: char bfr[BUFSIZ]; 178: char *logtime, *ctime(); 179: long t; 180: 181: (void) time(&t); 182: logtime = ctime(&t); 183: logtime[16] = 0; 184: logtime += 4; 185: 186: #ifdef IHCC 187: (void) sprintf(lfname, "%s/%s/errlog", logdir(HOME), LIBDIR); 188: #else 189: (void) sprintf(lfname, "%s/errlog", LIBDIR); 190: #endif 191: 192: (void) sprintf(bfr, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9); 193: fprintf(stderr, bfr); 194: if (access(lfname, 0) == 0 && (logfile = fopen(lfname, "a")) != NULL) { 195: #if defined(USG) || defined(BSD4_2) || defined(BSD4_1C) 196: int flags; 197: flags = fcntl(fileno(logfile), F_GETFL, 0); 198: (void) fcntl(fileno(logfile), F_SETFL, flags|O_APPEND); 199: #else /* v7 */ 200: (void) lseek(fileno(logfile), 0L, 2); 201: #endif /* v7 */ 202: fprintf(logfile, "%s\tbatch\t%s\n", logtime, bfr); 203: (void) fclose(logfile); 204: } 205: }