114522Ssam #ifndef lint 2*18661Sserge static char *sccsid = "@(#)aux.c 2.12 (Berkeley) 04/18/85"; 314522Ssam #endif 41219Skas 51219Skas #include "rcv.h" 61219Skas #include <sys/stat.h> 71219Skas #include <ctype.h> 81219Skas 91219Skas /* 101219Skas * Mail -- a mail program 111219Skas * 121219Skas * Auxiliary functions. 131219Skas */ 141219Skas 151219Skas /* 161219Skas * Return a pointer to a dynamic copy of the argument. 171219Skas */ 181219Skas 191219Skas char * 201219Skas savestr(str) 211219Skas char *str; 221219Skas { 231219Skas register char *cp, *cp2, *top; 241219Skas 251219Skas for (cp = str; *cp; cp++) 261219Skas ; 271219Skas top = salloc(cp-str + 1); 281219Skas if (top == NOSTR) 291219Skas return(NOSTR); 301219Skas for (cp = str, cp2 = top; *cp; cp++) 311219Skas *cp2++ = *cp; 321219Skas *cp2 = 0; 331219Skas return(top); 341219Skas } 351219Skas 361219Skas /* 371219Skas * Copy the name from the passed header line into the passed 381219Skas * name buffer. Null pad the name buffer. 391219Skas */ 401219Skas 411219Skas copyname(linebuf, nbuf) 421219Skas char *linebuf, *nbuf; 431219Skas { 441219Skas register char *cp, *cp2; 451219Skas 461219Skas for (cp = linebuf + 5, cp2 = nbuf; *cp != ' ' && cp2-nbuf < 8; cp++) 471219Skas *cp2++ = *cp; 481219Skas while (cp2-nbuf < 8) 491219Skas *cp2++ = 0; 501219Skas } 511219Skas 521219Skas /* 531219Skas * Announce a fatal error and die. 541219Skas */ 551219Skas 561219Skas panic(str) 571219Skas char *str; 581219Skas { 591219Skas prs("panic: "); 601219Skas prs(str); 611219Skas prs("\n"); 621219Skas exit(1); 631219Skas } 641219Skas 651219Skas /* 661219Skas * Catch stdio errors and report them more nicely. 671219Skas */ 681219Skas 691219Skas _error(str) 701219Skas char *str; 711219Skas { 721219Skas prs("Stdio Error: "); 731219Skas prs(str); 741219Skas prs("\n"); 751219Skas abort(); 761219Skas } 771219Skas 781219Skas /* 791219Skas * Print a string on diagnostic output. 801219Skas */ 811219Skas 821219Skas prs(str) 831219Skas char *str; 841219Skas { 851219Skas register char *s; 861219Skas 871219Skas for (s = str; *s; s++) 881219Skas ; 891219Skas write(2, str, s-str); 901219Skas } 911219Skas 921219Skas /* 931219Skas * Touch the named message by setting its MTOUCH flag. 941219Skas * Touched messages have the effect of not being sent 951219Skas * back to the system mailbox on exit. 961219Skas */ 971219Skas 981219Skas touch(mesg) 991219Skas { 1001479Skas register struct message *mp; 1011479Skas 1021479Skas if (mesg < 1 || mesg > msgCount) 1031479Skas return; 1041479Skas mp = &message[mesg-1]; 1051479Skas mp->m_flag |= MTOUCH; 1061479Skas if ((mp->m_flag & MREAD) == 0) 1071479Skas mp->m_flag |= MREAD|MSTATUS; 1081219Skas } 1091219Skas 1101219Skas /* 1111219Skas * Test to see if the passed file name is a directory. 1121219Skas * Return true if it is. 1131219Skas */ 1141219Skas 1151219Skas isdir(name) 1161219Skas char name[]; 1171219Skas { 1181219Skas struct stat sbuf; 1191219Skas 1201219Skas if (stat(name, &sbuf) < 0) 1211219Skas return(0); 1221219Skas return((sbuf.st_mode & S_IFMT) == S_IFDIR); 1231219Skas } 1241219Skas 1251219Skas /* 1261219Skas * Count the number of arguments in the given string raw list. 1271219Skas */ 1281219Skas 1291219Skas argcount(argv) 1301219Skas char **argv; 1311219Skas { 1321219Skas register char **ap; 1331219Skas 1341219Skas for (ap = argv; *ap != NOSTR; ap++) 1351219Skas ; 1361219Skas return(ap-argv); 1371219Skas } 1381219Skas 1391219Skas /* 1401219Skas * Given a file address, determine the 1411219Skas * block number it represents. 1421219Skas */ 1431219Skas 1441219Skas blockof(off) 1451219Skas off_t off; 1461219Skas { 1471219Skas off_t a; 1481219Skas 1491219Skas a = off >> 9; 1501219Skas a &= 077777; 1511219Skas return((int) a); 1521219Skas } 1531219Skas 1541219Skas /* 1551219Skas * Take a file address, and determine 1561219Skas * its offset in the current block. 1571219Skas */ 1581219Skas 1591219Skas offsetof(off) 1601219Skas off_t off; 1611219Skas { 1621219Skas off_t a; 1631219Skas 1641219Skas a = off & 0777; 1651219Skas return((int) a); 1661219Skas } 1671219Skas 1681219Skas /* 1691219Skas * Determine if the passed file is actually a tty, via a call to 1701219Skas * gtty. This is not totally reliable, but . . . 1711219Skas */ 1721219Skas 1731219Skas isatty(f) 1741219Skas { 1751219Skas struct sgttyb buf; 1761219Skas 1771219Skas if (gtty(f, &buf) < 0) 1781219Skas return(0); 1791219Skas return(1); 1801219Skas } 1811219Skas 1821219Skas /* 1831219Skas * Return the desired header line from the passed message 1841219Skas * pointer (or NOSTR if the desired header field is not available). 1851219Skas */ 1861219Skas 1871219Skas char * 1881219Skas hfield(field, mp) 1891219Skas char field[]; 1901219Skas struct message *mp; 1911219Skas { 1921219Skas register FILE *ibuf; 1931219Skas char linebuf[LINESIZE]; 1941219Skas register int lc; 1951219Skas 1961219Skas ibuf = setinput(mp); 1971219Skas if ((lc = mp->m_lines) <= 0) 1981219Skas return(NOSTR); 1991219Skas if (readline(ibuf, linebuf) < 0) 2001219Skas return(NOSTR); 2011219Skas lc--; 2021219Skas do { 2031219Skas lc = gethfield(ibuf, linebuf, lc); 2041219Skas if (lc == -1) 2051219Skas return(NOSTR); 2061219Skas if (ishfield(linebuf, field)) 2071219Skas return(savestr(hcontents(linebuf))); 2081219Skas } while (lc > 0); 2091219Skas return(NOSTR); 2101219Skas } 2111219Skas 2121219Skas /* 2131219Skas * Return the next header field found in the given message. 2141219Skas * Return > 0 if something found, <= 0 elsewise. 2151219Skas * Must deal with \ continuations & other such fraud. 2161219Skas */ 2171219Skas 2181219Skas gethfield(f, linebuf, rem) 2191219Skas register FILE *f; 2201219Skas char linebuf[]; 2211219Skas register int rem; 2221219Skas { 2231219Skas char line2[LINESIZE]; 2241219Skas long loc; 2251219Skas register char *cp, *cp2; 2261219Skas register int c; 2271219Skas 2281219Skas 2291219Skas for (;;) { 2301219Skas if (rem <= 0) 2311219Skas return(-1); 2321219Skas if (readline(f, linebuf) < 0) 2331219Skas return(-1); 2341219Skas rem--; 2351219Skas if (strlen(linebuf) == 0) 2361219Skas return(-1); 2371219Skas if (isspace(linebuf[0])) 2381219Skas continue; 2391219Skas if (linebuf[0] == '>') 2401219Skas continue; 2411219Skas cp = index(linebuf, ':'); 2421219Skas if (cp == NOSTR) 2431219Skas continue; 2441219Skas for (cp2 = linebuf; cp2 < cp; cp2++) 2451219Skas if (isdigit(*cp2)) 2461219Skas continue; 2471219Skas 2481219Skas /* 2491219Skas * I guess we got a headline. 2501219Skas * Handle wraparounding 2511219Skas */ 2521219Skas 2531219Skas for (;;) { 2541219Skas if (rem <= 0) 2551219Skas break; 2561219Skas #ifdef CANTELL 2571219Skas loc = ftell(f); 2581219Skas if (readline(f, line2) < 0) 2591219Skas break; 2601219Skas rem--; 2611219Skas if (!isspace(line2[0])) { 2621219Skas fseek(f, loc, 0); 2631219Skas rem++; 2641219Skas break; 2651219Skas } 2661219Skas #else 2671219Skas c = getc(f); 2681219Skas ungetc(c, f); 2691219Skas if (!isspace(c) || c == '\n') 2701219Skas break; 2711219Skas if (readline(f, line2) < 0) 2721219Skas break; 2731219Skas rem--; 2741219Skas #endif 2751219Skas cp2 = line2; 2761219Skas for (cp2 = line2; *cp2 != 0 && isspace(*cp2); cp2++) 2771219Skas ; 2781219Skas if (strlen(linebuf) + strlen(cp2) >= LINESIZE-2) 2791219Skas break; 2801219Skas cp = &linebuf[strlen(linebuf)]; 2811219Skas while (cp > linebuf && 2821219Skas (isspace(cp[-1]) || cp[-1] == '\\')) 2831219Skas cp--; 2841219Skas *cp++ = ' '; 2851219Skas for (cp2 = line2; *cp2 != 0 && isspace(*cp2); cp2++) 2861219Skas ; 2871219Skas strcpy(cp, cp2); 2881219Skas } 2891219Skas if ((c = strlen(linebuf)) > 0) { 2901219Skas cp = &linebuf[c-1]; 2911219Skas while (cp > linebuf && isspace(*cp)) 2921219Skas cp--; 2931219Skas *++cp = 0; 2941219Skas } 2951219Skas return(rem); 2961219Skas } 2971219Skas /* NOTREACHED */ 2981219Skas } 2991219Skas 3001219Skas /* 3011219Skas * Check whether the passed line is a header line of 3021219Skas * the desired breed. 3031219Skas */ 3041219Skas 3051219Skas ishfield(linebuf, field) 3061219Skas char linebuf[], field[]; 3071219Skas { 3081219Skas register char *cp; 3091219Skas register int c; 3101219Skas 3111219Skas if ((cp = index(linebuf, ':')) == NOSTR) 3121219Skas return(0); 3131219Skas if (cp == linebuf) 3141219Skas return(0); 3151219Skas cp--; 3161219Skas while (cp > linebuf && isspace(*cp)) 3171219Skas cp--; 3181219Skas c = *++cp; 3191219Skas *cp = 0; 3201219Skas if (icequal(linebuf ,field)) { 3211219Skas *cp = c; 3221219Skas return(1); 3231219Skas } 3241219Skas *cp = c; 3251219Skas return(0); 3261219Skas } 3271219Skas 3281219Skas /* 3291219Skas * Extract the non label information from the given header field 3301219Skas * and return it. 3311219Skas */ 3321219Skas 3331219Skas char * 3341219Skas hcontents(hfield) 3351219Skas char hfield[]; 3361219Skas { 3371219Skas register char *cp; 3381219Skas 3391219Skas if ((cp = index(hfield, ':')) == NOSTR) 3401219Skas return(NOSTR); 3411219Skas cp++; 3421219Skas while (*cp && isspace(*cp)) 3431219Skas cp++; 3441219Skas return(cp); 3451219Skas } 3461219Skas 3471219Skas /* 3481219Skas * Compare two strings, ignoring case. 3491219Skas */ 3501219Skas 3511219Skas icequal(s1, s2) 3521219Skas register char *s1, *s2; 3531219Skas { 3541219Skas 3551219Skas while (raise(*s1++) == raise(*s2)) 3561219Skas if (*s2++ == 0) 3571219Skas return(1); 3581219Skas return(0); 3591219Skas } 3601219Skas 3611219Skas /* 3627571Skurt * Copy a string, lowercasing it as we go. 3637571Skurt */ 3647571Skurt istrcpy(dest, src) 3657571Skurt char *dest, *src; 3667571Skurt { 3677571Skurt register char *cp, *cp2; 3687571Skurt 3697571Skurt cp2 = dest; 3707571Skurt cp = src; 3717571Skurt do { 3727571Skurt *cp2++ = little(*cp); 3737571Skurt } while (*cp++ != 0); 3747571Skurt } 3757571Skurt 3767571Skurt /* 3771219Skas * The following code deals with input stacking to do source 3781219Skas * commands. All but the current file pointer are saved on 3791219Skas * the stack. 3801219Skas */ 3811219Skas 3821219Skas static int ssp = -1; /* Top of file stack */ 3831519Skas struct sstack { 3841519Skas FILE *s_file; /* File we were in. */ 3851519Skas int s_cond; /* Saved state of conditionals */ 3865785Skurt int s_loading; /* Loading .mailrc, etc. */ 387*18661Sserge } sstack[NOFILE]; 3881219Skas 3891219Skas /* 3901219Skas * Pushdown current input file and switch to a new one. 3911219Skas * Set the global flag "sourcing" so that others will realize 3921219Skas * that they are no longer reading from a tty (in all probability). 3931219Skas */ 3941219Skas 3951219Skas source(name) 3961219Skas char name[]; 3971219Skas { 3981219Skas register FILE *fi; 3993914Skurt register char *cp; 4001219Skas 4013914Skurt if ((cp = expand(name)) == NOSTR) 4021219Skas return(1); 4033914Skurt if ((fi = fopen(cp, "r")) == NULL) { 4043914Skurt perror(cp); 4053914Skurt return(1); 4061219Skas } 407*18661Sserge if (ssp >= NOFILE - 2) { 4081219Skas printf("Too much \"sourcing\" going on.\n"); 4091219Skas fclose(fi); 4101219Skas return(1); 4111219Skas } 4121519Skas sstack[++ssp].s_file = input; 4131519Skas sstack[ssp].s_cond = cond; 4145785Skurt sstack[ssp].s_loading = loading; 4155785Skurt loading = 0; 4161519Skas cond = CANY; 4171219Skas input = fi; 4181219Skas sourcing++; 4191219Skas return(0); 4201219Skas } 4211219Skas 4221219Skas /* 4231219Skas * Source a file, but do nothing if the file cannot be opened. 4241219Skas */ 4251219Skas 4261219Skas source1(name) 4271219Skas char name[]; 4281219Skas { 4291219Skas register int f; 4301219Skas 4311219Skas if ((f = open(name, 0)) < 0) 4321219Skas return(0); 4331219Skas close(f); 4341219Skas source(name); 4351219Skas } 4361219Skas 4371219Skas /* 4381219Skas * Pop the current input back to the previous level. 4391219Skas * Update the "sourcing" flag as appropriate. 4401219Skas */ 4411219Skas 4421219Skas unstack() 4431219Skas { 4441219Skas if (ssp < 0) { 4451219Skas printf("\"Source\" stack over-pop.\n"); 4461219Skas sourcing = 0; 4471219Skas return(1); 4481219Skas } 4491219Skas fclose(input); 4501519Skas if (cond != CANY) 4511519Skas printf("Unmatched \"if\"\n"); 4521519Skas cond = sstack[ssp].s_cond; 4535785Skurt loading = sstack[ssp].s_loading; 4541519Skas input = sstack[ssp--].s_file; 4551219Skas if (ssp < 0) 4565785Skurt sourcing = loading; 4571219Skas return(0); 4581219Skas } 4591219Skas 4601219Skas /* 4611219Skas * Touch the indicated file. 4621219Skas * This is nifty for the shell. 4631219Skas * If we have the utime() system call, this is better served 4641219Skas * by using that, since it will work for empty files. 4651219Skas * On non-utime systems, we must sleep a second, then read. 4661219Skas */ 4671219Skas 4681219Skas alter(name) 4691219Skas char name[]; 4701219Skas { 4711219Skas #ifdef UTIME 4721219Skas struct stat statb; 4731219Skas long time(); 4741219Skas time_t time_p[2]; 4751219Skas #else 4761219Skas register int pid, f; 4771219Skas char w; 4781219Skas #endif UTIME 4791219Skas 4801219Skas #ifdef UTIME 4811219Skas if (stat(name, &statb) < 0) 4821219Skas return; 4831219Skas time_p[0] = time((long *) 0) + 1; 4841219Skas time_p[1] = statb.st_mtime; 4851219Skas utime(name, time_p); 4861219Skas #else 4871219Skas sleep(1); 4881219Skas if ((f = open(name, 0)) < 0) 4894389Skurt return; 4901219Skas read(f, &w, 1); 4911219Skas exit(0); 4921219Skas #endif 4931219Skas } 4941219Skas 4951219Skas /* 4961219Skas * Examine the passed line buffer and 4971219Skas * return true if it is all blanks and tabs. 4981219Skas */ 4991219Skas 5001219Skas blankline(linebuf) 5011219Skas char linebuf[]; 5021219Skas { 5031219Skas register char *cp; 5041219Skas 5051219Skas for (cp = linebuf; *cp; cp++) 506*18661Sserge if (*cp != ' ' && *cp != '\t') 5071219Skas return(0); 5081219Skas return(1); 5091219Skas } 5101219Skas 5111219Skas /* 5123195Skas * Get sender's name from this message. If the message has 5133195Skas * a bunch of arpanet stuff in it, we may have to skin the name 5143195Skas * before returning it. 5153195Skas */ 5163195Skas char * 5173195Skas nameof(mp, reptype) 5183195Skas register struct message *mp; 5193195Skas { 5205237Skurt register char *cp, *cp2; 5213195Skas 5225237Skurt cp = skin(name1(mp, reptype)); 5235237Skurt if (reptype != 0 || charcount(cp, '!') < 2) 5245237Skurt return(cp); 5255237Skurt cp2 = rindex(cp, '!'); 5265237Skurt cp2--; 5275237Skurt while (cp2 > cp && *cp2 != '!') 5285237Skurt cp2--; 5295237Skurt if (*cp2 == '!') 5305237Skurt return(cp2 + 1); 5315237Skurt return(cp); 5323195Skas } 5333195Skas 5343195Skas /* 5353195Skas * Skin an arpa net address according to the RFC 733 interpretation 5363195Skas * of "host-phrase." 5373195Skas */ 5383195Skas char * 5393195Skas skin(name) 5403195Skas char *name; 5413195Skas { 5423195Skas register int c; 5433195Skas register char *cp, *cp2; 5443195Skas int gotlt, lastsp; 5453195Skas char nbuf[BUFSIZ]; 546*18661Sserge int nesting; 5473195Skas 5483195Skas if (name == NOSTR) 5493195Skas return(NOSTR); 55012819Sleres if (index(name, '(') == NOSTR && index(name, '<') == NOSTR 55112819Sleres && index(name, ' ') == NOSTR) 5523195Skas return(name); 5533195Skas gotlt = 0; 5543195Skas lastsp = 0; 55512819Sleres for (cp = name, cp2 = nbuf; c = *cp++; ) { 5563195Skas switch (c) { 5573195Skas case '(': 558*18661Sserge nesting = 1; 559*18661Sserge while (*cp != '\0') { 560*18661Sserge switch (*cp++) { 561*18661Sserge case '(': 562*18661Sserge nesting++; 563*18661Sserge break; 564*18661Sserge 565*18661Sserge case ')': 566*18661Sserge --nesting; 567*18661Sserge break; 568*18661Sserge } 569*18661Sserge 570*18661Sserge if (nesting <= 0) 571*18661Sserge break; 572*18661Sserge } 57312819Sleres lastsp = 0; 5743195Skas break; 5753195Skas 5763195Skas case ' ': 57712819Sleres if (cp[0] == 'a' && cp[1] == 't' && cp[2] == ' ') 57812819Sleres cp += 3, *cp2++ = '@'; 57912819Sleres else 58012819Sleres if (cp[0] == '@' && cp[1] == ' ') 58112819Sleres cp += 2, *cp2++ = '@'; 58212819Sleres else 58312819Sleres lastsp = 1; 5843195Skas break; 5853195Skas 5863195Skas case '<': 5873195Skas cp2 = nbuf; 5883195Skas gotlt++; 5893195Skas lastsp = 0; 5903195Skas break; 5913195Skas 5923195Skas case '>': 5933195Skas if (gotlt) 5943195Skas goto done; 5953195Skas 5963195Skas /* Fall into . . . */ 5973195Skas 5983195Skas default: 5993195Skas if (lastsp) { 6003195Skas lastsp = 0; 6013195Skas *cp2++ = ' '; 6023195Skas } 6033195Skas *cp2++ = c; 6043195Skas break; 6053195Skas } 6063195Skas } 6073195Skas done: 6083195Skas *cp2 = 0; 6093195Skas 6103195Skas return(savestr(nbuf)); 6113195Skas } 6123195Skas 6133195Skas /* 6141219Skas * Fetch the sender's name from the passed message. 6153195Skas * Reptype can be 6163195Skas * 0 -- get sender's name for display purposes 6173195Skas * 1 -- get sender's name for reply 6183195Skas * 2 -- get sender's name for Reply 6191219Skas */ 6201219Skas 6211219Skas char * 6223195Skas name1(mp, reptype) 6231219Skas register struct message *mp; 6241219Skas { 6251219Skas char namebuf[LINESIZE]; 6261219Skas char linebuf[LINESIZE]; 6271219Skas register char *cp, *cp2; 6281219Skas register FILE *ibuf; 6291219Skas int first = 1; 6301219Skas 6313195Skas if ((cp = hfield("from", mp)) != NOSTR) 6323195Skas return(cp); 6333195Skas if (reptype == 0 && (cp = hfield("sender", mp)) != NOSTR) 6343195Skas return(cp); 6351219Skas ibuf = setinput(mp); 6361219Skas copy("", namebuf); 6371219Skas if (readline(ibuf, linebuf) <= 0) 6381219Skas return(savestr(namebuf)); 6391219Skas newname: 6401219Skas for (cp = linebuf; *cp != ' '; cp++) 6411219Skas ; 6421219Skas while (any(*cp, " \t")) 6431219Skas cp++; 6441219Skas for (cp2 = &namebuf[strlen(namebuf)]; *cp && !any(*cp, " \t") && 6451219Skas cp2-namebuf < LINESIZE-1; *cp2++ = *cp++) 6461219Skas ; 6471219Skas *cp2 = '\0'; 6481219Skas if (readline(ibuf, linebuf) <= 0) 6491219Skas return(savestr(namebuf)); 6501219Skas if ((cp = index(linebuf, 'F')) == NULL) 6511219Skas return(savestr(namebuf)); 6521219Skas if (strncmp(cp, "From", 4) != 0) 6531219Skas return(savestr(namebuf)); 6541219Skas while ((cp = index(cp, 'r')) != NULL) { 6551219Skas if (strncmp(cp, "remote", 6) == 0) { 6561219Skas if ((cp = index(cp, 'f')) == NULL) 6571219Skas break; 6581219Skas if (strncmp(cp, "from", 4) != 0) 6591219Skas break; 6601219Skas if ((cp = index(cp, ' ')) == NULL) 6611219Skas break; 6621219Skas cp++; 6631219Skas if (first) { 6641219Skas copy(cp, namebuf); 6651219Skas first = 0; 6661219Skas } else 6671219Skas strcpy(rindex(namebuf, '!')+1, cp); 6681219Skas strcat(namebuf, "!"); 6691219Skas goto newname; 6701219Skas } 6711219Skas cp++; 6721219Skas } 6731219Skas return(savestr(namebuf)); 6741219Skas } 6751219Skas 6761219Skas /* 6775237Skurt * Count the occurances of c in str 6785237Skurt */ 6795237Skurt charcount(str, c) 6805237Skurt char *str; 6815237Skurt { 6825237Skurt register char *cp; 6835237Skurt register int i; 6845237Skurt 6855237Skurt for (i = 0, cp = str; *cp; cp++) 6865237Skurt if (*cp == c) 6875237Skurt i++; 6885237Skurt return(i); 6895237Skurt } 6905237Skurt 6915237Skurt /* 6921219Skas * Find the rightmost pointer to an instance of the 6931219Skas * character in the string and return it. 6941219Skas */ 6951219Skas char * 6961219Skas rindex(str, c) 6971219Skas char str[]; 6981219Skas register int c; 6991219Skas { 7001219Skas register char *cp, *cp2; 7011219Skas 7021219Skas for (cp = str, cp2 = NOSTR; *cp; cp++) 7031219Skas if (c == *cp) 7041219Skas cp2 = cp; 7051219Skas return(cp2); 7061219Skas } 7071219Skas 7081219Skas /* 7091219Skas * See if the string is a number. 7101219Skas */ 7111219Skas 7121219Skas numeric(str) 7131219Skas char str[]; 7141219Skas { 7151219Skas register char *cp = str; 7161219Skas 7171219Skas while (*cp) 7181219Skas if (!isdigit(*cp++)) 7191219Skas return(0); 7201219Skas return(1); 7211219Skas } 7221219Skas 7231219Skas /* 7241219Skas * Are any of the characters in the two strings the same? 7251219Skas */ 7261219Skas 7271219Skas anyof(s1, s2) 7281219Skas register char *s1, *s2; 7291219Skas { 7301219Skas register int c; 7311219Skas 7321219Skas while (c = *s1++) 7331219Skas if (any(c, s2)) 7341219Skas return(1); 7351219Skas return(0); 7361219Skas } 7371219Skas 7381219Skas /* 7391219Skas * Determine the leftmost index of the character 7401219Skas * in the string. 7411219Skas */ 7421219Skas 7431219Skas char * 7441219Skas index(str, ch) 7451219Skas char *str; 7461219Skas { 7471219Skas register char *cp; 7481219Skas register int c; 7491219Skas 7501219Skas for (c = ch, cp = str; *cp; cp++) 7511219Skas if (*cp == c) 7521219Skas return(cp); 7531219Skas return(NOSTR); 7541219Skas } 7551219Skas 7561219Skas /* 7571219Skas * String compare two strings of bounded length. 7581219Skas */ 7591219Skas 7601219Skas strncmp(as1, as2, an) 7611219Skas char *as1, *as2; 7621219Skas { 7631219Skas register char *s1, *s2; 7641219Skas register int n; 7651219Skas 7661219Skas s1 = as1; 7671219Skas s2 = as2; 7681219Skas n = an; 7691219Skas while (--n >= 0 && *s1 == *s2++) 7701219Skas if (*s1++ == '\0') 7711219Skas return(0); 7721219Skas return(n<0 ? 0 : *s1 - *--s2); 7731219Skas } 7741219Skas 7757538Skurt /* 7767571Skurt * See if the given header field is supposed to be ignored. 7777571Skurt */ 7787571Skurt isign(field) 7797571Skurt char *field; 7807571Skurt { 7817571Skurt char realfld[BUFSIZ]; 7827571Skurt 783*18661Sserge /* 784*18661Sserge * Lower-case the string, so that "Status" and "status" 785*18661Sserge * will hash to the same place. 786*18661Sserge */ 7877571Skurt istrcpy(realfld, field); 788*18661Sserge 789*18661Sserge if (nretained > 0) 790*18661Sserge return (!member(realfld, retain)); 791*18661Sserge else 792*18661Sserge return (member(realfld, ignore)); 7937571Skurt } 794*18661Sserge 795*18661Sserge member(realfield, table) 796*18661Sserge register char *realfield; 797*18661Sserge register struct ignore **table; 798*18661Sserge { 799*18661Sserge register struct ignore *igp; 800*18661Sserge 801*18661Sserge for (igp = table[hash(realfield)]; igp != 0; igp = igp->i_link) 802*18661Sserge if (equal(igp->i_field, realfield)) 803*18661Sserge return (1); 804*18661Sserge 805*18661Sserge return (0); 806*18661Sserge } 807