util.c revision 18532
11590Srgrimes/* 21590Srgrimes * Copyright (c) 1980, 1993 31590Srgrimes * The Regents of the University of California. All rights reserved. 41590Srgrimes * 51590Srgrimes * Redistribution and use in source and binary forms, with or without 61590Srgrimes * modification, are permitted provided that the following conditions 71590Srgrimes * are met: 81590Srgrimes * 1. Redistributions of source code must retain the above copyright 91590Srgrimes * notice, this list of conditions and the following disclaimer. 101590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111590Srgrimes * notice, this list of conditions and the following disclaimer in the 121590Srgrimes * documentation and/or other materials provided with the distribution. 131590Srgrimes * 3. All advertising materials mentioning features or use of this software 141590Srgrimes * must display the following acknowledgement: 151590Srgrimes * This product includes software developed by the University of 161590Srgrimes * California, Berkeley and its contributors. 171590Srgrimes * 4. Neither the name of the University nor the names of its contributors 181590Srgrimes * may be used to endorse or promote products derived from this software 191590Srgrimes * without specific prior written permission. 201590Srgrimes * 211590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 221590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 231590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 241590Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 251590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 261590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 271590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 281590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 291590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 301590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 311590Srgrimes * SUCH DAMAGE. 321590Srgrimes */ 331590Srgrimes 341590Srgrimes#ifndef lint 351590Srgrimesstatic char sccsid[] = "@(#)aux.c 8.1 (Berkeley) 6/6/93"; 361590Srgrimes#endif /* not lint */ 371590Srgrimes 381590Srgrimes#include "rcv.h" 391590Srgrimes#include "extern.h" 401590Srgrimes 411590Srgrimes/* 421590Srgrimes * Mail -- a mail program 431590Srgrimes * 441590Srgrimes * Auxiliary functions. 451590Srgrimes */ 461590Srgrimes 471590Srgrimes/* 481590Srgrimes * Return a pointer to a dynamic copy of the argument. 491590Srgrimes */ 501590Srgrimeschar * 511590Srgrimessavestr(str) 521590Srgrimes char *str; 531590Srgrimes{ 541590Srgrimes char *new; 551590Srgrimes int size = strlen(str) + 1; 561590Srgrimes 571590Srgrimes if ((new = salloc(size)) != NOSTR) 581590Srgrimes bcopy(str, new, size); 591590Srgrimes return new; 601590Srgrimes} 611590Srgrimes 621590Srgrimes/* 631590Srgrimes * Make a copy of new argument incorporating old one. 641590Srgrimes */ 651590Srgrimeschar * 661590Srgrimessave2str(str, old) 671590Srgrimes char *str, *old; 681590Srgrimes{ 691590Srgrimes char *new; 701590Srgrimes int newsize = strlen(str) + 1; 711590Srgrimes int oldsize = old ? strlen(old) + 1 : 0; 721590Srgrimes 731590Srgrimes if ((new = salloc(newsize + oldsize)) != NOSTR) { 741590Srgrimes if (oldsize) { 751590Srgrimes bcopy(old, new, oldsize); 761590Srgrimes new[oldsize - 1] = ' '; 771590Srgrimes } 781590Srgrimes bcopy(str, new + oldsize, newsize); 791590Srgrimes } 801590Srgrimes return new; 811590Srgrimes} 821590Srgrimes 831590Srgrimes/* 841590Srgrimes * Announce a fatal error and die. 851590Srgrimes */ 861590Srgrimes#if __STDC__ 871590Srgrimes#include <stdarg.h> 881590Srgrimes#else 891590Srgrimes#include <varargs.h> 901590Srgrimes#endif 911590Srgrimes 921590Srgrimesvoid 931590Srgrimes#if __STDC__ 941590Srgrimespanic(const char *fmt, ...) 951590Srgrimes#else 961590Srgrimespanic(fmt, va_alist) 971590Srgrimes char *fmt; 981590Srgrimes va_dcl 991590Srgrimes#endif 1001590Srgrimes{ 1011590Srgrimes va_list ap; 1021590Srgrimes#if __STDC__ 1031590Srgrimes va_start(ap, fmt); 1041590Srgrimes#else 1051590Srgrimes va_start(ap); 1061590Srgrimes#endif 1071590Srgrimes (void)fprintf(stderr, "panic: "); 1081590Srgrimes vfprintf(stderr, fmt, ap); 1091590Srgrimes va_end(ap); 1101590Srgrimes (void)fprintf(stderr, "\n"); 1111590Srgrimes fflush(stderr); 1121590Srgrimes abort(); 1131590Srgrimes} 1141590Srgrimes 1151590Srgrimes/* 1161590Srgrimes * Touch the named message by setting its MTOUCH flag. 1171590Srgrimes * Touched messages have the effect of not being sent 1181590Srgrimes * back to the system mailbox on exit. 1191590Srgrimes */ 1201590Srgrimesvoid 1211590Srgrimestouch(mp) 1221590Srgrimes register struct message *mp; 1231590Srgrimes{ 1241590Srgrimes 1251590Srgrimes mp->m_flag |= MTOUCH; 1261590Srgrimes if ((mp->m_flag & MREAD) == 0) 1271590Srgrimes mp->m_flag |= MREAD|MSTATUS; 1281590Srgrimes} 1291590Srgrimes 1301590Srgrimes/* 1311590Srgrimes * Test to see if the passed file name is a directory. 1321590Srgrimes * Return true if it is. 1331590Srgrimes */ 1341590Srgrimesint 1351590Srgrimesisdir(name) 1361590Srgrimes char name[]; 1371590Srgrimes{ 1381590Srgrimes struct stat sbuf; 1391590Srgrimes 1401590Srgrimes if (stat(name, &sbuf) < 0) 1411590Srgrimes return(0); 1421590Srgrimes return((sbuf.st_mode & S_IFMT) == S_IFDIR); 1431590Srgrimes} 1441590Srgrimes 1451590Srgrimes/* 1461590Srgrimes * Count the number of arguments in the given string raw list. 1471590Srgrimes */ 1481590Srgrimesint 1491590Srgrimesargcount(argv) 1501590Srgrimes char **argv; 1511590Srgrimes{ 1521590Srgrimes register char **ap; 1531590Srgrimes 1541590Srgrimes for (ap = argv; *ap++ != NOSTR;) 1558874Srgrimes ; 1561590Srgrimes return ap - argv - 1; 1571590Srgrimes} 1581590Srgrimes 1591590Srgrimes/* 1601590Srgrimes * Return the desired header line from the passed message 1611590Srgrimes * pointer (or NOSTR if the desired header field is not available). 1621590Srgrimes */ 1631590Srgrimeschar * 1641590Srgrimeshfield(field, mp) 1651590Srgrimes char field[]; 1661590Srgrimes struct message *mp; 1671590Srgrimes{ 1681590Srgrimes register FILE *ibuf; 1691590Srgrimes char linebuf[LINESIZE]; 1701590Srgrimes register int lc; 1711590Srgrimes register char *hfield; 1721590Srgrimes char *colon, *oldhfield = NOSTR; 1731590Srgrimes 1741590Srgrimes ibuf = setinput(mp); 1751590Srgrimes if ((lc = mp->m_lines - 1) < 0) 1761590Srgrimes return NOSTR; 1771590Srgrimes if (readline(ibuf, linebuf, LINESIZE) < 0) 1781590Srgrimes return NOSTR; 1791590Srgrimes while (lc > 0) { 1801590Srgrimes if ((lc = gethfield(ibuf, linebuf, lc, &colon)) < 0) 1811590Srgrimes return oldhfield; 1821590Srgrimes if (hfield = ishfield(linebuf, colon, field)) 1831590Srgrimes oldhfield = save2str(hfield, oldhfield); 1841590Srgrimes } 1851590Srgrimes return oldhfield; 1861590Srgrimes} 1871590Srgrimes 1881590Srgrimes/* 1891590Srgrimes * Return the next header field found in the given message. 1901590Srgrimes * Return >= 0 if something found, < 0 elsewise. 1911590Srgrimes * "colon" is set to point to the colon in the header. 1921590Srgrimes * Must deal with \ continuations & other such fraud. 1931590Srgrimes */ 1941590Srgrimesint 1951590Srgrimesgethfield(f, linebuf, rem, colon) 1961590Srgrimes register FILE *f; 1971590Srgrimes char linebuf[]; 1981590Srgrimes register int rem; 1991590Srgrimes char **colon; 2001590Srgrimes{ 2011590Srgrimes char line2[LINESIZE]; 2021590Srgrimes register char *cp, *cp2; 2031590Srgrimes register int c; 2041590Srgrimes 2051590Srgrimes for (;;) { 2061590Srgrimes if (--rem < 0) 2071590Srgrimes return -1; 2081590Srgrimes if ((c = readline(f, linebuf, LINESIZE)) <= 0) 2091590Srgrimes return -1; 2101590Srgrimes for (cp = linebuf; isprint(*cp) && *cp != ' ' && *cp != ':'; 2111590Srgrimes cp++) 2121590Srgrimes ; 2131590Srgrimes if (*cp != ':' || cp == linebuf) 2141590Srgrimes continue; 2151590Srgrimes /* 2161590Srgrimes * I guess we got a headline. 2171590Srgrimes * Handle wraparounding 2181590Srgrimes */ 2191590Srgrimes *colon = cp; 2201590Srgrimes cp = linebuf + c; 2211590Srgrimes for (;;) { 2221590Srgrimes while (--cp >= linebuf && (*cp == ' ' || *cp == '\t')) 2231590Srgrimes ; 2241590Srgrimes cp++; 2251590Srgrimes if (rem <= 0) 2261590Srgrimes break; 2271590Srgrimes ungetc(c = getc(f), f); 2281590Srgrimes if (c != ' ' && c != '\t') 2291590Srgrimes break; 2301590Srgrimes if ((c = readline(f, line2, LINESIZE)) < 0) 2311590Srgrimes break; 2321590Srgrimes rem--; 2331590Srgrimes for (cp2 = line2; *cp2 == ' ' || *cp2 == '\t'; cp2++) 2341590Srgrimes ; 2351590Srgrimes c -= cp2 - line2; 2361590Srgrimes if (cp + c >= linebuf + LINESIZE - 2) 2371590Srgrimes break; 2381590Srgrimes *cp++ = ' '; 2391590Srgrimes bcopy(cp2, cp, c); 2401590Srgrimes cp += c; 2411590Srgrimes } 2421590Srgrimes *cp = 0; 2431590Srgrimes return rem; 2441590Srgrimes } 2451590Srgrimes /* NOTREACHED */ 2461590Srgrimes} 2471590Srgrimes 2481590Srgrimes/* 2491590Srgrimes * Check whether the passed line is a header line of 2501590Srgrimes * the desired breed. Return the field body, or 0. 2511590Srgrimes */ 2521590Srgrimes 2531590Srgrimeschar* 2541590Srgrimesishfield(linebuf, colon, field) 2551590Srgrimes char linebuf[], field[]; 2561590Srgrimes char *colon; 2571590Srgrimes{ 2581590Srgrimes register char *cp = colon; 2591590Srgrimes 2601590Srgrimes *cp = 0; 2611590Srgrimes if (strcasecmp(linebuf, field) != 0) { 2621590Srgrimes *cp = ':'; 2631590Srgrimes return 0; 2641590Srgrimes } 2651590Srgrimes *cp = ':'; 2661590Srgrimes for (cp++; *cp == ' ' || *cp == '\t'; cp++) 2671590Srgrimes ; 2681590Srgrimes return cp; 2691590Srgrimes} 2701590Srgrimes 2711590Srgrimes/* 2721590Srgrimes * Copy a string, lowercasing it as we go. 2731590Srgrimes */ 2741590Srgrimesvoid 2751590Srgrimesistrcpy(dest, src) 2761590Srgrimes register char *dest, *src; 2771590Srgrimes{ 2781590Srgrimes 2791590Srgrimes do { 2801590Srgrimes if (isupper(*src)) 2811590Srgrimes *dest++ = tolower(*src); 2821590Srgrimes else 2831590Srgrimes *dest++ = *src; 2841590Srgrimes } while (*src++ != 0); 2851590Srgrimes} 2861590Srgrimes 2871590Srgrimes/* 2881590Srgrimes * The following code deals with input stacking to do source 2891590Srgrimes * commands. All but the current file pointer are saved on 2901590Srgrimes * the stack. 2911590Srgrimes */ 2921590Srgrimes 2931590Srgrimesstatic int ssp; /* Top of file stack */ 2941590Srgrimesstruct sstack { 2951590Srgrimes FILE *s_file; /* File we were in. */ 2961590Srgrimes int s_cond; /* Saved state of conditionals */ 2971590Srgrimes int s_loading; /* Loading .mailrc, etc. */ 29818532Sbde}; 29918532Sbde#define SSTACK_SIZE 64 /* XXX was NOFILE. */ 30018532Sbdestatic struct sstack sstack[SSTACK_SIZE]; 3011590Srgrimes 3021590Srgrimes/* 3031590Srgrimes * Pushdown current input file and switch to a new one. 3041590Srgrimes * Set the global flag "sourcing" so that others will realize 3051590Srgrimes * that they are no longer reading from a tty (in all probability). 3061590Srgrimes */ 3071590Srgrimesint 3081590Srgrimessource(arglist) 3091590Srgrimes char **arglist; 3101590Srgrimes{ 3111590Srgrimes FILE *fi; 3121590Srgrimes char *cp; 3131590Srgrimes 3141590Srgrimes if ((cp = expand(*arglist)) == NOSTR) 3151590Srgrimes return(1); 3161590Srgrimes if ((fi = Fopen(cp, "r")) == NULL) { 3171590Srgrimes perror(cp); 3181590Srgrimes return(1); 3191590Srgrimes } 32018532Sbde if (ssp >= SSTACK_SIZE - 1) { 3211590Srgrimes printf("Too much \"sourcing\" going on.\n"); 3221590Srgrimes Fclose(fi); 3231590Srgrimes return(1); 3241590Srgrimes } 3251590Srgrimes sstack[ssp].s_file = input; 3261590Srgrimes sstack[ssp].s_cond = cond; 3271590Srgrimes sstack[ssp].s_loading = loading; 3281590Srgrimes ssp++; 3291590Srgrimes loading = 0; 3301590Srgrimes cond = CANY; 3311590Srgrimes input = fi; 3321590Srgrimes sourcing++; 3331590Srgrimes return(0); 3341590Srgrimes} 3351590Srgrimes 3361590Srgrimes/* 3371590Srgrimes * Pop the current input back to the previous level. 3381590Srgrimes * Update the "sourcing" flag as appropriate. 3391590Srgrimes */ 3401590Srgrimesint 3411590Srgrimesunstack() 3421590Srgrimes{ 3431590Srgrimes if (ssp <= 0) { 3441590Srgrimes printf("\"Source\" stack over-pop.\n"); 3451590Srgrimes sourcing = 0; 3461590Srgrimes return(1); 3471590Srgrimes } 3481590Srgrimes Fclose(input); 3491590Srgrimes if (cond != CANY) 3501590Srgrimes printf("Unmatched \"if\"\n"); 3511590Srgrimes ssp--; 3521590Srgrimes cond = sstack[ssp].s_cond; 3531590Srgrimes loading = sstack[ssp].s_loading; 3541590Srgrimes input = sstack[ssp].s_file; 3551590Srgrimes if (ssp == 0) 3561590Srgrimes sourcing = loading; 3571590Srgrimes return(0); 3581590Srgrimes} 3591590Srgrimes 3601590Srgrimes/* 3611590Srgrimes * Touch the indicated file. 3621590Srgrimes * This is nifty for the shell. 3631590Srgrimes */ 3641590Srgrimesvoid 3651590Srgrimesalter(name) 3661590Srgrimes char *name; 3671590Srgrimes{ 3681590Srgrimes struct stat sb; 3691590Srgrimes struct timeval tv[2]; 3701590Srgrimes time_t time(); 3711590Srgrimes 3721590Srgrimes if (stat(name, &sb)) 3731590Srgrimes return; 3741590Srgrimes tv[0].tv_sec = time((time_t *)0) + 1; 3751590Srgrimes tv[1].tv_sec = sb.st_mtime; 3761590Srgrimes tv[0].tv_usec = tv[1].tv_usec = 0; 3771590Srgrimes (void)utimes(name, tv); 3781590Srgrimes} 3791590Srgrimes 3801590Srgrimes/* 3811590Srgrimes * Examine the passed line buffer and 3821590Srgrimes * return true if it is all blanks and tabs. 3831590Srgrimes */ 3841590Srgrimesint 3851590Srgrimesblankline(linebuf) 3861590Srgrimes char linebuf[]; 3871590Srgrimes{ 3881590Srgrimes register char *cp; 3891590Srgrimes 3901590Srgrimes for (cp = linebuf; *cp; cp++) 3911590Srgrimes if (*cp != ' ' && *cp != '\t') 3921590Srgrimes return(0); 3931590Srgrimes return(1); 3941590Srgrimes} 3951590Srgrimes 3961590Srgrimes/* 3971590Srgrimes * Get sender's name from this message. If the message has 3981590Srgrimes * a bunch of arpanet stuff in it, we may have to skin the name 3991590Srgrimes * before returning it. 4001590Srgrimes */ 4011590Srgrimeschar * 4021590Srgrimesnameof(mp, reptype) 4031590Srgrimes register struct message *mp; 4041590Srgrimes int reptype; 4051590Srgrimes{ 4061590Srgrimes register char *cp, *cp2; 4071590Srgrimes 4081590Srgrimes cp = skin(name1(mp, reptype)); 4091590Srgrimes if (reptype != 0 || charcount(cp, '!') < 2) 4101590Srgrimes return(cp); 4111590Srgrimes cp2 = rindex(cp, '!'); 4121590Srgrimes cp2--; 4131590Srgrimes while (cp2 > cp && *cp2 != '!') 4141590Srgrimes cp2--; 4151590Srgrimes if (*cp2 == '!') 4161590Srgrimes return(cp2 + 1); 4171590Srgrimes return(cp); 4181590Srgrimes} 4191590Srgrimes 4201590Srgrimes/* 4211590Srgrimes * Start of a "comment". 4221590Srgrimes * Ignore it. 4231590Srgrimes */ 4241590Srgrimeschar * 4251590Srgrimesskip_comment(cp) 4261590Srgrimes register char *cp; 4271590Srgrimes{ 4281590Srgrimes register nesting = 1; 4291590Srgrimes 4301590Srgrimes for (; nesting > 0 && *cp; cp++) { 4311590Srgrimes switch (*cp) { 4321590Srgrimes case '\\': 4331590Srgrimes if (cp[1]) 4341590Srgrimes cp++; 4351590Srgrimes break; 4361590Srgrimes case '(': 4371590Srgrimes nesting++; 4381590Srgrimes break; 4391590Srgrimes case ')': 4401590Srgrimes nesting--; 4411590Srgrimes break; 4421590Srgrimes } 4431590Srgrimes } 4441590Srgrimes return cp; 4451590Srgrimes} 4461590Srgrimes 4471590Srgrimes/* 4481590Srgrimes * Skin an arpa net address according to the RFC 822 interpretation 4491590Srgrimes * of "host-phrase." 4501590Srgrimes */ 4511590Srgrimeschar * 4521590Srgrimesskin(name) 4531590Srgrimes char *name; 4541590Srgrimes{ 4551590Srgrimes register int c; 4561590Srgrimes register char *cp, *cp2; 4571590Srgrimes char *bufend; 4581590Srgrimes int gotlt, lastsp; 4591590Srgrimes char nbuf[BUFSIZ]; 4601590Srgrimes 4611590Srgrimes if (name == NOSTR) 4621590Srgrimes return(NOSTR); 4631590Srgrimes if (index(name, '(') == NOSTR && index(name, '<') == NOSTR 4641590Srgrimes && index(name, ' ') == NOSTR) 4651590Srgrimes return(name); 4661590Srgrimes gotlt = 0; 4671590Srgrimes lastsp = 0; 4681590Srgrimes bufend = nbuf; 4691590Srgrimes for (cp = name, cp2 = bufend; c = *cp++; ) { 4701590Srgrimes switch (c) { 4711590Srgrimes case '(': 4721590Srgrimes cp = skip_comment(cp); 4731590Srgrimes lastsp = 0; 4741590Srgrimes break; 4751590Srgrimes 4761590Srgrimes case '"': 4771590Srgrimes /* 4781590Srgrimes * Start of a "quoted-string". 4791590Srgrimes * Copy it in its entirety. 4801590Srgrimes */ 4811590Srgrimes while (c = *cp) { 4821590Srgrimes cp++; 4831590Srgrimes if (c == '"') 4841590Srgrimes break; 4851590Srgrimes if (c != '\\') 4861590Srgrimes *cp2++ = c; 4871590Srgrimes else if (c = *cp) { 4881590Srgrimes *cp2++ = c; 4891590Srgrimes cp++; 4901590Srgrimes } 4911590Srgrimes } 4921590Srgrimes lastsp = 0; 4931590Srgrimes break; 4941590Srgrimes 4951590Srgrimes case ' ': 4961590Srgrimes if (cp[0] == 'a' && cp[1] == 't' && cp[2] == ' ') 4971590Srgrimes cp += 3, *cp2++ = '@'; 4981590Srgrimes else 4991590Srgrimes if (cp[0] == '@' && cp[1] == ' ') 5001590Srgrimes cp += 2, *cp2++ = '@'; 5011590Srgrimes else 5021590Srgrimes lastsp = 1; 5031590Srgrimes break; 5041590Srgrimes 5051590Srgrimes case '<': 5061590Srgrimes cp2 = bufend; 5071590Srgrimes gotlt++; 5081590Srgrimes lastsp = 0; 5091590Srgrimes break; 5101590Srgrimes 5111590Srgrimes case '>': 5121590Srgrimes if (gotlt) { 5131590Srgrimes gotlt = 0; 5141590Srgrimes while ((c = *cp) && c != ',') { 5151590Srgrimes cp++; 5161590Srgrimes if (c == '(') 5171590Srgrimes cp = skip_comment(cp); 5181590Srgrimes else if (c == '"') 5191590Srgrimes while (c = *cp) { 5201590Srgrimes cp++; 5211590Srgrimes if (c == '"') 5221590Srgrimes break; 5231590Srgrimes if (c == '\\' && *cp) 5241590Srgrimes cp++; 5251590Srgrimes } 5261590Srgrimes } 5271590Srgrimes lastsp = 0; 5281590Srgrimes break; 5291590Srgrimes } 5301590Srgrimes /* Fall into . . . */ 5311590Srgrimes 5321590Srgrimes default: 5331590Srgrimes if (lastsp) { 5341590Srgrimes lastsp = 0; 5351590Srgrimes *cp2++ = ' '; 5361590Srgrimes } 5371590Srgrimes *cp2++ = c; 5381590Srgrimes if (c == ',' && !gotlt) { 5391590Srgrimes *cp2++ = ' '; 5401590Srgrimes for (; *cp == ' '; cp++) 5411590Srgrimes ; 5421590Srgrimes lastsp = 0; 5431590Srgrimes bufend = cp2; 5441590Srgrimes } 5451590Srgrimes } 5461590Srgrimes } 5471590Srgrimes *cp2 = 0; 5481590Srgrimes 5491590Srgrimes return(savestr(nbuf)); 5501590Srgrimes} 5511590Srgrimes 5521590Srgrimes/* 5531590Srgrimes * Fetch the sender's name from the passed message. 5541590Srgrimes * Reptype can be 5551590Srgrimes * 0 -- get sender's name for display purposes 5561590Srgrimes * 1 -- get sender's name for reply 5571590Srgrimes * 2 -- get sender's name for Reply 5581590Srgrimes */ 5591590Srgrimeschar * 5601590Srgrimesname1(mp, reptype) 5611590Srgrimes register struct message *mp; 5621590Srgrimes int reptype; 5631590Srgrimes{ 5641590Srgrimes char namebuf[LINESIZE]; 5651590Srgrimes char linebuf[LINESIZE]; 5661590Srgrimes register char *cp, *cp2; 5671590Srgrimes register FILE *ibuf; 5681590Srgrimes int first = 1; 5691590Srgrimes 5701590Srgrimes if ((cp = hfield("from", mp)) != NOSTR) 5711590Srgrimes return cp; 5721590Srgrimes if (reptype == 0 && (cp = hfield("sender", mp)) != NOSTR) 5731590Srgrimes return cp; 5741590Srgrimes ibuf = setinput(mp); 5751590Srgrimes namebuf[0] = 0; 5761590Srgrimes if (readline(ibuf, linebuf, LINESIZE) < 0) 5771590Srgrimes return(savestr(namebuf)); 5781590Srgrimesnewname: 5791590Srgrimes for (cp = linebuf; *cp && *cp != ' '; cp++) 5801590Srgrimes ; 5811590Srgrimes for (; *cp == ' ' || *cp == '\t'; cp++) 5821590Srgrimes ; 5831590Srgrimes for (cp2 = &namebuf[strlen(namebuf)]; 5841590Srgrimes *cp && *cp != ' ' && *cp != '\t' && cp2 < namebuf + LINESIZE - 1;) 5851590Srgrimes *cp2++ = *cp++; 5861590Srgrimes *cp2 = '\0'; 5871590Srgrimes if (readline(ibuf, linebuf, LINESIZE) < 0) 5881590Srgrimes return(savestr(namebuf)); 5891590Srgrimes if ((cp = index(linebuf, 'F')) == NULL) 5901590Srgrimes return(savestr(namebuf)); 5911590Srgrimes if (strncmp(cp, "From", 4) != 0) 5921590Srgrimes return(savestr(namebuf)); 5931590Srgrimes while ((cp = index(cp, 'r')) != NULL) { 5941590Srgrimes if (strncmp(cp, "remote", 6) == 0) { 5951590Srgrimes if ((cp = index(cp, 'f')) == NULL) 5961590Srgrimes break; 5971590Srgrimes if (strncmp(cp, "from", 4) != 0) 5981590Srgrimes break; 5991590Srgrimes if ((cp = index(cp, ' ')) == NULL) 6001590Srgrimes break; 6011590Srgrimes cp++; 6021590Srgrimes if (first) { 6031590Srgrimes strcpy(namebuf, cp); 6041590Srgrimes first = 0; 6051590Srgrimes } else 6061590Srgrimes strcpy(rindex(namebuf, '!')+1, cp); 6071590Srgrimes strcat(namebuf, "!"); 6081590Srgrimes goto newname; 6091590Srgrimes } 6101590Srgrimes cp++; 6111590Srgrimes } 6121590Srgrimes return(savestr(namebuf)); 6131590Srgrimes} 6141590Srgrimes 6151590Srgrimes/* 6161590Srgrimes * Count the occurances of c in str 6171590Srgrimes */ 6181590Srgrimesint 6191590Srgrimescharcount(str, c) 6201590Srgrimes char *str; 6211590Srgrimes int c; 6221590Srgrimes{ 6231590Srgrimes register char *cp; 6241590Srgrimes register int i; 6251590Srgrimes 6261590Srgrimes for (i = 0, cp = str; *cp; cp++) 6271590Srgrimes if (*cp == c) 6281590Srgrimes i++; 6291590Srgrimes return(i); 6301590Srgrimes} 6311590Srgrimes 6321590Srgrimes/* 6331590Srgrimes * Are any of the characters in the two strings the same? 6341590Srgrimes */ 6351590Srgrimesint 6361590Srgrimesanyof(s1, s2) 6371590Srgrimes register char *s1, *s2; 6381590Srgrimes{ 6391590Srgrimes 6401590Srgrimes while (*s1) 6411590Srgrimes if (index(s2, *s1++)) 6421590Srgrimes return 1; 6431590Srgrimes return 0; 6441590Srgrimes} 6451590Srgrimes 6461590Srgrimes/* 6471590Srgrimes * Convert c to upper case 6481590Srgrimes */ 6491590Srgrimesint 6501590Srgrimesraise(c) 6511590Srgrimes register int c; 6521590Srgrimes{ 6531590Srgrimes 6541590Srgrimes if (islower(c)) 6551590Srgrimes return toupper(c); 6561590Srgrimes return c; 6571590Srgrimes} 6581590Srgrimes 6591590Srgrimes/* 6601590Srgrimes * Copy s1 to s2, return pointer to null in s2. 6611590Srgrimes */ 6621590Srgrimeschar * 6631590Srgrimescopy(s1, s2) 6641590Srgrimes register char *s1, *s2; 6651590Srgrimes{ 6661590Srgrimes 6671590Srgrimes while (*s2++ = *s1++) 6681590Srgrimes ; 6691590Srgrimes return s2 - 1; 6701590Srgrimes} 6711590Srgrimes 6721590Srgrimes/* 6731590Srgrimes * See if the given header field is supposed to be ignored. 6741590Srgrimes */ 6751590Srgrimesint 6761590Srgrimesisign(field, ignore) 6771590Srgrimes char *field; 6781590Srgrimes struct ignoretab ignore[2]; 6791590Srgrimes{ 6801590Srgrimes char realfld[BUFSIZ]; 6811590Srgrimes 6821590Srgrimes if (ignore == ignoreall) 6831590Srgrimes return 1; 6841590Srgrimes /* 6851590Srgrimes * Lower-case the string, so that "Status" and "status" 6861590Srgrimes * will hash to the same place. 6871590Srgrimes */ 6881590Srgrimes istrcpy(realfld, field); 6891590Srgrimes if (ignore[1].i_count > 0) 6901590Srgrimes return (!member(realfld, ignore + 1)); 6911590Srgrimes else 6921590Srgrimes return (member(realfld, ignore)); 6931590Srgrimes} 6941590Srgrimes 6951590Srgrimesint 6961590Srgrimesmember(realfield, table) 6971590Srgrimes register char *realfield; 6981590Srgrimes struct ignoretab *table; 6991590Srgrimes{ 7001590Srgrimes register struct ignore *igp; 7011590Srgrimes 7021590Srgrimes for (igp = table->i_head[hash(realfield)]; igp != 0; igp = igp->i_link) 7031590Srgrimes if (*igp->i_field == *realfield && 7041590Srgrimes equal(igp->i_field, realfield)) 7051590Srgrimes return (1); 7061590Srgrimes return (0); 7071590Srgrimes} 708