10bee4c2cSEd Schouten /* 20bee4c2cSEd Schouten * Copyright (c) 1980, 1993 30bee4c2cSEd Schouten * The Regents of the University of California. All rights reserved. 40bee4c2cSEd Schouten * 50bee4c2cSEd Schouten * Redistribution and use in source and binary forms, with or without 60bee4c2cSEd Schouten * modification, are permitted provided that the following conditions 70bee4c2cSEd Schouten * are met: 80bee4c2cSEd Schouten * 1. Redistributions of source code must retain the above copyright 90bee4c2cSEd Schouten * notice, this list of conditions and the following disclaimer. 100bee4c2cSEd Schouten * 2. Redistributions in binary form must reproduce the above copyright 110bee4c2cSEd Schouten * notice, this list of conditions and the following disclaimer in the 120bee4c2cSEd Schouten * documentation and/or other materials provided with the distribution. 130bee4c2cSEd Schouten * 3. All advertising materials mentioning features or use of this software 140bee4c2cSEd Schouten * must display the following acknowledgement: 150bee4c2cSEd Schouten * This product includes software developed by the University of 160bee4c2cSEd Schouten * California, Berkeley and its contributors. 170bee4c2cSEd Schouten * 4. Neither the name of the University nor the names of its contributors 180bee4c2cSEd Schouten * may be used to endorse or promote products derived from this software 190bee4c2cSEd Schouten * without specific prior written permission. 200bee4c2cSEd Schouten * 210bee4c2cSEd Schouten * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 220bee4c2cSEd Schouten * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 230bee4c2cSEd Schouten * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 240bee4c2cSEd Schouten * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 250bee4c2cSEd Schouten * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 260bee4c2cSEd Schouten * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 270bee4c2cSEd Schouten * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 280bee4c2cSEd Schouten * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 290bee4c2cSEd Schouten * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 300bee4c2cSEd Schouten * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 310bee4c2cSEd Schouten * SUCH DAMAGE. 320bee4c2cSEd Schouten */ 330bee4c2cSEd Schouten 340bee4c2cSEd Schouten #ifndef lint 350bee4c2cSEd Schouten #if 0 360bee4c2cSEd Schouten static char sccsid[] = "@(#)aux.c 8.1 (Berkeley) 6/6/93"; 370bee4c2cSEd Schouten #endif 380bee4c2cSEd Schouten #endif /* not lint */ 390bee4c2cSEd Schouten #include <sys/cdefs.h> 400bee4c2cSEd Schouten __FBSDID("$FreeBSD$"); 410bee4c2cSEd Schouten 420bee4c2cSEd Schouten #include <sys/time.h> 430bee4c2cSEd Schouten 440bee4c2cSEd Schouten #include "rcv.h" 450bee4c2cSEd Schouten #include "extern.h" 460bee4c2cSEd Schouten 470bee4c2cSEd Schouten /* 480bee4c2cSEd Schouten * Mail -- a mail program 490bee4c2cSEd Schouten * 500bee4c2cSEd Schouten * Auxiliary functions. 510bee4c2cSEd Schouten */ 520bee4c2cSEd Schouten 530bee4c2cSEd Schouten static char *save2str(char *, char *); 540bee4c2cSEd Schouten 550bee4c2cSEd Schouten /* 560bee4c2cSEd Schouten * Return a pointer to a dynamic copy of the argument. 570bee4c2cSEd Schouten */ 580bee4c2cSEd Schouten char * 590bee4c2cSEd Schouten savestr(str) 600bee4c2cSEd Schouten char *str; 610bee4c2cSEd Schouten { 620bee4c2cSEd Schouten char *new; 630bee4c2cSEd Schouten int size = strlen(str) + 1; 640bee4c2cSEd Schouten 650bee4c2cSEd Schouten if ((new = salloc(size)) != NULL) 660bee4c2cSEd Schouten bcopy(str, new, size); 670bee4c2cSEd Schouten return (new); 680bee4c2cSEd Schouten } 690bee4c2cSEd Schouten 700bee4c2cSEd Schouten /* 710bee4c2cSEd Schouten * Make a copy of new argument incorporating old one. 720bee4c2cSEd Schouten */ 730bee4c2cSEd Schouten static char * 740bee4c2cSEd Schouten save2str(str, old) 750bee4c2cSEd Schouten char *str, *old; 760bee4c2cSEd Schouten { 770bee4c2cSEd Schouten char *new; 780bee4c2cSEd Schouten int newsize = strlen(str) + 1; 790bee4c2cSEd Schouten int oldsize = old ? strlen(old) + 1 : 0; 800bee4c2cSEd Schouten 810bee4c2cSEd Schouten if ((new = salloc(newsize + oldsize)) != NULL) { 820bee4c2cSEd Schouten if (oldsize) { 830bee4c2cSEd Schouten bcopy(old, new, oldsize); 840bee4c2cSEd Schouten new[oldsize - 1] = ' '; 850bee4c2cSEd Schouten } 860bee4c2cSEd Schouten bcopy(str, new + oldsize, newsize); 870bee4c2cSEd Schouten } 880bee4c2cSEd Schouten return (new); 890bee4c2cSEd Schouten } 900bee4c2cSEd Schouten 910bee4c2cSEd Schouten /* 920bee4c2cSEd Schouten * Touch the named message by setting its MTOUCH flag. 930bee4c2cSEd Schouten * Touched messages have the effect of not being sent 940bee4c2cSEd Schouten * back to the system mailbox on exit. 950bee4c2cSEd Schouten */ 960bee4c2cSEd Schouten void 970bee4c2cSEd Schouten touch(mp) 980bee4c2cSEd Schouten struct message *mp; 990bee4c2cSEd Schouten { 1000bee4c2cSEd Schouten 1010bee4c2cSEd Schouten mp->m_flag |= MTOUCH; 1020bee4c2cSEd Schouten if ((mp->m_flag & MREAD) == 0) 1030bee4c2cSEd Schouten mp->m_flag |= MREAD|MSTATUS; 1040bee4c2cSEd Schouten } 1050bee4c2cSEd Schouten 1060bee4c2cSEd Schouten /* 1070bee4c2cSEd Schouten * Test to see if the passed file name is a directory. 1080bee4c2cSEd Schouten * Return true if it is. 1090bee4c2cSEd Schouten */ 1100bee4c2cSEd Schouten int 1110bee4c2cSEd Schouten isdir(name) 1120bee4c2cSEd Schouten char name[]; 1130bee4c2cSEd Schouten { 1140bee4c2cSEd Schouten struct stat sbuf; 1150bee4c2cSEd Schouten 1160bee4c2cSEd Schouten if (stat(name, &sbuf) < 0) 1170bee4c2cSEd Schouten return (0); 1180bee4c2cSEd Schouten return (S_ISDIR(sbuf.st_mode)); 1190bee4c2cSEd Schouten } 1200bee4c2cSEd Schouten 1210bee4c2cSEd Schouten /* 1220bee4c2cSEd Schouten * Count the number of arguments in the given string raw list. 1230bee4c2cSEd Schouten */ 1240bee4c2cSEd Schouten int 1250bee4c2cSEd Schouten argcount(argv) 1260bee4c2cSEd Schouten char **argv; 1270bee4c2cSEd Schouten { 1280bee4c2cSEd Schouten char **ap; 1290bee4c2cSEd Schouten 1300bee4c2cSEd Schouten for (ap = argv; *ap++ != NULL;) 1310bee4c2cSEd Schouten ; 1320bee4c2cSEd Schouten return (ap - argv - 1); 1330bee4c2cSEd Schouten } 1340bee4c2cSEd Schouten 1350bee4c2cSEd Schouten /* 1360bee4c2cSEd Schouten * Return the desired header line from the passed message 1370bee4c2cSEd Schouten * pointer (or NULL if the desired header field is not available). 1380bee4c2cSEd Schouten */ 1390bee4c2cSEd Schouten char * 1400bee4c2cSEd Schouten hfield(field, mp) 1410bee4c2cSEd Schouten const char *field; 1420bee4c2cSEd Schouten struct message *mp; 1430bee4c2cSEd Schouten { 1440bee4c2cSEd Schouten FILE *ibuf; 1450bee4c2cSEd Schouten char linebuf[LINESIZE]; 1460bee4c2cSEd Schouten int lc; 1470bee4c2cSEd Schouten char *hfield; 1480bee4c2cSEd Schouten char *colon, *oldhfield = NULL; 1490bee4c2cSEd Schouten 1500bee4c2cSEd Schouten ibuf = setinput(mp); 1510bee4c2cSEd Schouten if ((lc = mp->m_lines - 1) < 0) 1520bee4c2cSEd Schouten return (NULL); 1530bee4c2cSEd Schouten if (readline(ibuf, linebuf, LINESIZE) < 0) 1540bee4c2cSEd Schouten return (NULL); 1550bee4c2cSEd Schouten while (lc > 0) { 1560bee4c2cSEd Schouten if ((lc = gethfield(ibuf, linebuf, lc, &colon)) < 0) 1570bee4c2cSEd Schouten return (oldhfield); 1580bee4c2cSEd Schouten if ((hfield = ishfield(linebuf, colon, field)) != NULL) 1590bee4c2cSEd Schouten oldhfield = save2str(hfield, oldhfield); 1600bee4c2cSEd Schouten } 1610bee4c2cSEd Schouten return (oldhfield); 1620bee4c2cSEd Schouten } 1630bee4c2cSEd Schouten 1640bee4c2cSEd Schouten /* 1650bee4c2cSEd Schouten * Return the next header field found in the given message. 1660bee4c2cSEd Schouten * Return >= 0 if something found, < 0 elsewise. 1670bee4c2cSEd Schouten * "colon" is set to point to the colon in the header. 1680bee4c2cSEd Schouten * Must deal with \ continuations & other such fraud. 1690bee4c2cSEd Schouten */ 1700bee4c2cSEd Schouten int 1710bee4c2cSEd Schouten gethfield(f, linebuf, rem, colon) 1720bee4c2cSEd Schouten FILE *f; 1730bee4c2cSEd Schouten char linebuf[]; 1740bee4c2cSEd Schouten int rem; 1750bee4c2cSEd Schouten char **colon; 1760bee4c2cSEd Schouten { 1770bee4c2cSEd Schouten char line2[LINESIZE]; 1780bee4c2cSEd Schouten char *cp, *cp2; 1790bee4c2cSEd Schouten int c; 1800bee4c2cSEd Schouten 1810bee4c2cSEd Schouten for (;;) { 1820bee4c2cSEd Schouten if (--rem < 0) 1830bee4c2cSEd Schouten return (-1); 1840bee4c2cSEd Schouten if ((c = readline(f, linebuf, LINESIZE)) <= 0) 1850bee4c2cSEd Schouten return (-1); 1860bee4c2cSEd Schouten for (cp = linebuf; isprint((unsigned char)*cp) && *cp != ' ' && *cp != ':'; 1870bee4c2cSEd Schouten cp++) 1880bee4c2cSEd Schouten ; 1890bee4c2cSEd Schouten if (*cp != ':' || cp == linebuf) 1900bee4c2cSEd Schouten continue; 1910bee4c2cSEd Schouten /* 1920bee4c2cSEd Schouten * I guess we got a headline. 1930bee4c2cSEd Schouten * Handle wraparounding 1940bee4c2cSEd Schouten */ 1950bee4c2cSEd Schouten *colon = cp; 1960bee4c2cSEd Schouten cp = linebuf + c; 1970bee4c2cSEd Schouten for (;;) { 1980bee4c2cSEd Schouten while (--cp >= linebuf && (*cp == ' ' || *cp == '\t')) 1990bee4c2cSEd Schouten ; 2000bee4c2cSEd Schouten cp++; 2010bee4c2cSEd Schouten if (rem <= 0) 2020bee4c2cSEd Schouten break; 2030bee4c2cSEd Schouten ungetc(c = getc(f), f); 2040bee4c2cSEd Schouten if (c != ' ' && c != '\t') 2050bee4c2cSEd Schouten break; 2060bee4c2cSEd Schouten if ((c = readline(f, line2, LINESIZE)) < 0) 2070bee4c2cSEd Schouten break; 2080bee4c2cSEd Schouten rem--; 2090bee4c2cSEd Schouten for (cp2 = line2; *cp2 == ' ' || *cp2 == '\t'; cp2++) 2100bee4c2cSEd Schouten ; 2110bee4c2cSEd Schouten c -= cp2 - line2; 2120bee4c2cSEd Schouten if (cp + c >= linebuf + LINESIZE - 2) 2130bee4c2cSEd Schouten break; 2140bee4c2cSEd Schouten *cp++ = ' '; 2150bee4c2cSEd Schouten bcopy(cp2, cp, c); 2160bee4c2cSEd Schouten cp += c; 2170bee4c2cSEd Schouten } 2180bee4c2cSEd Schouten *cp = 0; 2190bee4c2cSEd Schouten return (rem); 2200bee4c2cSEd Schouten } 2210bee4c2cSEd Schouten /* NOTREACHED */ 2220bee4c2cSEd Schouten } 2230bee4c2cSEd Schouten 2240bee4c2cSEd Schouten /* 2250bee4c2cSEd Schouten * Check whether the passed line is a header line of 2260bee4c2cSEd Schouten * the desired breed. Return the field body, or 0. 2270bee4c2cSEd Schouten */ 2280bee4c2cSEd Schouten 2290bee4c2cSEd Schouten char* 2300bee4c2cSEd Schouten ishfield(linebuf, colon, field) 2310bee4c2cSEd Schouten char linebuf[]; 2320bee4c2cSEd Schouten char *colon; 2330bee4c2cSEd Schouten const char *field; 2340bee4c2cSEd Schouten { 2350bee4c2cSEd Schouten char *cp = colon; 2360bee4c2cSEd Schouten 2370bee4c2cSEd Schouten *cp = 0; 2380bee4c2cSEd Schouten if (strcasecmp(linebuf, field) != 0) { 2390bee4c2cSEd Schouten *cp = ':'; 2400bee4c2cSEd Schouten return (0); 2410bee4c2cSEd Schouten } 2420bee4c2cSEd Schouten *cp = ':'; 2430bee4c2cSEd Schouten for (cp++; *cp == ' ' || *cp == '\t'; cp++) 2440bee4c2cSEd Schouten ; 2450bee4c2cSEd Schouten return (cp); 2460bee4c2cSEd Schouten } 2470bee4c2cSEd Schouten 2480bee4c2cSEd Schouten /* 2490bee4c2cSEd Schouten * Copy a string and lowercase the result. 2500bee4c2cSEd Schouten * dsize: space left in buffer (including space for NULL) 2510bee4c2cSEd Schouten */ 2520bee4c2cSEd Schouten void 2530bee4c2cSEd Schouten istrncpy(dest, src, dsize) 2540bee4c2cSEd Schouten char *dest; 2550bee4c2cSEd Schouten const char *src; 2560bee4c2cSEd Schouten size_t dsize; 2570bee4c2cSEd Schouten { 2580bee4c2cSEd Schouten 2590bee4c2cSEd Schouten strlcpy(dest, src, dsize); 2600bee4c2cSEd Schouten while (*dest) 2610bee4c2cSEd Schouten *dest++ = tolower((unsigned char)*dest); 2620bee4c2cSEd Schouten } 2630bee4c2cSEd Schouten 2640bee4c2cSEd Schouten /* 2650bee4c2cSEd Schouten * The following code deals with input stacking to do source 2660bee4c2cSEd Schouten * commands. All but the current file pointer are saved on 2670bee4c2cSEd Schouten * the stack. 2680bee4c2cSEd Schouten */ 2690bee4c2cSEd Schouten 2700bee4c2cSEd Schouten static int ssp; /* Top of file stack */ 2710bee4c2cSEd Schouten struct sstack { 2720bee4c2cSEd Schouten FILE *s_file; /* File we were in. */ 2730bee4c2cSEd Schouten int s_cond; /* Saved state of conditionals */ 2740bee4c2cSEd Schouten int s_loading; /* Loading .mailrc, etc. */ 2750bee4c2cSEd Schouten }; 2760bee4c2cSEd Schouten #define SSTACK_SIZE 64 /* XXX was NOFILE. */ 2770bee4c2cSEd Schouten static struct sstack sstack[SSTACK_SIZE]; 2780bee4c2cSEd Schouten 2790bee4c2cSEd Schouten /* 2800bee4c2cSEd Schouten * Pushdown current input file and switch to a new one. 2810bee4c2cSEd Schouten * Set the global flag "sourcing" so that others will realize 2820bee4c2cSEd Schouten * that they are no longer reading from a tty (in all probability). 2830bee4c2cSEd Schouten */ 2840bee4c2cSEd Schouten int 2850bee4c2cSEd Schouten source(arglist) 2860bee4c2cSEd Schouten char **arglist; 2870bee4c2cSEd Schouten { 2880bee4c2cSEd Schouten FILE *fi; 2890bee4c2cSEd Schouten char *cp; 2900bee4c2cSEd Schouten 2910bee4c2cSEd Schouten if ((cp = expand(*arglist)) == NULL) 2920bee4c2cSEd Schouten return (1); 2930bee4c2cSEd Schouten if ((fi = Fopen(cp, "r")) == NULL) { 2940bee4c2cSEd Schouten warn("%s", cp); 2950bee4c2cSEd Schouten return (1); 2960bee4c2cSEd Schouten } 2970bee4c2cSEd Schouten if (ssp >= SSTACK_SIZE - 1) { 2980bee4c2cSEd Schouten printf("Too much \"sourcing\" going on.\n"); 2990bee4c2cSEd Schouten (void)Fclose(fi); 3000bee4c2cSEd Schouten return (1); 3010bee4c2cSEd Schouten } 3020bee4c2cSEd Schouten sstack[ssp].s_file = input; 3030bee4c2cSEd Schouten sstack[ssp].s_cond = cond; 3040bee4c2cSEd Schouten sstack[ssp].s_loading = loading; 3050bee4c2cSEd Schouten ssp++; 3060bee4c2cSEd Schouten loading = 0; 3070bee4c2cSEd Schouten cond = CANY; 3080bee4c2cSEd Schouten input = fi; 3090bee4c2cSEd Schouten sourcing++; 3100bee4c2cSEd Schouten return (0); 3110bee4c2cSEd Schouten } 3120bee4c2cSEd Schouten 3130bee4c2cSEd Schouten /* 3140bee4c2cSEd Schouten * Pop the current input back to the previous level. 3150bee4c2cSEd Schouten * Update the "sourcing" flag as appropriate. 3160bee4c2cSEd Schouten */ 3170bee4c2cSEd Schouten int 3180bee4c2cSEd Schouten unstack() 3190bee4c2cSEd Schouten { 3200bee4c2cSEd Schouten if (ssp <= 0) { 3210bee4c2cSEd Schouten printf("\"Source\" stack over-pop.\n"); 3220bee4c2cSEd Schouten sourcing = 0; 3230bee4c2cSEd Schouten return (1); 3240bee4c2cSEd Schouten } 3250bee4c2cSEd Schouten (void)Fclose(input); 3260bee4c2cSEd Schouten if (cond != CANY) 3270bee4c2cSEd Schouten printf("Unmatched \"if\"\n"); 3280bee4c2cSEd Schouten ssp--; 3290bee4c2cSEd Schouten cond = sstack[ssp].s_cond; 3300bee4c2cSEd Schouten loading = sstack[ssp].s_loading; 3310bee4c2cSEd Schouten input = sstack[ssp].s_file; 3320bee4c2cSEd Schouten if (ssp == 0) 3330bee4c2cSEd Schouten sourcing = loading; 3340bee4c2cSEd Schouten return (0); 3350bee4c2cSEd Schouten } 3360bee4c2cSEd Schouten 3370bee4c2cSEd Schouten /* 3380bee4c2cSEd Schouten * Touch the indicated file. 3390bee4c2cSEd Schouten * This is nifty for the shell. 3400bee4c2cSEd Schouten */ 3410bee4c2cSEd Schouten void 3420bee4c2cSEd Schouten alter(name) 3430bee4c2cSEd Schouten char *name; 3440bee4c2cSEd Schouten { 3450bee4c2cSEd Schouten struct stat sb; 3460bee4c2cSEd Schouten struct timeval tv[2]; 3470bee4c2cSEd Schouten 3480bee4c2cSEd Schouten if (stat(name, &sb)) 3490bee4c2cSEd Schouten return; 3500bee4c2cSEd Schouten (void)gettimeofday(&tv[0], (struct timezone *)NULL); 3510bee4c2cSEd Schouten tv[0].tv_sec++; 35299742a23SEd Schouten TIMESPEC_TO_TIMEVAL(&tv[1], &sb.st_mtim); 3530bee4c2cSEd Schouten (void)utimes(name, tv); 3540bee4c2cSEd Schouten } 3550bee4c2cSEd Schouten 3560bee4c2cSEd Schouten /* 3570bee4c2cSEd Schouten * Get sender's name from this message. If the message has 3580bee4c2cSEd Schouten * a bunch of arpanet stuff in it, we may have to skin the name 3590bee4c2cSEd Schouten * before returning it. 3600bee4c2cSEd Schouten */ 3610bee4c2cSEd Schouten char * 3620bee4c2cSEd Schouten nameof(mp, reptype) 3630bee4c2cSEd Schouten struct message *mp; 3640bee4c2cSEd Schouten int reptype; 3650bee4c2cSEd Schouten { 3660bee4c2cSEd Schouten char *cp, *cp2; 3670bee4c2cSEd Schouten 3680bee4c2cSEd Schouten cp = skin(name1(mp, reptype)); 3690bee4c2cSEd Schouten if (reptype != 0 || charcount(cp, '!') < 2) 3700bee4c2cSEd Schouten return (cp); 3710bee4c2cSEd Schouten cp2 = strrchr(cp, '!'); 3720bee4c2cSEd Schouten cp2--; 3730bee4c2cSEd Schouten while (cp2 > cp && *cp2 != '!') 3740bee4c2cSEd Schouten cp2--; 3750bee4c2cSEd Schouten if (*cp2 == '!') 3760bee4c2cSEd Schouten return (cp2 + 1); 3770bee4c2cSEd Schouten return (cp); 3780bee4c2cSEd Schouten } 3790bee4c2cSEd Schouten 3800bee4c2cSEd Schouten /* 3810bee4c2cSEd Schouten * Start of a "comment". 3820bee4c2cSEd Schouten * Ignore it. 3830bee4c2cSEd Schouten */ 3840bee4c2cSEd Schouten char * 3850bee4c2cSEd Schouten skip_comment(cp) 3860bee4c2cSEd Schouten char *cp; 3870bee4c2cSEd Schouten { 3880bee4c2cSEd Schouten int nesting = 1; 3890bee4c2cSEd Schouten 3900bee4c2cSEd Schouten for (; nesting > 0 && *cp; cp++) { 3910bee4c2cSEd Schouten switch (*cp) { 3920bee4c2cSEd Schouten case '\\': 3930bee4c2cSEd Schouten if (cp[1]) 3940bee4c2cSEd Schouten cp++; 3950bee4c2cSEd Schouten break; 3960bee4c2cSEd Schouten case '(': 3970bee4c2cSEd Schouten nesting++; 3980bee4c2cSEd Schouten break; 3990bee4c2cSEd Schouten case ')': 4000bee4c2cSEd Schouten nesting--; 4010bee4c2cSEd Schouten break; 4020bee4c2cSEd Schouten } 4030bee4c2cSEd Schouten } 4040bee4c2cSEd Schouten return (cp); 4050bee4c2cSEd Schouten } 4060bee4c2cSEd Schouten 4070bee4c2cSEd Schouten /* 4080bee4c2cSEd Schouten * Skin an arpa net address according to the RFC 822 interpretation 4090bee4c2cSEd Schouten * of "host-phrase." 4100bee4c2cSEd Schouten */ 4110bee4c2cSEd Schouten char * 4120bee4c2cSEd Schouten skin(name) 4130bee4c2cSEd Schouten char *name; 4140bee4c2cSEd Schouten { 4150bee4c2cSEd Schouten char *nbuf, *bufend, *cp, *cp2; 4160bee4c2cSEd Schouten int c, gotlt, lastsp; 4170bee4c2cSEd Schouten 4180bee4c2cSEd Schouten if (name == NULL) 4190bee4c2cSEd Schouten return (NULL); 4200bee4c2cSEd Schouten if (strchr(name, '(') == NULL && strchr(name, '<') == NULL 4210bee4c2cSEd Schouten && strchr(name, ' ') == NULL) 4220bee4c2cSEd Schouten return (name); 4230bee4c2cSEd Schouten 4240bee4c2cSEd Schouten /* We assume that length(input) <= length(output) */ 4250bee4c2cSEd Schouten if ((nbuf = malloc(strlen(name) + 1)) == NULL) 4260bee4c2cSEd Schouten err(1, "Out of memory"); 4270bee4c2cSEd Schouten gotlt = 0; 4280bee4c2cSEd Schouten lastsp = 0; 4290bee4c2cSEd Schouten bufend = nbuf; 4300bee4c2cSEd Schouten for (cp = name, cp2 = bufend; (c = *cp++) != '\0'; ) { 4310bee4c2cSEd Schouten switch (c) { 4320bee4c2cSEd Schouten case '(': 4330bee4c2cSEd Schouten cp = skip_comment(cp); 4340bee4c2cSEd Schouten lastsp = 0; 4350bee4c2cSEd Schouten break; 4360bee4c2cSEd Schouten 4370bee4c2cSEd Schouten case '"': 4380bee4c2cSEd Schouten /* 4390bee4c2cSEd Schouten * Start of a "quoted-string". 4400bee4c2cSEd Schouten * Copy it in its entirety. 4410bee4c2cSEd Schouten */ 4420bee4c2cSEd Schouten while ((c = *cp) != '\0') { 4430bee4c2cSEd Schouten cp++; 4440bee4c2cSEd Schouten if (c == '"') 4450bee4c2cSEd Schouten break; 4460bee4c2cSEd Schouten if (c != '\\') 4470bee4c2cSEd Schouten *cp2++ = c; 4480bee4c2cSEd Schouten else if ((c = *cp) != '\0') { 4490bee4c2cSEd Schouten *cp2++ = c; 4500bee4c2cSEd Schouten cp++; 4510bee4c2cSEd Schouten } 4520bee4c2cSEd Schouten } 4530bee4c2cSEd Schouten lastsp = 0; 4540bee4c2cSEd Schouten break; 4550bee4c2cSEd Schouten 4560bee4c2cSEd Schouten case ' ': 4570bee4c2cSEd Schouten if (cp[0] == 'a' && cp[1] == 't' && cp[2] == ' ') 4580bee4c2cSEd Schouten cp += 3, *cp2++ = '@'; 4590bee4c2cSEd Schouten else 4600bee4c2cSEd Schouten if (cp[0] == '@' && cp[1] == ' ') 4610bee4c2cSEd Schouten cp += 2, *cp2++ = '@'; 4620bee4c2cSEd Schouten else 4630bee4c2cSEd Schouten lastsp = 1; 4640bee4c2cSEd Schouten break; 4650bee4c2cSEd Schouten 4660bee4c2cSEd Schouten case '<': 4670bee4c2cSEd Schouten cp2 = bufend; 4680bee4c2cSEd Schouten gotlt++; 4690bee4c2cSEd Schouten lastsp = 0; 4700bee4c2cSEd Schouten break; 4710bee4c2cSEd Schouten 4720bee4c2cSEd Schouten case '>': 4730bee4c2cSEd Schouten if (gotlt) { 4740bee4c2cSEd Schouten gotlt = 0; 4750bee4c2cSEd Schouten while ((c = *cp) != '\0' && c != ',') { 4760bee4c2cSEd Schouten cp++; 4770bee4c2cSEd Schouten if (c == '(') 4780bee4c2cSEd Schouten cp = skip_comment(cp); 4790bee4c2cSEd Schouten else if (c == '"') 4800bee4c2cSEd Schouten while ((c = *cp) != '\0') { 4810bee4c2cSEd Schouten cp++; 4820bee4c2cSEd Schouten if (c == '"') 4830bee4c2cSEd Schouten break; 4840bee4c2cSEd Schouten if (c == '\\' && *cp != '\0') 4850bee4c2cSEd Schouten cp++; 4860bee4c2cSEd Schouten } 4870bee4c2cSEd Schouten } 4880bee4c2cSEd Schouten lastsp = 0; 4890bee4c2cSEd Schouten break; 4900bee4c2cSEd Schouten } 4910bee4c2cSEd Schouten /* FALLTHROUGH */ 4920bee4c2cSEd Schouten 4930bee4c2cSEd Schouten default: 4940bee4c2cSEd Schouten if (lastsp) { 4950bee4c2cSEd Schouten lastsp = 0; 4960bee4c2cSEd Schouten *cp2++ = ' '; 4970bee4c2cSEd Schouten } 4980bee4c2cSEd Schouten *cp2++ = c; 499*a1d170a0SUlrich Spörlein if (c == ',' && !gotlt && 500*a1d170a0SUlrich Spörlein (*cp == ' ' || *cp == '"' || *cp == '<')) { 5010bee4c2cSEd Schouten *cp2++ = ' '; 502*a1d170a0SUlrich Spörlein while (*cp == ' ') 503*a1d170a0SUlrich Spörlein cp++; 5040bee4c2cSEd Schouten lastsp = 0; 5050bee4c2cSEd Schouten bufend = cp2; 5060bee4c2cSEd Schouten } 5070bee4c2cSEd Schouten } 5080bee4c2cSEd Schouten } 5090bee4c2cSEd Schouten *cp2 = '\0'; 5100bee4c2cSEd Schouten 5110bee4c2cSEd Schouten if ((cp = realloc(nbuf, strlen(nbuf) + 1)) != NULL) 5120bee4c2cSEd Schouten nbuf = cp; 5130bee4c2cSEd Schouten return (nbuf); 5140bee4c2cSEd Schouten } 5150bee4c2cSEd Schouten 5160bee4c2cSEd Schouten /* 5170bee4c2cSEd Schouten * Fetch the sender's name from the passed message. 5180bee4c2cSEd Schouten * Reptype can be 5190bee4c2cSEd Schouten * 0 -- get sender's name for display purposes 5200bee4c2cSEd Schouten * 1 -- get sender's name for reply 5210bee4c2cSEd Schouten * 2 -- get sender's name for Reply 5220bee4c2cSEd Schouten */ 5230bee4c2cSEd Schouten char * 5240bee4c2cSEd Schouten name1(mp, reptype) 5250bee4c2cSEd Schouten struct message *mp; 5260bee4c2cSEd Schouten int reptype; 5270bee4c2cSEd Schouten { 5280bee4c2cSEd Schouten char namebuf[LINESIZE]; 5290bee4c2cSEd Schouten char linebuf[LINESIZE]; 5300bee4c2cSEd Schouten char *cp, *cp2; 5310bee4c2cSEd Schouten FILE *ibuf; 5320bee4c2cSEd Schouten int first = 1; 5330bee4c2cSEd Schouten 5340bee4c2cSEd Schouten if ((cp = hfield("from", mp)) != NULL) 5350bee4c2cSEd Schouten return (cp); 5360bee4c2cSEd Schouten if (reptype == 0 && (cp = hfield("sender", mp)) != NULL) 5370bee4c2cSEd Schouten return (cp); 5380bee4c2cSEd Schouten ibuf = setinput(mp); 5390bee4c2cSEd Schouten namebuf[0] = '\0'; 5400bee4c2cSEd Schouten if (readline(ibuf, linebuf, LINESIZE) < 0) 5410bee4c2cSEd Schouten return (savestr(namebuf)); 5420bee4c2cSEd Schouten newname: 5430bee4c2cSEd Schouten for (cp = linebuf; *cp != '\0' && *cp != ' '; cp++) 5440bee4c2cSEd Schouten ; 5450bee4c2cSEd Schouten for (; *cp == ' ' || *cp == '\t'; cp++) 5460bee4c2cSEd Schouten ; 5470bee4c2cSEd Schouten for (cp2 = &namebuf[strlen(namebuf)]; 5480bee4c2cSEd Schouten *cp != '\0' && *cp != ' ' && *cp != '\t' && 5490bee4c2cSEd Schouten cp2 < namebuf + LINESIZE - 1;) 5500bee4c2cSEd Schouten *cp2++ = *cp++; 5510bee4c2cSEd Schouten *cp2 = '\0'; 5520bee4c2cSEd Schouten if (readline(ibuf, linebuf, LINESIZE) < 0) 5530bee4c2cSEd Schouten return (savestr(namebuf)); 5540bee4c2cSEd Schouten if ((cp = strchr(linebuf, 'F')) == NULL) 5550bee4c2cSEd Schouten return (savestr(namebuf)); 5560bee4c2cSEd Schouten if (strncmp(cp, "From", 4) != 0) 5570bee4c2cSEd Schouten return (savestr(namebuf)); 5580bee4c2cSEd Schouten while ((cp = strchr(cp, 'r')) != NULL) { 5590bee4c2cSEd Schouten if (strncmp(cp, "remote", 6) == 0) { 5600bee4c2cSEd Schouten if ((cp = strchr(cp, 'f')) == NULL) 5610bee4c2cSEd Schouten break; 5620bee4c2cSEd Schouten if (strncmp(cp, "from", 4) != 0) 5630bee4c2cSEd Schouten break; 5640bee4c2cSEd Schouten if ((cp = strchr(cp, ' ')) == NULL) 5650bee4c2cSEd Schouten break; 5660bee4c2cSEd Schouten cp++; 5670bee4c2cSEd Schouten if (first) { 5680bee4c2cSEd Schouten cp2 = namebuf; 5690bee4c2cSEd Schouten first = 0; 5700bee4c2cSEd Schouten } else 5710bee4c2cSEd Schouten cp2 = strrchr(namebuf, '!') + 1; 5720bee4c2cSEd Schouten strlcpy(cp2, cp, sizeof(namebuf) - (cp2 - namebuf) - 1); 5730bee4c2cSEd Schouten strcat(namebuf, "!"); 5740bee4c2cSEd Schouten goto newname; 5750bee4c2cSEd Schouten } 5760bee4c2cSEd Schouten cp++; 5770bee4c2cSEd Schouten } 5780bee4c2cSEd Schouten return (savestr(namebuf)); 5790bee4c2cSEd Schouten } 5800bee4c2cSEd Schouten 5810bee4c2cSEd Schouten /* 5820bee4c2cSEd Schouten * Count the occurances of c in str 5830bee4c2cSEd Schouten */ 5840bee4c2cSEd Schouten int 5850bee4c2cSEd Schouten charcount(str, c) 5860bee4c2cSEd Schouten char *str; 5870bee4c2cSEd Schouten int c; 5880bee4c2cSEd Schouten { 5890bee4c2cSEd Schouten char *cp; 5900bee4c2cSEd Schouten int i; 5910bee4c2cSEd Schouten 5920bee4c2cSEd Schouten for (i = 0, cp = str; *cp != '\0'; cp++) 5930bee4c2cSEd Schouten if (*cp == c) 5940bee4c2cSEd Schouten i++; 5950bee4c2cSEd Schouten return (i); 5960bee4c2cSEd Schouten } 5970bee4c2cSEd Schouten 5980bee4c2cSEd Schouten /* 5990bee4c2cSEd Schouten * See if the given header field is supposed to be ignored. 6000bee4c2cSEd Schouten */ 6010bee4c2cSEd Schouten int 6020bee4c2cSEd Schouten isign(field, ignore) 6030bee4c2cSEd Schouten const char *field; 6040bee4c2cSEd Schouten struct ignoretab ignore[2]; 6050bee4c2cSEd Schouten { 6060bee4c2cSEd Schouten char realfld[LINESIZE]; 6070bee4c2cSEd Schouten 6080bee4c2cSEd Schouten if (ignore == ignoreall) 6090bee4c2cSEd Schouten return (1); 6100bee4c2cSEd Schouten /* 6110bee4c2cSEd Schouten * Lower-case the string, so that "Status" and "status" 6120bee4c2cSEd Schouten * will hash to the same place. 6130bee4c2cSEd Schouten */ 6140bee4c2cSEd Schouten istrncpy(realfld, field, sizeof(realfld)); 6150bee4c2cSEd Schouten if (ignore[1].i_count > 0) 6160bee4c2cSEd Schouten return (!member(realfld, ignore + 1)); 6170bee4c2cSEd Schouten else 6180bee4c2cSEd Schouten return (member(realfld, ignore)); 6190bee4c2cSEd Schouten } 6200bee4c2cSEd Schouten 6210bee4c2cSEd Schouten int 6220bee4c2cSEd Schouten member(realfield, table) 6230bee4c2cSEd Schouten char *realfield; 6240bee4c2cSEd Schouten struct ignoretab *table; 6250bee4c2cSEd Schouten { 6260bee4c2cSEd Schouten struct ignore *igp; 6270bee4c2cSEd Schouten 6280bee4c2cSEd Schouten for (igp = table->i_head[hash(realfield)]; igp != NULL; igp = igp->i_link) 6290bee4c2cSEd Schouten if (*igp->i_field == *realfield && 6300bee4c2cSEd Schouten equal(igp->i_field, realfield)) 6310bee4c2cSEd Schouten return (1); 6320bee4c2cSEd Schouten return (0); 6330bee4c2cSEd Schouten } 634