xref: /csrg-svn/usr.bin/mail/aux.c (revision 36478)
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*36478Sedward static char sccsid[] = "@(#)aux.c	5.16 (Berkeley) 12/23/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 char *
351219Skas savestr(str)
361219Skas 	char *str;
371219Skas {
3834987Sedward 	char *new;
3934987Sedward 	int size = strlen(str) + 1;
401219Skas 
4134987Sedward 	if ((new = salloc(size)) != NOSTR)
4234987Sedward 		bcopy(str, new, size);
4334987Sedward 	return new;
441219Skas }
451219Skas 
461219Skas /*
471219Skas  * Announce a fatal error and die.
481219Skas  */
491219Skas 
5031142Sedward /*VARARGS1*/
5131142Sedward panic(fmt, a, b)
5231142Sedward 	char *fmt;
531219Skas {
5431142Sedward 	fprintf(stderr, "panic: ");
5531142Sedward 	fprintf(stderr, fmt, a, b);
5631142Sedward 	putc('\n', stderr);
571219Skas 	exit(1);
581219Skas }
591219Skas 
601219Skas /*
611219Skas  * Touch the named message by setting its MTOUCH flag.
621219Skas  * Touched messages have the effect of not being sent
631219Skas  * back to the system mailbox on exit.
641219Skas  */
6534987Sedward touch(mp)
6634987Sedward 	register struct message *mp;
671219Skas {
681479Skas 
691479Skas 	mp->m_flag |= MTOUCH;
701479Skas 	if ((mp->m_flag & MREAD) == 0)
711479Skas 		mp->m_flag |= MREAD|MSTATUS;
721219Skas }
731219Skas 
741219Skas /*
751219Skas  * Test to see if the passed file name is a directory.
761219Skas  * Return true if it is.
771219Skas  */
781219Skas isdir(name)
791219Skas 	char name[];
801219Skas {
811219Skas 	struct stat sbuf;
821219Skas 
831219Skas 	if (stat(name, &sbuf) < 0)
841219Skas 		return(0);
851219Skas 	return((sbuf.st_mode & S_IFMT) == S_IFDIR);
861219Skas }
871219Skas 
881219Skas /*
891219Skas  * Count the number of arguments in the given string raw list.
901219Skas  */
911219Skas argcount(argv)
921219Skas 	char **argv;
931219Skas {
941219Skas 	register char **ap;
951219Skas 
9631142Sedward 	for (ap = argv; *ap++ != NOSTR;)
971219Skas 		;
9831142Sedward 	return ap - argv - 1;
991219Skas }
1001219Skas 
1011219Skas /*
1021219Skas  * Return the desired header line from the passed message
1031219Skas  * pointer (or NOSTR if the desired header field is not available).
1041219Skas  */
1051219Skas char *
1061219Skas hfield(field, mp)
1071219Skas 	char field[];
1081219Skas 	struct message *mp;
1091219Skas {
1101219Skas 	register FILE *ibuf;
1111219Skas 	char linebuf[LINESIZE];
1121219Skas 	register int lc;
11331142Sedward 	register char *hfield;
11431142Sedward 	char *colon;
1151219Skas 
1161219Skas 	ibuf = setinput(mp);
11731142Sedward 	if ((lc = mp->m_lines - 1) < 0)
11831142Sedward 		return NOSTR;
119*36478Sedward 	if (readline(ibuf, linebuf, LINESIZE) < 0)
12031142Sedward 		return NOSTR;
12131142Sedward 	while (lc > 0) {
12231142Sedward 		if ((lc = gethfield(ibuf, linebuf, lc, &colon)) < 0)
12331142Sedward 			return NOSTR;
12431142Sedward 		if (hfield = ishfield(linebuf, colon, field))
12531142Sedward 			return savestr(hfield);
12631142Sedward 	}
12731142Sedward 	return NOSTR;
1281219Skas }
1291219Skas 
1301219Skas /*
1311219Skas  * Return the next header field found in the given message.
13231142Sedward  * Return >= 0 if something found, < 0 elsewise.
13331142Sedward  * "colon" is set to point to the colon in the header.
1341219Skas  * Must deal with \ continuations & other such fraud.
1351219Skas  */
13631142Sedward gethfield(f, linebuf, rem, colon)
1371219Skas 	register FILE *f;
1381219Skas 	char linebuf[];
1391219Skas 	register int rem;
14031142Sedward 	char **colon;
1411219Skas {
1421219Skas 	char line2[LINESIZE];
1431219Skas 	register char *cp, *cp2;
1441219Skas 	register int c;
1451219Skas 
1461219Skas 	for (;;) {
14731142Sedward 		if (--rem < 0)
14831142Sedward 			return -1;
149*36478Sedward 		if ((c = readline(f, linebuf, LINESIZE)) <= 0)
15031142Sedward 			return -1;
15131142Sedward 		for (cp = linebuf; isprint(*cp) && *cp != ' ' && *cp != ':';
15231142Sedward 		     cp++)
15331142Sedward 			;
15431142Sedward 		if (*cp != ':' || cp == linebuf)
1551219Skas 			continue;
1561219Skas 		/*
1571219Skas 		 * I guess we got a headline.
1581219Skas 		 * Handle wraparounding
1591219Skas 		 */
16031142Sedward 		*colon = cp;
16131142Sedward 		cp = linebuf + c;
1621219Skas 		for (;;) {
16331142Sedward 			while (--cp >= linebuf && (*cp == ' ' || *cp == '\t'))
16431142Sedward 				;
16531142Sedward 			cp++;
1661219Skas 			if (rem <= 0)
1671219Skas 				break;
16831142Sedward 			ungetc(c = getc(f), f);
16931142Sedward 			if (c != ' ' && c != '\t')
1701219Skas 				break;
171*36478Sedward 			if ((c = readline(f, line2, LINESIZE)) < 0)
1721219Skas 				break;
1731219Skas 			rem--;
17431142Sedward 			for (cp2 = line2; *cp2 == ' ' || *cp2 == '\t'; cp2++)
1751219Skas 				;
17631142Sedward 			c -= cp2 - line2;
17731142Sedward 			if (cp + c >= linebuf + LINESIZE - 2)
1781219Skas 				break;
1791219Skas 			*cp++ = ' ';
18031142Sedward 			bcopy(cp2, cp, c);
18131142Sedward 			cp += c;
1821219Skas 		}
18331142Sedward 		*cp = 0;
18431142Sedward 		return rem;
1851219Skas 	}
1861219Skas 	/* NOTREACHED */
1871219Skas }
1881219Skas 
1891219Skas /*
1901219Skas  * Check whether the passed line is a header line of
19131142Sedward  * the desired breed.  Return the field body, or 0.
1921219Skas  */
1931219Skas 
19431142Sedward char*
19531142Sedward ishfield(linebuf, colon, field)
1961219Skas 	char linebuf[], field[];
19731142Sedward 	char *colon;
1981219Skas {
19931142Sedward 	register char *cp = colon;
2001219Skas 
2011219Skas 	*cp = 0;
20234987Sedward 	if (strcasecmp(linebuf, field) != 0) {
20331142Sedward 		*cp = ':';
20431142Sedward 		return 0;
2051219Skas 	}
20631142Sedward 	*cp = ':';
20731142Sedward 	for (cp++; *cp == ' ' || *cp == '\t'; cp++)
20831142Sedward 		;
20931142Sedward 	return cp;
2101219Skas }
2111219Skas 
2121219Skas /*
2137571Skurt  * Copy a string, lowercasing it as we go.
2147571Skurt  */
2157571Skurt istrcpy(dest, src)
21631142Sedward 	register char *dest, *src;
2177571Skurt {
2187571Skurt 
2197571Skurt 	do {
22031142Sedward 		if (isupper(*src))
22131142Sedward 			*dest++ = tolower(*src);
22231142Sedward 		else
22331142Sedward 			*dest++ = *src;
22431142Sedward 	} while (*src++ != 0);
2257571Skurt }
2267571Skurt 
2277571Skurt /*
2281219Skas  * The following code deals with input stacking to do source
2291219Skas  * commands.  All but the current file pointer are saved on
2301219Skas  * the stack.
2311219Skas  */
2321219Skas 
23334965Sedward static	int	ssp;			/* Top of file stack */
2341519Skas struct sstack {
2351519Skas 	FILE	*s_file;		/* File we were in. */
2361519Skas 	int	s_cond;			/* Saved state of conditionals */
2375785Skurt 	int	s_loading;		/* Loading .mailrc, etc. */
23818661Sserge } sstack[NOFILE];
2391219Skas 
2401219Skas /*
2411219Skas  * Pushdown current input file and switch to a new one.
2421219Skas  * Set the global flag "sourcing" so that others will realize
2431219Skas  * that they are no longer reading from a tty (in all probability).
2441219Skas  */
24534966Sedward source(arglist)
24634966Sedward 	char **arglist;
2471219Skas {
24834966Sedward 	FILE *fi;
24934966Sedward 	char *cp;
2501219Skas 
25134966Sedward 	if ((cp = expand(*arglist)) == NOSTR)
2521219Skas 		return(1);
2533914Skurt 	if ((fi = fopen(cp, "r")) == NULL) {
2543914Skurt 		perror(cp);
2553914Skurt 		return(1);
2561219Skas 	}
25734965Sedward 	if (ssp >= NOFILE - 1) {
2581219Skas 		printf("Too much \"sourcing\" going on.\n");
2591219Skas 		fclose(fi);
2601219Skas 		return(1);
2611219Skas 	}
26234965Sedward 	sstack[ssp].s_file = input;
2631519Skas 	sstack[ssp].s_cond = cond;
2645785Skurt 	sstack[ssp].s_loading = loading;
26534965Sedward 	ssp++;
2665785Skurt 	loading = 0;
2671519Skas 	cond = CANY;
2681219Skas 	input = fi;
2691219Skas 	sourcing++;
2701219Skas 	return(0);
2711219Skas }
2721219Skas 
2731219Skas /*
2741219Skas  * Pop the current input back to the previous level.
2751219Skas  * Update the "sourcing" flag as appropriate.
2761219Skas  */
2771219Skas unstack()
2781219Skas {
27934965Sedward 	if (ssp <= 0) {
2801219Skas 		printf("\"Source\" stack over-pop.\n");
2811219Skas 		sourcing = 0;
2821219Skas 		return(1);
2831219Skas 	}
2841219Skas 	fclose(input);
2851519Skas 	if (cond != CANY)
2861519Skas 		printf("Unmatched \"if\"\n");
28734965Sedward 	ssp--;
2881519Skas 	cond = sstack[ssp].s_cond;
2895785Skurt 	loading = sstack[ssp].s_loading;
29034965Sedward 	input = sstack[ssp].s_file;
29134965Sedward 	if (ssp == 0)
2925785Skurt 		sourcing = loading;
2931219Skas 	return(0);
2941219Skas }
2951219Skas 
2961219Skas /*
2971219Skas  * Touch the indicated file.
2981219Skas  * This is nifty for the shell.
2991219Skas  */
3001219Skas alter(name)
3011219Skas 	char name[];
3021219Skas {
3031219Skas 	struct stat statb;
3041219Skas 	long time();
3051219Skas 	time_t time_p[2];
3061219Skas 
3071219Skas 	if (stat(name, &statb) < 0)
3081219Skas 		return;
3091219Skas 	time_p[0] = time((long *) 0) + 1;
3101219Skas 	time_p[1] = statb.st_mtime;
3111219Skas 	utime(name, time_p);
3121219Skas }
3131219Skas 
3141219Skas /*
3151219Skas  * Examine the passed line buffer and
3161219Skas  * return true if it is all blanks and tabs.
3171219Skas  */
3181219Skas blankline(linebuf)
3191219Skas 	char linebuf[];
3201219Skas {
3211219Skas 	register char *cp;
3221219Skas 
3231219Skas 	for (cp = linebuf; *cp; cp++)
32418661Sserge 		if (*cp != ' ' && *cp != '\t')
3251219Skas 			return(0);
3261219Skas 	return(1);
3271219Skas }
3281219Skas 
3291219Skas /*
3303195Skas  * Get sender's name from this message.  If the message has
3313195Skas  * a bunch of arpanet stuff in it, we may have to skin the name
3323195Skas  * before returning it.
3333195Skas  */
3343195Skas char *
3353195Skas nameof(mp, reptype)
3363195Skas 	register struct message *mp;
3373195Skas {
3385237Skurt 	register char *cp, *cp2;
3393195Skas 
3405237Skurt 	cp = skin(name1(mp, reptype));
3415237Skurt 	if (reptype != 0 || charcount(cp, '!') < 2)
3425237Skurt 		return(cp);
3435237Skurt 	cp2 = rindex(cp, '!');
3445237Skurt 	cp2--;
3455237Skurt 	while (cp2 > cp && *cp2 != '!')
3465237Skurt 		cp2--;
3475237Skurt 	if (*cp2 == '!')
3485237Skurt 		return(cp2 + 1);
3495237Skurt 	return(cp);
3503195Skas }
3513195Skas 
3523195Skas /*
35325912Smckusick  * Skin an arpa net address according to the RFC 822 interpretation
3543195Skas  * of "host-phrase."
3553195Skas  */
3563195Skas char *
3573195Skas skin(name)
3583195Skas 	char *name;
3593195Skas {
3603195Skas 	register int c;
3613195Skas 	register char *cp, *cp2;
36225912Smckusick 	char *bufend;
3633195Skas 	int gotlt, lastsp;
3643195Skas 	char nbuf[BUFSIZ];
36518661Sserge 	int nesting;
3663195Skas 
3673195Skas 	if (name == NOSTR)
3683195Skas 		return(NOSTR);
36912819Sleres 	if (index(name, '(') == NOSTR && index(name, '<') == NOSTR
37031142Sedward 	    && index(name, ' ') == NOSTR)
3713195Skas 		return(name);
3723195Skas 	gotlt = 0;
3733195Skas 	lastsp = 0;
37425912Smckusick 	bufend = nbuf;
37525912Smckusick 	for (cp = name, cp2 = bufend; c = *cp++; ) {
3763195Skas 		switch (c) {
3773195Skas 		case '(':
37825912Smckusick 			/*
37925912Smckusick 			 * Start of a "comment".
38025912Smckusick 			 * Ignore it.
38125912Smckusick 			 */
38218661Sserge 			nesting = 1;
38325912Smckusick 			while ((c = *cp) != 0) {
38425912Smckusick 				cp++;
38525912Smckusick 				switch (c) {
38625912Smckusick 				case '\\':
38725912Smckusick 					if (*cp == 0)
38825912Smckusick 						goto outcm;
38925912Smckusick 					cp++;
39025912Smckusick 					break;
39118661Sserge 				case '(':
39218661Sserge 					nesting++;
39318661Sserge 					break;
39418661Sserge 
39518661Sserge 				case ')':
39618661Sserge 					--nesting;
39718661Sserge 					break;
39818661Sserge 				}
39918661Sserge 
40018661Sserge 				if (nesting <= 0)
40118661Sserge 					break;
40218661Sserge 			}
40325912Smckusick 		outcm:
40412819Sleres 			lastsp = 0;
4053195Skas 			break;
4063195Skas 
40725912Smckusick 		case '"':
40825912Smckusick 			/*
40925912Smckusick 			 * Start of a "quoted-string".
41025912Smckusick 			 * Copy it in its entirety.
41125912Smckusick 			 */
41225912Smckusick 			while ((c = *cp) != 0) {
41325912Smckusick 				cp++;
41425912Smckusick 				switch (c) {
41525912Smckusick 				case '\\':
41625912Smckusick 					if ((c = *cp) == 0)
41725912Smckusick 						goto outqs;
41825912Smckusick 					cp++;
41925912Smckusick 					break;
42025912Smckusick 				case '"':
42125912Smckusick 					goto outqs;
42225912Smckusick 				}
42325912Smckusick 				*cp2++ = c;
42425912Smckusick 			}
42525912Smckusick 		outqs:
42625912Smckusick 			lastsp = 0;
42725912Smckusick 			break;
42825912Smckusick 
4293195Skas 		case ' ':
43012819Sleres 			if (cp[0] == 'a' && cp[1] == 't' && cp[2] == ' ')
43112819Sleres 				cp += 3, *cp2++ = '@';
43212819Sleres 			else
43312819Sleres 			if (cp[0] == '@' && cp[1] == ' ')
43412819Sleres 				cp += 2, *cp2++ = '@';
43512819Sleres 			else
43612819Sleres 				lastsp = 1;
4373195Skas 			break;
4383195Skas 
4393195Skas 		case '<':
44025912Smckusick 			cp2 = bufend;
4413195Skas 			gotlt++;
4423195Skas 			lastsp = 0;
4433195Skas 			break;
4443195Skas 
4453195Skas 		case '>':
44625912Smckusick 			if (gotlt) {
44725912Smckusick 				gotlt = 0;
44825912Smckusick 				while (*cp != ',' && *cp != 0)
44925912Smckusick 					cp++;
45025912Smckusick 				if (*cp == 0 )
45125912Smckusick 					goto done;
45225912Smckusick 				*cp2++ = ',';
45325912Smckusick 				*cp2++ = ' ';
45425912Smckusick 				bufend = cp2;
45525912Smckusick 				break;
45625912Smckusick 			}
4573195Skas 
4583195Skas 			/* Fall into . . . */
4593195Skas 
4603195Skas 		default:
4613195Skas 			if (lastsp) {
4623195Skas 				lastsp = 0;
4633195Skas 				*cp2++ = ' ';
4643195Skas 			}
4653195Skas 			*cp2++ = c;
4663195Skas 			break;
4673195Skas 		}
4683195Skas 	}
4693195Skas done:
4703195Skas 	*cp2 = 0;
4713195Skas 
4723195Skas 	return(savestr(nbuf));
4733195Skas }
4743195Skas 
4753195Skas /*
4761219Skas  * Fetch the sender's name from the passed message.
4773195Skas  * Reptype can be
4783195Skas  *	0 -- get sender's name for display purposes
4793195Skas  *	1 -- get sender's name for reply
4803195Skas  *	2 -- get sender's name for Reply
4811219Skas  */
4821219Skas char *
4833195Skas name1(mp, reptype)
4841219Skas 	register struct message *mp;
4851219Skas {
4861219Skas 	char namebuf[LINESIZE];
4871219Skas 	char linebuf[LINESIZE];
4881219Skas 	register char *cp, *cp2;
4891219Skas 	register FILE *ibuf;
4901219Skas 	int first = 1;
4911219Skas 
4923195Skas 	if ((cp = hfield("from", mp)) != NOSTR)
49331142Sedward 		return cp;
4943195Skas 	if (reptype == 0 && (cp = hfield("sender", mp)) != NOSTR)
49531142Sedward 		return cp;
4961219Skas 	ibuf = setinput(mp);
49731142Sedward 	namebuf[0] = 0;
498*36478Sedward 	if (readline(ibuf, linebuf, LINESIZE) < 0)
4991219Skas 		return(savestr(namebuf));
5001219Skas newname:
50131142Sedward 	for (cp = linebuf; *cp && *cp != ' '; cp++)
5021219Skas 		;
50331142Sedward 	for (; *cp == ' ' || *cp == '\t'; cp++)
5041219Skas 		;
50531142Sedward 	for (cp2 = &namebuf[strlen(namebuf)];
50631142Sedward 	     *cp && *cp != ' ' && *cp != '\t' && cp2 < namebuf + LINESIZE - 1;)
50731142Sedward 		*cp2++ = *cp++;
5081219Skas 	*cp2 = '\0';
509*36478Sedward 	if (readline(ibuf, linebuf, LINESIZE) < 0)
5101219Skas 		return(savestr(namebuf));
5111219Skas 	if ((cp = index(linebuf, 'F')) == NULL)
5121219Skas 		return(savestr(namebuf));
5131219Skas 	if (strncmp(cp, "From", 4) != 0)
5141219Skas 		return(savestr(namebuf));
5151219Skas 	while ((cp = index(cp, 'r')) != NULL) {
5161219Skas 		if (strncmp(cp, "remote", 6) == 0) {
5171219Skas 			if ((cp = index(cp, 'f')) == NULL)
5181219Skas 				break;
5191219Skas 			if (strncmp(cp, "from", 4) != 0)
5201219Skas 				break;
5211219Skas 			if ((cp = index(cp, ' ')) == NULL)
5221219Skas 				break;
5231219Skas 			cp++;
5241219Skas 			if (first) {
52531142Sedward 				strcpy(namebuf, cp);
5261219Skas 				first = 0;
5271219Skas 			} else
5281219Skas 				strcpy(rindex(namebuf, '!')+1, cp);
5291219Skas 			strcat(namebuf, "!");
5301219Skas 			goto newname;
5311219Skas 		}
5321219Skas 		cp++;
5331219Skas 	}
5341219Skas 	return(savestr(namebuf));
5351219Skas }
5361219Skas 
5371219Skas /*
5385237Skurt  * Count the occurances of c in str
5395237Skurt  */
5405237Skurt charcount(str, c)
5415237Skurt 	char *str;
5425237Skurt {
5435237Skurt 	register char *cp;
5445237Skurt 	register int i;
5455237Skurt 
5465237Skurt 	for (i = 0, cp = str; *cp; cp++)
5475237Skurt 		if (*cp == c)
5485237Skurt 			i++;
5495237Skurt 	return(i);
5505237Skurt }
5515237Skurt 
5525237Skurt /*
55331142Sedward  * Are any of the characters in the two strings the same?
5541219Skas  */
55531142Sedward anyof(s1, s2)
55631142Sedward 	register char *s1, *s2;
5571219Skas {
5581219Skas 
55931142Sedward 	while (*s1)
56031142Sedward 		if (index(s2, *s1++))
56131142Sedward 			return 1;
56231142Sedward 	return 0;
5631219Skas }
5641219Skas 
5651219Skas /*
56631142Sedward  * Convert c to upper case
5671219Skas  */
56831142Sedward raise(c)
56931142Sedward 	register c;
57031142Sedward {
57131142Sedward 
57231142Sedward 	if (islower(c))
57331142Sedward 		return toupper(c);
57431142Sedward 	return c;
57531142Sedward }
57631142Sedward 
57731142Sedward /*
57831142Sedward  * Copy s1 to s2, return pointer to null in s2.
57931142Sedward  */
58031142Sedward char *
58131142Sedward copy(s1, s2)
5821219Skas 	register char *s1, *s2;
5831219Skas {
5841219Skas 
58531142Sedward 	while (*s2++ = *s1++)
58631142Sedward 		;
58731142Sedward 	return s2 - 1;
5881219Skas }
5891219Skas 
5901219Skas /*
5917571Skurt  * See if the given header field is supposed to be ignored.
5927571Skurt  */
59334692Sedward isign(field, ignore)
5947571Skurt 	char *field;
59534692Sedward 	struct ignoretab ignore[2];
5967571Skurt {
5977571Skurt 	char realfld[BUFSIZ];
5987571Skurt 
59934969Sedward 	if (ignore == ignoreall)
60034969Sedward 		return 1;
60118661Sserge 	/*
60218661Sserge 	 * Lower-case the string, so that "Status" and "status"
60318661Sserge 	 * will hash to the same place.
60418661Sserge 	 */
6057571Skurt 	istrcpy(realfld, field);
60634692Sedward 	if (ignore[1].i_count > 0)
60734692Sedward 		return (!member(realfld, ignore + 1));
60818661Sserge 	else
60918661Sserge 		return (member(realfld, ignore));
6107571Skurt }
61118661Sserge 
61218661Sserge member(realfield, table)
61318661Sserge 	register char *realfield;
61434692Sedward 	struct ignoretab *table;
61518661Sserge {
61618661Sserge 	register struct ignore *igp;
61718661Sserge 
61834692Sedward 	for (igp = table->i_head[hash(realfield)]; igp != 0; igp = igp->i_link)
61931142Sedward 		if (*igp->i_field == *realfield &&
62031142Sedward 		    equal(igp->i_field, realfield))
62118661Sserge 			return (1);
62218661Sserge 	return (0);
62318661Sserge }
624