summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKaleb Keithley <kaleb@freedesktop.org>2003-11-14 15:54:52 +0000
committerKaleb Keithley <kaleb@freedesktop.org>2003-11-14 15:54:52 +0000
commit511f5a05d0cc763d60b6b39584ea29b287cb801c (patch)
tree41bb7da5e24be23bda89796a6f7d31e117eeb3b2
R6.6 is the Xorg base-lineXORG-MAINXORG-STABLE
-rw-r--r--iceauth.c165
-rw-r--r--iceauth.h49
-rw-r--r--iceauth.man41
-rw-r--r--process.c1562
4 files changed, 1817 insertions, 0 deletions
diff --git a/iceauth.c b/iceauth.c
new file mode 100644
index 0000000..7e7e676
--- /dev/null
+++ b/iceauth.c
@@ -0,0 +1,165 @@
+/*
+ * $Xorg: iceauth.c,v 1.4 2001/02/09 02:05:31 xorgcvs Exp $
+ *
+ * xauth - manipulate authorization file
+ *
+ *
+Copyright 1989, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+ * *
+ * Original Author of "xauth" : Jim Fulton, MIT X Consortium
+ * Modified into "iceauth" : Ralph Mor, X Consortium
+ */
+
+#include "iceauth.h"
+
+
+/*
+ * global data
+ */
+char *ProgramName; /* argv[0], set at top of main() */
+int verbose = -1; /* print certain messages */
+Bool ignore_locks = False; /* for error recovery */
+Bool break_locks = False; /* for error recovery */
+
+/*
+ * local data
+ */
+
+static char *authfilename = NULL; /* filename of cookie file */
+static char *defcmds[] = { "source", "-", NULL }; /* default command */
+static int ndefcmds = 2;
+static char *defsource = "(stdin)";
+
+/*
+ * utility routines
+ */
+static void usage ()
+{
+ static char *prefixmsg[] = {
+"",
+"where options include:",
+" -f authfilename name of authority file to use",
+" -v turn on extra messages",
+" -q turn off extra messages",
+" -i ignore locks on authority file",
+" -b break locks on authority file",
+"",
+"and commands have the following syntax:",
+"",
+NULL };
+ static char *suffixmsg[] = {
+"A dash may be used with the \"merge\" and \"source\" to read from the",
+"standard input. Commands beginning with \"n\" use numeric format.",
+"",
+NULL };
+ char **msg;
+
+ fprintf (stderr, "usage: %s [-options ...] [command arg ...]\n",
+ ProgramName);
+ for (msg = prefixmsg; *msg; msg++) {
+ fprintf (stderr, "%s\n", *msg);
+ }
+ print_help (stderr, NULL, " "); /* match prefix indentation */
+ fprintf (stderr, "\n");
+ for (msg = suffixmsg; *msg; msg++) {
+ fprintf (stderr, "%s\n", *msg);
+ }
+ exit (1);
+}
+
+
+/*
+ * The main routine - parses command line and calls action procedures
+ */
+main (argc, argv)
+ int argc;
+ char *argv[];
+{
+ int i;
+ char *sourcename = defsource;
+ char **arglist = defcmds;
+ int nargs = ndefcmds;
+ int status;
+
+ ProgramName = argv[0];
+
+ for (i = 1; i < argc; i++) {
+ char *arg = argv[i];
+
+ if (arg[0] == '-') {
+ char *flag;
+
+ for (flag = (arg + 1); *flag; flag++) {
+ switch (*flag) {
+ case 'f': /* -f authfilename */
+ if (++i >= argc) usage ();
+ authfilename = argv[i];
+ continue;
+ case 'v': /* -v */
+ verbose = 1;
+ continue;
+ case 'q': /* -q */
+ verbose = 0;
+ continue;
+ case 'b': /* -b */
+ break_locks = True;
+ continue;
+ case 'i': /* -i */
+ ignore_locks = True;
+ continue;
+ default:
+ usage ();
+ }
+ }
+ } else {
+ sourcename = "(argv)";
+ nargs = argc - i;
+ arglist = argv + i;
+ if (verbose == -1) verbose = 0;
+ break;
+ }
+ }
+
+ if (verbose == -1) { /* set default, don't junk stdout */
+ verbose = (isatty(fileno(stdout)) != 0);
+ }
+
+ if (!authfilename) {
+ authfilename = IceAuthFileName (); /* static name, do not free */
+ if (!authfilename) {
+ fprintf (stderr,
+ "%s: unable to generate an authority file name\n",
+ ProgramName);
+ exit (1);
+ }
+ }
+ if (auth_initialize (authfilename) != 0) {
+ /* error message printed in auth_initialize */
+ exit (1);
+ }
+
+ status = process_command (sourcename, 1, nargs, arglist);
+
+ (void) auth_finalize ();
+ exit ((status != 0) ? 1 : 0);
+}
diff --git a/iceauth.h b/iceauth.h
new file mode 100644
index 0000000..e151ec8
--- /dev/null
+++ b/iceauth.h
@@ -0,0 +1,49 @@
+/*
+ * $Xorg: iceauth.h,v 1.4 2001/02/09 02:05:31 xorgcvs Exp $
+ *
+ *
+Copyright 1989, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+ * *
+ * Author: Jim Fulton, MIT X Consortium
+ */
+
+#include <stdio.h>
+#include <X11/Xos.h>
+#include <X11/ICE/ICElib.h>
+#include <X11/ICE/ICEutil.h>
+#include <X11/Xfuncs.h>
+
+#ifndef True
+typedef int Bool;
+#define False 0
+#define True 1
+#endif
+
+extern char *ProgramName;
+
+extern char *malloc(), *realloc();
+int process_command(), auth_initialize(), auth_finalize();
+extern int print_help();
+extern int verbose;
+extern Bool ignore_locks;
+extern Bool break_locks;
diff --git a/iceauth.man b/iceauth.man
new file mode 100644
index 0000000..4db9fd3
--- /dev/null
+++ b/iceauth.man
@@ -0,0 +1,41 @@
+.\" $Xorg: iceauth.man,v 1.4 2001/02/09 02:05:31 xorgcvs Exp $
+
+.\" Copyright 1994, 1998 The Open Group
+.\"
+.\" Permission to use, copy, modify, distribute, and sell this software and its
+.\" documentation for any purpose is hereby granted without fee, provided that
+.\" the above copyright notice appear in all copies and that both that
+.\" copyright notice and this permission notice appear in supporting
+.\" documentation.
+.\"
+.\" The above copyright notice and this permission notice shall be included in
+.\" all copies or substantial portions of the Software.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+.\" IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+.\" FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+.\" THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+.\" WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+.\" OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+.\" SOFTWARE.
+.\"
+.\" Except as contained in this notice, the name of The Open Group shall not
+.\" be used in advertising or otherwise to promote the sale, use or other
+.\" dealing in this Software without prior written authorization from the
+.\" The Open Group.
+.TH ICEAUTH 1 "Release 6.4" "X Version 11"
+.SH NAME
+iceauth \- ICE authority file utility
+.SH SYNOPSIS
+.B iceauth
+[ \fB\-f\fP \fIauthfile\fP ] [ \fB\-vqib\fP ] [ \fIcommand arg ...\fP ]
+.SH DESCRIPTION
+.PP
+The \fIiceauth\fP program is used to edit and display the authorization
+information used in connecting with ICE. This program is usually
+used to extract authorization records from one machine and merge them in on
+another (as is the case when using remote logins or granting access to
+other users). Commands (described below) may be entered interactively,
+on the \fIiceauth\fP command line, or in scripts.
+.SH AUTHOR
+Ralph Mor, X Consortium
diff --git a/process.c b/process.c
new file mode 100644
index 0000000..ce75fcd
--- /dev/null
+++ b/process.c
@@ -0,0 +1,1562 @@
+/*
+ * $Xorg: process.c,v 1.5 2001/02/09 02:05:31 xorgcvs Exp $
+ *
+ *
+Copyright 1989, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+ * *
+ * Original Author of "xauth" : Jim Fulton, MIT X Consortium
+ * Modified into "iceauth" : Ralph Mor, X Consortium
+ */
+
+#include "iceauth.h"
+#include <ctype.h>
+#include <errno.h>
+#ifdef X_NOT_STDC_ENV
+extern int errno;
+#endif
+
+#include <signal.h>
+
+#define SECURERPC "SUN-DES-1"
+#define K5AUTH "KERBEROS-V5-1"
+
+#define ICEAUTH_DEFAULT_RETRIES 10 /* number of competitors we expect */
+#define ICEAUTH_DEFAULT_TIMEOUT 2 /* in seconds, be quick */
+#define ICEAUTH_DEFAULT_DEADTIME 600L /* 10 minutes in seconds */
+
+typedef struct _AuthList { /* linked list of entries */
+ struct _AuthList *next;
+ IceAuthFileEntry *auth;
+} AuthList;
+
+#define add_to_list(h,t,e) {if (t) (t)->next = (e); else (h) = (e); (t) = (e);}
+
+typedef struct _CommandTable { /* commands that are understood */
+ char *name; /* full name */
+ int minlen; /* unique prefix */
+ int maxlen; /* strlen(name) */
+ int (*processfunc)(); /* handler */
+ char *helptext; /* what to print for help */
+} CommandTable;
+
+struct _extract_data { /* for iterating */
+ FILE *fp; /* input source */
+ char *filename; /* name of input */
+ Bool used_stdout; /* whether or not need to close */
+ int nwritten; /* number of entries written */
+ char *cmd; /* for error messages */
+};
+
+struct _list_data { /* for iterating */
+ FILE *fp; /* output file */
+};
+
+
+/*
+ * private data
+ */
+static char *stdin_filename = "(stdin)"; /* for messages */
+static char *stdout_filename = "(stdout)"; /* for messages */
+static char *Yes = "yes"; /* for messages */
+static char *No = "no"; /* for messages */
+
+static int do_list(), do_merge(), do_extract(), do_add(), do_remove();
+static int do_help(), do_source(), do_info(), do_exit();
+static int do_quit(), do_questionmark();
+
+static CommandTable command_table[] = { /* table of known commands */
+{ "add", 2, 3, do_add,
+"\
+add add an entry\n\
+ add protoname protodata netid authname authdata"
+},
+
+{ "exit", 3, 4, do_exit,
+"\
+exit save changes and exit program"
+},
+
+{ "extract", 3, 7, do_extract,
+"\
+extract extract entries into file\n\
+ extract filename <protoname=$> <protodata=$> <netid=$> <authname=$>"
+},
+
+{ "help", 1, 4, do_help,
+"\
+help print help\n\
+ help <topic>"
+},
+
+{ "info", 1, 4, do_info,
+"\
+info print information about entries"
+},
+
+{ "list", 1, 4, do_list,
+"\
+list list entries\n\
+ list <protoname=$> <protodata=$> <netid=$> <authname=$>"
+},
+
+{ "merge", 1, 5, do_merge,
+"\
+merge merge entries from files\n\
+ merge filename1 <filename2> <filename3> ..."
+},
+
+{ "quit", 1, 4, do_quit,
+"\
+quit abort changes and exit program" },
+
+{ "remove", 1, 6, do_remove,
+"\
+remove remove entries\n\
+ remove <protoname=$> <protodata=$> <netid=$> <authname=$>"
+},
+
+{ "source", 1, 6, do_source,
+"\
+source read commands from file\n\
+ source filename"
+},
+
+{ "?", 1, 1, do_questionmark,
+"\
+? list available commands" },
+
+{ NULL, 0, 0, NULL, NULL },
+};
+
+#define COMMAND_NAMES_PADDED_WIDTH 10 /* wider than anything above */
+
+
+static Bool okay_to_use_stdin = True; /* set to false after using */
+
+static char *hex_table[] = { /* for printing hex digits */
+ "00", "01", "02", "03", "04", "05", "06", "07",
+ "08", "09", "0a", "0b", "0c", "0d", "0e", "0f",
+ "10", "11", "12", "13", "14", "15", "16", "17",
+ "18", "19", "1a", "1b", "1c", "1d", "1e", "1f",
+ "20", "21", "22", "23", "24", "25", "26", "27",
+ "28", "29", "2a", "2b", "2c", "2d", "2e", "2f",
+ "30", "31", "32", "33", "34", "35", "36", "37",
+ "38", "39", "3a", "3b", "3c", "3d", "3e", "3f",
+ "40", "41", "42", "43", "44", "45", "46", "47",
+ "48", "49", "4a", "4b", "4c", "4d", "4e", "4f",
+ "50", "51", "52", "53", "54", "55", "56", "57",
+ "58", "59", "5a", "5b", "5c", "5d", "5e", "5f",
+ "60", "61", "62", "63", "64", "65", "66", "67",
+ "68", "69", "6a", "6b", "6c", "6d", "6e", "6f",
+ "70", "71", "72", "73", "74", "75", "76", "77",
+ "78", "79", "7a", "7b", "7c", "7d", "7e", "7f",
+ "80", "81", "82", "83", "84", "85", "86", "87",
+ "88", "89", "8a", "8b", "8c", "8d", "8e", "8f",
+ "90", "91", "92", "93", "94", "95", "96", "97",
+ "98", "99", "9a", "9b", "9c", "9d", "9e", "9f",
+ "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7",
+ "a8", "a9", "aa", "ab", "ac", "ad", "ae", "af",
+ "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7",
+ "b8", "b9", "ba", "bb", "bc", "bd", "be", "bf",
+ "c0", "c1", "c2", "c3", "c4", "c5", "c6", "c7",
+ "c8", "c9", "ca", "cb", "cc", "cd", "ce", "cf",
+ "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
+ "d8", "d9", "da", "db", "dc", "dd", "de", "df",
+ "e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7",
+ "e8", "e9", "ea", "eb", "ec", "ed", "ee", "ef",
+ "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
+ "f8", "f9", "fa", "fb", "fc", "fd", "fe", "ff",
+};
+
+static unsigned int hexvalues[256]; /* for parsing hex input */
+
+static int original_umask = 0; /* for restoring */
+
+
+/*
+ * private utility procedures
+ */
+
+static char *copystring (src)
+ char *src;
+{
+ int len = strlen (src);
+ char *cp;
+
+ if (!src) return NULL;
+ cp = malloc (len + 1);
+ if (cp)
+ strcpy (cp, src);
+ return cp;
+}
+
+static int
+binaryEqual (a, b, len)
+
+register char *a, *b;
+register unsigned len;
+
+{
+ while (len--)
+ if (*a++ != *b++)
+ return 0;
+ return 1;
+}
+
+static void prefix (fn, n)
+ char *fn;
+ int n;
+{
+ fprintf (stderr, "%s: %s:%d: ", ProgramName, fn, n);
+}
+
+static void badcommandline (cmd)
+ char *cmd;
+{
+ fprintf (stderr, "bad \"%s\" command line\n", cmd);
+}
+
+static char *skip_space (s)
+ register char *s;
+{
+ if (!s) return NULL;
+
+ for ( ; *s && isascii(*s) && isspace(*s); s++)
+ ;
+ return s;
+}
+
+
+static char *skip_nonspace (s)
+ register char *s;
+{
+ if (!s) return NULL;
+
+ /* put quoting into loop if need be */
+ for ( ; *s && isascii(*s) && !isspace(*s); s++)
+ ;
+ return s;
+}
+
+static char **split_into_words (src, argcp) /* argvify string */
+ char *src;
+ int *argcp;
+{
+ char *jword;
+ char savec;
+ char **argv;
+ int cur, total;
+
+ *argcp = 0;
+#define WORDSTOALLOC 4 /* most lines are short */
+ argv = (char **) malloc (WORDSTOALLOC * sizeof (char *));
+ if (!argv) return NULL;
+ cur = 0;
+ total = WORDSTOALLOC;
+
+ /*
+ * split the line up into separate, nul-terminated tokens; the last
+ * "token" will point to the empty string so that it can be bashed into
+ * a null pointer.
+ */
+
+ do {
+ jword = skip_space (src);
+ src = skip_nonspace (jword);
+ savec = *src;
+ *src = '\0';
+ if (cur == total) {
+ total += WORDSTOALLOC;
+ argv = (char **) realloc (argv, total * sizeof (char *));
+ if (!argv) return NULL;
+ }
+ argv[cur++] = jword;
+ if (savec) src++; /* if not last on line advance */
+ } while (jword != src);
+
+ argv[--cur] = NULL; /* smash empty token to end list */
+ *argcp = cur;
+ return argv;
+}
+
+
+static FILE *open_file (filenamep, mode, usedstdp, srcfn, srcln, cmd)
+ char **filenamep;
+ char *mode;
+ Bool *usedstdp;
+ char *srcfn;
+ int srcln;
+ char *cmd;
+{
+ FILE *fp;
+
+ if (strcmp (*filenamep, "-") == 0) {
+ *usedstdp = True;
+ /* select std descriptor to use */
+ if (mode[0] == 'r') {
+ if (okay_to_use_stdin) {
+ okay_to_use_stdin = False;
+ *filenamep = stdin_filename;
+ return stdin;
+ } else {
+ prefix (srcfn, srcln);
+ fprintf (stderr, "%s: stdin already in use\n", cmd);
+ return NULL;
+ }
+ } else {
+ *filenamep = stdout_filename;
+ return stdout; /* always okay to use stdout */
+ }
+ }
+
+ fp = fopen (*filenamep, mode);
+ if (!fp) {
+ prefix (srcfn, srcln);
+ fprintf (stderr, "%s: unable to open file %s\n", cmd, *filenamep);
+ }
+ return fp;
+}
+
+
+static int read_auth_entries (fp, headp, tailp)
+ FILE *fp;
+ AuthList **headp, **tailp;
+{
+ IceAuthFileEntry *auth;
+ AuthList *head, *tail;
+ int n;
+
+ head = tail = NULL;
+ n = 0;
+ /* put all records into linked list */
+ while ((auth = IceReadAuthFileEntry (fp)) != NULL) {
+ AuthList *l = (AuthList *) malloc (sizeof (AuthList));
+ if (!l) {
+ fprintf (stderr,
+ "%s: unable to alloc entry reading auth file\n",
+ ProgramName);
+ exit (1);
+ }
+ l->next = NULL;
+ l->auth = auth;
+ if (tail) /* if not first time through append */
+ tail->next = l;
+ else
+ head = l; /* first time through, so assign */
+ tail = l;
+ n++;
+ }
+ *headp = head;
+ *tailp = tail;
+ return n;
+}
+
+
+static int cvthexkey (hexstr, ptrp) /* turn hex key string into octets */
+ char *hexstr;
+ char **ptrp;
+{
+ int i;
+ int len = 0;
+ char *retval, *s;
+ unsigned char *us;
+ char c;
+ char savec = '\0';
+
+ /* count */
+ for (s = hexstr; *s; s++) {
+ if (!isascii(*s)) return -1;
+ if (isspace(*s)) continue;
+ if (!isxdigit(*s)) return -1;
+ len++;
+ }
+
+ /* if odd then there was an error */
+ if ((len & 1) == 1) return -1;
+
+
+ /* now we know that the input is good */
+ len >>= 1;
+ retval = malloc (len);
+ if (!retval) {
+ fprintf (stderr, "%s: unable to allocate %d bytes for hexkey\n",
+ ProgramName, len);
+ return -1;
+ }
+
+ for (us = (unsigned char *) retval, i = len; i > 0; hexstr++) {
+ c = *hexstr;
+ if (isspace(c)) continue; /* already know it is ascii */
+ if (isupper(c))
+ c = tolower(c);
+ if (savec) {
+#define atoh(c) ((c) - (((c) >= '0' && (c) <= '9') ? '0' : ('a'-10)))
+ *us = (unsigned char)((atoh(savec) << 4) + atoh(c));
+#undef atoh
+ savec = 0; /* ready for next character */
+ us++;
+ i--;
+ } else {
+ savec = c;
+ }
+ }
+ *ptrp = retval;
+ return len;
+}
+
+static int dispatch_command (inputfilename, lineno, argc, argv, tab, statusp)
+ char *inputfilename;
+ int lineno;
+ int argc;
+ char **argv;
+ CommandTable *tab;
+ int *statusp;
+{
+ CommandTable *ct;
+ char *cmd;
+ int n;
+ /* scan table for command */
+ cmd = argv[0];
+ n = strlen (cmd);
+ for (ct = tab; ct->name; ct++) {
+ /* look for unique prefix */
+ if (n >= ct->minlen && n <= ct->maxlen &&
+ strncmp (cmd, ct->name, n) == 0) {
+ *statusp = (*(ct->processfunc))(inputfilename, lineno, argc, argv);
+ return 1;
+ }
+ }
+
+ *statusp = 1;
+ return 0;
+}
+
+
+static AuthList *iceauth_head = NULL; /* list of auth entries */
+static Bool iceauth_existed = False; /* if was present at initialize */
+static Bool iceauth_modified = False; /* if added, removed, or merged */
+static Bool iceauth_allowed = True; /* if allowed to write auth file */
+static char *iceauth_filename = NULL;
+static Bool dieing = False;
+
+#ifdef SIGNALRETURNSINT
+#define _signal_t int
+#else
+#define _signal_t void
+#endif
+
+/* ARGSUSED */
+static _signal_t die (sig)
+ int sig;
+{
+ dieing = True;
+ exit (auth_finalize ());
+ /* NOTREACHED */
+#ifdef SIGNALRETURNSINT
+ return -1; /* for picky compilers */
+#endif
+}
+
+static _signal_t catchsig (sig)
+ int sig;
+{
+#ifdef SYSV
+ if (sig > 0) signal (sig, die); /* re-establish signal handler */
+#endif
+ if (verbose && iceauth_modified) printf ("\r\n");
+ die (sig);
+ /* NOTREACHED */
+#ifdef SIGNALRETURNSINT
+ return -1; /* for picky compilers */
+#endif
+}
+
+static void register_signals ()
+{
+ signal (SIGINT, catchsig);
+ signal (SIGTERM, catchsig);
+#ifdef SIGHUP
+ signal (SIGHUP, catchsig);
+#endif
+ return;
+}
+
+
+/*
+ * public procedures for parsing lines of input
+ */
+
+int auth_initialize (authfilename)
+ char *authfilename;
+{
+ int n;
+ AuthList *head, *tail;
+ FILE *authfp;
+ Bool exists;
+
+ register_signals ();
+
+ bzero ((char *) hexvalues, sizeof hexvalues);
+ hexvalues['0'] = 0;
+ hexvalues['1'] = 1;
+ hexvalues['2'] = 2;
+ hexvalues['3'] = 3;
+ hexvalues['4'] = 4;
+ hexvalues['5'] = 5;
+ hexvalues['6'] = 6;
+ hexvalues['7'] = 7;
+ hexvalues['8'] = 8;
+ hexvalues['9'] = 9;
+ hexvalues['a'] = hexvalues['A'] = 0xa;
+ hexvalues['b'] = hexvalues['B'] = 0xb;
+ hexvalues['c'] = hexvalues['C'] = 0xc;
+ hexvalues['d'] = hexvalues['D'] = 0xd;
+ hexvalues['e'] = hexvalues['E'] = 0xe;
+ hexvalues['f'] = hexvalues['F'] = 0xf;
+
+ if (break_locks && verbose) {
+ printf ("Attempting to break locks on authority file %s\n",
+ authfilename);
+ }
+
+ if (ignore_locks) {
+ if (break_locks) IceUnlockAuthFile (authfilename);
+ } else {
+ n = IceLockAuthFile (authfilename, ICEAUTH_DEFAULT_RETRIES,
+ ICEAUTH_DEFAULT_TIMEOUT,
+ (break_locks ? 0L : ICEAUTH_DEFAULT_DEADTIME));
+ if (n != IceAuthLockSuccess) {
+ char *reason = "unknown error";
+ switch (n) {
+ case IceAuthLockError:
+ reason = "error";
+ break;
+ case IceAuthLockTimeout:
+ reason = "timeout";
+ break;
+ }
+ fprintf (stderr, "%s: %s in locking authority file %s\n",
+ ProgramName, reason, authfilename);
+ return -1;
+ }
+ }
+
+ /* these checks can only be done reliably after the file is locked */
+ exists = (access (authfilename, F_OK) == 0);
+ if (exists && access (authfilename, W_OK) != 0) {
+ fprintf (stderr,
+ "%s: %s not writable, changes will be ignored\n",
+ ProgramName, authfilename);
+ iceauth_allowed = False;
+ }
+
+ original_umask = umask (0077); /* disallow non-owner access */
+
+ authfp = fopen (authfilename, "rb");
+ if (!authfp) {
+ int olderrno = errno;
+
+ /* if file there then error */
+ if (access (authfilename, F_OK) == 0) { /* then file does exist! */
+ errno = olderrno;
+ return -1;
+ } /* else ignore it */
+ fprintf (stderr,
+ "%s: creating new authority file %s\n",
+ ProgramName, authfilename);
+ } else {
+ iceauth_existed = True;
+ n = read_auth_entries (authfp, &head, &tail);
+ (void) fclose (authfp);
+ if (n < 0) {
+ fprintf (stderr,
+ "%s: unable to read auth entries from file \"%s\"\n",
+ ProgramName, authfilename);
+ return -1;
+ }
+ iceauth_head = head;
+ }
+
+ n = strlen (authfilename);
+ iceauth_filename = malloc (n + 1);
+ if (iceauth_filename) strcpy (iceauth_filename, authfilename);
+ iceauth_modified = False;
+
+ if (verbose) {
+ printf ("%s authority file %s\n",
+ ignore_locks ? "Ignoring locks on" : "Using", authfilename);
+ }
+ return 0;
+}
+
+static int write_auth_file (tmp_nam)
+ char *tmp_nam;
+{
+ FILE *fp;
+ AuthList *list;
+
+ strcpy (tmp_nam, iceauth_filename);
+ strcat (tmp_nam, "-n"); /* for new */
+ (void) unlink (tmp_nam);
+ fp = fopen (tmp_nam, "wb"); /* umask is still set to 0077 */
+ if (!fp) {
+ fprintf (stderr, "%s: unable to open tmp file \"%s\"\n",
+ ProgramName, tmp_nam);
+ return -1;
+ }
+
+ for (list = iceauth_head; list; list = list->next)
+ IceWriteAuthFileEntry (fp, list->auth);
+
+ (void) fclose (fp);
+ return 0;
+}
+
+int auth_finalize ()
+{
+ char temp_name[1024]; /* large filename size */
+
+ if (iceauth_modified) {
+ if (dieing) {
+ if (verbose) {
+ printf ("Aborting changes to authority file %s\n",
+ iceauth_filename);
+ }
+ } else if (!iceauth_allowed) {
+ fprintf (stderr,
+ "%s: %s not writable, changes ignored\n",
+ ProgramName, iceauth_filename);
+ } else {
+ if (verbose) {
+ printf ("%s authority file %s\n",
+ ignore_locks ? "Ignoring locks and writing" :
+ "Writing", iceauth_filename);
+ }
+ temp_name[0] = '\0';
+ if (write_auth_file (temp_name) == -1) {
+ fprintf (stderr,
+ "%s: unable to write authority file %s\n",
+ ProgramName, temp_name);
+ } else {
+ (void) unlink (iceauth_filename);
+#ifdef WIN32
+ if (rename(temp_name, iceauth_filename) == -1)
+#else
+ if (link (temp_name, iceauth_filename) == -1)
+#endif
+ {
+ fprintf (stderr,
+ "%s: unable to link authority file %s, use %s\n",
+ ProgramName, iceauth_filename, temp_name);
+ } else {
+ (void) unlink (temp_name);
+ }
+ }
+ }
+ }
+
+ if (!ignore_locks) {
+ IceUnlockAuthFile (iceauth_filename);
+ }
+ (void) umask (original_umask);
+ return 0;
+}
+
+int process_command (inputfilename, lineno, argc, argv)
+ char *inputfilename;
+ int lineno;
+ int argc;
+ char **argv;
+{
+ int status;
+
+ if (argc < 1 || !argv || !argv[0]) return 1;
+
+ if (dispatch_command (inputfilename, lineno, argc, argv,
+ command_table, &status))
+ return status;
+
+ prefix (inputfilename, lineno);
+ fprintf (stderr, "unknown command \"%s\"\n", argv[0]);
+ return 1;
+}
+
+
+/*
+ * utility routines
+ */
+
+static void fprintfhex (fp, len, cp)
+ register FILE *fp;
+ unsigned int len;
+ char *cp;
+{
+ unsigned char *ucp = (unsigned char *) cp;
+
+ for (; len > 0; len--, ucp++) {
+ register char *s = hex_table[*ucp];
+ putc (s[0], fp);
+ putc (s[1], fp);
+ }
+ return;
+}
+
+/* ARGSUSED */
+static int dump_entry (inputfilename, lineno, auth, data)
+ char *inputfilename;
+ int lineno;
+ IceAuthFileEntry *auth;
+ char *data;
+{
+ struct _list_data *ld = (struct _list_data *) data;
+ FILE *fp = ld->fp;
+
+ fprintf (fp, "%s", auth->protocol_name);
+ putc (' ', fp);
+ if (auth->protocol_data_length > 0)
+ fprintfhex (fp, auth->protocol_data_length, auth->protocol_data);
+ else
+ fprintf (fp, "\"\"");
+ putc (' ', fp);
+ fprintf (fp, "%s", auth->network_id);
+ putc (' ', fp);
+ fprintf (fp, "%s", auth->auth_name);
+ putc (' ', fp);
+
+ if (auth->auth_data_length == 0)
+ fprintf (fp, "\"\"");
+ else if (!strcmp(auth->auth_name, SECURERPC) ||
+ !strcmp(auth->auth_name, K5AUTH))
+ fwrite (auth->auth_data, sizeof (char), auth->auth_data_length, fp);
+ else
+ fprintfhex (fp, auth->auth_data_length, auth->auth_data);
+ putc ('\n', fp);
+
+ return 0;
+}
+
+static int extract_entry (inputfilename, lineno, auth, data)
+ char *inputfilename;
+ int lineno;
+ IceAuthFileEntry *auth;
+ char *data;
+{
+ struct _extract_data *ed = (struct _extract_data *) data;
+
+ if (!ed->fp) {
+ ed->fp = open_file (&ed->filename, "wb",
+ &ed->used_stdout,
+ inputfilename, lineno, ed->cmd);
+ if (!ed->fp) {
+ prefix (inputfilename, lineno);
+ fprintf (stderr,
+ "unable to open extraction file \"%s\"\n",
+ ed->filename);
+ return -1;
+ }
+ }
+ IceWriteAuthFileEntry (ed->fp, auth);
+ ed->nwritten++;
+
+ return 0;
+}
+
+
+static int match_auth (a, b, authDataSame)
+ register IceAuthFileEntry *a, *b;
+ int *authDataSame;
+{
+ int match = strcmp (a->protocol_name, b->protocol_name) == 0 &&
+ strcmp (a->network_id, b->network_id) == 0 &&
+ strcmp (a->auth_name, b->auth_name) == 0;
+
+ if (match)
+ {
+ *authDataSame = (a->auth_data_length == b->auth_data_length &&
+ binaryEqual (a->auth_data, b->auth_data, a->auth_data_length));
+ }
+ else
+ *authDataSame = 0;
+
+ return (match);
+}
+
+
+static int merge_entries (firstp, second, nnewp, nreplp, ndupp)
+ AuthList **firstp, *second;
+ int *nnewp, *nreplp, *ndupp;
+{
+ AuthList *a, *b, *first, *tail;
+ int n = 0, nnew = 0, nrepl = 0, ndup = 0;
+
+ if (!second) return 0;
+
+ if (!*firstp) { /* if nothing to merge into */
+ *firstp = second;
+ for (tail = *firstp, n = 1; tail->next; n++, tail = tail->next) ;
+ *nnewp = n;
+ *nreplp = 0;
+ *ndupp = 0;
+ return n;
+ }
+
+ first = *firstp;
+ /*
+ * find end of first list and stick second list on it
+ */
+ for (tail = first; tail->next; tail = tail->next) ;
+ tail->next = second;
+
+ /*
+ * run down list freeing duplicate entries; if an entry is okay, then
+ * bump the tail up to include it, otherwise, cut the entry out of
+ * the chain.
+ */
+ for (b = second; b; ) {
+ AuthList *next = b->next; /* in case we free it */
+ int duplicate;
+
+ duplicate = 0;
+ a = first;
+ for (;;) {
+ int authDataSame;
+ if (match_auth (a->auth, b->auth, &authDataSame)) {
+ if (authDataSame)
+ {
+ /* found a complete duplicate, ignore */
+ duplicate = 1;
+ break;
+ }
+ else
+ {
+ /* found a duplicate, but auth data differs */
+
+ AuthList tmp; /* swap it in for old one */
+ tmp = *a;
+ *a = *b;
+ *b = tmp;
+ a->next = b->next;
+ IceFreeAuthFileEntry (b->auth);
+ free ((char *) b);
+ b = NULL;
+ tail->next = next;
+ nrepl++;
+ nnew--;
+ break;
+ }
+ }
+ if (a == tail) break; /* if have looked at left side */
+ a = a->next;
+ }
+ if (!duplicate && b) { /* if we didn't remove it */
+ tail = b; /* bump end of first list */
+ }
+ b = next;
+
+ if (duplicate)
+ ndup++;
+ else
+ {
+ n++;
+ nnew++;
+ }
+ }
+
+ *nnewp = nnew;
+ *nreplp = nrepl;
+ *ndupp = ndup;
+ return n;
+
+}
+
+
+static int search_and_do (inputfilename, lineno, start,
+ argc, argv, do_func, data)
+ char *inputfilename;
+ int lineno;
+ int start;
+ int argc;
+ char *argv[];
+ int (*do_func)();
+ char *data;
+{
+ int i;
+ int status = 0;
+ int errors = 0;
+ AuthList *l, *next;
+ char *protoname, *protodata, *netid, *authname;
+
+ for (l = iceauth_head; l; l = next)
+ {
+ next = l->next;
+
+ protoname = protodata = netid = authname = NULL;
+
+ for (i = start; i < argc; i++)
+ {
+ if (!strncmp ("protoname=", argv[i], 10))
+ protoname = argv[i] + 10;
+ else if (!strncmp ("protodata=", argv[i], 10))
+ protodata = argv[i] + 10;
+ else if (!strncmp ("netid=", argv[i], 6))
+ netid = argv[i] + 6;
+ else if (!strncmp ("authname=", argv[i], 9))
+ authname = argv[i] + 9;
+ }
+
+ status = 0;
+
+ if (protoname || protodata || netid || authname)
+ {
+ if (protoname && strcmp (protoname, l->auth->protocol_name))
+ continue;
+
+ if (protodata && !binaryEqual (protodata,
+ l->auth->protocol_data, l->auth->protocol_data_length))
+ continue;
+
+ if (netid && strcmp (netid, l->auth->network_id))
+ continue;
+
+ if (authname && strcmp (authname, l->auth->auth_name))
+ continue;
+
+ status = (*do_func) (inputfilename, lineno, l->auth, data);
+
+ if (status < 0)
+ break;
+ }
+ }
+
+ if (status < 0)
+ errors -= status; /* since status is negative */
+
+ return (errors);
+}
+
+
+/* ARGSUSED */
+static int remove_entry (inputfilename, lineno, auth, data)
+ char *inputfilename;
+ int lineno;
+ IceAuthFileEntry *auth;
+ char *data;
+{
+ int *nremovedp = (int *) data;
+ AuthList **listp = &iceauth_head;
+ AuthList *list;
+
+ /*
+ * unlink the auth we were asked to
+ */
+ while ((list = *listp)->auth != auth)
+ listp = &list->next;
+ *listp = list->next;
+ IceFreeAuthFileEntry (list->auth); /* free the auth */
+ free (list); /* free the link */
+ iceauth_modified = True;
+ (*nremovedp)++;
+ return 1;
+}
+
+/*
+ * action routines
+ */
+
+/*
+ * help
+ */
+int print_help (fp, cmd)
+ FILE *fp;
+ char *cmd;
+{
+ CommandTable *ct;
+ int n = 0;
+
+ fprintf (fp, "\n");
+ if (!cmd) { /* if no cmd, print all help */
+ for (ct = command_table; ct->name; ct++) {
+ fprintf (fp, "%s\n\n", ct->helptext);
+ n++;
+ }
+ } else {
+ int len = strlen (cmd);
+ for (ct = command_table; ct->name; ct++) {
+ if (strncmp (cmd, ct->name, len) == 0) {
+ fprintf (fp, "%s\n\n", ct->helptext);
+ n++;
+ }
+ }
+ }
+
+ return n;
+}
+
+static int do_help (inputfilename, lineno, argc, argv)
+ char *inputfilename;
+ int lineno;
+ int argc;
+ char **argv;
+{
+ char *cmd = (argc > 1 ? argv[1] : NULL);
+ int n;
+
+ n = print_help (stdout, cmd);
+
+ if (n < 0 || (n == 0 && !cmd)) {
+ prefix (inputfilename, lineno);
+ fprintf (stderr, "internal error with help");
+ if (cmd) {
+ fprintf (stderr, " on command \"%s\"", cmd);
+ }
+ fprintf (stderr, "\n");
+ return 1;
+ }
+
+ if (n == 0) {
+ prefix (inputfilename, lineno);
+ /* already know that cmd is set in this case */
+ fprintf (stderr, "no help for noexistent command \"%s\"\n", cmd);
+ }
+
+ return 0;
+}
+
+/*
+ * questionmark
+ */
+/* ARGSUSED */
+static int do_questionmark (inputfilename, lineno, argc, argv)
+ char *inputfilename;
+ int lineno;
+ int argc;
+ char **argv;
+{
+ CommandTable *ct;
+ int i;
+#define WIDEST_COLUMN 72
+ int col = WIDEST_COLUMN;
+
+ printf ("Commands:\n");
+ for (ct = command_table; ct->name; ct++) {
+ if ((col + ct->maxlen) > WIDEST_COLUMN) {
+ if (ct != command_table) {
+ putc ('\n', stdout);
+ }
+ fputs (" ", stdout);
+ col = 8; /* length of string above */
+ }
+ fputs (ct->name, stdout);
+ col += ct->maxlen;
+ for (i = ct->maxlen; i < COMMAND_NAMES_PADDED_WIDTH; i++) {
+ putc (' ', stdout);
+ col++;
+ }
+ }
+ if (col != 0) {
+ putc ('\n', stdout);
+ }
+
+ /* allow bad lines since this is help */
+ return 0;
+}
+
+/*
+ * list [displayname ...]
+ */
+static int do_list (inputfilename, lineno, argc, argv)
+ char *inputfilename;
+ int lineno;
+ int argc;
+ char **argv;
+{
+ struct _list_data ld;
+
+ ld.fp = stdout;
+
+ if (argc == 1) {
+ register AuthList *l;
+
+ if (iceauth_head) {
+ for (l = iceauth_head; l; l = l->next) {
+ dump_entry (inputfilename, lineno, l->auth, (char *) &ld);
+ }
+ }
+ return 0;
+ }
+ else
+ {
+ return (search_and_do (inputfilename, lineno, 1, argc, argv,
+ dump_entry, (char *) &ld));
+ }
+}
+
+/*
+ * merge filename [filename ...]
+ */
+static int do_merge (inputfilename, lineno, argc, argv)
+ char *inputfilename;
+ int lineno;
+ int argc;
+ char **argv;
+{
+ int i;
+ int errors = 0;
+ AuthList *head, *tail, *listhead, *listtail;
+ int nentries, nnew, nrepl, ndup;
+
+ if (argc < 2) {
+ prefix (inputfilename, lineno);
+ badcommandline (argv[0]);
+ return 1;
+ }
+
+ listhead = listtail = NULL;
+
+ for (i = 1; i < argc; i++) {
+ char *filename = argv[i];
+ FILE *fp;
+ Bool used_stdin = False;
+
+ fp = open_file (&filename, "rb",
+ &used_stdin, inputfilename, lineno,
+ argv[0]);
+ if (!fp) {
+ errors++;
+ continue;
+ }
+
+ head = tail = NULL;
+ nentries = read_auth_entries (fp, &head, &tail);
+ if (nentries == 0) {
+ prefix (inputfilename, lineno);
+ fprintf (stderr, "unable to read any entries from file \"%s\"\n",
+ filename);
+ errors++;
+ } else { /* link it in */
+ add_to_list (listhead, listtail, head);
+ }
+
+ if (!used_stdin) (void) fclose (fp);
+ }
+
+ /*
+ * if we have new entries, merge them in (freeing any duplicates)
+ */
+ if (listhead) {
+ nentries = merge_entries (&iceauth_head, listhead,
+ &nnew, &nrepl, &ndup);
+ if (verbose)
+ printf ("%d entries read in: %d new, %d replacement%s\n",
+ nentries, nnew, nrepl, nrepl != 1 ? "s" : "");
+ if (nentries > 0) iceauth_modified = True;
+ }
+
+ return 0;
+}
+
+/*
+ * extract filename displayname [displayname ...]
+ */
+static int do_extract (inputfilename, lineno, argc, argv)
+ char *inputfilename;
+ int lineno;
+ int argc;
+ char **argv;
+{
+ int errors;
+ struct _extract_data ed;
+
+ if (argc < 3) {
+ prefix (inputfilename, lineno);
+ badcommandline (argv[0]);
+ return 1;
+ }
+
+ ed.fp = NULL;
+ ed.filename = argv[1];
+ ed.nwritten = 0;
+ ed.cmd = argv[0];
+
+ errors = search_and_do (inputfilename, lineno, 2, argc, argv,
+ extract_entry, (char *) &ed);
+
+ if (!ed.fp) {
+ fprintf (stderr,
+ "No matches found, authority file \"%s\" not written\n",
+ ed.filename);
+ } else {
+ if (verbose) {
+ printf ("%d entries written to \"%s\"\n",
+ ed.nwritten, ed.filename);
+ }
+ if (!ed.used_stdout) {
+ (void) fclose (ed.fp);
+ }
+ }
+
+ return errors;
+}
+
+
+/*
+ * add protoname protodata netid authname authdata
+ */
+static int do_add (inputfilename, lineno, argc, argv)
+ char *inputfilename;
+ int lineno;
+ int argc;
+ char **argv;
+{
+ int n, nnew, nrepl, ndup;
+ char *protoname;
+ char *protodata_hex;
+ char *protodata = NULL; /* not required */
+ char *netid;
+ char *authname;
+ char *authdata_hex;
+ char *authdata;
+ int protodata_len, authdata_len;
+ IceAuthFileEntry *auth;
+ AuthList *list;
+ int status = 0;
+
+ if (argc != 6 || !argv[1] || !argv[2] ||
+ !argv[3] || !argv[4] || !argv[5])
+ {
+ prefix (inputfilename, lineno);
+ badcommandline (argv[0]);
+ return 1;
+ }
+
+ protoname = argv[1];
+ protodata_hex = argv[2];
+ netid = argv[3];
+ authname = argv[4];
+ authdata_hex = argv[5];
+
+ protodata_len = strlen (protodata_hex);
+ if (protodata_len > 0)
+ {
+ if (protodata_hex[0] == '"' && protodata_hex[protodata_len - 1] == '"')
+ {
+ protodata = malloc (protodata_len - 1);
+ if (protodata)
+ {
+ strncpy (protodata, protodata_hex + 1, protodata_len - 2);
+ protodata_len -= 2;
+ }
+ else
+ goto add_bad_malloc;
+ }
+ else
+ {
+ protodata_len = cvthexkey (protodata_hex, &protodata);
+ if (protodata_len < 0)
+ {
+ prefix (inputfilename, lineno);
+ fprintf (stderr,
+ "protodata_hex contains odd number of or non-hex characters\n");
+ return (1);
+ }
+ }
+ }
+
+ authdata_len = strlen (authdata_hex);
+ if (authdata_hex[0] == '"' && authdata_hex[authdata_len - 1] == '"')
+ {
+ authdata = malloc (authdata_len - 1);
+ if (authdata)
+ {
+ strncpy (authdata, authdata_hex + 1, authdata_len - 2);
+ authdata_len -= 2;
+ }
+ else
+ goto add_bad_malloc;
+ }
+ else if (!strcmp (protoname, SECURERPC) || !strcmp (protoname, K5AUTH))
+ {
+ authdata = malloc (authdata_len + 1);
+ if (authdata)
+ strcpy (authdata, authdata_hex);
+ else
+ goto add_bad_malloc;
+ }
+ else
+ {
+ authdata_len = cvthexkey (authdata_hex, &authdata);
+ if (authdata_len < 0)
+ {
+ prefix (inputfilename, lineno);
+ fprintf (stderr,
+ "authdata_hex contains odd number of or non-hex characters\n");
+ free (protodata);
+ return (1);
+ }
+ }
+
+ auth = (IceAuthFileEntry *) malloc (sizeof (IceAuthFileEntry));
+
+ if (!auth)
+ goto add_bad_malloc;
+
+ auth->protocol_name = copystring (protoname);
+ auth->protocol_data_length = protodata_len;
+ auth->protocol_data = protodata;
+ auth->network_id = copystring (netid);
+ auth->auth_name = copystring (authname);
+ auth->auth_data_length = authdata_len;
+ auth->auth_data = authdata;
+
+ if (!auth->protocol_name ||
+ (!auth->protocol_data && auth->protocol_data_length > 0) ||
+ !auth->network_id || !auth->auth_name ||
+ (!auth->auth_data && auth->auth_data_length > 0))
+ {
+ goto add_bad_malloc;
+ }
+
+ list = (AuthList *) malloc (sizeof (AuthList));
+
+ if (!list)
+ goto add_bad_malloc;
+
+ list->next = NULL;
+ list->auth = auth;
+
+ /*
+ * merge it in; note that merge will deal with allocation
+ */
+
+ n = merge_entries (&iceauth_head, list, &nnew, &nrepl, &ndup);
+
+ if (n > 0)
+ iceauth_modified = True;
+ else
+ {
+ prefix (inputfilename, lineno);
+ if (ndup > 0)
+ {
+ status = 0;
+ fprintf (stderr, "no records added - all duplicate\n");
+ }
+ else
+ {
+ status = 1;
+ fprintf (stderr, "unable to merge in added record\n");
+ }
+ goto cant_add;
+ }
+
+ return 0;
+
+
+add_bad_malloc:
+
+ status = 1;
+ prefix (inputfilename, lineno);
+ fprintf (stderr, "unable to allocate memory to add an entry\n");
+
+cant_add:
+
+ if (protodata)
+ free (protodata);
+ if (authdata)
+ free (authdata);
+ if (auth)
+ {
+ if (auth->protocol_name)
+ free (auth->protocol_name);
+ if (auth->protocol_data)
+ free (auth->protocol_data);
+ if (auth->network_id)
+ free (auth->network_id);
+ if (auth->auth_name)
+ free (auth->auth_name);
+ if (auth->auth_data)
+ free (auth->auth_data);
+ free ((char *) auth);
+ }
+
+ return status;
+}
+
+/*
+ * remove displayname
+ */
+static int do_remove (inputfilename, lineno, argc, argv)
+ char *inputfilename;
+ int lineno;
+ int argc;
+ char **argv;
+{
+ int nremoved = 0;
+ int errors;
+
+ if (argc < 2) {
+ prefix (inputfilename, lineno);
+ badcommandline (argv[0]);
+ return 1;
+ }
+
+ errors = search_and_do (inputfilename, lineno, 1, argc, argv,
+ remove_entry, (char *) &nremoved);
+ if (verbose) printf ("%d entries removed\n", nremoved);
+ return errors;
+}
+
+/*
+ * info
+ */
+static int do_info (inputfilename, lineno, argc, argv)
+ char *inputfilename;
+ int lineno;
+ int argc;
+ char **argv;
+{
+ int n;
+ AuthList *l;
+
+ if (argc != 1) {
+ prefix (inputfilename, lineno);
+ badcommandline (argv[0]);
+ return 1;
+ }
+
+ for (l = iceauth_head, n = 0; l; l = l->next, n++) ;
+
+ printf ("Authority file: %s\n",
+ iceauth_filename ? iceauth_filename : "(none)");
+ printf ("File new: %s\n", iceauth_existed ? No : Yes);
+ printf ("File locked: %s\n", ignore_locks ? No : Yes);
+ printf ("Number of entries: %d\n", n);
+ printf ("Changes honored: %s\n", iceauth_allowed ? Yes : No);
+ printf ("Changes made: %s\n", iceauth_modified ? Yes : No);
+ printf ("Current input: %s:%d\n", inputfilename, lineno);
+ return 0;
+}
+
+
+/*
+ * exit
+ */
+static Bool alldone = False;
+
+/* ARGSUSED */
+static int do_exit (inputfilename, lineno, argc, argv)
+ char *inputfilename;
+ int lineno;
+ int argc;
+ char **argv;
+{
+ /* allow bogus stuff */
+ alldone = True;
+ return 0;
+}
+
+/*
+ * quit
+ */
+/* ARGSUSED */
+static int do_quit (inputfilename, lineno, argc, argv)
+ char *inputfilename;
+ int lineno;
+ int argc;
+ char **argv;
+{
+ /* allow bogus stuff */
+ die (0);
+ /* NOTREACHED */
+ return -1; /* for picky compilers */
+}
+
+
+/*
+ * source filename
+ */
+static int do_source (inputfilename, lineno, argc, argv)
+ char *inputfilename;
+ int lineno;
+ int argc;
+ char **argv;
+{
+ char *script;
+ char buf[BUFSIZ];
+ FILE *fp;
+ Bool used_stdin = False;
+ int len;
+ int errors = 0, status;
+ int sublineno = 0;
+ char **subargv;
+ int subargc;
+ Bool prompt = False; /* only true if reading from tty */
+
+ if (argc != 2 || !argv[1]) {
+ prefix (inputfilename, lineno);
+ badcommandline (argv[0]);
+ return 1;
+ }
+
+ script = argv[1];
+
+ fp = open_file (&script, "r", &used_stdin, inputfilename, lineno, argv[0]);
+ if (!fp) {
+ return 1;
+ }
+
+ if (verbose && used_stdin && isatty (fileno (fp))) prompt = True;
+
+ while (!alldone) {
+ buf[0] = '\0';
+ if (prompt) {
+ printf ("iceauth> ");
+ fflush (stdout);
+ }
+ if (fgets (buf, sizeof buf, fp) == NULL) break;
+ sublineno++;
+ len = strlen (buf);
+ if (len == 0 || buf[0] == '#') continue;
+ if (buf[len-1] != '\n') {
+ prefix (script, sublineno);
+ fprintf (stderr, "line too long\n");
+ errors++;
+ break;
+ }
+ buf[--len] = '\0'; /* remove new line */
+ subargv = split_into_words (buf, &subargc);
+ if (subargv) {
+ status = process_command (script, sublineno, subargc, subargv);
+ free ((char *) subargv);
+ errors += status;
+ } else {
+ prefix (script, sublineno);
+ fprintf (stderr, "unable to break line into words\n");
+ errors++;
+ }
+ }
+
+ if (!used_stdin) {
+ (void) fclose (fp);
+ }
+ return errors;
+}