xref: /csrg-svn/usr.bin/mail/aux.c (revision 34966)
122444Sdist /*
222444Sdist  * Copyright (c) 1980 Regents of the University of California.
333499Sbostic  * All rights reserved.
433499Sbostic  *
533499Sbostic  * Redistribution and use in source and binary forms are permitted
634905Sbostic  * provided that the above copyright notice and this paragraph are
734905Sbostic  * duplicated in all such forms and that any documentation,
834905Sbostic  * advertising materials, and other materials related to such
934905Sbostic  * distribution and use acknowledge that the software was developed
1034905Sbostic  * by the University of California, Berkeley.  The name of the
1134905Sbostic  * University may not be used to endorse or promote products derived
1234905Sbostic  * from this software without specific prior written permission.
1334905Sbostic  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1434905Sbostic  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1534905Sbostic  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1622444Sdist  */
1722444Sdist 
1834905Sbostic #ifndef lint
19*34966Sedward static char sccsid[] = "@(#)aux.c	5.13 (Berkeley) 07/07/88";
2034905Sbostic #endif /* not lint */
211219Skas 
221219Skas #include "rcv.h"
231219Skas #include <sys/stat.h>
241219Skas 
251219Skas /*
261219Skas  * Mail -- a mail program
271219Skas  *
281219Skas  * Auxiliary functions.
291219Skas  */
301219Skas 
311219Skas /*
321219Skas  * Return a pointer to a dynamic copy of the argument.
331219Skas  */
341219Skas 
351219Skas char *
361219Skas savestr(str)
371219Skas 	char *str;
381219Skas {
391219Skas 	register char *cp, *cp2, *top;
401219Skas 
411219Skas 	for (cp = str; *cp; cp++)
421219Skas 		;
431219Skas 	top = salloc(cp-str + 1);
441219Skas 	if (top == NOSTR)
451219Skas 		return(NOSTR);
461219Skas 	for (cp = str, cp2 = top; *cp; cp++)
471219Skas 		*cp2++ = *cp;
481219Skas 	*cp2 = 0;
491219Skas 	return(top);
501219Skas }
511219Skas 
521219Skas /*
531219Skas  * Announce a fatal error and die.
541219Skas  */
551219Skas 
5631142Sedward /*VARARGS1*/
5731142Sedward panic(fmt, a, b)
5831142Sedward 	char *fmt;
591219Skas {
6031142Sedward 	fprintf(stderr, "panic: ");
6131142Sedward 	fprintf(stderr, fmt, a, b);
6231142Sedward 	putc('\n', stderr);
631219Skas 	exit(1);
641219Skas }
651219Skas 
661219Skas /*
671219Skas  * Touch the named message by setting its MTOUCH flag.
681219Skas  * Touched messages have the effect of not being sent
691219Skas  * back to the system mailbox on exit.
701219Skas  */
711219Skas 
721219Skas touch(mesg)
731219Skas {
741479Skas 	register struct message *mp;
751479Skas 
761479Skas 	if (mesg < 1 || mesg > msgCount)
771479Skas 		return;
781479Skas 	mp = &message[mesg-1];
791479Skas 	mp->m_flag |= MTOUCH;
801479Skas 	if ((mp->m_flag & MREAD) == 0)
811479Skas 		mp->m_flag |= MREAD|MSTATUS;
821219Skas }
831219Skas 
841219Skas /*
851219Skas  * Test to see if the passed file name is a directory.
861219Skas  * Return true if it is.
871219Skas  */
881219Skas 
891219Skas isdir(name)
901219Skas 	char name[];
911219Skas {
921219Skas 	struct stat sbuf;
931219Skas 
941219Skas 	if (stat(name, &sbuf) < 0)
951219Skas 		return(0);
961219Skas 	return((sbuf.st_mode & S_IFMT) == S_IFDIR);
971219Skas }
981219Skas 
991219Skas /*
1001219Skas  * Count the number of arguments in the given string raw list.
1011219Skas  */
1021219Skas 
1031219Skas argcount(argv)
1041219Skas 	char **argv;
1051219Skas {
1061219Skas 	register char **ap;
1071219Skas 
10831142Sedward 	for (ap = argv; *ap++ != NOSTR;)
1091219Skas 		;
11031142Sedward 	return ap - argv - 1;
1111219Skas }
1121219Skas 
1131219Skas /*
1141219Skas  * Return the desired header line from the passed message
1151219Skas  * pointer (or NOSTR if the desired header field is not available).
1161219Skas  */
1171219Skas 
1181219Skas char *
1191219Skas hfield(field, mp)
1201219Skas 	char field[];
1211219Skas 	struct message *mp;
1221219Skas {
1231219Skas 	register FILE *ibuf;
1241219Skas 	char linebuf[LINESIZE];
1251219Skas 	register int lc;
12631142Sedward 	register char *hfield;
12731142Sedward 	char *colon;
1281219Skas 
1291219Skas 	ibuf = setinput(mp);
13031142Sedward 	if ((lc = mp->m_lines - 1) < 0)
13131142Sedward 		return NOSTR;
1321219Skas 	if (readline(ibuf, linebuf) < 0)
13331142Sedward 		return NOSTR;
13431142Sedward 	while (lc > 0) {
13531142Sedward 		if ((lc = gethfield(ibuf, linebuf, lc, &colon)) < 0)
13631142Sedward 			return NOSTR;
13731142Sedward 		if (hfield = ishfield(linebuf, colon, field))
13831142Sedward 			return savestr(hfield);
13931142Sedward 	}
14031142Sedward 	return NOSTR;
1411219Skas }
1421219Skas 
1431219Skas /*
1441219Skas  * Return the next header field found in the given message.
14531142Sedward  * Return >= 0 if something found, < 0 elsewise.
14631142Sedward  * "colon" is set to point to the colon in the header.
1471219Skas  * Must deal with \ continuations & other such fraud.
1481219Skas  */
1491219Skas 
15031142Sedward gethfield(f, linebuf, rem, colon)
1511219Skas 	register FILE *f;
1521219Skas 	char linebuf[];
1531219Skas 	register int rem;
15431142Sedward 	char **colon;
1551219Skas {
1561219Skas 	char line2[LINESIZE];
1571219Skas 	register char *cp, *cp2;
1581219Skas 	register int c;
1591219Skas 
1601219Skas 	for (;;) {
16131142Sedward 		if (--rem < 0)
16231142Sedward 			return -1;
16331142Sedward 		if ((c = readline(f, linebuf)) <= 0)
16431142Sedward 			return -1;
16531142Sedward 		for (cp = linebuf; isprint(*cp) && *cp != ' ' && *cp != ':';
16631142Sedward 		     cp++)
16731142Sedward 			;
16831142Sedward 		if (*cp != ':' || cp == linebuf)
1691219Skas 			continue;
1701219Skas 		/*
1711219Skas 		 * I guess we got a headline.
1721219Skas 		 * Handle wraparounding
1731219Skas 		 */
17431142Sedward 		*colon = cp;
17531142Sedward 		cp = linebuf + c;
1761219Skas 		for (;;) {
17731142Sedward 			while (--cp >= linebuf && (*cp == ' ' || *cp == '\t'))
17831142Sedward 				;
17931142Sedward 			cp++;
1801219Skas 			if (rem <= 0)
1811219Skas 				break;
18231142Sedward 			ungetc(c = getc(f), f);
18331142Sedward 			if (c != ' ' && c != '\t')
1841219Skas 				break;
18531142Sedward 			if ((c = readline(f, line2)) < 0)
1861219Skas 				break;
1871219Skas 			rem--;
18831142Sedward 			for (cp2 = line2; *cp2 == ' ' || *cp2 == '\t'; cp2++)
1891219Skas 				;
19031142Sedward 			c -= cp2 - line2;
19131142Sedward 			if (cp + c >= linebuf + LINESIZE - 2)
1921219Skas 				break;
1931219Skas 			*cp++ = ' ';
19431142Sedward 			bcopy(cp2, cp, c);
19531142Sedward 			cp += c;
1961219Skas 		}
19731142Sedward 		*cp = 0;
19831142Sedward 		return rem;
1991219Skas 	}
2001219Skas 	/* NOTREACHED */
2011219Skas }
2021219Skas 
2031219Skas /*
2041219Skas  * Check whether the passed line is a header line of
20531142Sedward  * the desired breed.  Return the field body, or 0.
2061219Skas  */
2071219Skas 
20831142Sedward char*
20931142Sedward ishfield(linebuf, colon, field)
2101219Skas 	char linebuf[], field[];
21131142Sedward 	char *colon;
2121219Skas {
21331142Sedward 	register char *cp = colon;
2141219Skas 
2151219Skas 	*cp = 0;
21631142Sedward 	if (!icequal(linebuf, field)) {
21731142Sedward 		*cp = ':';
21831142Sedward 		return 0;
2191219Skas 	}
22031142Sedward 	*cp = ':';
22131142Sedward 	for (cp++; *cp == ' ' || *cp == '\t'; cp++)
22231142Sedward 		;
22331142Sedward 	return cp;
2241219Skas }
2251219Skas 
2261219Skas /*
2271219Skas  * Compare two strings, ignoring case.
2281219Skas  */
2291219Skas 
2301219Skas icequal(s1, s2)
2311219Skas 	register char *s1, *s2;
2321219Skas {
23331142Sedward 	register c1, c2;
2341219Skas 
23531142Sedward 	for (;;) {
23631142Sedward 		if ((c1 = (unsigned char)*s1++) !=
23731142Sedward 		    (c2 = (unsigned char)*s2++)) {
23831142Sedward 			if (isupper(c1))
23931142Sedward 				c1 = tolower(c1);
24031142Sedward 			if (c1 != c2)
24131142Sedward 				return 0;
24231142Sedward 		}
24331142Sedward 		if (c1 == 0)
24431142Sedward 			return 1;
24531142Sedward 	}
24631142Sedward 	/*NOTREACHED*/
2471219Skas }
2481219Skas 
2491219Skas /*
2507571Skurt  * Copy a string, lowercasing it as we go.
2517571Skurt  */
2527571Skurt istrcpy(dest, src)
25331142Sedward 	register char *dest, *src;
2547571Skurt {
2557571Skurt 
2567571Skurt 	do {
25731142Sedward 		if (isupper(*src))
25831142Sedward 			*dest++ = tolower(*src);
25931142Sedward 		else
26031142Sedward 			*dest++ = *src;
26131142Sedward 	} while (*src++ != 0);
2627571Skurt }
2637571Skurt 
2647571Skurt /*
2651219Skas  * The following code deals with input stacking to do source
2661219Skas  * commands.  All but the current file pointer are saved on
2671219Skas  * the stack.
2681219Skas  */
2691219Skas 
27034965Sedward static	int	ssp;			/* Top of file stack */
2711519Skas struct sstack {
2721519Skas 	FILE	*s_file;		/* File we were in. */
2731519Skas 	int	s_cond;			/* Saved state of conditionals */
2745785Skurt 	int	s_loading;		/* Loading .mailrc, etc. */
27518661Sserge } sstack[NOFILE];
2761219Skas 
2771219Skas /*
2781219Skas  * Pushdown current input file and switch to a new one.
2791219Skas  * Set the global flag "sourcing" so that others will realize
2801219Skas  * that they are no longer reading from a tty (in all probability).
2811219Skas  */
282*34966Sedward source(arglist)
283*34966Sedward 	char **arglist;
2841219Skas {
285*34966Sedward 	FILE *fi;
286*34966Sedward 	char *cp;
2871219Skas 
288*34966Sedward 	if ((cp = expand(*arglist)) == NOSTR)
2891219Skas 		return(1);
2903914Skurt 	if ((fi = fopen(cp, "r")) == NULL) {
2913914Skurt 		perror(cp);
2923914Skurt 		return(1);
2931219Skas 	}
29434965Sedward 	if (ssp >= NOFILE - 1) {
2951219Skas 		printf("Too much \"sourcing\" going on.\n");
2961219Skas 		fclose(fi);
2971219Skas 		return(1);
2981219Skas 	}
29934965Sedward 	sstack[ssp].s_file = input;
3001519Skas 	sstack[ssp].s_cond = cond;
3015785Skurt 	sstack[ssp].s_loading = loading;
30234965Sedward 	ssp++;
3035785Skurt 	loading = 0;
3041519Skas 	cond = CANY;
3051219Skas 	input = fi;
3061219Skas 	sourcing++;
3071219Skas 	return(0);
3081219Skas }
3091219Skas 
3101219Skas /*
3111219Skas  * Pop the current input back to the previous level.
3121219Skas  * Update the "sourcing" flag as appropriate.
3131219Skas  */
3141219Skas 
3151219Skas unstack()
3161219Skas {
31734965Sedward 	if (ssp <= 0) {
3181219Skas 		printf("\"Source\" stack over-pop.\n");
3191219Skas 		sourcing = 0;
3201219Skas 		return(1);
3211219Skas 	}
3221219Skas 	fclose(input);
3231519Skas 	if (cond != CANY)
3241519Skas 		printf("Unmatched \"if\"\n");
32534965Sedward 	ssp--;
3261519Skas 	cond = sstack[ssp].s_cond;
3275785Skurt 	loading = sstack[ssp].s_loading;
32834965Sedward 	input = sstack[ssp].s_file;
32934965Sedward 	if (ssp == 0)
3305785Skurt 		sourcing = loading;
3311219Skas 	return(0);
3321219Skas }
3331219Skas 
3341219Skas /*
3351219Skas  * Touch the indicated file.
3361219Skas  * This is nifty for the shell.
3371219Skas  */
3381219Skas 
3391219Skas alter(name)
3401219Skas 	char name[];
3411219Skas {
3421219Skas 	struct stat statb;
3431219Skas 	long time();
3441219Skas 	time_t time_p[2];
3451219Skas 
3461219Skas 	if (stat(name, &statb) < 0)
3471219Skas 		return;
3481219Skas 	time_p[0] = time((long *) 0) + 1;
3491219Skas 	time_p[1] = statb.st_mtime;
3501219Skas 	utime(name, time_p);
3511219Skas }
3521219Skas 
3531219Skas /*
3541219Skas  * Examine the passed line buffer and
3551219Skas  * return true if it is all blanks and tabs.
3561219Skas  */
3571219Skas 
3581219Skas blankline(linebuf)
3591219Skas 	char linebuf[];
3601219Skas {
3611219Skas 	register char *cp;
3621219Skas 
3631219Skas 	for (cp = linebuf; *cp; cp++)
36418661Sserge 		if (*cp != ' ' && *cp != '\t')
3651219Skas 			return(0);
3661219Skas 	return(1);
3671219Skas }
3681219Skas 
3691219Skas /*
3703195Skas  * Get sender's name from this message.  If the message has
3713195Skas  * a bunch of arpanet stuff in it, we may have to skin the name
3723195Skas  * before returning it.
3733195Skas  */
3743195Skas char *
3753195Skas nameof(mp, reptype)
3763195Skas 	register struct message *mp;
3773195Skas {
3785237Skurt 	register char *cp, *cp2;
3793195Skas 
3805237Skurt 	cp = skin(name1(mp, reptype));
3815237Skurt 	if (reptype != 0 || charcount(cp, '!') < 2)
3825237Skurt 		return(cp);
3835237Skurt 	cp2 = rindex(cp, '!');
3845237Skurt 	cp2--;
3855237Skurt 	while (cp2 > cp && *cp2 != '!')
3865237Skurt 		cp2--;
3875237Skurt 	if (*cp2 == '!')
3885237Skurt 		return(cp2 + 1);
3895237Skurt 	return(cp);
3903195Skas }
3913195Skas 
3923195Skas /*
39325912Smckusick  * Skin an arpa net address according to the RFC 822 interpretation
3943195Skas  * of "host-phrase."
3953195Skas  */
3963195Skas char *
3973195Skas skin(name)
3983195Skas 	char *name;
3993195Skas {
4003195Skas 	register int c;
4013195Skas 	register char *cp, *cp2;
40225912Smckusick 	char *bufend;
4033195Skas 	int gotlt, lastsp;
4043195Skas 	char nbuf[BUFSIZ];
40518661Sserge 	int nesting;
4063195Skas 
4073195Skas 	if (name == NOSTR)
4083195Skas 		return(NOSTR);
40912819Sleres 	if (index(name, '(') == NOSTR && index(name, '<') == NOSTR
41031142Sedward 	    && index(name, ' ') == NOSTR)
4113195Skas 		return(name);
4123195Skas 	gotlt = 0;
4133195Skas 	lastsp = 0;
41425912Smckusick 	bufend = nbuf;
41525912Smckusick 	for (cp = name, cp2 = bufend; c = *cp++; ) {
4163195Skas 		switch (c) {
4173195Skas 		case '(':
41825912Smckusick 			/*
41925912Smckusick 			 * Start of a "comment".
42025912Smckusick 			 * Ignore it.
42125912Smckusick 			 */
42218661Sserge 			nesting = 1;
42325912Smckusick 			while ((c = *cp) != 0) {
42425912Smckusick 				cp++;
42525912Smckusick 				switch (c) {
42625912Smckusick 				case '\\':
42725912Smckusick 					if (*cp == 0)
42825912Smckusick 						goto outcm;
42925912Smckusick 					cp++;
43025912Smckusick 					break;
43118661Sserge 				case '(':
43218661Sserge 					nesting++;
43318661Sserge 					break;
43418661Sserge 
43518661Sserge 				case ')':
43618661Sserge 					--nesting;
43718661Sserge 					break;
43818661Sserge 				}
43918661Sserge 
44018661Sserge 				if (nesting <= 0)
44118661Sserge 					break;
44218661Sserge 			}
44325912Smckusick 		outcm:
44412819Sleres 			lastsp = 0;
4453195Skas 			break;
4463195Skas 
44725912Smckusick 		case '"':
44825912Smckusick 			/*
44925912Smckusick 			 * Start of a "quoted-string".
45025912Smckusick 			 * Copy it in its entirety.
45125912Smckusick 			 */
45225912Smckusick 			while ((c = *cp) != 0) {
45325912Smckusick 				cp++;
45425912Smckusick 				switch (c) {
45525912Smckusick 				case '\\':
45625912Smckusick 					if ((c = *cp) == 0)
45725912Smckusick 						goto outqs;
45825912Smckusick 					cp++;
45925912Smckusick 					break;
46025912Smckusick 				case '"':
46125912Smckusick 					goto outqs;
46225912Smckusick 				}
46325912Smckusick 				*cp2++ = c;
46425912Smckusick 			}
46525912Smckusick 		outqs:
46625912Smckusick 			lastsp = 0;
46725912Smckusick 			break;
46825912Smckusick 
4693195Skas 		case ' ':
47012819Sleres 			if (cp[0] == 'a' && cp[1] == 't' && cp[2] == ' ')
47112819Sleres 				cp += 3, *cp2++ = '@';
47212819Sleres 			else
47312819Sleres 			if (cp[0] == '@' && cp[1] == ' ')
47412819Sleres 				cp += 2, *cp2++ = '@';
47512819Sleres 			else
47612819Sleres 				lastsp = 1;
4773195Skas 			break;
4783195Skas 
4793195Skas 		case '<':
48025912Smckusick 			cp2 = bufend;
4813195Skas 			gotlt++;
4823195Skas 			lastsp = 0;
4833195Skas 			break;
4843195Skas 
4853195Skas 		case '>':
48625912Smckusick 			if (gotlt) {
48725912Smckusick 				gotlt = 0;
48825912Smckusick 				while (*cp != ',' && *cp != 0)
48925912Smckusick 					cp++;
49025912Smckusick 				if (*cp == 0 )
49125912Smckusick 					goto done;
49225912Smckusick 				*cp2++ = ',';
49325912Smckusick 				*cp2++ = ' ';
49425912Smckusick 				bufend = cp2;
49525912Smckusick 				break;
49625912Smckusick 			}
4973195Skas 
4983195Skas 			/* Fall into . . . */
4993195Skas 
5003195Skas 		default:
5013195Skas 			if (lastsp) {
5023195Skas 				lastsp = 0;
5033195Skas 				*cp2++ = ' ';
5043195Skas 			}
5053195Skas 			*cp2++ = c;
5063195Skas 			break;
5073195Skas 		}
5083195Skas 	}
5093195Skas done:
5103195Skas 	*cp2 = 0;
5113195Skas 
5123195Skas 	return(savestr(nbuf));
5133195Skas }
5143195Skas 
5153195Skas /*
5161219Skas  * Fetch the sender's name from the passed message.
5173195Skas  * Reptype can be
5183195Skas  *	0 -- get sender's name for display purposes
5193195Skas  *	1 -- get sender's name for reply
5203195Skas  *	2 -- get sender's name for Reply
5211219Skas  */
5221219Skas 
5231219Skas char *
5243195Skas name1(mp, reptype)
5251219Skas 	register struct message *mp;
5261219Skas {
5271219Skas 	char namebuf[LINESIZE];
5281219Skas 	char linebuf[LINESIZE];
5291219Skas 	register char *cp, *cp2;
5301219Skas 	register FILE *ibuf;
5311219Skas 	int first = 1;
5321219Skas 
5333195Skas 	if ((cp = hfield("from", mp)) != NOSTR)
53431142Sedward 		return cp;
5353195Skas 	if (reptype == 0 && (cp = hfield("sender", mp)) != NOSTR)
53631142Sedward 		return cp;
5371219Skas 	ibuf = setinput(mp);
53831142Sedward 	namebuf[0] = 0;
53931142Sedward 	if (readline(ibuf, linebuf) < 0)
5401219Skas 		return(savestr(namebuf));
5411219Skas newname:
54231142Sedward 	for (cp = linebuf; *cp && *cp != ' '; cp++)
5431219Skas 		;
54431142Sedward 	for (; *cp == ' ' || *cp == '\t'; cp++)
5451219Skas 		;
54631142Sedward 	for (cp2 = &namebuf[strlen(namebuf)];
54731142Sedward 	     *cp && *cp != ' ' && *cp != '\t' && cp2 < namebuf + LINESIZE - 1;)
54831142Sedward 		*cp2++ = *cp++;
5491219Skas 	*cp2 = '\0';
55031142Sedward 	if (readline(ibuf, linebuf) < 0)
5511219Skas 		return(savestr(namebuf));
5521219Skas 	if ((cp = index(linebuf, 'F')) == NULL)
5531219Skas 		return(savestr(namebuf));
5541219Skas 	if (strncmp(cp, "From", 4) != 0)
5551219Skas 		return(savestr(namebuf));
5561219Skas 	while ((cp = index(cp, 'r')) != NULL) {
5571219Skas 		if (strncmp(cp, "remote", 6) == 0) {
5581219Skas 			if ((cp = index(cp, 'f')) == NULL)
5591219Skas 				break;
5601219Skas 			if (strncmp(cp, "from", 4) != 0)
5611219Skas 				break;
5621219Skas 			if ((cp = index(cp, ' ')) == NULL)
5631219Skas 				break;
5641219Skas 			cp++;
5651219Skas 			if (first) {
56631142Sedward 				strcpy(namebuf, cp);
5671219Skas 				first = 0;
5681219Skas 			} else
5691219Skas 				strcpy(rindex(namebuf, '!')+1, cp);
5701219Skas 			strcat(namebuf, "!");
5711219Skas 			goto newname;
5721219Skas 		}
5731219Skas 		cp++;
5741219Skas 	}
5751219Skas 	return(savestr(namebuf));
5761219Skas }
5771219Skas 
5781219Skas /*
5795237Skurt  * Count the occurances of c in str
5805237Skurt  */
5815237Skurt charcount(str, c)
5825237Skurt 	char *str;
5835237Skurt {
5845237Skurt 	register char *cp;
5855237Skurt 	register int i;
5865237Skurt 
5875237Skurt 	for (i = 0, cp = str; *cp; cp++)
5885237Skurt 		if (*cp == c)
5895237Skurt 			i++;
5905237Skurt 	return(i);
5915237Skurt }
5925237Skurt 
5935237Skurt /*
59431142Sedward  * Are any of the characters in the two strings the same?
5951219Skas  */
5961219Skas 
59731142Sedward anyof(s1, s2)
59831142Sedward 	register char *s1, *s2;
5991219Skas {
6001219Skas 
60131142Sedward 	while (*s1)
60231142Sedward 		if (index(s2, *s1++))
60331142Sedward 			return 1;
60431142Sedward 	return 0;
6051219Skas }
6061219Skas 
6071219Skas /*
60831142Sedward  * Convert c to upper case
6091219Skas  */
6101219Skas 
61131142Sedward raise(c)
61231142Sedward 	register c;
61331142Sedward {
61431142Sedward 
61531142Sedward 	if (islower(c))
61631142Sedward 		return toupper(c);
61731142Sedward 	return c;
61831142Sedward }
61931142Sedward 
62031142Sedward /*
62131142Sedward  * Copy s1 to s2, return pointer to null in s2.
62231142Sedward  */
62331142Sedward 
62431142Sedward char *
62531142Sedward copy(s1, s2)
6261219Skas 	register char *s1, *s2;
6271219Skas {
6281219Skas 
62931142Sedward 	while (*s2++ = *s1++)
63031142Sedward 		;
63131142Sedward 	return s2 - 1;
6321219Skas }
6331219Skas 
6341219Skas /*
6357571Skurt  * See if the given header field is supposed to be ignored.
6367571Skurt  */
63734692Sedward isign(field, ignore)
6387571Skurt 	char *field;
63934692Sedward 	struct ignoretab ignore[2];
6407571Skurt {
6417571Skurt 	char realfld[BUFSIZ];
6427571Skurt 
64318661Sserge 	/*
64418661Sserge 	 * Lower-case the string, so that "Status" and "status"
64518661Sserge 	 * will hash to the same place.
64618661Sserge 	 */
6477571Skurt 	istrcpy(realfld, field);
64834692Sedward 	if (ignore[1].i_count > 0)
64934692Sedward 		return (!member(realfld, ignore + 1));
65018661Sserge 	else
65118661Sserge 		return (member(realfld, ignore));
6527571Skurt }
65318661Sserge 
65418661Sserge member(realfield, table)
65518661Sserge 	register char *realfield;
65634692Sedward 	struct ignoretab *table;
65718661Sserge {
65818661Sserge 	register struct ignore *igp;
65918661Sserge 
66034692Sedward 	for (igp = table->i_head[hash(realfield)]; igp != 0; igp = igp->i_link)
66131142Sedward 		if (*igp->i_field == *realfield &&
66231142Sedward 		    equal(igp->i_field, realfield))
66318661Sserge 			return (1);
66418661Sserge 	return (0);
66518661Sserge }
666