1*14552Ssam #ifndef lint 2*14552Ssam static char sccsid[] = "@(#)bugfiler.c 4.4 (Berkeley) 08/11/83"; 3*14552Ssam #endif 4*14552Ssam 512375Sralph /* 612375Sralph * Bug report processing program. 712375Sralph * It is designed to be invoked by alias(5) and to be compatible with mh. 812375Sralph */ 912375Sralph 1012375Sralph #include <stdio.h> 1112375Sralph #include <ctype.h> 1212375Sralph #include <signal.h> 1312375Sralph #include <sys/types.h> 1412375Sralph #include <sys/stat.h> 1512695Sralph #include <sys/dir.h> 1612375Sralph 1712375Sralph char deliver[] = "/usr/local/lib/mh/deliver"; 1812375Sralph char unixtomh[] = "/usr/local/lib/mh/unixtomh"; 1912375Sralph char *maildir = "/ra/bugs/mail"; 2012375Sralph char ackfile[] = ".ack"; 2112375Sralph char errfile[] = ".format"; 2212375Sralph char sumfile[] = "summary"; 2312375Sralph char logfile[] = "errors/log"; 2412375Sralph char tmpname[] = "BfXXXXXX"; 2512375Sralph char draft[] = "RpXXXXXX"; 2612375Sralph 2712695Sralph char buf[8192]; 2812375Sralph char folder[MAXNAMLEN]; 2912375Sralph int num; 3012375Sralph int msg_prot = 0664; 3112375Sralph 3212375Sralph int debug; 3312375Sralph 3412375Sralph char *index(); 3512375Sralph char *rindex(); 3612375Sralph char *fixaddr(); 3712375Sralph 3812375Sralph main(argc, argv) 3912375Sralph char *argv[]; 4012375Sralph { 4112375Sralph register char *cp; 4212695Sralph register int n; 4312695Sralph int pfd[2]; 4412375Sralph 4512375Sralph if (argc > 3) { 4612375Sralph usage: 4712695Sralph fprintf(stderr, "Usage: bugfiler [-d] [-mmsg_mode] [maildir]\n"); 4812375Sralph exit(1); 4912375Sralph } 5012375Sralph while (--argc > 0) { 5112375Sralph cp = *++argv; 5212695Sralph if (*cp == '-') 5312695Sralph switch (cp[1]) { 5412375Sralph case 'd': 5512375Sralph debug++; 5612375Sralph break; 5712695Sralph 5812695Sralph case 'm': /* set message protection */ 5912695Sralph n = 0; 6012695Sralph for (cp += 2; *cp >= '0' && *cp <= '7'; ) 6112695Sralph n = (n << 3) + (*cp++ - '0'); 6212695Sralph msg_prot = n & 0777; 6312695Sralph break; 6412695Sralph 6512375Sralph default: 6612375Sralph goto usage; 6712375Sralph } 6812375Sralph else 6912375Sralph maildir = cp; 7012375Sralph } 7112695Sralph if (!debug) 7212695Sralph freopen(logfile, "a", stderr); 7312695Sralph 7412375Sralph if (chdir(maildir) < 0) { 7512375Sralph fprintf(stderr, "can't chdir to %s\n", maildir); 7612375Sralph exit(1); 7712375Sralph } 7812695Sralph umask(0); 7912695Sralph 8012695Sralph #ifdef UNIXCOMP 8112695Sralph /* 8212695Sralph * Convert UNIX style mail to mh style by filtering stdin through 8312695Sralph * unixtomh. 8412695Sralph */ 8512695Sralph if (pipe(pfd) >= 0) { 8612695Sralph while ((n = fork()) == -1) 8712695Sralph sleep(5); 8812695Sralph if (n == 0) { 8912695Sralph close(pfd[0]); 9012695Sralph dup2(pfd[1], 1); 9112695Sralph close(pfd[1]); 9212695Sralph execl(unixtomh, "unixtomh", 0); 9312695Sralph _exit(127); 9412695Sralph } 9512695Sralph close(pfd[1]); 9612695Sralph dup2(pfd[0], 0); 9712695Sralph close(pfd[0]); 9812695Sralph } 9912695Sralph #endif 10012695Sralph while (process()) 10112695Sralph ; 10212695Sralph exit(0); 10312375Sralph } 10412375Sralph 10512695Sralph /* states */ 10612695Sralph 10712695Sralph #define EOM 0 /* End of message seen */ 10812695Sralph #define FLD 1 /* Looking for header lines */ 10912695Sralph #define BODY 2 /* Looking for message body lines */ 11012695Sralph 11112375Sralph /* defines used for tag attributes */ 11212375Sralph 11312375Sralph #define H_REQ 01 11412695Sralph #define H_SAV 02 11512695Sralph #define H_HDR 04 11612695Sralph #define H_FND 010 11712375Sralph 11812375Sralph #define FROM_I headers[0].h_info 11912375Sralph #define SUBJECT_I headers[1].h_info 12012375Sralph #define INDEX &headers[2] 12112375Sralph #define INDEX_I headers[2].h_info 12212375Sralph #define DATE_I headers[3].h_info 12312375Sralph #define MSGID_I headers[4].h_info 12412375Sralph #define REPLYTO_I headers[5].h_info 12512375Sralph #define RETURNPATH_I headers[6].h_info 12612375Sralph #define TO_I headers[7].h_info 12712375Sralph #define CC_I headers[8].h_info 12812375Sralph #define FIX headers[11] 12912375Sralph 13012375Sralph struct header { 13112375Sralph char *h_tag; 13212375Sralph int h_flags; 13312375Sralph char *h_info; 13412375Sralph } headers[] = { 13512695Sralph "From", H_REQ|H_SAV|H_HDR, 0, 13612695Sralph "Subject", H_REQ|H_SAV|H_HDR, 0, 13712375Sralph "Index", H_REQ|H_SAV, 0, 13812695Sralph "Date", H_SAV|H_HDR, 0, 13912695Sralph "Message-Id", H_SAV|H_HDR, 0, 14012695Sralph "Reply-To", H_SAV|H_HDR, 0, 14112695Sralph "Return-Path", H_SAV|H_HDR, 0, 14212695Sralph "To", H_SAV|H_HDR, 0, 14312695Sralph "Cc", H_SAV|H_HDR, 0, 14412375Sralph "Description", H_REQ, 0, 14512375Sralph "Repeat-By", H_REQ, 0, 14612695Sralph "Fix", 0, 0, 14712375Sralph 0, 0, 0, 14812375Sralph }; 14912375Sralph 15012695Sralph struct header *findheader(); 15112695Sralph 15212375Sralph process() 15312375Sralph { 15412375Sralph register struct header *hp; 15512375Sralph register char *cp; 15612695Sralph register int c; 15712375Sralph char *info; 15812695Sralph int state, tmp; 15912695Sralph FILE *tfp, *fs; 16012375Sralph 16112375Sralph /* 16212375Sralph * Insure all headers are in a consistent 16312375Sralph * state. Anything left there is free'd. 16412375Sralph */ 16512375Sralph for (hp = headers; hp->h_tag; hp++) { 16612695Sralph hp->h_flags &= ~H_FND; 16712375Sralph if (hp->h_info) { 16812695Sralph free(hp->h_info); 16912375Sralph hp->h_info = 0; 17012375Sralph } 17112375Sralph } 17212375Sralph /* 17312375Sralph * Read the report and make a copy. Must conform to RFC822 and 17412375Sralph * be of the form... <tag>: <info> 17512695Sralph * Note that the input is expected to be in mh mail format 17612695Sralph * (i.e., messages are separated by lines of ^A's). 17712375Sralph */ 17812695Sralph while ((c = getchar()) == '\001' && peekc(stdin) == '\001') 17912695Sralph while (getchar() != '\n') 18012695Sralph ; 18112695Sralph if (c == EOF) 18212695Sralph return(0); /* all done */ 18312695Sralph 18412375Sralph mktemp(tmpname); 18512695Sralph if ((tmp = creat(tmpname, msg_prot)) < 0) { 18612695Sralph fprintf(stderr, "cannont create %s\n", tmpname); 18712695Sralph exit(1); 18812695Sralph } 18912695Sralph if ((tfp = fdopen(tmp, "w")) == NULL) { 19012695Sralph fprintf(stderr, "cannot fdopen temp file\n"); 19112695Sralph exit(1); 19212695Sralph } 19312695Sralph 19412695Sralph for (state = FLD; state != EOF && state != EOM; c = getchar()) { 19512695Sralph switch (state) { 19612695Sralph case FLD: 19712695Sralph if (c == '\n' || c == '-') 19812695Sralph goto body; 19912695Sralph for (cp = buf; c != ':'; c = getchar()) { 20012695Sralph if (cp < buf+sizeof(buf)-1 && c != '\n' && c != EOF) { 20112695Sralph *cp++ = c; 20212695Sralph continue; 20312695Sralph } 20412695Sralph *cp = '\0'; 20512695Sralph fputs(buf, tfp); 20612695Sralph state = EOF; 20712695Sralph while (c != EOF) { 20812695Sralph if (c == '\n') 20912695Sralph if ((tmp = peekc(stdin)) == EOF) 21012695Sralph break; 21112695Sralph else if (tmp == '\001') { 21212695Sralph state = EOM; 21312695Sralph break; 21412695Sralph } 21512695Sralph putc(c, tfp); 21612695Sralph c = getchar(); 21712695Sralph } 21812695Sralph fclose(tfp); 21912695Sralph goto badfmt; 22012695Sralph } 22112695Sralph *cp = '\0'; 22212695Sralph fprintf(tfp, "%s:", buf); 22312695Sralph hp = findheader(buf, state); 22412695Sralph 22512695Sralph for (cp = buf; ; ) { 22612695Sralph if (cp >= buf+sizeof(buf)-1) { 22712695Sralph fprintf(stderr, "field truncated\n"); 22812695Sralph while ((c = getchar()) != EOF && c != '\n') 22912695Sralph putc(c, tfp); 23012695Sralph } 23112695Sralph if ((c = getchar()) == EOF) { 23212695Sralph state = EOF; 23312695Sralph break; 23412695Sralph } 23512695Sralph putc(c, tfp); 23612695Sralph *cp++ = c; 23712695Sralph if (c == '\n') 23812695Sralph if ((c = peekc(stdin)) != ' ' && c != '\t') { 23912695Sralph if (c == EOF) 24012695Sralph state = EOF; 24112695Sralph else if (c == '\001') 24212695Sralph state = EOM; 24312695Sralph break; 24412695Sralph } 24512695Sralph } 24612695Sralph *cp = '\0'; 24712695Sralph cp = buf; 24812695Sralph break; 24912695Sralph 25012695Sralph body: 25112695Sralph state = BODY; 25212695Sralph case BODY: 25312695Sralph for (cp = buf; ; c = getchar()) { 25412695Sralph if (c == EOF) { 25512695Sralph state = EOF; 25612695Sralph break; 25712695Sralph } 25812695Sralph if (c == '\001' && peekc(stdin) == '\001') { 25912695Sralph state = EOM; 26012695Sralph break; 26112695Sralph } 26212695Sralph putc(c, tfp); 26312695Sralph *cp++ = c; 26412695Sralph if (cp >= buf+sizeof(buf)-1 || c == '\n') 26512695Sralph break; 26612695Sralph } 26712695Sralph *cp = '\0'; 26812695Sralph if ((cp = index(buf, ':')) == NULL) 26912695Sralph continue; 27012695Sralph *cp++ = '\0'; 27112695Sralph hp = findheader(buf, state); 27212695Sralph } 27312695Sralph 27412695Sralph /* 27512695Sralph * Don't save the info if the header wasn't found, we don't 27612695Sralph * care about the info, or the header is repeated. 27712695Sralph */ 27812695Sralph if (hp == NULL || !(hp->h_flags & H_SAV) || hp->h_info) 27912375Sralph continue; 28012375Sralph while (isspace(*cp)) 28112375Sralph cp++; 28212375Sralph if (*cp) { 28312375Sralph info = cp; 28412375Sralph while (*cp++); 28512375Sralph cp--; 28612375Sralph while (isspace(cp[-1])) 28712375Sralph *--cp = '\0'; 28812375Sralph hp->h_info = (char *) malloc(strlen(info) + 1); 28912695Sralph if (hp->h_info == NULL) { 29012695Sralph fprintf(stderr, "ran out of memory\n"); 29112375Sralph continue; 29212695Sralph } 29312375Sralph strcpy(hp->h_info, info); 29412375Sralph if (hp == INDEX) 29512375Sralph chkindex(hp); 29612375Sralph } 29712375Sralph } 29812695Sralph fclose(tfp); 29912375Sralph /* 30012375Sralph * Verify all the required pieces of information 30112375Sralph * are present. 30212375Sralph */ 30312695Sralph for (hp = headers; hp->h_tag; hp++) { 30412375Sralph /* 30512375Sralph * Mail the bug report back to the sender with a note 30612375Sralph * explaining they must conform to the specification. 30712375Sralph */ 30812695Sralph if ((hp->h_flags & H_REQ) && !(hp->h_flags & H_FND)) { 30912695Sralph if (debug) 31012695Sralph printf("Missing %s\n", hp->h_tag); 31112695Sralph badfmt: 31212695Sralph reply(FROM_I, errfile, tmpname); 31312695Sralph file(tmpname, "errors"); 31412695Sralph return(state == EOM); 31512695Sralph } 31612375Sralph } 31712375Sralph /* 31812695Sralph * Acknowledge receipt. 31912695Sralph */ 32012695Sralph reply(FROM_I, ackfile, (char *)0); 32112695Sralph file(tmpname, folder); 32212695Sralph /* 32312375Sralph * Append information about the new bug report 32412375Sralph * to the summary file. 32512375Sralph */ 32612695Sralph if ((fs = fopen(sumfile, "a")) == NULL) 32712375Sralph fprintf(stderr, "Can't open %s\n", sumfile); 32812695Sralph else { 32912695Sralph fprintf(fs, "%14.14s/%-3d ", folder, num); 33012695Sralph fprintf(fs, "%-51.51s Recv\n", INDEX_I); 33112695Sralph fprintf(fs, "\t\t %-51.51s\n", SUBJECT_I); 33212375Sralph } 33312375Sralph fclose(fs); 33412695Sralph return(state == EOM); 33512375Sralph } 33612375Sralph 33712375Sralph /* 33812695Sralph * Lookup the string in the list of headers and return a pointer 33912695Sralph * to the entry or NULL. 34012695Sralph */ 34112695Sralph 34212695Sralph struct header * 34312695Sralph findheader(name, state) 34412695Sralph char *name; 34512695Sralph int state; 34612695Sralph { 34712695Sralph register struct header *hp; 34812695Sralph 34912695Sralph if (debug) 35012695Sralph printf("findheader(%s, %d)\n", name, state); 35112695Sralph 35212695Sralph for (hp = headers; hp->h_tag; hp++) { 35312695Sralph if (!streq(hp->h_tag, buf)) 35412695Sralph continue; 35512695Sralph if ((hp->h_flags & H_HDR) && state != FLD) 35612695Sralph continue; 35712695Sralph hp->h_flags |= H_FND; 35812695Sralph return(hp); 35912695Sralph } 36012695Sralph return(NULL); 36112695Sralph } 36212695Sralph 36312695Sralph /* 36412375Sralph * Check the format of the Index information. 36512375Sralph * A side effect is to set the name of the folder if all is well. 36612375Sralph */ 36712375Sralph 36812375Sralph chkindex(hp) 36912375Sralph struct header *hp; 37012375Sralph { 37112695Sralph register char *cp1, *cp2; 37212375Sralph register char c; 37312375Sralph struct stat stbuf; 37412375Sralph 37512375Sralph if (debug) 37612695Sralph printf("chkindex(%s)\n", hp->h_info); 37712375Sralph /* 37812695Sralph * Strip of leading "/", "usr/", "src/" or "sys/". 37912695Sralph */ 38012695Sralph cp1 = hp->h_info; 38112695Sralph while (*cp1 == '/') 38212695Sralph cp1++; 38312695Sralph while (substr(cp1, "usr/") || substr(cp1, "src/") || substr(cp1, "sys/")) 38412695Sralph cp1 += 4; 38512695Sralph /* 38612375Sralph * Read the folder name and remove it from the index line. 38712375Sralph */ 38812695Sralph for (cp2 = folder; ;) { 38912695Sralph switch (c = *cp1++) { 39012695Sralph case '/': 39112695Sralph if (cp2 == folder) 39212695Sralph continue; 39312375Sralph break; 39412695Sralph case '\0': 39512695Sralph cp1--; 39612695Sralph break; 39712695Sralph case ' ': 39812695Sralph case '\t': 39912695Sralph while (isspace(*cp1)) 40012695Sralph cp1++; 40112695Sralph break; 40212695Sralph default: 40312695Sralph if (cp2 < folder+sizeof(folder)-1) 40412695Sralph *cp2++ = c; 40512695Sralph continue; 40612375Sralph } 40712695Sralph *cp2 = '\0'; 40812695Sralph for (cp2 = hp->h_info; *cp2++ = *cp1++; ) 40912695Sralph ; 41012695Sralph break; 41112375Sralph } 41212695Sralph if (debug) 41312695Sralph printf("folder = %s\n", folder); 41412375Sralph /* 41512375Sralph * Check to make sure we have a valid folder name 41612375Sralph */ 41712375Sralph if (stat(folder, &stbuf) == 0 && (stbuf.st_mode & S_IFMT) == S_IFDIR) 41812375Sralph return; 41912375Sralph /* 42012375Sralph * The Index line is not in the correct format so clear 42112695Sralph * the H_FND flag to mail back the correct format. 42212375Sralph */ 42312695Sralph hp->h_flags &= ~H_FND; 42412375Sralph } 42512375Sralph 42612375Sralph /* 42712375Sralph * Move or copy the file msg to the folder (directory). 42812375Sralph * A side effect is to set num to the number of the file in folder. 42912375Sralph */ 43012375Sralph 43112375Sralph file(fname, folder) 43212375Sralph char *fname, *folder; 43312375Sralph { 43412375Sralph register char *cp, n; 43512375Sralph char msgname[MAXNAMLEN*2+2]; 43612375Sralph struct stat stbuf; 43712375Sralph DIR *dirp; 43812375Sralph struct direct *d; 43912375Sralph 44012375Sralph if (debug) 44112695Sralph printf("file(%s, %s)\n", fname, folder); 44212375Sralph /* 44312375Sralph * Get the next number to use by finding the last message number 44412375Sralph * in folder and adding one. 44512375Sralph */ 44612375Sralph if ((dirp = opendir(folder)) == NULL) { 44712375Sralph fprintf(stderr, "Cannot open %s/%s\n", maildir, folder); 44812375Sralph return; 44912375Sralph } 45012375Sralph num = 0; 45112375Sralph while ((d = readdir(dirp)) != NULL) { 45212375Sralph cp = d->d_name; 45312375Sralph n = 0; 45412375Sralph while (isdigit(*cp)) 45512375Sralph n = n * 10 + (*cp++ - '0'); 45612375Sralph if (*cp == '\0' && n > num) 45712375Sralph num = n; 45812375Sralph } 45912375Sralph closedir(dirp); 46012375Sralph num++; 46112375Sralph /* 46212375Sralph * Create the destination file "folder/num" and copy fname to it. 46312375Sralph */ 46412375Sralph sprintf(msgname, "%s/%d", folder, num); 46512375Sralph if (link(fname, msgname) < 0) { 46612375Sralph int fin, fout; 46712375Sralph 46812695Sralph if ((fin = open(fname, 0)) < 0) { 46912695Sralph fprintf(stderr, "cannot open %s\n", fname); 47012375Sralph return; 47112695Sralph } 47212695Sralph if ((fout = creat(msgname, msg_prot)) < 0) { 47312695Sralph fprintf(stderr, "cannot create %s\n", msgname); 47412375Sralph return; 47512695Sralph } 47612695Sralph while ((n = read(fin, buf, sizeof(buf))) > 0) 47712695Sralph write(fout, buf, n); 47812375Sralph close(fin); 47912375Sralph close(fout); 48012375Sralph } 48112375Sralph unlink(fname); 48212375Sralph } 48312375Sralph 48412375Sralph /* 48512375Sralph * Mail file1 and file2 back to the sender. 48612375Sralph */ 48712375Sralph 48812375Sralph reply(to, file1, file2) 48912375Sralph char *to, *file1, *file2; 49012375Sralph { 49112375Sralph int (*istat)(), (*qstat)(); 49212375Sralph int pid, w, status, pfd[2], in; 49312375Sralph FILE *fout; 49412375Sralph 49512375Sralph if (debug) 49612695Sralph printf("reply(%s, %s, %s)\n", to, file1, file2); 49712695Sralph 49812375Sralph /* 49912375Sralph * Create a temporary file to put the message in. 50012375Sralph */ 50112375Sralph mktemp(draft); 50212375Sralph if ((fout = fopen(draft, "w")) == NULL) { 50312375Sralph fprintf(stderr, "Can't create %s\n", draft); 50412375Sralph return; 50512375Sralph } 50612375Sralph /* 50712375Sralph * Output the proper header information. 50812375Sralph */ 50914342Skarels fprintf(fout, "Reply-To: 4bsd-bugs%%ucbarpa@BERKELEY\n"); 51012375Sralph if (RETURNPATH_I != NULL) 51112375Sralph to = RETURNPATH_I; 51212375Sralph if (REPLYTO_I != NULL) 51312375Sralph to = REPLYTO_I; 51412375Sralph if ((to = fixaddr(to)) == 0) { 51512375Sralph fprintf(stderr, "No one to reply to\n"); 51612375Sralph return; 51712375Sralph } 51812375Sralph fprintf(fout, "To: %s\n", to); 51912375Sralph if (SUBJECT_I) { 52012375Sralph fprintf(fout, "Subject: "); 52112375Sralph if ((SUBJECT_I[0] != 'R' && SUBJECT_I[0] != 'r') || 52212375Sralph (SUBJECT_I[1] != 'E' && SUBJECT_I[1] != 'e') || 52312375Sralph SUBJECT_I[2] != ':') 52412375Sralph fprintf(fout, "Re: "); 52512375Sralph fprintf(fout, "%s\n", SUBJECT_I); 52612375Sralph } 52712375Sralph if (DATE_I) { 52812375Sralph fprintf(fout, "In-Acknowledgement-Of: Your message of "); 52912375Sralph fprintf(fout, "%s.\n", DATE_I); 53012375Sralph if (MSGID_I) 53112375Sralph fprintf(fout, " %s\n", MSGID_I); 53212375Sralph } 53312375Sralph fprintf(fout, "----------\n"); 53412375Sralph if ((in = open(file1, 0)) >= 0) { 53512695Sralph while ((w = read(in, buf, sizeof(buf))) > 0) 53612695Sralph fwrite(buf, 1, w, fout); 53712375Sralph close(in); 53812375Sralph } 53912375Sralph if (file2 && (in = open(file2, 0)) >= 0) { 54012695Sralph while ((w = read(in, buf, sizeof(buf))) > 0) 54112695Sralph fwrite(buf, 1, w, fout); 54212375Sralph close(in); 54312375Sralph } 54412375Sralph fclose(fout); 54512375Sralph while ((pid = fork()) == -1) 54612375Sralph sleep(5); 54712375Sralph if (pid == 0) { 54812375Sralph execl(deliver, "deliver", draft, 0); 54912375Sralph _exit(127); 55012375Sralph } 55112375Sralph istat = signal(SIGINT, SIG_IGN); 55212375Sralph qstat = signal(SIGQUIT, SIG_IGN); 55312375Sralph while ((w = wait(&status)) != -1 && w != pid); 55412375Sralph signal(SIGINT, istat); 55512375Sralph signal(SIGQUIT, qstat); 55612375Sralph if (w != -1 && status == 0) 55712375Sralph unlink(draft); 55812375Sralph } 55912375Sralph 56012375Sralph /* 56112375Sralph * fix names like "xxx (something)" to "xxx" and 56212375Sralph * "xxx <something>" to "something". 56312375Sralph */ 56412375Sralph 56512375Sralph char * 56612375Sralph fixaddr(text) 56712375Sralph char *text; 56812375Sralph { 56912375Sralph register char *cp, *lp, c; 57012375Sralph char *tp; 57112375Sralph 57212375Sralph if (!text) 57312375Sralph return(0); 57412375Sralph for (lp = cp = text; ; ) { 57512375Sralph switch (c = *cp++) { 57612375Sralph case '(': 57712375Sralph while (*cp && *cp++ != ')'); 57812375Sralph continue; 57912375Sralph case '<': 58012375Sralph lp = text; 58112375Sralph case '>': 58212375Sralph continue; 58312375Sralph case '\0': 58412375Sralph while (lp != text && (*lp == ' ' || *lp == '\t')) 58512375Sralph lp--; 58612375Sralph *lp = c; 58712375Sralph return(text); 58812375Sralph } 58912375Sralph *lp++ = c; 59012375Sralph } 59112375Sralph } 59212375Sralph 59312375Sralph /* 59412375Sralph * Compare two strings and convert any upper case letters to lower case. 59512375Sralph */ 59612375Sralph 59712695Sralph streq(s1, s2) 59812695Sralph register char *s1, *s2; 59912375Sralph { 60012375Sralph register int c; 60112375Sralph 60212695Sralph while (c = *s1++) 60312695Sralph if ((c | 040) != (*s2++ | 040)) 60412375Sralph return(0); 60512695Sralph return(*s2 == '\0'); 60612375Sralph } 60712695Sralph 60812695Sralph /* 60912695Sralph * Return true if string s2 matches the first part of s1. 61012695Sralph */ 61112695Sralph 61212695Sralph substr(s1, s2) 61312695Sralph register char *s1, *s2; 61412695Sralph { 61512695Sralph register int c; 61612695Sralph 61712695Sralph while (c = *s2++) 61812695Sralph if (c != *s1++) 61912695Sralph return(0); 62012695Sralph return(1); 62112695Sralph } 62212695Sralph 62312695Sralph peekc(fp) 62412695Sralph FILE *fp; 62512695Sralph { 62612695Sralph register c; 62712695Sralph 62812695Sralph c = getc(fp); 62912695Sralph ungetc(c, fp); 63012695Sralph return(c); 63112695Sralph } 632