122444Sdist /* 222444Sdist * Copyright (c) 1980 Regents of the University of California. 322444Sdist * All rights reserved. The Berkeley software License Agreement 422444Sdist * specifies the terms and conditions for redistribution. 522444Sdist */ 622444Sdist 714522Ssam #ifndef lint 8*25912Smckusick static char *sccsid = "@(#)aux.c 5.4 (Berkeley) 01/13/86"; 922444Sdist #endif not lint 101219Skas 111219Skas #include "rcv.h" 121219Skas #include <sys/stat.h> 131219Skas #include <ctype.h> 141219Skas 151219Skas /* 161219Skas * Mail -- a mail program 171219Skas * 181219Skas * Auxiliary functions. 191219Skas */ 201219Skas 211219Skas /* 221219Skas * Return a pointer to a dynamic copy of the argument. 231219Skas */ 241219Skas 251219Skas char * 261219Skas savestr(str) 271219Skas char *str; 281219Skas { 291219Skas register char *cp, *cp2, *top; 301219Skas 311219Skas for (cp = str; *cp; cp++) 321219Skas ; 331219Skas top = salloc(cp-str + 1); 341219Skas if (top == NOSTR) 351219Skas return(NOSTR); 361219Skas for (cp = str, cp2 = top; *cp; cp++) 371219Skas *cp2++ = *cp; 381219Skas *cp2 = 0; 391219Skas return(top); 401219Skas } 411219Skas 421219Skas /* 431219Skas * Copy the name from the passed header line into the passed 441219Skas * name buffer. Null pad the name buffer. 451219Skas */ 461219Skas 471219Skas copyname(linebuf, nbuf) 481219Skas char *linebuf, *nbuf; 491219Skas { 501219Skas register char *cp, *cp2; 511219Skas 521219Skas for (cp = linebuf + 5, cp2 = nbuf; *cp != ' ' && cp2-nbuf < 8; cp++) 531219Skas *cp2++ = *cp; 541219Skas while (cp2-nbuf < 8) 551219Skas *cp2++ = 0; 561219Skas } 571219Skas 581219Skas /* 591219Skas * Announce a fatal error and die. 601219Skas */ 611219Skas 621219Skas panic(str) 631219Skas char *str; 641219Skas { 651219Skas prs("panic: "); 661219Skas prs(str); 671219Skas prs("\n"); 681219Skas exit(1); 691219Skas } 701219Skas 711219Skas /* 721219Skas * Catch stdio errors and report them more nicely. 731219Skas */ 741219Skas 751219Skas _error(str) 761219Skas char *str; 771219Skas { 781219Skas prs("Stdio Error: "); 791219Skas prs(str); 801219Skas prs("\n"); 811219Skas abort(); 821219Skas } 831219Skas 841219Skas /* 851219Skas * Print a string on diagnostic output. 861219Skas */ 871219Skas 881219Skas prs(str) 891219Skas char *str; 901219Skas { 911219Skas register char *s; 921219Skas 931219Skas for (s = str; *s; s++) 941219Skas ; 951219Skas write(2, str, s-str); 961219Skas } 971219Skas 981219Skas /* 991219Skas * Touch the named message by setting its MTOUCH flag. 1001219Skas * Touched messages have the effect of not being sent 1011219Skas * back to the system mailbox on exit. 1021219Skas */ 1031219Skas 1041219Skas touch(mesg) 1051219Skas { 1061479Skas register struct message *mp; 1071479Skas 1081479Skas if (mesg < 1 || mesg > msgCount) 1091479Skas return; 1101479Skas mp = &message[mesg-1]; 1111479Skas mp->m_flag |= MTOUCH; 1121479Skas if ((mp->m_flag & MREAD) == 0) 1131479Skas mp->m_flag |= MREAD|MSTATUS; 1141219Skas } 1151219Skas 1161219Skas /* 1171219Skas * Test to see if the passed file name is a directory. 1181219Skas * Return true if it is. 1191219Skas */ 1201219Skas 1211219Skas isdir(name) 1221219Skas char name[]; 1231219Skas { 1241219Skas struct stat sbuf; 1251219Skas 1261219Skas if (stat(name, &sbuf) < 0) 1271219Skas return(0); 1281219Skas return((sbuf.st_mode & S_IFMT) == S_IFDIR); 1291219Skas } 1301219Skas 1311219Skas /* 1321219Skas * Count the number of arguments in the given string raw list. 1331219Skas */ 1341219Skas 1351219Skas argcount(argv) 1361219Skas char **argv; 1371219Skas { 1381219Skas register char **ap; 1391219Skas 1401219Skas for (ap = argv; *ap != NOSTR; ap++) 1411219Skas ; 1421219Skas return(ap-argv); 1431219Skas } 1441219Skas 1451219Skas /* 1461219Skas * Given a file address, determine the 1471219Skas * block number it represents. 1481219Skas */ 1491219Skas 1501219Skas blockof(off) 1511219Skas off_t off; 1521219Skas { 1531219Skas off_t a; 1541219Skas 1551219Skas a = off >> 9; 1561219Skas a &= 077777; 1571219Skas return((int) a); 1581219Skas } 1591219Skas 1601219Skas /* 1611219Skas * Take a file address, and determine 1621219Skas * its offset in the current block. 1631219Skas */ 1641219Skas 1651219Skas offsetof(off) 1661219Skas off_t off; 1671219Skas { 1681219Skas off_t a; 1691219Skas 1701219Skas a = off & 0777; 1711219Skas return((int) a); 1721219Skas } 1731219Skas 1741219Skas /* 1751219Skas * Return the desired header line from the passed message 1761219Skas * pointer (or NOSTR if the desired header field is not available). 1771219Skas */ 1781219Skas 1791219Skas char * 1801219Skas hfield(field, mp) 1811219Skas char field[]; 1821219Skas struct message *mp; 1831219Skas { 1841219Skas register FILE *ibuf; 1851219Skas char linebuf[LINESIZE]; 1861219Skas register int lc; 1871219Skas 1881219Skas ibuf = setinput(mp); 1891219Skas if ((lc = mp->m_lines) <= 0) 1901219Skas return(NOSTR); 1911219Skas if (readline(ibuf, linebuf) < 0) 1921219Skas return(NOSTR); 1931219Skas lc--; 1941219Skas do { 1951219Skas lc = gethfield(ibuf, linebuf, lc); 1961219Skas if (lc == -1) 1971219Skas return(NOSTR); 1981219Skas if (ishfield(linebuf, field)) 1991219Skas return(savestr(hcontents(linebuf))); 2001219Skas } while (lc > 0); 2011219Skas return(NOSTR); 2021219Skas } 2031219Skas 2041219Skas /* 2051219Skas * Return the next header field found in the given message. 2061219Skas * Return > 0 if something found, <= 0 elsewise. 2071219Skas * Must deal with \ continuations & other such fraud. 2081219Skas */ 2091219Skas 2101219Skas gethfield(f, linebuf, rem) 2111219Skas register FILE *f; 2121219Skas char linebuf[]; 2131219Skas register int rem; 2141219Skas { 2151219Skas char line2[LINESIZE]; 2161219Skas long loc; 2171219Skas register char *cp, *cp2; 2181219Skas register int c; 2191219Skas 2201219Skas 2211219Skas for (;;) { 2221219Skas if (rem <= 0) 2231219Skas return(-1); 2241219Skas if (readline(f, linebuf) < 0) 2251219Skas return(-1); 2261219Skas rem--; 2271219Skas if (strlen(linebuf) == 0) 2281219Skas return(-1); 2291219Skas if (isspace(linebuf[0])) 2301219Skas continue; 2311219Skas if (linebuf[0] == '>') 2321219Skas continue; 2331219Skas cp = index(linebuf, ':'); 2341219Skas if (cp == NOSTR) 2351219Skas continue; 2361219Skas for (cp2 = linebuf; cp2 < cp; cp2++) 2371219Skas if (isdigit(*cp2)) 2381219Skas continue; 2391219Skas 2401219Skas /* 2411219Skas * I guess we got a headline. 2421219Skas * Handle wraparounding 2431219Skas */ 2441219Skas 2451219Skas for (;;) { 2461219Skas if (rem <= 0) 2471219Skas break; 2481219Skas #ifdef CANTELL 2491219Skas loc = ftell(f); 2501219Skas if (readline(f, line2) < 0) 2511219Skas break; 2521219Skas rem--; 2531219Skas if (!isspace(line2[0])) { 2541219Skas fseek(f, loc, 0); 2551219Skas rem++; 2561219Skas break; 2571219Skas } 2581219Skas #else 2591219Skas c = getc(f); 2601219Skas ungetc(c, f); 2611219Skas if (!isspace(c) || c == '\n') 2621219Skas break; 2631219Skas if (readline(f, line2) < 0) 2641219Skas break; 2651219Skas rem--; 2661219Skas #endif 2671219Skas cp2 = line2; 2681219Skas for (cp2 = line2; *cp2 != 0 && isspace(*cp2); cp2++) 2691219Skas ; 2701219Skas if (strlen(linebuf) + strlen(cp2) >= LINESIZE-2) 2711219Skas break; 2721219Skas cp = &linebuf[strlen(linebuf)]; 2731219Skas while (cp > linebuf && 2741219Skas (isspace(cp[-1]) || cp[-1] == '\\')) 2751219Skas cp--; 2761219Skas *cp++ = ' '; 2771219Skas for (cp2 = line2; *cp2 != 0 && isspace(*cp2); cp2++) 2781219Skas ; 2791219Skas strcpy(cp, cp2); 2801219Skas } 2811219Skas if ((c = strlen(linebuf)) > 0) { 2821219Skas cp = &linebuf[c-1]; 2831219Skas while (cp > linebuf && isspace(*cp)) 2841219Skas cp--; 2851219Skas *++cp = 0; 2861219Skas } 2871219Skas return(rem); 2881219Skas } 2891219Skas /* NOTREACHED */ 2901219Skas } 2911219Skas 2921219Skas /* 2931219Skas * Check whether the passed line is a header line of 2941219Skas * the desired breed. 2951219Skas */ 2961219Skas 2971219Skas ishfield(linebuf, field) 2981219Skas char linebuf[], field[]; 2991219Skas { 3001219Skas register char *cp; 3011219Skas register int c; 3021219Skas 3031219Skas if ((cp = index(linebuf, ':')) == NOSTR) 3041219Skas return(0); 3051219Skas if (cp == linebuf) 3061219Skas return(0); 3071219Skas cp--; 3081219Skas while (cp > linebuf && isspace(*cp)) 3091219Skas cp--; 3101219Skas c = *++cp; 3111219Skas *cp = 0; 3121219Skas if (icequal(linebuf ,field)) { 3131219Skas *cp = c; 3141219Skas return(1); 3151219Skas } 3161219Skas *cp = c; 3171219Skas return(0); 3181219Skas } 3191219Skas 3201219Skas /* 3211219Skas * Extract the non label information from the given header field 3221219Skas * and return it. 3231219Skas */ 3241219Skas 3251219Skas char * 3261219Skas hcontents(hfield) 3271219Skas char hfield[]; 3281219Skas { 3291219Skas register char *cp; 3301219Skas 3311219Skas if ((cp = index(hfield, ':')) == NOSTR) 3321219Skas return(NOSTR); 3331219Skas cp++; 3341219Skas while (*cp && isspace(*cp)) 3351219Skas cp++; 3361219Skas return(cp); 3371219Skas } 3381219Skas 3391219Skas /* 3401219Skas * Compare two strings, ignoring case. 3411219Skas */ 3421219Skas 3431219Skas icequal(s1, s2) 3441219Skas register char *s1, *s2; 3451219Skas { 3461219Skas 3471219Skas while (raise(*s1++) == raise(*s2)) 3481219Skas if (*s2++ == 0) 3491219Skas return(1); 3501219Skas return(0); 3511219Skas } 3521219Skas 3531219Skas /* 3547571Skurt * Copy a string, lowercasing it as we go. 3557571Skurt */ 3567571Skurt istrcpy(dest, src) 3577571Skurt char *dest, *src; 3587571Skurt { 3597571Skurt register char *cp, *cp2; 3607571Skurt 3617571Skurt cp2 = dest; 3627571Skurt cp = src; 3637571Skurt do { 3647571Skurt *cp2++ = little(*cp); 3657571Skurt } while (*cp++ != 0); 3667571Skurt } 3677571Skurt 3687571Skurt /* 3691219Skas * The following code deals with input stacking to do source 3701219Skas * commands. All but the current file pointer are saved on 3711219Skas * the stack. 3721219Skas */ 3731219Skas 3741219Skas static int ssp = -1; /* Top of file stack */ 3751519Skas struct sstack { 3761519Skas FILE *s_file; /* File we were in. */ 3771519Skas int s_cond; /* Saved state of conditionals */ 3785785Skurt int s_loading; /* Loading .mailrc, etc. */ 37918661Sserge } sstack[NOFILE]; 3801219Skas 3811219Skas /* 3821219Skas * Pushdown current input file and switch to a new one. 3831219Skas * Set the global flag "sourcing" so that others will realize 3841219Skas * that they are no longer reading from a tty (in all probability). 3851219Skas */ 3861219Skas 3871219Skas source(name) 3881219Skas char name[]; 3891219Skas { 3901219Skas register FILE *fi; 3913914Skurt register char *cp; 3921219Skas 3933914Skurt if ((cp = expand(name)) == NOSTR) 3941219Skas return(1); 3953914Skurt if ((fi = fopen(cp, "r")) == NULL) { 3963914Skurt perror(cp); 3973914Skurt return(1); 3981219Skas } 39918661Sserge if (ssp >= NOFILE - 2) { 4001219Skas printf("Too much \"sourcing\" going on.\n"); 4011219Skas fclose(fi); 4021219Skas return(1); 4031219Skas } 4041519Skas sstack[++ssp].s_file = input; 4051519Skas sstack[ssp].s_cond = cond; 4065785Skurt sstack[ssp].s_loading = loading; 4075785Skurt loading = 0; 4081519Skas cond = CANY; 4091219Skas input = fi; 4101219Skas sourcing++; 4111219Skas return(0); 4121219Skas } 4131219Skas 4141219Skas /* 4151219Skas * Source a file, but do nothing if the file cannot be opened. 4161219Skas */ 4171219Skas 4181219Skas source1(name) 4191219Skas char name[]; 4201219Skas { 4211219Skas register int f; 4221219Skas 4231219Skas if ((f = open(name, 0)) < 0) 4241219Skas return(0); 4251219Skas close(f); 4261219Skas source(name); 4271219Skas } 4281219Skas 4291219Skas /* 4301219Skas * Pop the current input back to the previous level. 4311219Skas * Update the "sourcing" flag as appropriate. 4321219Skas */ 4331219Skas 4341219Skas unstack() 4351219Skas { 4361219Skas if (ssp < 0) { 4371219Skas printf("\"Source\" stack over-pop.\n"); 4381219Skas sourcing = 0; 4391219Skas return(1); 4401219Skas } 4411219Skas fclose(input); 4421519Skas if (cond != CANY) 4431519Skas printf("Unmatched \"if\"\n"); 4441519Skas cond = sstack[ssp].s_cond; 4455785Skurt loading = sstack[ssp].s_loading; 4461519Skas input = sstack[ssp--].s_file; 4471219Skas if (ssp < 0) 4485785Skurt sourcing = loading; 4491219Skas return(0); 4501219Skas } 4511219Skas 4521219Skas /* 4531219Skas * Touch the indicated file. 4541219Skas * This is nifty for the shell. 4551219Skas * If we have the utime() system call, this is better served 4561219Skas * by using that, since it will work for empty files. 4571219Skas * On non-utime systems, we must sleep a second, then read. 4581219Skas */ 4591219Skas 4601219Skas alter(name) 4611219Skas char name[]; 4621219Skas { 4631219Skas #ifdef UTIME 4641219Skas struct stat statb; 4651219Skas long time(); 4661219Skas time_t time_p[2]; 4671219Skas #else 4681219Skas register int pid, f; 4691219Skas char w; 4701219Skas #endif UTIME 4711219Skas 4721219Skas #ifdef UTIME 4731219Skas if (stat(name, &statb) < 0) 4741219Skas return; 4751219Skas time_p[0] = time((long *) 0) + 1; 4761219Skas time_p[1] = statb.st_mtime; 4771219Skas utime(name, time_p); 4781219Skas #else 4791219Skas sleep(1); 4801219Skas if ((f = open(name, 0)) < 0) 4814389Skurt return; 4821219Skas read(f, &w, 1); 4831219Skas exit(0); 4841219Skas #endif 4851219Skas } 4861219Skas 4871219Skas /* 4881219Skas * Examine the passed line buffer and 4891219Skas * return true if it is all blanks and tabs. 4901219Skas */ 4911219Skas 4921219Skas blankline(linebuf) 4931219Skas char linebuf[]; 4941219Skas { 4951219Skas register char *cp; 4961219Skas 4971219Skas for (cp = linebuf; *cp; cp++) 49818661Sserge if (*cp != ' ' && *cp != '\t') 4991219Skas return(0); 5001219Skas return(1); 5011219Skas } 5021219Skas 5031219Skas /* 5043195Skas * Get sender's name from this message. If the message has 5053195Skas * a bunch of arpanet stuff in it, we may have to skin the name 5063195Skas * before returning it. 5073195Skas */ 5083195Skas char * 5093195Skas nameof(mp, reptype) 5103195Skas register struct message *mp; 5113195Skas { 5125237Skurt register char *cp, *cp2; 5133195Skas 5145237Skurt cp = skin(name1(mp, reptype)); 5155237Skurt if (reptype != 0 || charcount(cp, '!') < 2) 5165237Skurt return(cp); 5175237Skurt cp2 = rindex(cp, '!'); 5185237Skurt cp2--; 5195237Skurt while (cp2 > cp && *cp2 != '!') 5205237Skurt cp2--; 5215237Skurt if (*cp2 == '!') 5225237Skurt return(cp2 + 1); 5235237Skurt return(cp); 5243195Skas } 5253195Skas 5263195Skas /* 527*25912Smckusick * Skin an arpa net address according to the RFC 822 interpretation 5283195Skas * of "host-phrase." 5293195Skas */ 5303195Skas char * 5313195Skas skin(name) 5323195Skas char *name; 5333195Skas { 5343195Skas register int c; 5353195Skas register char *cp, *cp2; 536*25912Smckusick char *bufend; 5373195Skas int gotlt, lastsp; 5383195Skas char nbuf[BUFSIZ]; 53918661Sserge int nesting; 5403195Skas 5413195Skas if (name == NOSTR) 5423195Skas return(NOSTR); 54312819Sleres if (index(name, '(') == NOSTR && index(name, '<') == NOSTR 54412819Sleres && index(name, ' ') == NOSTR) 5453195Skas return(name); 5463195Skas gotlt = 0; 5473195Skas lastsp = 0; 548*25912Smckusick bufend = nbuf; 549*25912Smckusick for (cp = name, cp2 = bufend; c = *cp++; ) { 5503195Skas switch (c) { 5513195Skas case '(': 552*25912Smckusick /* 553*25912Smckusick * Start of a "comment". 554*25912Smckusick * Ignore it. 555*25912Smckusick */ 55618661Sserge nesting = 1; 557*25912Smckusick while ((c = *cp) != 0) { 558*25912Smckusick cp++; 559*25912Smckusick switch (c) { 560*25912Smckusick case '\\': 561*25912Smckusick if (*cp == 0) 562*25912Smckusick goto outcm; 563*25912Smckusick cp++; 564*25912Smckusick break; 56518661Sserge case '(': 56618661Sserge nesting++; 56718661Sserge break; 56818661Sserge 56918661Sserge case ')': 57018661Sserge --nesting; 57118661Sserge break; 57218661Sserge } 57318661Sserge 57418661Sserge if (nesting <= 0) 57518661Sserge break; 57618661Sserge } 577*25912Smckusick outcm: 57812819Sleres lastsp = 0; 5793195Skas break; 5803195Skas 581*25912Smckusick case '"': 582*25912Smckusick /* 583*25912Smckusick * Start of a "quoted-string". 584*25912Smckusick * Copy it in its entirety. 585*25912Smckusick */ 586*25912Smckusick while ((c = *cp) != 0) { 587*25912Smckusick cp++; 588*25912Smckusick switch (c) { 589*25912Smckusick case '\\': 590*25912Smckusick if ((c = *cp) == 0) 591*25912Smckusick goto outqs; 592*25912Smckusick cp++; 593*25912Smckusick break; 594*25912Smckusick case '"': 595*25912Smckusick goto outqs; 596*25912Smckusick } 597*25912Smckusick *cp2++ = c; 598*25912Smckusick } 599*25912Smckusick outqs: 600*25912Smckusick lastsp = 0; 601*25912Smckusick break; 602*25912Smckusick 6033195Skas case ' ': 60412819Sleres if (cp[0] == 'a' && cp[1] == 't' && cp[2] == ' ') 60512819Sleres cp += 3, *cp2++ = '@'; 60612819Sleres else 60712819Sleres if (cp[0] == '@' && cp[1] == ' ') 60812819Sleres cp += 2, *cp2++ = '@'; 60912819Sleres else 61012819Sleres lastsp = 1; 6113195Skas break; 6123195Skas 6133195Skas case '<': 614*25912Smckusick cp2 = bufend; 6153195Skas gotlt++; 6163195Skas lastsp = 0; 6173195Skas break; 6183195Skas 6193195Skas case '>': 620*25912Smckusick if (gotlt) { 621*25912Smckusick gotlt = 0; 622*25912Smckusick while (*cp != ',' && *cp != 0) 623*25912Smckusick cp++; 624*25912Smckusick if (*cp == 0 ) 625*25912Smckusick goto done; 626*25912Smckusick *cp2++ = ','; 627*25912Smckusick *cp2++ = ' '; 628*25912Smckusick bufend = cp2; 629*25912Smckusick break; 630*25912Smckusick } 6313195Skas 6323195Skas /* Fall into . . . */ 6333195Skas 6343195Skas default: 6353195Skas if (lastsp) { 6363195Skas lastsp = 0; 6373195Skas *cp2++ = ' '; 6383195Skas } 6393195Skas *cp2++ = c; 6403195Skas break; 6413195Skas } 6423195Skas } 6433195Skas done: 6443195Skas *cp2 = 0; 6453195Skas 6463195Skas return(savestr(nbuf)); 6473195Skas } 6483195Skas 6493195Skas /* 6501219Skas * Fetch the sender's name from the passed message. 6513195Skas * Reptype can be 6523195Skas * 0 -- get sender's name for display purposes 6533195Skas * 1 -- get sender's name for reply 6543195Skas * 2 -- get sender's name for Reply 6551219Skas */ 6561219Skas 6571219Skas char * 6583195Skas name1(mp, reptype) 6591219Skas register struct message *mp; 6601219Skas { 6611219Skas char namebuf[LINESIZE]; 6621219Skas char linebuf[LINESIZE]; 6631219Skas register char *cp, *cp2; 6641219Skas register FILE *ibuf; 6651219Skas int first = 1; 6661219Skas 6673195Skas if ((cp = hfield("from", mp)) != NOSTR) 6683195Skas return(cp); 6693195Skas if (reptype == 0 && (cp = hfield("sender", mp)) != NOSTR) 6703195Skas return(cp); 6711219Skas ibuf = setinput(mp); 6721219Skas copy("", namebuf); 6731219Skas if (readline(ibuf, linebuf) <= 0) 6741219Skas return(savestr(namebuf)); 6751219Skas newname: 6761219Skas for (cp = linebuf; *cp != ' '; cp++) 6771219Skas ; 6781219Skas while (any(*cp, " \t")) 6791219Skas cp++; 6801219Skas for (cp2 = &namebuf[strlen(namebuf)]; *cp && !any(*cp, " \t") && 6811219Skas cp2-namebuf < LINESIZE-1; *cp2++ = *cp++) 6821219Skas ; 6831219Skas *cp2 = '\0'; 6841219Skas if (readline(ibuf, linebuf) <= 0) 6851219Skas return(savestr(namebuf)); 6861219Skas if ((cp = index(linebuf, 'F')) == NULL) 6871219Skas return(savestr(namebuf)); 6881219Skas if (strncmp(cp, "From", 4) != 0) 6891219Skas return(savestr(namebuf)); 6901219Skas while ((cp = index(cp, 'r')) != NULL) { 6911219Skas if (strncmp(cp, "remote", 6) == 0) { 6921219Skas if ((cp = index(cp, 'f')) == NULL) 6931219Skas break; 6941219Skas if (strncmp(cp, "from", 4) != 0) 6951219Skas break; 6961219Skas if ((cp = index(cp, ' ')) == NULL) 6971219Skas break; 6981219Skas cp++; 6991219Skas if (first) { 7001219Skas copy(cp, namebuf); 7011219Skas first = 0; 7021219Skas } else 7031219Skas strcpy(rindex(namebuf, '!')+1, cp); 7041219Skas strcat(namebuf, "!"); 7051219Skas goto newname; 7061219Skas } 7071219Skas cp++; 7081219Skas } 7091219Skas return(savestr(namebuf)); 7101219Skas } 7111219Skas 7121219Skas /* 7135237Skurt * Count the occurances of c in str 7145237Skurt */ 7155237Skurt charcount(str, c) 7165237Skurt char *str; 7175237Skurt { 7185237Skurt register char *cp; 7195237Skurt register int i; 7205237Skurt 7215237Skurt for (i = 0, cp = str; *cp; cp++) 7225237Skurt if (*cp == c) 7235237Skurt i++; 7245237Skurt return(i); 7255237Skurt } 7265237Skurt 7275237Skurt /* 7281219Skas * Find the rightmost pointer to an instance of the 7291219Skas * character in the string and return it. 7301219Skas */ 7311219Skas char * 7321219Skas rindex(str, c) 7331219Skas char str[]; 7341219Skas register int c; 7351219Skas { 7361219Skas register char *cp, *cp2; 7371219Skas 7381219Skas for (cp = str, cp2 = NOSTR; *cp; cp++) 7391219Skas if (c == *cp) 7401219Skas cp2 = cp; 7411219Skas return(cp2); 7421219Skas } 7431219Skas 7441219Skas /* 7451219Skas * See if the string is a number. 7461219Skas */ 7471219Skas 7481219Skas numeric(str) 7491219Skas char str[]; 7501219Skas { 7511219Skas register char *cp = str; 7521219Skas 7531219Skas while (*cp) 7541219Skas if (!isdigit(*cp++)) 7551219Skas return(0); 7561219Skas return(1); 7571219Skas } 7581219Skas 7591219Skas /* 7601219Skas * Are any of the characters in the two strings the same? 7611219Skas */ 7621219Skas 7631219Skas anyof(s1, s2) 7641219Skas register char *s1, *s2; 7651219Skas { 7661219Skas register int c; 7671219Skas 7681219Skas while (c = *s1++) 7691219Skas if (any(c, s2)) 7701219Skas return(1); 7711219Skas return(0); 7721219Skas } 7731219Skas 7741219Skas /* 7751219Skas * Determine the leftmost index of the character 7761219Skas * in the string. 7771219Skas */ 7781219Skas 7791219Skas char * 7801219Skas index(str, ch) 7811219Skas char *str; 7821219Skas { 7831219Skas register char *cp; 7841219Skas register int c; 7851219Skas 7861219Skas for (c = ch, cp = str; *cp; cp++) 7871219Skas if (*cp == c) 7881219Skas return(cp); 7891219Skas return(NOSTR); 7901219Skas } 7911219Skas 7921219Skas /* 7937571Skurt * See if the given header field is supposed to be ignored. 7947571Skurt */ 7957571Skurt isign(field) 7967571Skurt char *field; 7977571Skurt { 7987571Skurt char realfld[BUFSIZ]; 7997571Skurt 80018661Sserge /* 80118661Sserge * Lower-case the string, so that "Status" and "status" 80218661Sserge * will hash to the same place. 80318661Sserge */ 8047571Skurt istrcpy(realfld, field); 80518661Sserge 80618661Sserge if (nretained > 0) 80718661Sserge return (!member(realfld, retain)); 80818661Sserge else 80918661Sserge return (member(realfld, ignore)); 8107571Skurt } 81118661Sserge 81218661Sserge member(realfield, table) 81318661Sserge register char *realfield; 81418661Sserge register struct ignore **table; 81518661Sserge { 81618661Sserge register struct ignore *igp; 81718661Sserge 81818661Sserge for (igp = table[hash(realfield)]; igp != 0; igp = igp->i_link) 81918661Sserge if (equal(igp->i_field, realfield)) 82018661Sserge return (1); 82118661Sserge 82218661Sserge return (0); 82318661Sserge } 824