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 633499Sbostic * provided that this notice is preserved and that due credit is given 733499Sbostic * to the University of California at Berkeley. The name of the University 833499Sbostic * may not be used to endorse or promote products derived from this 933499Sbostic * software without specific prior written permission. This software 1033499Sbostic * is provided ``as is'' without express or implied warranty. 1122444Sdist */ 1222444Sdist 1333499Sbostic #ifdef notdef 14*34692Sedward static char sccsid[] = "@(#)aux.c 5.8 (Berkeley) 06/09/88"; 1533499Sbostic #endif /* notdef */ 161219Skas 171219Skas #include "rcv.h" 181219Skas #include <sys/stat.h> 191219Skas 201219Skas /* 211219Skas * Mail -- a mail program 221219Skas * 231219Skas * Auxiliary functions. 241219Skas */ 251219Skas 261219Skas /* 271219Skas * Return a pointer to a dynamic copy of the argument. 281219Skas */ 291219Skas 301219Skas char * 311219Skas savestr(str) 321219Skas char *str; 331219Skas { 341219Skas register char *cp, *cp2, *top; 351219Skas 361219Skas for (cp = str; *cp; cp++) 371219Skas ; 381219Skas top = salloc(cp-str + 1); 391219Skas if (top == NOSTR) 401219Skas return(NOSTR); 411219Skas for (cp = str, cp2 = top; *cp; cp++) 421219Skas *cp2++ = *cp; 431219Skas *cp2 = 0; 441219Skas return(top); 451219Skas } 461219Skas 471219Skas /* 481219Skas * Announce a fatal error and die. 491219Skas */ 501219Skas 5131142Sedward /*VARARGS1*/ 5231142Sedward panic(fmt, a, b) 5331142Sedward char *fmt; 541219Skas { 5531142Sedward fprintf(stderr, "panic: "); 5631142Sedward fprintf(stderr, fmt, a, b); 5731142Sedward putc('\n', stderr); 581219Skas exit(1); 591219Skas } 601219Skas 611219Skas /* 621219Skas * Touch the named message by setting its MTOUCH flag. 631219Skas * Touched messages have the effect of not being sent 641219Skas * back to the system mailbox on exit. 651219Skas */ 661219Skas 671219Skas touch(mesg) 681219Skas { 691479Skas register struct message *mp; 701479Skas 711479Skas if (mesg < 1 || mesg > msgCount) 721479Skas return; 731479Skas mp = &message[mesg-1]; 741479Skas mp->m_flag |= MTOUCH; 751479Skas if ((mp->m_flag & MREAD) == 0) 761479Skas mp->m_flag |= MREAD|MSTATUS; 771219Skas } 781219Skas 791219Skas /* 801219Skas * Test to see if the passed file name is a directory. 811219Skas * Return true if it is. 821219Skas */ 831219Skas 841219Skas isdir(name) 851219Skas char name[]; 861219Skas { 871219Skas struct stat sbuf; 881219Skas 891219Skas if (stat(name, &sbuf) < 0) 901219Skas return(0); 911219Skas return((sbuf.st_mode & S_IFMT) == S_IFDIR); 921219Skas } 931219Skas 941219Skas /* 951219Skas * Count the number of arguments in the given string raw list. 961219Skas */ 971219Skas 981219Skas argcount(argv) 991219Skas char **argv; 1001219Skas { 1011219Skas register char **ap; 1021219Skas 10331142Sedward for (ap = argv; *ap++ != NOSTR;) 1041219Skas ; 10531142Sedward return ap - argv - 1; 1061219Skas } 1071219Skas 1081219Skas /* 1091219Skas * Return the desired header line from the passed message 1101219Skas * pointer (or NOSTR if the desired header field is not available). 1111219Skas */ 1121219Skas 1131219Skas char * 1141219Skas hfield(field, mp) 1151219Skas char field[]; 1161219Skas struct message *mp; 1171219Skas { 1181219Skas register FILE *ibuf; 1191219Skas char linebuf[LINESIZE]; 1201219Skas register int lc; 12131142Sedward register char *hfield; 12231142Sedward char *colon; 1231219Skas 1241219Skas ibuf = setinput(mp); 12531142Sedward if ((lc = mp->m_lines - 1) < 0) 12631142Sedward return NOSTR; 1271219Skas if (readline(ibuf, linebuf) < 0) 12831142Sedward return NOSTR; 12931142Sedward while (lc > 0) { 13031142Sedward if ((lc = gethfield(ibuf, linebuf, lc, &colon)) < 0) 13131142Sedward return NOSTR; 13231142Sedward if (hfield = ishfield(linebuf, colon, field)) 13331142Sedward return savestr(hfield); 13431142Sedward } 13531142Sedward return NOSTR; 1361219Skas } 1371219Skas 1381219Skas /* 1391219Skas * Return the next header field found in the given message. 14031142Sedward * Return >= 0 if something found, < 0 elsewise. 14131142Sedward * "colon" is set to point to the colon in the header. 1421219Skas * Must deal with \ continuations & other such fraud. 1431219Skas */ 1441219Skas 14531142Sedward gethfield(f, linebuf, rem, colon) 1461219Skas register FILE *f; 1471219Skas char linebuf[]; 1481219Skas register int rem; 14931142Sedward char **colon; 1501219Skas { 1511219Skas char line2[LINESIZE]; 1521219Skas register char *cp, *cp2; 1531219Skas register int c; 1541219Skas 1551219Skas for (;;) { 15631142Sedward if (--rem < 0) 15731142Sedward return -1; 15831142Sedward if ((c = readline(f, linebuf)) <= 0) 15931142Sedward return -1; 16031142Sedward for (cp = linebuf; isprint(*cp) && *cp != ' ' && *cp != ':'; 16131142Sedward cp++) 16231142Sedward ; 16331142Sedward if (*cp != ':' || cp == linebuf) 1641219Skas continue; 1651219Skas /* 1661219Skas * I guess we got a headline. 1671219Skas * Handle wraparounding 1681219Skas */ 16931142Sedward *colon = cp; 17031142Sedward cp = linebuf + c; 1711219Skas for (;;) { 17231142Sedward while (--cp >= linebuf && (*cp == ' ' || *cp == '\t')) 17331142Sedward ; 17431142Sedward cp++; 1751219Skas if (rem <= 0) 1761219Skas break; 17731142Sedward ungetc(c = getc(f), f); 17831142Sedward if (c != ' ' && c != '\t') 1791219Skas break; 18031142Sedward if ((c = readline(f, line2)) < 0) 1811219Skas break; 1821219Skas rem--; 18331142Sedward for (cp2 = line2; *cp2 == ' ' || *cp2 == '\t'; cp2++) 1841219Skas ; 18531142Sedward c -= cp2 - line2; 18631142Sedward if (cp + c >= linebuf + LINESIZE - 2) 1871219Skas break; 1881219Skas *cp++ = ' '; 18931142Sedward bcopy(cp2, cp, c); 19031142Sedward cp += c; 1911219Skas } 19231142Sedward *cp = 0; 19331142Sedward return rem; 1941219Skas } 1951219Skas /* NOTREACHED */ 1961219Skas } 1971219Skas 1981219Skas /* 1991219Skas * Check whether the passed line is a header line of 20031142Sedward * the desired breed. Return the field body, or 0. 2011219Skas */ 2021219Skas 20331142Sedward char* 20431142Sedward ishfield(linebuf, colon, field) 2051219Skas char linebuf[], field[]; 20631142Sedward char *colon; 2071219Skas { 20831142Sedward register char *cp = colon; 2091219Skas 2101219Skas *cp = 0; 21131142Sedward if (!icequal(linebuf, field)) { 21231142Sedward *cp = ':'; 21331142Sedward return 0; 2141219Skas } 21531142Sedward *cp = ':'; 21631142Sedward for (cp++; *cp == ' ' || *cp == '\t'; cp++) 21731142Sedward ; 21831142Sedward return cp; 2191219Skas } 2201219Skas 2211219Skas /* 2221219Skas * Compare two strings, ignoring case. 2231219Skas */ 2241219Skas 2251219Skas icequal(s1, s2) 2261219Skas register char *s1, *s2; 2271219Skas { 22831142Sedward register c1, c2; 2291219Skas 23031142Sedward for (;;) { 23131142Sedward if ((c1 = (unsigned char)*s1++) != 23231142Sedward (c2 = (unsigned char)*s2++)) { 23331142Sedward if (isupper(c1)) 23431142Sedward c1 = tolower(c1); 23531142Sedward if (c1 != c2) 23631142Sedward return 0; 23731142Sedward } 23831142Sedward if (c1 == 0) 23931142Sedward return 1; 24031142Sedward } 24131142Sedward /*NOTREACHED*/ 2421219Skas } 2431219Skas 2441219Skas /* 2457571Skurt * Copy a string, lowercasing it as we go. 2467571Skurt */ 2477571Skurt istrcpy(dest, src) 24831142Sedward register char *dest, *src; 2497571Skurt { 2507571Skurt 2517571Skurt do { 25231142Sedward if (isupper(*src)) 25331142Sedward *dest++ = tolower(*src); 25431142Sedward else 25531142Sedward *dest++ = *src; 25631142Sedward } while (*src++ != 0); 2577571Skurt } 2587571Skurt 2597571Skurt /* 2601219Skas * The following code deals with input stacking to do source 2611219Skas * commands. All but the current file pointer are saved on 2621219Skas * the stack. 2631219Skas */ 2641219Skas 2651219Skas static int ssp = -1; /* Top of file stack */ 2661519Skas struct sstack { 2671519Skas FILE *s_file; /* File we were in. */ 2681519Skas int s_cond; /* Saved state of conditionals */ 2695785Skurt int s_loading; /* Loading .mailrc, etc. */ 27018661Sserge } sstack[NOFILE]; 2711219Skas 2721219Skas /* 2731219Skas * Pushdown current input file and switch to a new one. 2741219Skas * Set the global flag "sourcing" so that others will realize 2751219Skas * that they are no longer reading from a tty (in all probability). 2761219Skas */ 2771219Skas 2781219Skas source(name) 2791219Skas char name[]; 2801219Skas { 2811219Skas register FILE *fi; 2823914Skurt register char *cp; 2831219Skas 2843914Skurt if ((cp = expand(name)) == NOSTR) 2851219Skas return(1); 2863914Skurt if ((fi = fopen(cp, "r")) == NULL) { 2873914Skurt perror(cp); 2883914Skurt return(1); 2891219Skas } 29018661Sserge if (ssp >= NOFILE - 2) { 2911219Skas printf("Too much \"sourcing\" going on.\n"); 2921219Skas fclose(fi); 2931219Skas return(1); 2941219Skas } 2951519Skas sstack[++ssp].s_file = input; 2961519Skas sstack[ssp].s_cond = cond; 2975785Skurt sstack[ssp].s_loading = loading; 2985785Skurt loading = 0; 2991519Skas cond = CANY; 3001219Skas input = fi; 3011219Skas sourcing++; 3021219Skas return(0); 3031219Skas } 3041219Skas 3051219Skas /* 3061219Skas * Pop the current input back to the previous level. 3071219Skas * Update the "sourcing" flag as appropriate. 3081219Skas */ 3091219Skas 3101219Skas unstack() 3111219Skas { 3121219Skas if (ssp < 0) { 3131219Skas printf("\"Source\" stack over-pop.\n"); 3141219Skas sourcing = 0; 3151219Skas return(1); 3161219Skas } 3171219Skas fclose(input); 3181519Skas if (cond != CANY) 3191519Skas printf("Unmatched \"if\"\n"); 3201519Skas cond = sstack[ssp].s_cond; 3215785Skurt loading = sstack[ssp].s_loading; 3221519Skas input = sstack[ssp--].s_file; 3231219Skas if (ssp < 0) 3245785Skurt sourcing = loading; 3251219Skas return(0); 3261219Skas } 3271219Skas 3281219Skas /* 3291219Skas * Touch the indicated file. 3301219Skas * This is nifty for the shell. 3311219Skas * If we have the utime() system call, this is better served 3321219Skas * by using that, since it will work for empty files. 3331219Skas * On non-utime systems, we must sleep a second, then read. 3341219Skas */ 3351219Skas 3361219Skas alter(name) 3371219Skas char name[]; 3381219Skas { 3391219Skas #ifdef UTIME 3401219Skas struct stat statb; 3411219Skas long time(); 3421219Skas time_t time_p[2]; 3431219Skas #else 3441219Skas register int pid, f; 3451219Skas char w; 3461219Skas #endif UTIME 3471219Skas 3481219Skas #ifdef UTIME 3491219Skas if (stat(name, &statb) < 0) 3501219Skas return; 3511219Skas time_p[0] = time((long *) 0) + 1; 3521219Skas time_p[1] = statb.st_mtime; 3531219Skas utime(name, time_p); 3541219Skas #else 3551219Skas sleep(1); 3561219Skas if ((f = open(name, 0)) < 0) 3574389Skurt return; 3581219Skas read(f, &w, 1); 3591219Skas exit(0); 3601219Skas #endif 3611219Skas } 3621219Skas 3631219Skas /* 3641219Skas * Examine the passed line buffer and 3651219Skas * return true if it is all blanks and tabs. 3661219Skas */ 3671219Skas 3681219Skas blankline(linebuf) 3691219Skas char linebuf[]; 3701219Skas { 3711219Skas register char *cp; 3721219Skas 3731219Skas for (cp = linebuf; *cp; cp++) 37418661Sserge if (*cp != ' ' && *cp != '\t') 3751219Skas return(0); 3761219Skas return(1); 3771219Skas } 3781219Skas 3791219Skas /* 3803195Skas * Get sender's name from this message. If the message has 3813195Skas * a bunch of arpanet stuff in it, we may have to skin the name 3823195Skas * before returning it. 3833195Skas */ 3843195Skas char * 3853195Skas nameof(mp, reptype) 3863195Skas register struct message *mp; 3873195Skas { 3885237Skurt register char *cp, *cp2; 3893195Skas 3905237Skurt cp = skin(name1(mp, reptype)); 3915237Skurt if (reptype != 0 || charcount(cp, '!') < 2) 3925237Skurt return(cp); 3935237Skurt cp2 = rindex(cp, '!'); 3945237Skurt cp2--; 3955237Skurt while (cp2 > cp && *cp2 != '!') 3965237Skurt cp2--; 3975237Skurt if (*cp2 == '!') 3985237Skurt return(cp2 + 1); 3995237Skurt return(cp); 4003195Skas } 4013195Skas 4023195Skas /* 40325912Smckusick * Skin an arpa net address according to the RFC 822 interpretation 4043195Skas * of "host-phrase." 4053195Skas */ 4063195Skas char * 4073195Skas skin(name) 4083195Skas char *name; 4093195Skas { 4103195Skas register int c; 4113195Skas register char *cp, *cp2; 41225912Smckusick char *bufend; 4133195Skas int gotlt, lastsp; 4143195Skas char nbuf[BUFSIZ]; 41518661Sserge int nesting; 4163195Skas 4173195Skas if (name == NOSTR) 4183195Skas return(NOSTR); 41912819Sleres if (index(name, '(') == NOSTR && index(name, '<') == NOSTR 42031142Sedward && index(name, ' ') == NOSTR) 4213195Skas return(name); 4223195Skas gotlt = 0; 4233195Skas lastsp = 0; 42425912Smckusick bufend = nbuf; 42525912Smckusick for (cp = name, cp2 = bufend; c = *cp++; ) { 4263195Skas switch (c) { 4273195Skas case '(': 42825912Smckusick /* 42925912Smckusick * Start of a "comment". 43025912Smckusick * Ignore it. 43125912Smckusick */ 43218661Sserge nesting = 1; 43325912Smckusick while ((c = *cp) != 0) { 43425912Smckusick cp++; 43525912Smckusick switch (c) { 43625912Smckusick case '\\': 43725912Smckusick if (*cp == 0) 43825912Smckusick goto outcm; 43925912Smckusick cp++; 44025912Smckusick break; 44118661Sserge case '(': 44218661Sserge nesting++; 44318661Sserge break; 44418661Sserge 44518661Sserge case ')': 44618661Sserge --nesting; 44718661Sserge break; 44818661Sserge } 44918661Sserge 45018661Sserge if (nesting <= 0) 45118661Sserge break; 45218661Sserge } 45325912Smckusick outcm: 45412819Sleres lastsp = 0; 4553195Skas break; 4563195Skas 45725912Smckusick case '"': 45825912Smckusick /* 45925912Smckusick * Start of a "quoted-string". 46025912Smckusick * Copy it in its entirety. 46125912Smckusick */ 46225912Smckusick while ((c = *cp) != 0) { 46325912Smckusick cp++; 46425912Smckusick switch (c) { 46525912Smckusick case '\\': 46625912Smckusick if ((c = *cp) == 0) 46725912Smckusick goto outqs; 46825912Smckusick cp++; 46925912Smckusick break; 47025912Smckusick case '"': 47125912Smckusick goto outqs; 47225912Smckusick } 47325912Smckusick *cp2++ = c; 47425912Smckusick } 47525912Smckusick outqs: 47625912Smckusick lastsp = 0; 47725912Smckusick break; 47825912Smckusick 4793195Skas case ' ': 48012819Sleres if (cp[0] == 'a' && cp[1] == 't' && cp[2] == ' ') 48112819Sleres cp += 3, *cp2++ = '@'; 48212819Sleres else 48312819Sleres if (cp[0] == '@' && cp[1] == ' ') 48412819Sleres cp += 2, *cp2++ = '@'; 48512819Sleres else 48612819Sleres lastsp = 1; 4873195Skas break; 4883195Skas 4893195Skas case '<': 49025912Smckusick cp2 = bufend; 4913195Skas gotlt++; 4923195Skas lastsp = 0; 4933195Skas break; 4943195Skas 4953195Skas case '>': 49625912Smckusick if (gotlt) { 49725912Smckusick gotlt = 0; 49825912Smckusick while (*cp != ',' && *cp != 0) 49925912Smckusick cp++; 50025912Smckusick if (*cp == 0 ) 50125912Smckusick goto done; 50225912Smckusick *cp2++ = ','; 50325912Smckusick *cp2++ = ' '; 50425912Smckusick bufend = cp2; 50525912Smckusick break; 50625912Smckusick } 5073195Skas 5083195Skas /* Fall into . . . */ 5093195Skas 5103195Skas default: 5113195Skas if (lastsp) { 5123195Skas lastsp = 0; 5133195Skas *cp2++ = ' '; 5143195Skas } 5153195Skas *cp2++ = c; 5163195Skas break; 5173195Skas } 5183195Skas } 5193195Skas done: 5203195Skas *cp2 = 0; 5213195Skas 5223195Skas return(savestr(nbuf)); 5233195Skas } 5243195Skas 5253195Skas /* 5261219Skas * Fetch the sender's name from the passed message. 5273195Skas * Reptype can be 5283195Skas * 0 -- get sender's name for display purposes 5293195Skas * 1 -- get sender's name for reply 5303195Skas * 2 -- get sender's name for Reply 5311219Skas */ 5321219Skas 5331219Skas char * 5343195Skas name1(mp, reptype) 5351219Skas register struct message *mp; 5361219Skas { 5371219Skas char namebuf[LINESIZE]; 5381219Skas char linebuf[LINESIZE]; 5391219Skas register char *cp, *cp2; 5401219Skas register FILE *ibuf; 5411219Skas int first = 1; 5421219Skas 5433195Skas if ((cp = hfield("from", mp)) != NOSTR) 54431142Sedward return cp; 5453195Skas if (reptype == 0 && (cp = hfield("sender", mp)) != NOSTR) 54631142Sedward return cp; 5471219Skas ibuf = setinput(mp); 54831142Sedward namebuf[0] = 0; 54931142Sedward if (readline(ibuf, linebuf) < 0) 5501219Skas return(savestr(namebuf)); 5511219Skas newname: 55231142Sedward for (cp = linebuf; *cp && *cp != ' '; cp++) 5531219Skas ; 55431142Sedward for (; *cp == ' ' || *cp == '\t'; cp++) 5551219Skas ; 55631142Sedward for (cp2 = &namebuf[strlen(namebuf)]; 55731142Sedward *cp && *cp != ' ' && *cp != '\t' && cp2 < namebuf + LINESIZE - 1;) 55831142Sedward *cp2++ = *cp++; 5591219Skas *cp2 = '\0'; 56031142Sedward if (readline(ibuf, linebuf) < 0) 5611219Skas return(savestr(namebuf)); 5621219Skas if ((cp = index(linebuf, 'F')) == NULL) 5631219Skas return(savestr(namebuf)); 5641219Skas if (strncmp(cp, "From", 4) != 0) 5651219Skas return(savestr(namebuf)); 5661219Skas while ((cp = index(cp, 'r')) != NULL) { 5671219Skas if (strncmp(cp, "remote", 6) == 0) { 5681219Skas if ((cp = index(cp, 'f')) == NULL) 5691219Skas break; 5701219Skas if (strncmp(cp, "from", 4) != 0) 5711219Skas break; 5721219Skas if ((cp = index(cp, ' ')) == NULL) 5731219Skas break; 5741219Skas cp++; 5751219Skas if (first) { 57631142Sedward strcpy(namebuf, cp); 5771219Skas first = 0; 5781219Skas } else 5791219Skas strcpy(rindex(namebuf, '!')+1, cp); 5801219Skas strcat(namebuf, "!"); 5811219Skas goto newname; 5821219Skas } 5831219Skas cp++; 5841219Skas } 5851219Skas return(savestr(namebuf)); 5861219Skas } 5871219Skas 5881219Skas /* 5895237Skurt * Count the occurances of c in str 5905237Skurt */ 5915237Skurt charcount(str, c) 5925237Skurt char *str; 5935237Skurt { 5945237Skurt register char *cp; 5955237Skurt register int i; 5965237Skurt 5975237Skurt for (i = 0, cp = str; *cp; cp++) 5985237Skurt if (*cp == c) 5995237Skurt i++; 6005237Skurt return(i); 6015237Skurt } 6025237Skurt 6035237Skurt /* 60431142Sedward * Are any of the characters in the two strings the same? 6051219Skas */ 6061219Skas 60731142Sedward anyof(s1, s2) 60831142Sedward register char *s1, *s2; 6091219Skas { 6101219Skas 61131142Sedward while (*s1) 61231142Sedward if (index(s2, *s1++)) 61331142Sedward return 1; 61431142Sedward return 0; 6151219Skas } 6161219Skas 6171219Skas /* 61831142Sedward * Convert c to upper case 6191219Skas */ 6201219Skas 62131142Sedward raise(c) 62231142Sedward register c; 62331142Sedward { 62431142Sedward 62531142Sedward if (islower(c)) 62631142Sedward return toupper(c); 62731142Sedward return c; 62831142Sedward } 62931142Sedward 63031142Sedward /* 63131142Sedward * Copy s1 to s2, return pointer to null in s2. 63231142Sedward */ 63331142Sedward 63431142Sedward char * 63531142Sedward copy(s1, s2) 6361219Skas register char *s1, *s2; 6371219Skas { 6381219Skas 63931142Sedward while (*s2++ = *s1++) 64031142Sedward ; 64131142Sedward return s2 - 1; 6421219Skas } 6431219Skas 6441219Skas /* 64531142Sedward * Add a single character onto a string. 64631142Sedward */ 64731142Sedward 64831142Sedward stradd(str, c) 64931142Sedward register char *str; 65031142Sedward { 65131142Sedward 65231142Sedward while (*str++) 65331142Sedward ; 65431142Sedward str[-1] = c; 65531142Sedward *str = 0; 65631142Sedward } 65731142Sedward 65831142Sedward /* 6597571Skurt * See if the given header field is supposed to be ignored. 6607571Skurt */ 661*34692Sedward isign(field, ignore) 6627571Skurt char *field; 663*34692Sedward struct ignoretab ignore[2]; 6647571Skurt { 6657571Skurt char realfld[BUFSIZ]; 6667571Skurt 66718661Sserge /* 66818661Sserge * Lower-case the string, so that "Status" and "status" 66918661Sserge * will hash to the same place. 67018661Sserge */ 6717571Skurt istrcpy(realfld, field); 672*34692Sedward if (ignore[1].i_count > 0) 673*34692Sedward return (!member(realfld, ignore + 1)); 67418661Sserge else 67518661Sserge return (member(realfld, ignore)); 6767571Skurt } 67718661Sserge 67818661Sserge member(realfield, table) 67918661Sserge register char *realfield; 680*34692Sedward struct ignoretab *table; 68118661Sserge { 68218661Sserge register struct ignore *igp; 68318661Sserge 684*34692Sedward for (igp = table->i_head[hash(realfield)]; igp != 0; igp = igp->i_link) 68531142Sedward if (*igp->i_field == *realfield && 68631142Sedward equal(igp->i_field, realfield)) 68718661Sserge return (1); 68818661Sserge return (0); 68918661Sserge } 690