process.c revision 9fe995a9
19fe995a9Smrg/*
29fe995a9Smrg * $Xorg: process.c,v 1.5 2001/02/09 02:05:31 xorgcvs Exp $
39fe995a9Smrg * $XdotOrg: $
49fe995a9Smrg *
59fe995a9SmrgCopyright 1989, 1998  The Open Group
69fe995a9Smrg
79fe995a9SmrgPermission to use, copy, modify, distribute, and sell this software and its
89fe995a9Smrgdocumentation for any purpose is hereby granted without fee, provided that
99fe995a9Smrgthe above copyright notice appear in all copies and that both that
109fe995a9Smrgcopyright notice and this permission notice appear in supporting
119fe995a9Smrgdocumentation.
129fe995a9Smrg
139fe995a9SmrgThe above copyright notice and this permission notice shall be included in
149fe995a9Smrgall copies or substantial portions of the Software.
159fe995a9Smrg
169fe995a9SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
179fe995a9SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
189fe995a9SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
199fe995a9SmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
209fe995a9SmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
219fe995a9SmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
229fe995a9Smrg
239fe995a9SmrgExcept as contained in this notice, the name of The Open Group shall not be
249fe995a9Smrgused in advertising or otherwise to promote the sale, use or other dealings
259fe995a9Smrgin this Software without prior written authorization from The Open Group.
269fe995a9Smrg * *
279fe995a9Smrg * Original Author of "xauth" : Jim Fulton, MIT X Consortium
289fe995a9Smrg * Modified into "iceauth"    : Ralph Mor, X Consortium
299fe995a9Smrg */
309fe995a9Smrg
319fe995a9Smrg/* $XFree86: xc/programs/iceauth/process.c,v 3.7 2001/12/14 20:00:49 dawes Exp $ */
329fe995a9Smrg
339fe995a9Smrg#include "iceauth.h"
349fe995a9Smrg#include <ctype.h>
359fe995a9Smrg#include <errno.h>
369fe995a9Smrg#include <sys/types.h>
379fe995a9Smrg#include <sys/stat.h>
389fe995a9Smrg#include <signal.h>
399fe995a9Smrg
409fe995a9Smrg#define SECURERPC "SUN-DES-1"
419fe995a9Smrg#define K5AUTH "KERBEROS-V5-1"
429fe995a9Smrg
439fe995a9Smrg#define ICEAUTH_DEFAULT_RETRIES 10	/* number of competitors we expect */
449fe995a9Smrg#define ICEAUTH_DEFAULT_TIMEOUT 2	/* in seconds, be quick */
459fe995a9Smrg#define ICEAUTH_DEFAULT_DEADTIME 600L	/* 10 minutes in seconds */
469fe995a9Smrg
479fe995a9Smrgtypedef struct _AuthList {		/* linked list of entries */
489fe995a9Smrg    struct _AuthList *next;
499fe995a9Smrg    IceAuthFileEntry *auth;
509fe995a9Smrg} AuthList;
519fe995a9Smrg
529fe995a9Smrg#define add_to_list(h,t,e) {if (t) (t)->next = (e); else (h) = (e); (t) = (e);}
539fe995a9Smrg
549fe995a9Smrgtypedef int (*ProcessFunc)(const char *, int, int, char **);
559fe995a9Smrgtypedef int (*DoFunc)(const char *, int, IceAuthFileEntry *, char *);
569fe995a9Smrg
579fe995a9Smrgtypedef struct _CommandTable {		/* commands that are understood */
589fe995a9Smrg    char *name;				/* full name */
599fe995a9Smrg    int minlen;				/* unique prefix */
609fe995a9Smrg    int maxlen;				/* strlen(name) */
619fe995a9Smrg    ProcessFunc processfunc;		/* handler */
629fe995a9Smrg    char *helptext;			/* what to print for help */
639fe995a9Smrg} CommandTable;
649fe995a9Smrg
659fe995a9Smrgstruct _extract_data {			/* for iterating */
669fe995a9Smrg    FILE *fp;				/* input source */
679fe995a9Smrg    char *filename;			/* name of input */
689fe995a9Smrg    Bool used_stdout;			/* whether or not need to close */
699fe995a9Smrg    int nwritten;			/* number of entries written */
709fe995a9Smrg    char *cmd;				/* for error messages */
719fe995a9Smrg};
729fe995a9Smrg
739fe995a9Smrgstruct _list_data {			/* for iterating */
749fe995a9Smrg    FILE *fp;				/* output file */
759fe995a9Smrg};
769fe995a9Smrg
779fe995a9Smrg
789fe995a9Smrg/*
799fe995a9Smrg * private data
809fe995a9Smrg */
819fe995a9Smrgstatic char *stdin_filename = "(stdin)";  /* for messages */
829fe995a9Smrgstatic char *stdout_filename = "(stdout)";  /* for messages */
839fe995a9Smrgstatic const char *Yes = "yes";		/* for messages */
849fe995a9Smrgstatic const char *No = "no";			/* for messages */
859fe995a9Smrg
869fe995a9Smrgstatic int binaryEqual ( const char *a, const char *b, unsigned len );
879fe995a9Smrgstatic void prefix ( const char *fn, int n );
889fe995a9Smrgstatic void badcommandline ( const char *cmd );
899fe995a9Smrgstatic char *skip_space ( char *s );
909fe995a9Smrgstatic char *skip_nonspace ( char *s );
919fe995a9Smrgstatic char **split_into_words ( char *src, int *argcp );
929fe995a9Smrgstatic FILE *open_file ( char **filenamep, const char *mode, Bool *usedstdp, const char *srcfn, int srcln, const char *cmd );
939fe995a9Smrgstatic int read_auth_entries ( FILE *fp, AuthList **headp, AuthList **tailp );
949fe995a9Smrgstatic int cvthexkey ( char *hexstr, char **ptrp );
959fe995a9Smrgstatic int dispatch_command ( const char *inputfilename, int lineno, int argc, char **argv, const CommandTable *tab, int *statusp );
969fe995a9Smrgstatic void die ( int sig );
979fe995a9Smrgstatic void catchsig ( int sig );
989fe995a9Smrgstatic void register_signals ( void );
999fe995a9Smrgstatic int write_auth_file ( char *tmp_nam, size_t tmp_nam_len );
1009fe995a9Smrgstatic void fprintfhex ( FILE *fp, unsigned int len, const char *cp );
1019fe995a9Smrgstatic int dump_entry ( const char *inputfilename, int lineno, IceAuthFileEntry *auth, char *data );
1029fe995a9Smrgstatic int extract_entry ( const char *inputfilename, int lineno, IceAuthFileEntry *auth, char *data );
1039fe995a9Smrgstatic int match_auth ( IceAuthFileEntry *a, IceAuthFileEntry *b, int *authDataSame );
1049fe995a9Smrgstatic int merge_entries ( AuthList **firstp, AuthList *second, int *nnewp, int *nreplp, int *ndupp );
1059fe995a9Smrgstatic int search_and_do ( const char *inputfilename, int lineno, int start, int argc, char *argv[], DoFunc do_func, char *data );
1069fe995a9Smrgstatic int remove_entry ( const char *inputfilename, int lineno, IceAuthFileEntry *auth, char *data );
1079fe995a9Smrgstatic int do_help ( const char *inputfilename, int lineno, int argc, char **argv );
1089fe995a9Smrgstatic int do_questionmark ( const char *inputfilename, int lineno, int argc, char **argv );
1099fe995a9Smrgstatic int do_list ( const char *inputfilename, int lineno, int argc, char **argv );
1109fe995a9Smrgstatic int do_merge ( const char *inputfilename, int lineno, int argc, char **argv );
1119fe995a9Smrgstatic int do_extract ( const char *inputfilename, int lineno, int argc, char **argv );
1129fe995a9Smrgstatic int do_add ( const char *inputfilename, int lineno, int argc, char **argv );
1139fe995a9Smrgstatic int do_remove ( const char *inputfilename, int lineno, int argc, char **argv );
1149fe995a9Smrgstatic int do_info ( const char *inputfilename, int lineno, int argc, char **argv );
1159fe995a9Smrgstatic int do_exit ( const char *inputfilename, int lineno, int argc, char **argv );
1169fe995a9Smrgstatic int do_quit ( const char *inputfilename, int lineno, int argc, char **argv );
1179fe995a9Smrgstatic int do_source ( const char *inputfilename, int lineno, int argc, char **argv );
1189fe995a9Smrg
1199fe995a9Smrgstatic const CommandTable command_table[] = {	/* table of known commands */
1209fe995a9Smrg{ "add", 2, 3, do_add,
1219fe995a9Smrg"\
1229fe995a9Smrgadd       add an entry\n\
1239fe995a9Smrg          add protoname protodata netid authname authdata"
1249fe995a9Smrg},
1259fe995a9Smrg
1269fe995a9Smrg{ "exit", 3, 4, do_exit,
1279fe995a9Smrg"\
1289fe995a9Smrgexit      save changes and exit program"
1299fe995a9Smrg},
1309fe995a9Smrg
1319fe995a9Smrg{ "extract", 3, 7, do_extract,
1329fe995a9Smrg"\
1339fe995a9Smrgextract   extract entries into file\n\
1349fe995a9Smrg          extract filename <protoname=$> <protodata=$> <netid=$> <authname=$>"
1359fe995a9Smrg},
1369fe995a9Smrg
1379fe995a9Smrg{ "help", 1, 4, do_help,
1389fe995a9Smrg"\
1399fe995a9Smrghelp      print help\n\
1409fe995a9Smrg          help <topic>"
1419fe995a9Smrg},
1429fe995a9Smrg
1439fe995a9Smrg{ "info", 1, 4, do_info,
1449fe995a9Smrg"\
1459fe995a9Smrginfo      print information about entries"
1469fe995a9Smrg},
1479fe995a9Smrg
1489fe995a9Smrg{ "list", 1, 4, do_list,
1499fe995a9Smrg"\
1509fe995a9Smrglist      list entries\n\
1519fe995a9Smrg          list <protoname=$> <protodata=$> <netid=$> <authname=$>"
1529fe995a9Smrg},
1539fe995a9Smrg
1549fe995a9Smrg{ "merge", 1, 5, do_merge,
1559fe995a9Smrg"\
1569fe995a9Smrgmerge     merge entries from files\n\
1579fe995a9Smrg          merge filename1 <filename2> <filename3> ..."
1589fe995a9Smrg},
1599fe995a9Smrg
1609fe995a9Smrg{ "quit", 1, 4, do_quit,
1619fe995a9Smrg"\
1629fe995a9Smrgquit      abort changes and exit program" },
1639fe995a9Smrg
1649fe995a9Smrg{ "remove", 1, 6, do_remove,
1659fe995a9Smrg"\
1669fe995a9Smrgremove    remove entries\n\
1679fe995a9Smrg          remove <protoname=$> <protodata=$> <netid=$> <authname=$>"
1689fe995a9Smrg},
1699fe995a9Smrg
1709fe995a9Smrg{ "source", 1, 6, do_source,
1719fe995a9Smrg"\
1729fe995a9Smrgsource    read commands from file\n\
1739fe995a9Smrg          source filename"
1749fe995a9Smrg},
1759fe995a9Smrg
1769fe995a9Smrg{ "?", 1, 1, do_questionmark,
1779fe995a9Smrg"\
1789fe995a9Smrg?         list available commands" },
1799fe995a9Smrg
1809fe995a9Smrg{ NULL, 0, 0, NULL, NULL },
1819fe995a9Smrg};
1829fe995a9Smrg
1839fe995a9Smrg#define COMMAND_NAMES_PADDED_WIDTH 10	/* wider than anything above */
1849fe995a9Smrg
1859fe995a9Smrg
1869fe995a9Smrgstatic Bool okay_to_use_stdin = True;	/* set to false after using */
1879fe995a9Smrg
1889fe995a9Smrgstatic const char * const hex_table[] = {	/* for printing hex digits */
1899fe995a9Smrg    "00", "01", "02", "03", "04", "05", "06", "07",
1909fe995a9Smrg    "08", "09", "0a", "0b", "0c", "0d", "0e", "0f",
1919fe995a9Smrg    "10", "11", "12", "13", "14", "15", "16", "17",
1929fe995a9Smrg    "18", "19", "1a", "1b", "1c", "1d", "1e", "1f",
1939fe995a9Smrg    "20", "21", "22", "23", "24", "25", "26", "27",
1949fe995a9Smrg    "28", "29", "2a", "2b", "2c", "2d", "2e", "2f",
1959fe995a9Smrg    "30", "31", "32", "33", "34", "35", "36", "37",
1969fe995a9Smrg    "38", "39", "3a", "3b", "3c", "3d", "3e", "3f",
1979fe995a9Smrg    "40", "41", "42", "43", "44", "45", "46", "47",
1989fe995a9Smrg    "48", "49", "4a", "4b", "4c", "4d", "4e", "4f",
1999fe995a9Smrg    "50", "51", "52", "53", "54", "55", "56", "57",
2009fe995a9Smrg    "58", "59", "5a", "5b", "5c", "5d", "5e", "5f",
2019fe995a9Smrg    "60", "61", "62", "63", "64", "65", "66", "67",
2029fe995a9Smrg    "68", "69", "6a", "6b", "6c", "6d", "6e", "6f",
2039fe995a9Smrg    "70", "71", "72", "73", "74", "75", "76", "77",
2049fe995a9Smrg    "78", "79", "7a", "7b", "7c", "7d", "7e", "7f",
2059fe995a9Smrg    "80", "81", "82", "83", "84", "85", "86", "87",
2069fe995a9Smrg    "88", "89", "8a", "8b", "8c", "8d", "8e", "8f",
2079fe995a9Smrg    "90", "91", "92", "93", "94", "95", "96", "97",
2089fe995a9Smrg    "98", "99", "9a", "9b", "9c", "9d", "9e", "9f",
2099fe995a9Smrg    "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7",
2109fe995a9Smrg    "a8", "a9", "aa", "ab", "ac", "ad", "ae", "af",
2119fe995a9Smrg    "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7",
2129fe995a9Smrg    "b8", "b9", "ba", "bb", "bc", "bd", "be", "bf",
2139fe995a9Smrg    "c0", "c1", "c2", "c3", "c4", "c5", "c6", "c7",
2149fe995a9Smrg    "c8", "c9", "ca", "cb", "cc", "cd", "ce", "cf",
2159fe995a9Smrg    "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
2169fe995a9Smrg    "d8", "d9", "da", "db", "dc", "dd", "de", "df",
2179fe995a9Smrg    "e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7",
2189fe995a9Smrg    "e8", "e9", "ea", "eb", "ec", "ed", "ee", "ef",
2199fe995a9Smrg    "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
2209fe995a9Smrg    "f8", "f9", "fa", "fb", "fc", "fd", "fe", "ff",
2219fe995a9Smrg};
2229fe995a9Smrg
2239fe995a9Smrgstatic unsigned int hexvalues[256];	/* for parsing hex input */
2249fe995a9Smrg
2259fe995a9Smrgstatic mode_t original_umask = 0;	/* for restoring */
2269fe995a9Smrg
2279fe995a9Smrg
2289fe995a9Smrg/*
2299fe995a9Smrg * private utility procedures
2309fe995a9Smrg */
2319fe995a9Smrg
2329fe995a9Smrg#define copystring(s)	( s != NULL ? strdup(s) : NULL )
2339fe995a9Smrg
2349fe995a9Smrgstatic int
2359fe995a9SmrgbinaryEqual (
2369fe995a9Smrg    register const char	*a,
2379fe995a9Smrg    register const char	*b,
2389fe995a9Smrg    register unsigned	len)
2399fe995a9Smrg
2409fe995a9Smrg{
2419fe995a9Smrg    while (len--)
2429fe995a9Smrg	if (*a++ != *b++)
2439fe995a9Smrg	    return 0;
2449fe995a9Smrg    return 1;
2459fe995a9Smrg}
2469fe995a9Smrg
2479fe995a9Smrgstatic void prefix (const char *fn, int n)
2489fe995a9Smrg{
2499fe995a9Smrg    fprintf (stderr, "%s: %s:%d:  ", ProgramName, fn, n);
2509fe995a9Smrg}
2519fe995a9Smrg
2529fe995a9Smrgstatic void badcommandline (const char *cmd)
2539fe995a9Smrg{
2549fe995a9Smrg    fprintf (stderr, "bad \"%s\" command line\n", cmd);
2559fe995a9Smrg}
2569fe995a9Smrg
2579fe995a9Smrgstatic char *skip_space (register char *s)
2589fe995a9Smrg{
2599fe995a9Smrg    if (!s) return NULL;
2609fe995a9Smrg
2619fe995a9Smrg    for ( ; *s && isascii(*s) && isspace(*s); s++)
2629fe995a9Smrg	;
2639fe995a9Smrg    return s;
2649fe995a9Smrg}
2659fe995a9Smrg
2669fe995a9Smrg
2679fe995a9Smrgstatic char *skip_nonspace (register char *s)
2689fe995a9Smrg{
2699fe995a9Smrg    if (!s) return NULL;
2709fe995a9Smrg
2719fe995a9Smrg    /* put quoting into loop if need be */
2729fe995a9Smrg    for ( ; *s && isascii(*s) && !isspace(*s); s++)
2739fe995a9Smrg	;
2749fe995a9Smrg    return s;
2759fe995a9Smrg}
2769fe995a9Smrg
2779fe995a9Smrgstatic char **split_into_words (  /* argvify string */
2789fe995a9Smrg    char *src,
2799fe995a9Smrg    int *argcp)
2809fe995a9Smrg{
2819fe995a9Smrg    char *jword;
2829fe995a9Smrg    char savec;
2839fe995a9Smrg    char **argv;
2849fe995a9Smrg    int cur, total;
2859fe995a9Smrg
2869fe995a9Smrg    *argcp = 0;
2879fe995a9Smrg#define WORDSTOALLOC 4			/* most lines are short */
2889fe995a9Smrg    argv = (char **) malloc (WORDSTOALLOC * sizeof (char *));
2899fe995a9Smrg    if (!argv) return NULL;
2909fe995a9Smrg    cur = 0;
2919fe995a9Smrg    total = WORDSTOALLOC;
2929fe995a9Smrg
2939fe995a9Smrg    /*
2949fe995a9Smrg     * split the line up into separate, nul-terminated tokens; the last
2959fe995a9Smrg     * "token" will point to the empty string so that it can be bashed into
2969fe995a9Smrg     * a null pointer.
2979fe995a9Smrg     */
2989fe995a9Smrg
2999fe995a9Smrg    do {
3009fe995a9Smrg	jword = skip_space (src);
3019fe995a9Smrg	src = skip_nonspace (jword);
3029fe995a9Smrg	savec = *src;
3039fe995a9Smrg	*src = '\0';
3049fe995a9Smrg	if (cur == total) {
3059fe995a9Smrg	    total += WORDSTOALLOC;
3069fe995a9Smrg	    argv = (char **) realloc (argv, total * sizeof (char *));
3079fe995a9Smrg	    if (!argv) return NULL;
3089fe995a9Smrg	}
3099fe995a9Smrg	argv[cur++] = jword;
3109fe995a9Smrg	if (savec) src++;		/* if not last on line advance */
3119fe995a9Smrg    } while (jword != src);
3129fe995a9Smrg
3139fe995a9Smrg    argv[--cur] = NULL;			/* smash empty token to end list */
3149fe995a9Smrg    *argcp = cur;
3159fe995a9Smrg    return argv;
3169fe995a9Smrg}
3179fe995a9Smrg
3189fe995a9Smrg
3199fe995a9Smrgstatic FILE *open_file (
3209fe995a9Smrg    char **filenamep,
3219fe995a9Smrg    const char *mode,
3229fe995a9Smrg    Bool *usedstdp,
3239fe995a9Smrg    const char *srcfn,
3249fe995a9Smrg    int srcln,
3259fe995a9Smrg    const char *cmd)
3269fe995a9Smrg{
3279fe995a9Smrg    FILE *fp;
3289fe995a9Smrg
3299fe995a9Smrg    if (strcmp (*filenamep, "-") == 0) {
3309fe995a9Smrg	*usedstdp = True;
3319fe995a9Smrg					/* select std descriptor to use */
3329fe995a9Smrg	if (mode[0] == 'r') {
3339fe995a9Smrg	    if (okay_to_use_stdin) {
3349fe995a9Smrg		okay_to_use_stdin = False;
3359fe995a9Smrg		*filenamep = stdin_filename;
3369fe995a9Smrg		return stdin;
3379fe995a9Smrg	    } else {
3389fe995a9Smrg		prefix (srcfn, srcln);
3399fe995a9Smrg		fprintf (stderr, "%s:  stdin already in use\n", cmd);
3409fe995a9Smrg		return NULL;
3419fe995a9Smrg	    }
3429fe995a9Smrg	} else {
3439fe995a9Smrg	    *filenamep = stdout_filename;
3449fe995a9Smrg	    return stdout;		/* always okay to use stdout */
3459fe995a9Smrg	}
3469fe995a9Smrg    }
3479fe995a9Smrg
3489fe995a9Smrg    fp = fopen (*filenamep, mode);
3499fe995a9Smrg    if (!fp) {
3509fe995a9Smrg	prefix (srcfn, srcln);
3519fe995a9Smrg	fprintf (stderr, "%s:  unable to open file %s\n", cmd, *filenamep);
3529fe995a9Smrg    }
3539fe995a9Smrg    return fp;
3549fe995a9Smrg}
3559fe995a9Smrg
3569fe995a9Smrg
3579fe995a9Smrgstatic int read_auth_entries (FILE *fp, AuthList **headp, AuthList **tailp)
3589fe995a9Smrg{
3599fe995a9Smrg    IceAuthFileEntry *auth;
3609fe995a9Smrg    AuthList *head, *tail;
3619fe995a9Smrg    int n;
3629fe995a9Smrg
3639fe995a9Smrg    head = tail = NULL;
3649fe995a9Smrg    n = 0;
3659fe995a9Smrg					/* put all records into linked list */
3669fe995a9Smrg    while ((auth = IceReadAuthFileEntry (fp)) != NULL) {
3679fe995a9Smrg	AuthList *l = (AuthList *) malloc (sizeof (AuthList));
3689fe995a9Smrg	if (!l) {
3699fe995a9Smrg	    fprintf (stderr,
3709fe995a9Smrg		     "%s:  unable to alloc entry reading auth file\n",
3719fe995a9Smrg		     ProgramName);
3729fe995a9Smrg	    exit (1);
3739fe995a9Smrg	}
3749fe995a9Smrg	l->next = NULL;
3759fe995a9Smrg	l->auth = auth;
3769fe995a9Smrg	if (tail) 			/* if not first time through append */
3779fe995a9Smrg	  tail->next = l;
3789fe995a9Smrg	else
3799fe995a9Smrg	  head = l;			/* first time through, so assign */
3809fe995a9Smrg	tail = l;
3819fe995a9Smrg	n++;
3829fe995a9Smrg    }
3839fe995a9Smrg    *headp = head;
3849fe995a9Smrg    *tailp = tail;
3859fe995a9Smrg    return n;
3869fe995a9Smrg}
3879fe995a9Smrg
3889fe995a9Smrg
3899fe995a9Smrgstatic int cvthexkey (	/* turn hex key string into octets */
3909fe995a9Smrg    char *hexstr,
3919fe995a9Smrg    char **ptrp)
3929fe995a9Smrg{
3939fe995a9Smrg    int i;
3949fe995a9Smrg    int len = 0;
3959fe995a9Smrg    char *retval, *s;
3969fe995a9Smrg    unsigned char *us;
3979fe995a9Smrg    char c;
3989fe995a9Smrg    char savec = '\0';
3999fe995a9Smrg
4009fe995a9Smrg    /* count */
4019fe995a9Smrg    for (s = hexstr; *s; s++) {
4029fe995a9Smrg	if (!isascii(*s)) return -1;
4039fe995a9Smrg	if (isspace(*s)) continue;
4049fe995a9Smrg	if (!isxdigit(*s)) return -1;
4059fe995a9Smrg	len++;
4069fe995a9Smrg    }
4079fe995a9Smrg
4089fe995a9Smrg    /* if odd then there was an error */
4099fe995a9Smrg    if ((len & 1) == 1) return -1;
4109fe995a9Smrg
4119fe995a9Smrg
4129fe995a9Smrg    /* now we know that the input is good */
4139fe995a9Smrg    len >>= 1;
4149fe995a9Smrg    retval = malloc (len);
4159fe995a9Smrg    if (!retval) {
4169fe995a9Smrg	fprintf (stderr, "%s:  unable to allocate %d bytes for hexkey\n",
4179fe995a9Smrg		 ProgramName, len);
4189fe995a9Smrg	return -1;
4199fe995a9Smrg    }
4209fe995a9Smrg
4219fe995a9Smrg    for (us = (unsigned char *) retval, i = len; i > 0; hexstr++) {
4229fe995a9Smrg	c = *hexstr;
4239fe995a9Smrg	if (isspace(c)) continue;	 /* already know it is ascii */
4249fe995a9Smrg	if (isupper(c))
4259fe995a9Smrg	    c = tolower(c);
4269fe995a9Smrg	if (savec) {
4279fe995a9Smrg#define atoh(c) ((c) - (((c) >= '0' && (c) <= '9') ? '0' : ('a'-10)))
4289fe995a9Smrg	    *us = (unsigned char)((atoh(savec) << 4) + atoh(c));
4299fe995a9Smrg#undef atoh
4309fe995a9Smrg	    savec = 0;		/* ready for next character */
4319fe995a9Smrg	    us++;
4329fe995a9Smrg	    i--;
4339fe995a9Smrg	} else {
4349fe995a9Smrg	    savec = c;
4359fe995a9Smrg	}
4369fe995a9Smrg    }
4379fe995a9Smrg    *ptrp = retval;
4389fe995a9Smrg    return len;
4399fe995a9Smrg}
4409fe995a9Smrg
4419fe995a9Smrgstatic int dispatch_command (
4429fe995a9Smrg    const char *inputfilename,
4439fe995a9Smrg    int lineno,
4449fe995a9Smrg    int argc,
4459fe995a9Smrg    char **argv,
4469fe995a9Smrg    const CommandTable *tab,
4479fe995a9Smrg    int *statusp)
4489fe995a9Smrg{
4499fe995a9Smrg    const CommandTable *ct;
4509fe995a9Smrg    char *cmd;
4519fe995a9Smrg    int n;
4529fe995a9Smrg					/* scan table for command */
4539fe995a9Smrg    cmd = argv[0];
4549fe995a9Smrg    n = strlen (cmd);
4559fe995a9Smrg    for (ct = tab; ct->name; ct++) {
4569fe995a9Smrg					/* look for unique prefix */
4579fe995a9Smrg	if (n >= ct->minlen && n <= ct->maxlen &&
4589fe995a9Smrg	    strncmp (cmd, ct->name, n) == 0) {
4599fe995a9Smrg	    *statusp = (*(ct->processfunc))(inputfilename, lineno, argc, argv);
4609fe995a9Smrg	    return 1;
4619fe995a9Smrg	}
4629fe995a9Smrg    }
4639fe995a9Smrg
4649fe995a9Smrg    *statusp = 1;
4659fe995a9Smrg    return 0;
4669fe995a9Smrg}
4679fe995a9Smrg
4689fe995a9Smrg
4699fe995a9Smrgstatic AuthList *iceauth_head = NULL;	/* list of auth entries */
4709fe995a9Smrgstatic Bool iceauth_existed = False;	/* if was present at initialize */
4719fe995a9Smrgstatic Bool iceauth_modified = False;	/* if added, removed, or merged */
4729fe995a9Smrgstatic Bool iceauth_allowed = True;	/* if allowed to write auth file */
4739fe995a9Smrgstatic char *iceauth_filename = NULL;
4749fe995a9Smrgstatic volatile Bool dieing = False;
4759fe995a9Smrg
4769fe995a9Smrg#ifdef RETSIGTYPE /* autoconf AC_TYPE_SIGNAL */
4779fe995a9Smrg# define _signal_t RETSIGTYPE
4789fe995a9Smrg#else /* Imake */
4799fe995a9Smrg#ifdef SIGNALRETURNSINT
4809fe995a9Smrg#define _signal_t int
4819fe995a9Smrg#else
4829fe995a9Smrg#define _signal_t void
4839fe995a9Smrg#endif
4849fe995a9Smrg#endif /* RETSIGTYPE */
4859fe995a9Smrg
4869fe995a9Smrg/* poor man's puts(), for under signal handlers */
4879fe995a9Smrg#define WRITES(fd, S) (void)write((fd), (S), strlen((S)))
4889fe995a9Smrg
4899fe995a9Smrg/* ARGSUSED */
4909fe995a9Smrgstatic _signal_t die (int sig)
4919fe995a9Smrg{
4929fe995a9Smrg    dieing = True;
4939fe995a9Smrg    _exit (auth_finalize ());
4949fe995a9Smrg    /* NOTREACHED */
4959fe995a9Smrg#ifdef SIGNALRETURNSINT
4969fe995a9Smrg    return -1;				/* for picky compilers */
4979fe995a9Smrg#endif
4989fe995a9Smrg}
4999fe995a9Smrg
5009fe995a9Smrgstatic _signal_t catchsig (int sig)
5019fe995a9Smrg{
5029fe995a9Smrg#ifdef SYSV
5039fe995a9Smrg    if (sig > 0) signal (sig, die);	/* re-establish signal handler */
5049fe995a9Smrg#endif
5059fe995a9Smrg    /*
5069fe995a9Smrg     * fileno() might not be reentrant, avoid it if possible, and use
5079fe995a9Smrg     * stderr instead of stdout
5089fe995a9Smrg     */
5099fe995a9Smrg#ifdef STDERR_FILENO
5109fe995a9Smrg    if (verbose && iceauth_modified) WRITES(STDERR_FILENO, "\r\n");
5119fe995a9Smrg#else
5129fe995a9Smrg    if (verbose && iceauth_modified) WRITES(fileno(stderr), "\r\n");
5139fe995a9Smrg#endif
5149fe995a9Smrg    die (sig);
5159fe995a9Smrg    /* NOTREACHED */
5169fe995a9Smrg#ifdef SIGNALRETURNSINT
5179fe995a9Smrg    return -1;				/* for picky compilers */
5189fe995a9Smrg#endif
5199fe995a9Smrg}
5209fe995a9Smrg
5219fe995a9Smrgstatic void register_signals (void)
5229fe995a9Smrg{
5239fe995a9Smrg    signal (SIGINT, catchsig);
5249fe995a9Smrg    signal (SIGTERM, catchsig);
5259fe995a9Smrg#ifdef SIGHUP
5269fe995a9Smrg    signal (SIGHUP, catchsig);
5279fe995a9Smrg#endif
5289fe995a9Smrg    return;
5299fe995a9Smrg}
5309fe995a9Smrg
5319fe995a9Smrg
5329fe995a9Smrg/*
5339fe995a9Smrg * public procedures for parsing lines of input
5349fe995a9Smrg */
5359fe995a9Smrg
5369fe995a9Smrgint auth_initialize ( char *authfilename )
5379fe995a9Smrg{
5389fe995a9Smrg    int n;
5399fe995a9Smrg    AuthList *head, *tail;
5409fe995a9Smrg    FILE *authfp;
5419fe995a9Smrg    Bool exists;
5429fe995a9Smrg
5439fe995a9Smrg    register_signals ();
5449fe995a9Smrg
5459fe995a9Smrg    bzero ((char *) hexvalues, sizeof hexvalues);
5469fe995a9Smrg    hexvalues['0'] = 0;
5479fe995a9Smrg    hexvalues['1'] = 1;
5489fe995a9Smrg    hexvalues['2'] = 2;
5499fe995a9Smrg    hexvalues['3'] = 3;
5509fe995a9Smrg    hexvalues['4'] = 4;
5519fe995a9Smrg    hexvalues['5'] = 5;
5529fe995a9Smrg    hexvalues['6'] = 6;
5539fe995a9Smrg    hexvalues['7'] = 7;
5549fe995a9Smrg    hexvalues['8'] = 8;
5559fe995a9Smrg    hexvalues['9'] = 9;
5569fe995a9Smrg    hexvalues['a'] = hexvalues['A'] = 0xa;
5579fe995a9Smrg    hexvalues['b'] = hexvalues['B'] = 0xb;
5589fe995a9Smrg    hexvalues['c'] = hexvalues['C'] = 0xc;
5599fe995a9Smrg    hexvalues['d'] = hexvalues['D'] = 0xd;
5609fe995a9Smrg    hexvalues['e'] = hexvalues['E'] = 0xe;
5619fe995a9Smrg    hexvalues['f'] = hexvalues['F'] = 0xf;
5629fe995a9Smrg
5639fe995a9Smrg    if (break_locks && verbose) {
5649fe995a9Smrg	printf ("Attempting to break locks on authority file %s\n",
5659fe995a9Smrg		authfilename);
5669fe995a9Smrg    }
5679fe995a9Smrg
5689fe995a9Smrg    iceauth_filename = strdup(authfilename);
5699fe995a9Smrg
5709fe995a9Smrg    if (ignore_locks) {
5719fe995a9Smrg	if (break_locks) IceUnlockAuthFile (authfilename);
5729fe995a9Smrg    } else {
5739fe995a9Smrg	n = IceLockAuthFile (authfilename, ICEAUTH_DEFAULT_RETRIES,
5749fe995a9Smrg			 ICEAUTH_DEFAULT_TIMEOUT,
5759fe995a9Smrg			 (break_locks ? 0L : ICEAUTH_DEFAULT_DEADTIME));
5769fe995a9Smrg	if (n != IceAuthLockSuccess) {
5779fe995a9Smrg	    char *reason = "unknown error";
5789fe995a9Smrg	    switch (n) {
5799fe995a9Smrg	      case IceAuthLockError:
5809fe995a9Smrg		reason = "error";
5819fe995a9Smrg		break;
5829fe995a9Smrg	      case IceAuthLockTimeout:
5839fe995a9Smrg		reason = "timeout";
5849fe995a9Smrg		break;
5859fe995a9Smrg	    }
5869fe995a9Smrg	    fprintf (stderr, "%s:  %s in locking authority file %s\n",
5879fe995a9Smrg		     ProgramName, reason, authfilename);
5889fe995a9Smrg	    return -1;
5899fe995a9Smrg	}
5909fe995a9Smrg    }
5919fe995a9Smrg
5929fe995a9Smrg    /* these checks can only be done reliably after the file is locked */
5939fe995a9Smrg    exists = (access (authfilename, F_OK) == 0);
5949fe995a9Smrg    if (exists && access (authfilename, W_OK) != 0) {
5959fe995a9Smrg	fprintf (stderr,
5969fe995a9Smrg	 "%s:  %s not writable, changes will be ignored\n",
5979fe995a9Smrg		 ProgramName, authfilename);
5989fe995a9Smrg	iceauth_allowed = False;
5999fe995a9Smrg    }
6009fe995a9Smrg
6019fe995a9Smrg    original_umask = umask (0077);	/* disallow non-owner access */
6029fe995a9Smrg
6039fe995a9Smrg    authfp = fopen (authfilename, "rb");
6049fe995a9Smrg    if (!authfp) {
6059fe995a9Smrg	int olderrno = errno;
6069fe995a9Smrg
6079fe995a9Smrg					/* if file there then error */
6089fe995a9Smrg	if (access (authfilename, F_OK) == 0) {	 /* then file does exist! */
6099fe995a9Smrg	    errno = olderrno;
6109fe995a9Smrg	    return -1;
6119fe995a9Smrg	}				/* else ignore it */
6129fe995a9Smrg	fprintf (stderr,
6139fe995a9Smrg		 "%s:  creating new authority file %s\n",
6149fe995a9Smrg		 ProgramName, authfilename);
6159fe995a9Smrg    } else {
6169fe995a9Smrg	iceauth_existed = True;
6179fe995a9Smrg	n = read_auth_entries (authfp, &head, &tail);
6189fe995a9Smrg	(void) fclose (authfp);
6199fe995a9Smrg	if (n < 0) {
6209fe995a9Smrg	    fprintf (stderr,
6219fe995a9Smrg		     "%s:  unable to read auth entries from file \"%s\"\n",
6229fe995a9Smrg		     ProgramName, authfilename);
6239fe995a9Smrg	    return -1;
6249fe995a9Smrg	}
6259fe995a9Smrg	iceauth_head = head;
6269fe995a9Smrg    }
6279fe995a9Smrg
6289fe995a9Smrg    iceauth_modified = False;
6299fe995a9Smrg
6309fe995a9Smrg    if (verbose) {
6319fe995a9Smrg	printf ("%s authority file %s\n",
6329fe995a9Smrg		ignore_locks ? "Ignoring locks on" : "Using", authfilename);
6339fe995a9Smrg    }
6349fe995a9Smrg    return 0;
6359fe995a9Smrg}
6369fe995a9Smrg
6379fe995a9Smrgstatic int write_auth_file (char *tmp_nam, size_t tmp_nam_len)
6389fe995a9Smrg{
6399fe995a9Smrg    FILE *fp;
6409fe995a9Smrg    AuthList *list;
6419fe995a9Smrg
6429fe995a9Smrg    if ((strlen(iceauth_filename) + 3) > tmp_nam_len) {
6439fe995a9Smrg	strncpy(tmp_nam, "filename too long", tmp_nam_len);
6449fe995a9Smrg	tmp_nam[tmp_nam_len - 1] = '\0';
6459fe995a9Smrg	return -1;
6469fe995a9Smrg    }
6479fe995a9Smrg
6489fe995a9Smrg    strcpy (tmp_nam, iceauth_filename);
6499fe995a9Smrg    strcat (tmp_nam, "-n");		/* for new */
6509fe995a9Smrg    (void) unlink (tmp_nam);
6519fe995a9Smrg    fp = fopen (tmp_nam, "wb");		/* umask is still set to 0077 */
6529fe995a9Smrg    if (!fp) {
6539fe995a9Smrg	fprintf (stderr, "%s:  unable to open tmp file \"%s\"\n",
6549fe995a9Smrg		 ProgramName, tmp_nam);
6559fe995a9Smrg	return -1;
6569fe995a9Smrg    }
6579fe995a9Smrg
6589fe995a9Smrg    for (list = iceauth_head; list; list = list->next)
6599fe995a9Smrg	IceWriteAuthFileEntry (fp, list->auth);
6609fe995a9Smrg
6619fe995a9Smrg    (void) fclose (fp);
6629fe995a9Smrg    return 0;
6639fe995a9Smrg}
6649fe995a9Smrg
6659fe995a9Smrgint auth_finalize (void)
6669fe995a9Smrg{
6679fe995a9Smrg    char temp_name[1024];			/* large filename size */
6689fe995a9Smrg
6699fe995a9Smrg    if (iceauth_modified) {
6709fe995a9Smrg	if (dieing) {
6719fe995a9Smrg	    if (verbose) {
6729fe995a9Smrg		/*
6739fe995a9Smrg		 * called from a signal handler -- printf is *not* reentrant; also
6749fe995a9Smrg		 * fileno() might not be reentrant, avoid it if possible, and use
6759fe995a9Smrg		 * stderr instead of stdout
6769fe995a9Smrg		 */
6779fe995a9Smrg#ifdef STDERR_FILENO
6789fe995a9Smrg		WRITES(STDERR_FILENO, "\nAborting changes to authority file ");
6799fe995a9Smrg		WRITES(STDERR_FILENO, iceauth_filename);
6809fe995a9Smrg		WRITES(STDERR_FILENO, "\n");
6819fe995a9Smrg#else
6829fe995a9Smrg		WRITES(fileno(stderr), "\nAborting changes to authority file ");
6839fe995a9Smrg		WRITES(fileno(stderr), iceauth_filename);
6849fe995a9Smrg		WRITES(fileno(stderr), "\n");
6859fe995a9Smrg#endif
6869fe995a9Smrg	    }
6879fe995a9Smrg	} else if (!iceauth_allowed) {
6889fe995a9Smrg	    fprintf (stderr,
6899fe995a9Smrg		     "%s:  %s not writable, changes ignored\n",
6909fe995a9Smrg		     ProgramName, iceauth_filename);
6919fe995a9Smrg	} else {
6929fe995a9Smrg	    if (verbose) {
6939fe995a9Smrg		printf ("%s authority file %s\n",
6949fe995a9Smrg			ignore_locks ? "Ignoring locks and writing" :
6959fe995a9Smrg			"Writing", iceauth_filename);
6969fe995a9Smrg	    }
6979fe995a9Smrg	    temp_name[0] = '\0';
6989fe995a9Smrg	    if (write_auth_file (temp_name, sizeof(temp_name)) == -1) {
6999fe995a9Smrg		fprintf (stderr,
7009fe995a9Smrg			 "%s:  unable to write authority file %s\n",
7019fe995a9Smrg			 ProgramName, temp_name);
7029fe995a9Smrg	    } else {
7039fe995a9Smrg		(void) unlink (iceauth_filename);
7049fe995a9Smrg#if defined(WIN32) || defined(__UNIXOS2__)
7059fe995a9Smrg		if (rename(temp_name, iceauth_filename) == -1)
7069fe995a9Smrg#else
7079fe995a9Smrg		if (link (temp_name, iceauth_filename) == -1)
7089fe995a9Smrg#endif
7099fe995a9Smrg		{
7109fe995a9Smrg		    fprintf (stderr,
7119fe995a9Smrg		     "%s:  unable to link authority file %s, use %s\n",
7129fe995a9Smrg			     ProgramName, iceauth_filename, temp_name);
7139fe995a9Smrg		} else {
7149fe995a9Smrg		    (void) unlink (temp_name);
7159fe995a9Smrg		}
7169fe995a9Smrg	    }
7179fe995a9Smrg	}
7189fe995a9Smrg    }
7199fe995a9Smrg
7209fe995a9Smrg    if (!ignore_locks && (iceauth_filename != NULL)) {
7219fe995a9Smrg	IceUnlockAuthFile (iceauth_filename);
7229fe995a9Smrg    }
7239fe995a9Smrg    (void) umask (original_umask);
7249fe995a9Smrg    return 0;
7259fe995a9Smrg}
7269fe995a9Smrg
7279fe995a9Smrgint process_command (
7289fe995a9Smrg    const char *inputfilename,
7299fe995a9Smrg    int lineno,
7309fe995a9Smrg    int argc,
7319fe995a9Smrg    char **argv)
7329fe995a9Smrg{
7339fe995a9Smrg    int status;
7349fe995a9Smrg
7359fe995a9Smrg    if (argc < 1 || !argv || !argv[0]) return 1;
7369fe995a9Smrg
7379fe995a9Smrg    if (dispatch_command (inputfilename, lineno, argc, argv,
7389fe995a9Smrg			  command_table, &status))
7399fe995a9Smrg      return status;
7409fe995a9Smrg
7419fe995a9Smrg    prefix (inputfilename, lineno);
7429fe995a9Smrg    fprintf (stderr, "unknown command \"%s\"\n", argv[0]);
7439fe995a9Smrg    return 1;
7449fe995a9Smrg}
7459fe995a9Smrg
7469fe995a9Smrg
7479fe995a9Smrg/*
7489fe995a9Smrg * utility routines
7499fe995a9Smrg */
7509fe995a9Smrg
7519fe995a9Smrgstatic void fprintfhex (
7529fe995a9Smrg    register FILE *fp,
7539fe995a9Smrg    unsigned int len,
7549fe995a9Smrg    const char *cp)
7559fe995a9Smrg{
7569fe995a9Smrg    const unsigned char *ucp = (const unsigned char *) cp;
7579fe995a9Smrg
7589fe995a9Smrg    for (; len > 0; len--, ucp++) {
7599fe995a9Smrg	register const char *s = hex_table[*ucp];
7609fe995a9Smrg	putc (s[0], fp);
7619fe995a9Smrg	putc (s[1], fp);
7629fe995a9Smrg    }
7639fe995a9Smrg    return;
7649fe995a9Smrg}
7659fe995a9Smrg
7669fe995a9Smrg/* ARGSUSED */
7679fe995a9Smrgstatic int dump_entry (
7689fe995a9Smrg    const char *inputfilename,
7699fe995a9Smrg    int lineno,
7709fe995a9Smrg    IceAuthFileEntry *auth,
7719fe995a9Smrg    char *data)
7729fe995a9Smrg{
7739fe995a9Smrg    struct _list_data *ld = (struct _list_data *) data;
7749fe995a9Smrg    FILE *fp = ld->fp;
7759fe995a9Smrg
7769fe995a9Smrg    fprintf (fp, "%s", auth->protocol_name);
7779fe995a9Smrg    putc (' ', fp);
7789fe995a9Smrg    if (auth->protocol_data_length > 0)
7799fe995a9Smrg	fprintfhex (fp, auth->protocol_data_length, auth->protocol_data);
7809fe995a9Smrg    else
7819fe995a9Smrg	fprintf (fp, "\"\"");
7829fe995a9Smrg    putc (' ', fp);
7839fe995a9Smrg    fprintf (fp, "%s", auth->network_id);
7849fe995a9Smrg    putc (' ', fp);
7859fe995a9Smrg    fprintf (fp, "%s", auth->auth_name);
7869fe995a9Smrg    putc (' ', fp);
7879fe995a9Smrg
7889fe995a9Smrg    if (auth->auth_data_length == 0)
7899fe995a9Smrg	fprintf (fp, "\"\"");
7909fe995a9Smrg    else if (!strcmp(auth->auth_name, SECURERPC) ||
7919fe995a9Smrg	!strcmp(auth->auth_name, K5AUTH))
7929fe995a9Smrg	fwrite (auth->auth_data, sizeof (char), auth->auth_data_length, fp);
7939fe995a9Smrg    else
7949fe995a9Smrg	fprintfhex (fp, auth->auth_data_length, auth->auth_data);
7959fe995a9Smrg    putc ('\n', fp);
7969fe995a9Smrg
7979fe995a9Smrg    return 0;
7989fe995a9Smrg}
7999fe995a9Smrg
8009fe995a9Smrgstatic int extract_entry (
8019fe995a9Smrg    const char *inputfilename,
8029fe995a9Smrg    int lineno,
8039fe995a9Smrg    IceAuthFileEntry *auth,
8049fe995a9Smrg    char *data)
8059fe995a9Smrg{
8069fe995a9Smrg    struct _extract_data *ed = (struct _extract_data *) data;
8079fe995a9Smrg
8089fe995a9Smrg    if (!ed->fp) {
8099fe995a9Smrg	ed->fp = open_file (&ed->filename, "wb",
8109fe995a9Smrg			    &ed->used_stdout,
8119fe995a9Smrg			    inputfilename, lineno, ed->cmd);
8129fe995a9Smrg	if (!ed->fp) {
8139fe995a9Smrg	    prefix (inputfilename, lineno);
8149fe995a9Smrg	    fprintf (stderr,
8159fe995a9Smrg		     "unable to open extraction file \"%s\"\n",
8169fe995a9Smrg		     ed->filename);
8179fe995a9Smrg	    return -1;
8189fe995a9Smrg	}
8199fe995a9Smrg    }
8209fe995a9Smrg    IceWriteAuthFileEntry (ed->fp, auth);
8219fe995a9Smrg    ed->nwritten++;
8229fe995a9Smrg
8239fe995a9Smrg    return 0;
8249fe995a9Smrg}
8259fe995a9Smrg
8269fe995a9Smrg
8279fe995a9Smrgstatic int match_auth (
8289fe995a9Smrg    register IceAuthFileEntry *a,
8299fe995a9Smrg    register IceAuthFileEntry *b,
8309fe995a9Smrg    int *authDataSame)
8319fe995a9Smrg{
8329fe995a9Smrg    int match = strcmp (a->protocol_name, b->protocol_name) == 0 &&
8339fe995a9Smrg	    strcmp (a->network_id, b->network_id) == 0 &&
8349fe995a9Smrg            strcmp (a->auth_name, b->auth_name) == 0;
8359fe995a9Smrg
8369fe995a9Smrg    if (match)
8379fe995a9Smrg    {
8389fe995a9Smrg	*authDataSame = (a->auth_data_length == b->auth_data_length &&
8399fe995a9Smrg	    binaryEqual (a->auth_data, b->auth_data, a->auth_data_length));
8409fe995a9Smrg    }
8419fe995a9Smrg    else
8429fe995a9Smrg	*authDataSame = 0;
8439fe995a9Smrg
8449fe995a9Smrg    return (match);
8459fe995a9Smrg}
8469fe995a9Smrg
8479fe995a9Smrg
8489fe995a9Smrgstatic int merge_entries (
8499fe995a9Smrg    AuthList **firstp, AuthList *second,
8509fe995a9Smrg    int *nnewp, int *nreplp, int *ndupp)
8519fe995a9Smrg{
8529fe995a9Smrg    AuthList *a, *b, *first, *tail;
8539fe995a9Smrg    int n = 0, nnew = 0, nrepl = 0, ndup = 0;
8549fe995a9Smrg
8559fe995a9Smrg    if (!second) return 0;
8569fe995a9Smrg
8579fe995a9Smrg    if (!*firstp) {			/* if nothing to merge into */
8589fe995a9Smrg	*firstp = second;
8599fe995a9Smrg	for (tail = *firstp, n = 1; tail->next; n++, tail = tail->next) ;
8609fe995a9Smrg	*nnewp = n;
8619fe995a9Smrg	*nreplp = 0;
8629fe995a9Smrg	*ndupp = 0;
8639fe995a9Smrg	return n;
8649fe995a9Smrg    }
8659fe995a9Smrg
8669fe995a9Smrg    first = *firstp;
8679fe995a9Smrg    /*
8689fe995a9Smrg     * find end of first list and stick second list on it
8699fe995a9Smrg     */
8709fe995a9Smrg    for (tail = first; tail->next; tail = tail->next) ;
8719fe995a9Smrg    tail->next = second;
8729fe995a9Smrg
8739fe995a9Smrg    /*
8749fe995a9Smrg     * run down list freeing duplicate entries; if an entry is okay, then
8759fe995a9Smrg     * bump the tail up to include it, otherwise, cut the entry out of
8769fe995a9Smrg     * the chain.
8779fe995a9Smrg     */
8789fe995a9Smrg    for (b = second; b; ) {
8799fe995a9Smrg	AuthList *next = b->next;	/* in case we free it */
8809fe995a9Smrg	int duplicate;
8819fe995a9Smrg
8829fe995a9Smrg	duplicate = 0;
8839fe995a9Smrg	a = first;
8849fe995a9Smrg	for (;;) {
8859fe995a9Smrg	    int authDataSame;
8869fe995a9Smrg	    if (match_auth (a->auth, b->auth, &authDataSame)) {
8879fe995a9Smrg		if (authDataSame)
8889fe995a9Smrg		{
8899fe995a9Smrg		    /* found a complete duplicate, ignore */
8909fe995a9Smrg		    duplicate = 1;
8919fe995a9Smrg		    break;
8929fe995a9Smrg		}
8939fe995a9Smrg		else
8949fe995a9Smrg		{
8959fe995a9Smrg		    /* found a duplicate, but auth data differs */
8969fe995a9Smrg
8979fe995a9Smrg		    AuthList tmp;		/* swap it in for old one */
8989fe995a9Smrg		    tmp = *a;
8999fe995a9Smrg		    *a = *b;
9009fe995a9Smrg		    *b = tmp;
9019fe995a9Smrg		    a->next = b->next;
9029fe995a9Smrg		    IceFreeAuthFileEntry (b->auth);
9039fe995a9Smrg		    free ((char *) b);
9049fe995a9Smrg		    b = NULL;
9059fe995a9Smrg		    tail->next = next;
9069fe995a9Smrg		    nrepl++;
9079fe995a9Smrg		    nnew--;
9089fe995a9Smrg		    break;
9099fe995a9Smrg		}
9109fe995a9Smrg	    }
9119fe995a9Smrg	    if (a == tail) break;	/* if have looked at left side */
9129fe995a9Smrg	    a = a->next;
9139fe995a9Smrg	}
9149fe995a9Smrg	if (!duplicate && b) {		/* if we didn't remove it */
9159fe995a9Smrg	    tail = b;			/* bump end of first list */
9169fe995a9Smrg	}
9179fe995a9Smrg	b = next;
9189fe995a9Smrg
9199fe995a9Smrg	if (duplicate)
9209fe995a9Smrg	    ndup++;
9219fe995a9Smrg	else
9229fe995a9Smrg	{
9239fe995a9Smrg	    n++;
9249fe995a9Smrg	    nnew++;
9259fe995a9Smrg	}
9269fe995a9Smrg    }
9279fe995a9Smrg
9289fe995a9Smrg    *nnewp = nnew;
9299fe995a9Smrg    *nreplp = nrepl;
9309fe995a9Smrg    *ndupp = ndup;
9319fe995a9Smrg    return n;
9329fe995a9Smrg
9339fe995a9Smrg}
9349fe995a9Smrg
9359fe995a9Smrg
9369fe995a9Smrgstatic int search_and_do (
9379fe995a9Smrg    const char *inputfilename,
9389fe995a9Smrg    int lineno,
9399fe995a9Smrg    int start,
9409fe995a9Smrg    int argc,
9419fe995a9Smrg    char *argv[],
9429fe995a9Smrg    DoFunc do_func,
9439fe995a9Smrg    char *data)
9449fe995a9Smrg{
9459fe995a9Smrg    int i;
9469fe995a9Smrg    int status = 0;
9479fe995a9Smrg    int errors = 0;
9489fe995a9Smrg    AuthList *l, *next;
9499fe995a9Smrg    char *protoname, *protodata, *netid, *authname;
9509fe995a9Smrg
9519fe995a9Smrg    for (l = iceauth_head; l; l = next)
9529fe995a9Smrg    {
9539fe995a9Smrg	next = l->next;
9549fe995a9Smrg
9559fe995a9Smrg	protoname = protodata = netid = authname = NULL;
9569fe995a9Smrg
9579fe995a9Smrg	for (i = start; i < argc; i++)
9589fe995a9Smrg	{
9599fe995a9Smrg	    if (!strncmp ("protoname=", argv[i], 10))
9609fe995a9Smrg		protoname = argv[i] + 10;
9619fe995a9Smrg	    else if (!strncmp ("protodata=", argv[i], 10))
9629fe995a9Smrg		protodata = argv[i] + 10;
9639fe995a9Smrg	    else if (!strncmp ("netid=", argv[i], 6))
9649fe995a9Smrg		netid = argv[i] + 6;
9659fe995a9Smrg	    else if (!strncmp ("authname=", argv[i], 9))
9669fe995a9Smrg		authname = argv[i] + 9;
9679fe995a9Smrg	}
9689fe995a9Smrg
9699fe995a9Smrg	status = 0;
9709fe995a9Smrg
9719fe995a9Smrg	if (protoname || protodata || netid || authname)
9729fe995a9Smrg	{
9739fe995a9Smrg	    if (protoname && strcmp (protoname, l->auth->protocol_name))
9749fe995a9Smrg		continue;
9759fe995a9Smrg
9769fe995a9Smrg	    if (protodata && !binaryEqual (protodata,
9779fe995a9Smrg		l->auth->protocol_data, l->auth->protocol_data_length))
9789fe995a9Smrg		continue;
9799fe995a9Smrg
9809fe995a9Smrg	    if (netid && strcmp (netid, l->auth->network_id))
9819fe995a9Smrg		continue;
9829fe995a9Smrg
9839fe995a9Smrg	    if (authname && strcmp (authname, l->auth->auth_name))
9849fe995a9Smrg		continue;
9859fe995a9Smrg
9869fe995a9Smrg	    status = (*do_func) (inputfilename, lineno, l->auth, data);
9879fe995a9Smrg
9889fe995a9Smrg	    if (status < 0)
9899fe995a9Smrg		break;
9909fe995a9Smrg	}
9919fe995a9Smrg    }
9929fe995a9Smrg
9939fe995a9Smrg    if (status < 0)
9949fe995a9Smrg	errors -= status;		/* since status is negative */
9959fe995a9Smrg
9969fe995a9Smrg    return (errors);
9979fe995a9Smrg}
9989fe995a9Smrg
9999fe995a9Smrg
10009fe995a9Smrg/* ARGSUSED */
10019fe995a9Smrgstatic int remove_entry (
10029fe995a9Smrg    const char *inputfilename,
10039fe995a9Smrg    int lineno,
10049fe995a9Smrg    IceAuthFileEntry *auth,
10059fe995a9Smrg    char *data)
10069fe995a9Smrg{
10079fe995a9Smrg    int *nremovedp = (int *) data;
10089fe995a9Smrg    AuthList **listp = &iceauth_head;
10099fe995a9Smrg    AuthList *list;
10109fe995a9Smrg
10119fe995a9Smrg    /*
10129fe995a9Smrg     * unlink the auth we were asked to
10139fe995a9Smrg     */
10149fe995a9Smrg    while ((list = *listp)->auth != auth)
10159fe995a9Smrg	listp = &list->next;
10169fe995a9Smrg    *listp = list->next;
10179fe995a9Smrg    IceFreeAuthFileEntry (list->auth);                    /* free the auth */
10189fe995a9Smrg    free (list);				    /* free the link */
10199fe995a9Smrg    iceauth_modified = True;
10209fe995a9Smrg    (*nremovedp)++;
10219fe995a9Smrg    return 1;
10229fe995a9Smrg}
10239fe995a9Smrg
10249fe995a9Smrg/*
10259fe995a9Smrg * action routines
10269fe995a9Smrg */
10279fe995a9Smrg
10289fe995a9Smrg/*
10299fe995a9Smrg * help
10309fe995a9Smrg */
10319fe995a9Smrgint print_help (
10329fe995a9Smrg    FILE *fp,
10339fe995a9Smrg    const char *cmd)
10349fe995a9Smrg{
10359fe995a9Smrg    const CommandTable *ct;
10369fe995a9Smrg    int n = 0;
10379fe995a9Smrg
10389fe995a9Smrg    fprintf (fp, "\n");
10399fe995a9Smrg    if (!cmd) {				/* if no cmd, print all help */
10409fe995a9Smrg	for (ct = command_table; ct->name; ct++) {
10419fe995a9Smrg	    fprintf (fp, "%s\n\n", ct->helptext);
10429fe995a9Smrg	    n++;
10439fe995a9Smrg	}
10449fe995a9Smrg    } else {
10459fe995a9Smrg	int len = strlen (cmd);
10469fe995a9Smrg	for (ct = command_table; ct->name; ct++) {
10479fe995a9Smrg	    if (strncmp (cmd, ct->name, len) == 0) {
10489fe995a9Smrg		fprintf (fp, "%s\n\n", ct->helptext);
10499fe995a9Smrg		n++;
10509fe995a9Smrg	    }
10519fe995a9Smrg	}
10529fe995a9Smrg    }
10539fe995a9Smrg
10549fe995a9Smrg    return n;
10559fe995a9Smrg}
10569fe995a9Smrg
10579fe995a9Smrgstatic int do_help (
10589fe995a9Smrg    const char *inputfilename,
10599fe995a9Smrg    int lineno,
10609fe995a9Smrg    int argc,
10619fe995a9Smrg    char **argv)
10629fe995a9Smrg{
10639fe995a9Smrg    char *cmd = (argc > 1 ? argv[1] : NULL);
10649fe995a9Smrg    int n;
10659fe995a9Smrg
10669fe995a9Smrg    n = print_help (stdout, cmd);
10679fe995a9Smrg
10689fe995a9Smrg    if (n < 0 || (n == 0 && !cmd)) {
10699fe995a9Smrg	prefix (inputfilename, lineno);
10709fe995a9Smrg	fprintf (stderr, "internal error with help");
10719fe995a9Smrg	if (cmd) {
10729fe995a9Smrg	    fprintf (stderr, " on command \"%s\"", cmd);
10739fe995a9Smrg	}
10749fe995a9Smrg	fprintf (stderr, "\n");
10759fe995a9Smrg	return 1;
10769fe995a9Smrg    }
10779fe995a9Smrg
10789fe995a9Smrg    if (n == 0) {
10799fe995a9Smrg	prefix (inputfilename, lineno);
10809fe995a9Smrg	/* already know that cmd is set in this case */
10819fe995a9Smrg	fprintf (stderr, "no help for noexistent command \"%s\"\n", cmd);
10829fe995a9Smrg    }
10839fe995a9Smrg
10849fe995a9Smrg    return 0;
10859fe995a9Smrg}
10869fe995a9Smrg
10879fe995a9Smrg/*
10889fe995a9Smrg * questionmark
10899fe995a9Smrg */
10909fe995a9Smrg/* ARGSUSED */
10919fe995a9Smrgstatic int do_questionmark (
10929fe995a9Smrg    const char *inputfilename,
10939fe995a9Smrg    int lineno,
10949fe995a9Smrg    int argc,
10959fe995a9Smrg    char **argv)
10969fe995a9Smrg{
10979fe995a9Smrg    const CommandTable *ct;
10989fe995a9Smrg    int i;
10999fe995a9Smrg#define WIDEST_COLUMN 72
11009fe995a9Smrg    int col = WIDEST_COLUMN;
11019fe995a9Smrg
11029fe995a9Smrg    printf ("Commands:\n");
11039fe995a9Smrg    for (ct = command_table; ct->name; ct++) {
11049fe995a9Smrg	if ((col + ct->maxlen) > WIDEST_COLUMN) {
11059fe995a9Smrg	    if (ct != command_table) {
11069fe995a9Smrg		putc ('\n', stdout);
11079fe995a9Smrg	    }
11089fe995a9Smrg	    fputs ("        ", stdout);
11099fe995a9Smrg	    col = 8;			/* length of string above */
11109fe995a9Smrg	}
11119fe995a9Smrg	fputs (ct->name, stdout);
11129fe995a9Smrg	col += ct->maxlen;
11139fe995a9Smrg	for (i = ct->maxlen; i < COMMAND_NAMES_PADDED_WIDTH; i++) {
11149fe995a9Smrg	    putc (' ', stdout);
11159fe995a9Smrg	    col++;
11169fe995a9Smrg	}
11179fe995a9Smrg    }
11189fe995a9Smrg    if (col != 0) {
11199fe995a9Smrg	putc ('\n', stdout);
11209fe995a9Smrg    }
11219fe995a9Smrg
11229fe995a9Smrg    /* allow bad lines since this is help */
11239fe995a9Smrg    return 0;
11249fe995a9Smrg}
11259fe995a9Smrg
11269fe995a9Smrg/*
11279fe995a9Smrg * list [displayname ...]
11289fe995a9Smrg */
11299fe995a9Smrgstatic int do_list (
11309fe995a9Smrg    const char *inputfilename,
11319fe995a9Smrg    int lineno,
11329fe995a9Smrg    int argc,
11339fe995a9Smrg    char **argv)
11349fe995a9Smrg{
11359fe995a9Smrg    struct _list_data ld;
11369fe995a9Smrg
11379fe995a9Smrg    ld.fp = stdout;
11389fe995a9Smrg
11399fe995a9Smrg    if (argc == 1) {
11409fe995a9Smrg	register AuthList *l;
11419fe995a9Smrg
11429fe995a9Smrg	if (iceauth_head) {
11439fe995a9Smrg	    for (l = iceauth_head; l; l = l->next) {
11449fe995a9Smrg		dump_entry (inputfilename, lineno, l->auth, (char *) &ld);
11459fe995a9Smrg	    }
11469fe995a9Smrg	}
11479fe995a9Smrg	return 0;
11489fe995a9Smrg    }
11499fe995a9Smrg    else
11509fe995a9Smrg    {
11519fe995a9Smrg	return (search_and_do (inputfilename, lineno, 1, argc, argv,
11529fe995a9Smrg	    dump_entry, (char *) &ld));
11539fe995a9Smrg    }
11549fe995a9Smrg}
11559fe995a9Smrg
11569fe995a9Smrg/*
11579fe995a9Smrg * merge filename [filename ...]
11589fe995a9Smrg */
11599fe995a9Smrgstatic int do_merge (
11609fe995a9Smrg    const char *inputfilename,
11619fe995a9Smrg    int lineno,
11629fe995a9Smrg    int argc,
11639fe995a9Smrg    char **argv)
11649fe995a9Smrg{
11659fe995a9Smrg    int i;
11669fe995a9Smrg    int errors = 0;
11679fe995a9Smrg    AuthList *head, *tail, *listhead, *listtail;
11689fe995a9Smrg    int nentries, nnew, nrepl, ndup;
11699fe995a9Smrg
11709fe995a9Smrg    if (argc < 2) {
11719fe995a9Smrg	prefix (inputfilename, lineno);
11729fe995a9Smrg	badcommandline (argv[0]);
11739fe995a9Smrg	return 1;
11749fe995a9Smrg    }
11759fe995a9Smrg
11769fe995a9Smrg    listhead = listtail = NULL;
11779fe995a9Smrg
11789fe995a9Smrg    for (i = 1; i < argc; i++) {
11799fe995a9Smrg	char *filename = argv[i];
11809fe995a9Smrg	FILE *fp;
11819fe995a9Smrg	Bool used_stdin = False;
11829fe995a9Smrg
11839fe995a9Smrg	fp = open_file (&filename, "rb",
11849fe995a9Smrg			&used_stdin, inputfilename, lineno,
11859fe995a9Smrg			argv[0]);
11869fe995a9Smrg	if (!fp) {
11879fe995a9Smrg	    errors++;
11889fe995a9Smrg	    continue;
11899fe995a9Smrg	}
11909fe995a9Smrg
11919fe995a9Smrg	head = tail = NULL;
11929fe995a9Smrg	nentries = read_auth_entries (fp, &head, &tail);
11939fe995a9Smrg	if (nentries == 0) {
11949fe995a9Smrg	    prefix (inputfilename, lineno);
11959fe995a9Smrg	    fprintf (stderr, "unable to read any entries from file \"%s\"\n",
11969fe995a9Smrg		     filename);
11979fe995a9Smrg	    errors++;
11989fe995a9Smrg	} else {			/* link it in */
11999fe995a9Smrg	    add_to_list (listhead, listtail, head);
12009fe995a9Smrg 	}
12019fe995a9Smrg
12029fe995a9Smrg	if (!used_stdin) (void) fclose (fp);
12039fe995a9Smrg    }
12049fe995a9Smrg
12059fe995a9Smrg    /*
12069fe995a9Smrg     * if we have new entries, merge them in (freeing any duplicates)
12079fe995a9Smrg     */
12089fe995a9Smrg    if (listhead) {
12099fe995a9Smrg	nentries = merge_entries (&iceauth_head, listhead,
12109fe995a9Smrg	    &nnew, &nrepl, &ndup);
12119fe995a9Smrg	if (verbose)
12129fe995a9Smrg	  printf ("%d entries read in:  %d new, %d replacement%s\n",
12139fe995a9Smrg	  	  nentries, nnew, nrepl, nrepl != 1 ? "s" : "");
12149fe995a9Smrg	if (nentries > 0) iceauth_modified = True;
12159fe995a9Smrg    }
12169fe995a9Smrg
12179fe995a9Smrg    return 0;
12189fe995a9Smrg}
12199fe995a9Smrg
12209fe995a9Smrg/*
12219fe995a9Smrg * extract filename displayname [displayname ...]
12229fe995a9Smrg */
12239fe995a9Smrgstatic int do_extract (
12249fe995a9Smrg    const char *inputfilename,
12259fe995a9Smrg    int lineno,
12269fe995a9Smrg    int argc,
12279fe995a9Smrg    char **argv)
12289fe995a9Smrg{
12299fe995a9Smrg    int errors;
12309fe995a9Smrg    struct _extract_data ed;
12319fe995a9Smrg
12329fe995a9Smrg    if (argc < 3) {
12339fe995a9Smrg	prefix (inputfilename, lineno);
12349fe995a9Smrg	badcommandline (argv[0]);
12359fe995a9Smrg	return 1;
12369fe995a9Smrg    }
12379fe995a9Smrg
12389fe995a9Smrg    ed.fp = NULL;
12399fe995a9Smrg    ed.filename = argv[1];
12409fe995a9Smrg    ed.nwritten = 0;
12419fe995a9Smrg    ed.cmd = argv[0];
12429fe995a9Smrg
12439fe995a9Smrg    errors = search_and_do (inputfilename, lineno, 2, argc, argv,
12449fe995a9Smrg	extract_entry, (char *) &ed);
12459fe995a9Smrg
12469fe995a9Smrg    if (!ed.fp) {
12479fe995a9Smrg	fprintf (stderr,
12489fe995a9Smrg		 "No matches found, authority file \"%s\" not written\n",
12499fe995a9Smrg		 ed.filename);
12509fe995a9Smrg    } else {
12519fe995a9Smrg	if (verbose) {
12529fe995a9Smrg	    printf ("%d entries written to \"%s\"\n",
12539fe995a9Smrg		    ed.nwritten, ed.filename);
12549fe995a9Smrg	}
12559fe995a9Smrg	if (!ed.used_stdout) {
12569fe995a9Smrg	    (void) fclose (ed.fp);
12579fe995a9Smrg	}
12589fe995a9Smrg    }
12599fe995a9Smrg
12609fe995a9Smrg    return errors;
12619fe995a9Smrg}
12629fe995a9Smrg
12639fe995a9Smrg
12649fe995a9Smrg/*
12659fe995a9Smrg * add protoname protodata netid authname authdata
12669fe995a9Smrg */
12679fe995a9Smrgstatic int do_add (
12689fe995a9Smrg    const char *inputfilename,
12699fe995a9Smrg    int lineno,
12709fe995a9Smrg    int argc,
12719fe995a9Smrg    char **argv)
12729fe995a9Smrg{
12739fe995a9Smrg    int n, nnew, nrepl, ndup;
12749fe995a9Smrg    char *protoname;
12759fe995a9Smrg    char *protodata_hex;
12769fe995a9Smrg    char *protodata = NULL; /* not required */
12779fe995a9Smrg    char *netid;
12789fe995a9Smrg    char *authname;
12799fe995a9Smrg    char *authdata_hex;
12809fe995a9Smrg    char *authdata = NULL;
12819fe995a9Smrg    int protodata_len, authdata_len;
12829fe995a9Smrg    IceAuthFileEntry *auth = NULL;
12839fe995a9Smrg    AuthList *list;
12849fe995a9Smrg    int status = 0;
12859fe995a9Smrg
12869fe995a9Smrg    if (argc != 6 || !argv[1] || !argv[2] ||
12879fe995a9Smrg	!argv[3] || !argv[4] || !argv[5])
12889fe995a9Smrg    {
12899fe995a9Smrg	prefix (inputfilename, lineno);
12909fe995a9Smrg	badcommandline (argv[0]);
12919fe995a9Smrg	return 1;
12929fe995a9Smrg    }
12939fe995a9Smrg
12949fe995a9Smrg    protoname = argv[1];
12959fe995a9Smrg    protodata_hex = argv[2];
12969fe995a9Smrg    netid = argv[3];
12979fe995a9Smrg    authname = argv[4];
12989fe995a9Smrg    authdata_hex = argv[5];
12999fe995a9Smrg
13009fe995a9Smrg    protodata_len = strlen (protodata_hex);
13019fe995a9Smrg    if (protodata_len > 0)
13029fe995a9Smrg    {
13039fe995a9Smrg	if (protodata_hex[0] == '"' && protodata_hex[protodata_len - 1] == '"')
13049fe995a9Smrg	{
13059fe995a9Smrg	    protodata = malloc (protodata_len - 1);
13069fe995a9Smrg	    if (protodata)
13079fe995a9Smrg	    {
13089fe995a9Smrg		strncpy (protodata, protodata_hex + 1, protodata_len - 2);
13099fe995a9Smrg		protodata_len -= 2;
13109fe995a9Smrg	    }
13119fe995a9Smrg	    else
13129fe995a9Smrg		goto add_bad_malloc;
13139fe995a9Smrg	}
13149fe995a9Smrg	else
13159fe995a9Smrg	{
13169fe995a9Smrg	    protodata_len = cvthexkey (protodata_hex, &protodata);
13179fe995a9Smrg	    if (protodata_len < 0)
13189fe995a9Smrg	    {
13199fe995a9Smrg		prefix (inputfilename, lineno);
13209fe995a9Smrg		fprintf (stderr,
13219fe995a9Smrg	       "protodata_hex contains odd number of or non-hex characters\n");
13229fe995a9Smrg		return (1);
13239fe995a9Smrg	    }
13249fe995a9Smrg	}
13259fe995a9Smrg    }
13269fe995a9Smrg
13279fe995a9Smrg    authdata_len = strlen (authdata_hex);
13289fe995a9Smrg    if (authdata_hex[0] == '"' && authdata_hex[authdata_len - 1] == '"')
13299fe995a9Smrg    {
13309fe995a9Smrg	authdata = malloc (authdata_len - 1);
13319fe995a9Smrg	if (authdata)
13329fe995a9Smrg	{
13339fe995a9Smrg	    strncpy (authdata, authdata_hex + 1, authdata_len - 2);
13349fe995a9Smrg	    authdata_len -= 2;
13359fe995a9Smrg	}
13369fe995a9Smrg	else
13379fe995a9Smrg	    goto add_bad_malloc;
13389fe995a9Smrg    }
13399fe995a9Smrg    else if (!strcmp (protoname, SECURERPC) || !strcmp (protoname, K5AUTH))
13409fe995a9Smrg    {
13419fe995a9Smrg	authdata = malloc (authdata_len + 1);
13429fe995a9Smrg	if (authdata)
13439fe995a9Smrg	    strcpy (authdata, authdata_hex);
13449fe995a9Smrg	else
13459fe995a9Smrg	    goto add_bad_malloc;
13469fe995a9Smrg    }
13479fe995a9Smrg    else
13489fe995a9Smrg    {
13499fe995a9Smrg	authdata_len = cvthexkey (authdata_hex, &authdata);
13509fe995a9Smrg	if (authdata_len < 0)
13519fe995a9Smrg	{
13529fe995a9Smrg	    prefix (inputfilename, lineno);
13539fe995a9Smrg	    fprintf (stderr,
13549fe995a9Smrg	       "authdata_hex contains odd number of or non-hex characters\n");
13559fe995a9Smrg	    free (protodata);
13569fe995a9Smrg	    return (1);
13579fe995a9Smrg	}
13589fe995a9Smrg    }
13599fe995a9Smrg
13609fe995a9Smrg    auth = (IceAuthFileEntry *) malloc (sizeof (IceAuthFileEntry));
13619fe995a9Smrg
13629fe995a9Smrg    if (!auth)
13639fe995a9Smrg	goto add_bad_malloc;
13649fe995a9Smrg
13659fe995a9Smrg    auth->protocol_name = copystring (protoname);
13669fe995a9Smrg    auth->protocol_data_length = protodata_len;
13679fe995a9Smrg    auth->protocol_data = protodata;
13689fe995a9Smrg    auth->network_id = copystring (netid);
13699fe995a9Smrg    auth->auth_name = copystring (authname);
13709fe995a9Smrg    auth->auth_data_length = authdata_len;
13719fe995a9Smrg    auth->auth_data = authdata;
13729fe995a9Smrg
13739fe995a9Smrg    if (!auth->protocol_name ||
13749fe995a9Smrg	(!auth->protocol_data && auth->protocol_data_length > 0) ||
13759fe995a9Smrg        !auth->network_id || !auth->auth_name ||
13769fe995a9Smrg	(!auth->auth_data && auth->auth_data_length > 0))
13779fe995a9Smrg    {
13789fe995a9Smrg	goto add_bad_malloc;
13799fe995a9Smrg    }
13809fe995a9Smrg
13819fe995a9Smrg    list = (AuthList *) malloc (sizeof (AuthList));
13829fe995a9Smrg
13839fe995a9Smrg    if (!list)
13849fe995a9Smrg	goto add_bad_malloc;
13859fe995a9Smrg
13869fe995a9Smrg    list->next = NULL;
13879fe995a9Smrg    list->auth = auth;
13889fe995a9Smrg
13899fe995a9Smrg    /*
13909fe995a9Smrg     * merge it in; note that merge will deal with allocation
13919fe995a9Smrg     */
13929fe995a9Smrg
13939fe995a9Smrg    n = merge_entries (&iceauth_head, list, &nnew, &nrepl, &ndup);
13949fe995a9Smrg
13959fe995a9Smrg    if (n > 0)
13969fe995a9Smrg	iceauth_modified = True;
13979fe995a9Smrg    else
13989fe995a9Smrg    {
13999fe995a9Smrg	prefix (inputfilename, lineno);
14009fe995a9Smrg	if (ndup > 0)
14019fe995a9Smrg	{
14029fe995a9Smrg	    status = 0;
14039fe995a9Smrg	    fprintf (stderr, "no records added - all duplicate\n");
14049fe995a9Smrg	}
14059fe995a9Smrg	else
14069fe995a9Smrg	{
14079fe995a9Smrg	    status = 1;
14089fe995a9Smrg	    fprintf (stderr, "unable to merge in added record\n");
14099fe995a9Smrg	}
14109fe995a9Smrg	goto cant_add;
14119fe995a9Smrg    }
14129fe995a9Smrg
14139fe995a9Smrg    return 0;
14149fe995a9Smrg
14159fe995a9Smrg
14169fe995a9Smrgadd_bad_malloc:
14179fe995a9Smrg
14189fe995a9Smrg    status = 1;
14199fe995a9Smrg    prefix (inputfilename, lineno);
14209fe995a9Smrg    fprintf (stderr, "unable to allocate memory to add an entry\n");
14219fe995a9Smrg
14229fe995a9Smrgcant_add:
14239fe995a9Smrg
14249fe995a9Smrg    if (protodata)
14259fe995a9Smrg	free (protodata);
14269fe995a9Smrg    if (authdata)
14279fe995a9Smrg	free (authdata);
14289fe995a9Smrg    if (auth)
14299fe995a9Smrg    {
14309fe995a9Smrg	if (auth->protocol_name)
14319fe995a9Smrg	    free (auth->protocol_name);
14329fe995a9Smrg	/* auth->protocol_data already freed,
14339fe995a9Smrg	   since it's the same as protodata */
14349fe995a9Smrg	if (auth->network_id)
14359fe995a9Smrg	    free (auth->network_id);
14369fe995a9Smrg	if (auth->auth_name)
14379fe995a9Smrg	    free (auth->auth_name);
14389fe995a9Smrg	/* auth->auth_data already freed,
14399fe995a9Smrg	   since it's the same as authdata */
14409fe995a9Smrg	free ((char *) auth);
14419fe995a9Smrg    }
14429fe995a9Smrg
14439fe995a9Smrg    return status;
14449fe995a9Smrg}
14459fe995a9Smrg
14469fe995a9Smrg/*
14479fe995a9Smrg * remove displayname
14489fe995a9Smrg */
14499fe995a9Smrgstatic int do_remove (
14509fe995a9Smrg    const char *inputfilename,
14519fe995a9Smrg    int lineno,
14529fe995a9Smrg    int argc,
14539fe995a9Smrg    char **argv)
14549fe995a9Smrg{
14559fe995a9Smrg    int nremoved = 0;
14569fe995a9Smrg    int errors;
14579fe995a9Smrg
14589fe995a9Smrg    if (argc < 2) {
14599fe995a9Smrg	prefix (inputfilename, lineno);
14609fe995a9Smrg	badcommandline (argv[0]);
14619fe995a9Smrg	return 1;
14629fe995a9Smrg    }
14639fe995a9Smrg
14649fe995a9Smrg    errors = search_and_do (inputfilename, lineno, 1, argc, argv,
14659fe995a9Smrg	remove_entry, (char *) &nremoved);
14669fe995a9Smrg    if (verbose) printf ("%d entries removed\n", nremoved);
14679fe995a9Smrg    return errors;
14689fe995a9Smrg}
14699fe995a9Smrg
14709fe995a9Smrg/*
14719fe995a9Smrg * info
14729fe995a9Smrg */
14739fe995a9Smrgstatic int do_info (
14749fe995a9Smrg    const char *inputfilename,
14759fe995a9Smrg    int lineno,
14769fe995a9Smrg    int argc,
14779fe995a9Smrg    char **argv)
14789fe995a9Smrg{
14799fe995a9Smrg    int n;
14809fe995a9Smrg    AuthList *l;
14819fe995a9Smrg
14829fe995a9Smrg    if (argc != 1) {
14839fe995a9Smrg	prefix (inputfilename, lineno);
14849fe995a9Smrg	badcommandline (argv[0]);
14859fe995a9Smrg	return 1;
14869fe995a9Smrg    }
14879fe995a9Smrg
14889fe995a9Smrg    for (l = iceauth_head, n = 0; l; l = l->next, n++) ;
14899fe995a9Smrg
14909fe995a9Smrg    printf ("Authority file:       %s\n",
14919fe995a9Smrg	    iceauth_filename ? iceauth_filename : "(none)");
14929fe995a9Smrg    printf ("File new:             %s\n", iceauth_existed ? No : Yes);
14939fe995a9Smrg    printf ("File locked:          %s\n", ignore_locks ? No : Yes);
14949fe995a9Smrg    printf ("Number of entries:    %d\n", n);
14959fe995a9Smrg    printf ("Changes honored:      %s\n", iceauth_allowed ? Yes : No);
14969fe995a9Smrg    printf ("Changes made:         %s\n", iceauth_modified ? Yes : No);
14979fe995a9Smrg    printf ("Current input:        %s:%d\n", inputfilename, lineno);
14989fe995a9Smrg    return 0;
14999fe995a9Smrg}
15009fe995a9Smrg
15019fe995a9Smrg
15029fe995a9Smrg/*
15039fe995a9Smrg * exit
15049fe995a9Smrg */
15059fe995a9Smrgstatic Bool alldone = False;
15069fe995a9Smrg
15079fe995a9Smrg/* ARGSUSED */
15089fe995a9Smrgstatic int do_exit (
15099fe995a9Smrg    const char *inputfilename,
15109fe995a9Smrg    int lineno,
15119fe995a9Smrg    int argc,
15129fe995a9Smrg    char **argv)
15139fe995a9Smrg{
15149fe995a9Smrg    /* allow bogus stuff */
15159fe995a9Smrg    alldone = True;
15169fe995a9Smrg    return 0;
15179fe995a9Smrg}
15189fe995a9Smrg
15199fe995a9Smrg/*
15209fe995a9Smrg * quit
15219fe995a9Smrg */
15229fe995a9Smrg/* ARGSUSED */
15239fe995a9Smrgstatic int do_quit (
15249fe995a9Smrg    const char *inputfilename,
15259fe995a9Smrg    int lineno,
15269fe995a9Smrg    int argc,
15279fe995a9Smrg    char **argv)
15289fe995a9Smrg{
15299fe995a9Smrg    /* allow bogus stuff */
15309fe995a9Smrg    die (0);
15319fe995a9Smrg    /* NOTREACHED */
15329fe995a9Smrg    return -1;				/* for picky compilers */
15339fe995a9Smrg}
15349fe995a9Smrg
15359fe995a9Smrg
15369fe995a9Smrg/*
15379fe995a9Smrg * source filename
15389fe995a9Smrg */
15399fe995a9Smrgstatic int do_source (
15409fe995a9Smrg    const char *inputfilename,
15419fe995a9Smrg    int lineno,
15429fe995a9Smrg    int argc,
15439fe995a9Smrg    char **argv)
15449fe995a9Smrg{
15459fe995a9Smrg    char *script;
15469fe995a9Smrg    char buf[BUFSIZ];
15479fe995a9Smrg    FILE *fp;
15489fe995a9Smrg    Bool used_stdin = False;
15499fe995a9Smrg    int len;
15509fe995a9Smrg    int errors = 0, status;
15519fe995a9Smrg    int sublineno = 0;
15529fe995a9Smrg    char **subargv;
15539fe995a9Smrg    int subargc;
15549fe995a9Smrg    Bool prompt = False;		/* only true if reading from tty */
15559fe995a9Smrg
15569fe995a9Smrg    if (argc != 2 || !argv[1]) {
15579fe995a9Smrg	prefix (inputfilename, lineno);
15589fe995a9Smrg	badcommandline (argv[0]);
15599fe995a9Smrg	return 1;
15609fe995a9Smrg    }
15619fe995a9Smrg
15629fe995a9Smrg    script = argv[1];
15639fe995a9Smrg
15649fe995a9Smrg    fp = open_file (&script, "r", &used_stdin, inputfilename, lineno, argv[0]);
15659fe995a9Smrg    if (!fp) {
15669fe995a9Smrg	return 1;
15679fe995a9Smrg    }
15689fe995a9Smrg
15699fe995a9Smrg    if (verbose && used_stdin && isatty (fileno (fp))) prompt = True;
15709fe995a9Smrg
15719fe995a9Smrg    while (!alldone) {
15729fe995a9Smrg	buf[0] = '\0';
15739fe995a9Smrg	if (prompt) {
15749fe995a9Smrg	    printf ("iceauth> ");
15759fe995a9Smrg	    fflush (stdout);
15769fe995a9Smrg	}
15779fe995a9Smrg	if (fgets (buf, sizeof buf, fp) == NULL) break;
15789fe995a9Smrg	sublineno++;
15799fe995a9Smrg	len = strlen (buf);
15809fe995a9Smrg	if (len == 0 || buf[0] == '#') continue;
15819fe995a9Smrg	if (buf[len-1] != '\n') {
15829fe995a9Smrg	    prefix (script, sublineno);
15839fe995a9Smrg	    fprintf (stderr, "line too long\n");
15849fe995a9Smrg	    errors++;
15859fe995a9Smrg	    break;
15869fe995a9Smrg	}
15879fe995a9Smrg	buf[--len] = '\0';		/* remove new line */
15889fe995a9Smrg	subargv = split_into_words (buf, &subargc);
15899fe995a9Smrg	if (subargv) {
15909fe995a9Smrg	    status = process_command (script, sublineno, subargc, subargv);
15919fe995a9Smrg	    free ((char *) subargv);
15929fe995a9Smrg	    errors += status;
15939fe995a9Smrg	} else {
15949fe995a9Smrg	    prefix (script, sublineno);
15959fe995a9Smrg	    fprintf (stderr, "unable to break line into words\n");
15969fe995a9Smrg	    errors++;
15979fe995a9Smrg	}
15989fe995a9Smrg    }
15999fe995a9Smrg
16009fe995a9Smrg    if (!used_stdin) {
16019fe995a9Smrg	(void) fclose (fp);
16029fe995a9Smrg    }
16039fe995a9Smrg    return errors;
16049fe995a9Smrg}
1605