alex.c

来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 901 行 · 第 1/2 页

C
901
字号
/**************************************************************//* FILE:	alex.c					      *//* AUTHOR:	Peter Walburn @ DEC (EUEG) Reading, England.  *//* DATE:	February 28, 1990			      *//* CONTENTS:	Address Extraction Utility		      *//**************************************************************/static char rcsid[] = "$Id: alex.c,v 1.14 90/11/25 19:04:05 sharpe Exp $";#include "../h/mh.h"#include "../h/addrsbr.h"#include "../h/aliasbr.h"#include "../h/dropsbr.h"#include <stdio.h>#include "../zotnet/mts.h"#include <ctype.h>#include <errno.h>#include <setjmp.h>#include <sys/types.h>#include <signal.h>#include <sys/file.h>#include <limits.h>#define MAKESTR(X) (char *)malloc(strlen(X) + 1)#define MAKESTRUCT(X) (struct X *)malloc(sizeof(struct X))#define MAKEARGV(X) (char **)malloc(sizeof(char *) * X)#define NULLFILE (FILE *)NULLstatic struct swit  switches[] = {  /* switches is a structure storing */#define	ADDRSW	0		    /* all the options for 'alex'.     */    "address string", 0,	    /* It is used for parsing the      */				    /* command line and also for       */#define	ALIASW	1		    /* displaying all the options when */    "alias name", 0,		    /* the -help option is used.       */#define	COMPSW  2	    "compress", 0,#define	NCOMPSW	3    "nocompress", 0,#define	FIELDSW	4    "field name{/name}", 0,#define NFIELDSW 5    "nofield name{/name}", 0,#define GLOBSW  6    "global", 0,#define NGLOBSW 7    "noglobal", 0,#define	NAMESW	8    "name name", 0,#define	QUERYSW	9    "query", 0,#define	NQUERYSW 10    "noquery", 0,#define	REPLSW	11    "replace", 0,#define	NREPLSW	12    "noreplace", 0,#define	WIDTHSW	13    "width n", 0,#define HELPSW 14    "help", 0,    NULL, NULL};/*  */struct fields { 	  /* Structure for storing which fields to search */    char **priorities;    struct fields *next;}; struct entry {		  /* Structure for storing aliases */    char *words;    char **address_list;    struct entry *next;};struct entry *get_alias ();struct entry *read_alias_file ();struct fields *add_field ();static void del_field (), del_all_fields (), output_aliases (), 	    add_alias_entry (), compress_alias ();/* ARGSUSED */main (argc, argv)int	argc;char   *argv[];{    char *cp,	 **argp,	 **ap,	 *folder = NULL,       /* Stores the mail folder to be used. */	 *maildir, 	       /* Stores full path name for mail folder. */	 *alias_file = NULL,   /* Stores name of alias file to be used. */	 *alias_name = NULL,   /* Stores name to be used for alias. */	 *msgs[MAXARGS],       /* Stores the messages to be searched. */	 buf[BUFSIZ],	       /* General purpose buffer. */	 *msg = NULL,	       /* Holds path of message being searched. */	 name[NAMESZ],	       /* Field name being looked at in message. */	 *arguments[MAXARGS],	 *address = NULL,      /* Stores address specified on command line. */	 *addr1;	       /* Stores full address from field. */    int msgp = 0,	compnum,	count = 0,     /* General purpose index variable. */	replace = 0,   /* flag which is set if -replace option given. */	compress = 0,  /* flag set if -compress option given. */	query = 0,     /* flag set if -query option given. */	width = 72,    /* used for specifying maximum width of alias line; */		       /* 72 is default. Can be changed with -width option. */	global = 0,    /* Used for specifying if all occurrences of an alias */		       /* in alias file should be updated.  */	alias_num = 0, /* Counts the number of occurrences of an alias. */	low_msg,       /* Set to the lowest message in specified sequence. */	hgh_msg,       /* Set to highest message in specified sequence. */	found,	       /* Flag set if header field is found. */	do_default = 1,/* If no field values given, then use default. */	msgnum,	state; 	      /* state is used in searching mail messages; it   */		      /* corresponds to a header field or the body of a */		      /* mail message. */	    static struct fields *ref;    static struct msgs *mp = NULL;     /* Holds info about current , highest */				       /* and lowest message, etc.	     */    static struct mailname *mail_name; /* Holds all info about a mail address */    FILE *in,	 *out;    static struct fields *field_vals = NULL; /* Holds header fields to search */    static struct entry *alias_lists = NULL; /* Holds alias file info */    static struct entry *new_alias = NULL;   /* Holds new alias info */    invo_name = r1bindex (argv[0], '/');    if ((cp = m_find (invo_name)) != NULL) {	ap = brkstring (cp = getcpy (cp), " ", "\n");	ap = copyip (ap, arguments);    }    else	ap = arguments;    (void) copyip (argv + 1, ap);    argp = arguments;    while (cp = *argp++) {	if (*cp == '-')	    switch (smatch (++cp, switches)) {		case AMBIGSW: 		    ambigsw (cp, switches);		    done (1);		case UNKWNSW: 		    adios (NULLCP, "-%s unknown", cp);		case HELPSW: 		    (void) sprintf (buf, "%s [+folder] [switches]", invo_name);		    help (buf, switches);		    done (1);		case ADDRSW: 		    if (!(address = *argp++) || *cp == '-')			adios (NULLCP, "missing argument to %s", argp[-2]);		    address = trimcpy (address); /* Remove white spaces */		    continue;		case ALIASW: /* Argument following -alias can be a string or */			     /* can be "-", to output on stdout.	     */		    if (!(cp = *argp++))			adios (NULLCP, "missing argument to %s", argp[-2]);		    if (*cp == '-') {			if (*++cp)			    adios (NULLCP, "missing argument to %s", argp[-2]);			alias_file = NULL;		    }		    else		        alias_file = cp;		    continue;				case GLOBSW:		    global++;		    continue;		case NGLOBSW:		    global = 0;		    continue;		case COMPSW: 		    compress++;		    continue;		case NCOMPSW: 		    compress = 0;		    continue;		case FIELDSW: 		    if (!(cp = *argp++) || *cp == '-')			adios (NULLCP, "missing argument to %s", argp[-2]);		    field_vals = add_field (field_vals,cp);		    do_default = 0;		    continue;		case NFIELDSW: 		    if (!(cp = *argp++) || *cp == '-')			adios (NULLCP, "missing argument to %s", argp[-2]);		    if (uleq (cp, "all"))			del_all_fields (field_vals);		    else		        del_field (field_vals, cp);		    continue;		case NAMESW: 		    if (!(cp = *argp++) || *cp == '-')			adios (NULLCP, "missing argument to %s", argp[-2]);		    alias_name = cp;		    continue;		case QUERYSW:		    query++;		    continue;		case NQUERYSW:		    query = 0;		    continue;		case REPLSW: 		    replace++;		    continue;		case NREPLSW: 		    replace = 0;		    continue;		case WIDTHSW:		    if (!(cp = *argp++) || *cp == '-')			adios (NULLCP, "missing argument to %s", argp[-2]);		    if ((width = atoi (cp)) < 1)			adios (NULLCP, "bad argument %s %s", argp[-2], cp);		    continue;	    }	if (*cp == '+' || *cp == '@') {	    if (folder)		adios (NULLCP, "only one folder at a time!");	    else	 	folder = path (cp + 1, *cp == '+' ? TFOLDER : TSUBCWF);	}	else	    msgs[msgp++] = cp;    }/* If no field values specified then use default : */    if (do_default)	field_vals = add_field (field_vals,"reply-to/sender/from/to");/* If there is no command-line alias file name, then see if there is a default * one provided in the 'Aliasfile: ' profile entry... */    if (alias_file == NULL || *alias_file == '\0')	alias_file = m_find ("Aliasfile");/* Ensure that any relative aliasfile is found in the MAIL directory. */    if (alias_file && *alias_file)	alias_file = m_mailpath (alias_file);/* Read in the alias file and store all the lines in alias_lists. */    if (alias_file && *alias_file && alias_name && *alias_name) 	alias_lists = read_alias_file (alias_lists, alias_file);    if (!msgp)	msgs[msgp++] = "cur";    if (!folder)	folder = m_getfolder ();    maildir = m_maildir (folder);    if (chdir (maildir) == NOTOK)	adios (maildir, "unable to change directory to");    if (!(mp = m_gmsg (folder)))	adios (NULLCP, "unable to read folder %s", folder);    if (mp -> hghmsg == 0)	adios (NULLCP, "no messages in %s", folder);    for (msgnum = 0; msgnum < msgp; msgnum++) 	if (!m_convert (mp, msgs[msgnum]))	    done (1);    m_setseq (mp);    low_msg = mp -> lowsel;    hgh_msg = mp -> hghsel;/* new_alias is where the new addresses are going to be stored; *//* If the alias already exists, new_alias points to structure holding all *//* that alias information. */    new_alias = get_alias (alias_lists, (alias_name) ? alias_name : "",			  replace, global, alias_num);    do {/* Repeat this for each message in the sequence given on the command line. */        for (msgnum =low_msg; msgnum <= hgh_msg; msgnum++) {            if (mp -> msgstats[msgnum] & SELECTED)	        mp -> lowsel = msgnum;            if (mp -> lowsel != mp -> curmsg)                m_setcur (mp, mp -> lowsel);            m_sync (mp);            m_update ();            msg = getcpy (m_name (mp -> lowsel));/* If addresses are to be taken from header fields, then search through each *//* specified message for each field in turn. */            if (!address && (mp -> lowsel == msgnum)) {                if ((in = fopen (msg, "r")) == NULLFILE)	            adios (msg, "unable to open");                ref = field_vals;                while (ref != (struct fields *)NULL) {	            if (ref -> priorities[count] == NULLCP) {		        ref = ref -> next;		        count = 0;		    }		    else {		        found = 0;                        for (compnum = 1, state = FLD;;) {    	                    switch (state = m_getfld (state, name, buf, 						      sizeof buf, in)) {	                        case FLD:	                        case FLDEOF:	                        case FLDPLUS:	                            compnum++;	                            cp = add (buf, NULLCP);	                            while (state == FLDPLUS) {	 	                        state = m_getfld (state, name, buf, 						          sizeof buf, in);		                        cp = add (buf, cp);	                            }/* Compare the current header field to that being sought. The comparison *//* is case insensitive.							 */	                            if (ref != (struct fields *)NULL && 					uleq (name, ref -> priorities[count])) {				        cp = trimcpy (cp); /* Remove spaces *//* This next bit strips off unnecessary parts of the address, eg. the  *//* signature part. mail_name is a structure which holds the whole      */	/* address, mail_name -> m_mbox holds the actual address.	       */				        if (global || !alias_num) {    			                    while (addr1 = getname(cp)) {			                        if ((mail_name = getm (addr1, 						    NULLCP, 0, AD_HOST, 						    NULLCP)) == NULL)					            adios(NULLCP,"bad address");			                        add_alias_entry (new_alias, 							        mail_name -> m_mbox, 							        query);				                mnfree (mail_name);				            }				        }					found = 1;	                            }	                            free (cp);	                            if (state != FLDEOF)		                        continue;	                            break;   	        	                        case BODY:	                        case BODYEOF:	                        case FILEEOF:		                    break;    	                        case LENERR:                                case FMTERR:		                    adios (NULLCP, 				          "message format error in component #%d",			                  compnum);        	                        default:		                    adios(NULLCP,"getfld() returned %d",state);	                    } /* end of switch */	                    break;                        } /* end of for compnum */			if (found) {			    ref = ref -> next;			    count = 0;			}			else		            count++;	                (void) fseek (in, 0L, 0); /* Go back to beginning of  */	            }			   /* mail message to search for next */	        			   /* header field.		      */                }                (void) fclose (in);            }        }           if (address)					  /* Take address  */ 	    add_alias_entry (new_alias, address, query);  /* from string.  */         if (compress)	    compress_alias (new_alias); /* compress the aliases if required. */        if (!alias_file || !alias_name)            output_aliases (new_alias, stdout, width, alias_name);        if (alias_name && *alias_name) { 	    new_alias = new_alias -> next;            alias_num++;	    if (new_alias != (struct entry *)NULL)		        new_alias = get_alias (new_alias, alias_name, replace, 1, 				       alias_num);        }        else 	    new_alias = (struct entry *)NULL;    } while (new_alias != (struct entry *)NULL);    for (msgnum = low_msg; msgnum <= hgh_msg; msgnum++) /* We've looked at */	mp -> msgstats[msgnum] &= ~SELECTED;		/* these msgs, so  */							/* unset selected  */							/* flag.	   */    if (alias_file && *alias_file && alias_name && *alias_name) {        (void) strcpy (buf, m_backup (alias_file));  /* Make a backup of the */        if (rename (alias_file, buf) == NOTOK)       /* alias file.          */            adios (buf, "unable to backup %s to", alias_file);/* Output aliases to alias file. */	if ((out = fopen (alias_file, "w")) == NULLFILE) 	    adios (NULLCP, "unable to fopen %s", alias_file);	output_aliases (alias_lists, out, width, alias_name);	(void) fclose (out);    }    if ((alias_num > 1) && alias_file && *alias_file) {	(void) fprintf (stderr, "Warning: there are %d aliases with name %s in alias file\n", alias_num, alias_name);        if (!global)	    (void) fprintf (stderr, "         only the first occurrence was changed.\n");    }}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?