home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / X / mit / clients / xauth / process.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-07-21  |  38.6 KB  |  1,630 lines

  1. /*
  2.  * $XConsortium: process.c,v 1.42 92/02/18 18:05:00 gildea Exp $
  3.  *
  4.  * Copyright 1989 Massachusetts Institute of Technology
  5.  *
  6.  * Permission to use, copy, modify, and distribute this software and its
  7.  * documentation for any purpose and without fee is hereby granted, provided
  8.  * that the above copyright notice appear in all copies and that both that
  9.  * copyright notice and this permission notice appear in supporting
  10.  * documentation, and that the name of M.I.T. not be used in advertising
  11.  * or publicity pertaining to distribution of the software without specific,
  12.  * written prior permission.  M.I.T. makes no representations about the
  13.  * suitability of this software for any purpose.  It is provided "as is"
  14.  * without express or implied warranty.
  15.  *
  16.  * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
  17.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T.
  18.  * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  19.  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  20.  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 
  21.  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  22.  *
  23.  * Author:  Jim Fulton, MIT X Consortium
  24.  */
  25.  
  26. #include "xauth.h"
  27. #include <ctype.h>
  28. #include <errno.h>
  29. extern int errno;            /* for stupid errno.h files */
  30. #include <signal.h>
  31. #include <X11/X.h>            /* for Family constants */
  32.  
  33. extern char *get_hostname();
  34. extern Bool nameserver_timedout;
  35.  
  36. #ifndef DEFAULT_PROTOCOL_ABBREV        /* to make add command easier */
  37. #define DEFAULT_PROTOCOL_ABBREV "."
  38. #endif
  39. #ifndef DEFAULT_PROTOCOL        /* for protocol abbreviation */
  40. #define DEFAULT_PROTOCOL "MIT-MAGIC-COOKIE-1"
  41. #endif
  42.  
  43. #define SECURERPC "SUN-DES-1"
  44.  
  45. #define XAUTH_DEFAULT_RETRIES 10    /* number of competitors we expect */
  46. #define XAUTH_DEFAULT_TIMEOUT 2        /* in seconds, be quick */
  47. #define XAUTH_DEFAULT_DEADTIME 600L    /* 10 minutes in seconds */
  48.  
  49. typedef struct _AuthList {        /* linked list of entries */
  50.     struct _AuthList *next;
  51.     Xauth *auth;
  52. } AuthList;
  53.  
  54. #define add_to_list(h,t,e) {if (t) (t)->next = (e); else (h) = (e); (t) = (e);}
  55.  
  56. typedef struct _CommandTable {        /* commands that are understood */
  57.     char *name;                /* full name */
  58.     int minlen;                /* unique prefix */
  59.     int maxlen;                /* strlen(name) */
  60.     int (*processfunc)();        /* handler */
  61.     char *helptext;            /* what to print for help */
  62. } CommandTable;
  63.  
  64. struct _extract_data {            /* for iterating */
  65.     FILE *fp;                /* input source */
  66.     char *filename;            /* name of input */
  67.     Bool used_stdout;            /* whether or not need to close */
  68.     Bool numeric;            /* format in which to write */
  69.     int nwritten;            /* number of entries written */
  70.     char *cmd;                /* for error messages */
  71. };
  72.  
  73. struct _list_data {            /* for iterating */
  74.     FILE *fp;                /* output file */
  75.     Bool numeric;            /* format in which to write */
  76. };
  77.  
  78.  
  79. /*
  80.  * private data
  81.  */
  82. static char *stdin_filename = "(stdin)";  /* for messages */
  83. static char *stdout_filename = "(stdout)";  /* for messages */
  84. static char *Yes = "yes";        /* for messages */
  85. static char *No = "no";            /* for messages */
  86.  
  87. static int do_list(), do_merge(), do_extract(), do_add(), do_remove();
  88. static int do_help(), do_source(), do_info(), do_exit();
  89. static int do_quit(), do_questionmark();
  90.  
  91. static CommandTable command_table[] = {    /* table of known commands */
  92.     { "add",      2, 3, do_add,
  93.     "add dpyname protoname hexkey   add entry" },
  94.     { "exit",     3, 4, do_exit,
  95.     "exit                           save changes and exit program" },
  96.     { "extract",  3, 7, do_extract,
  97.     "extract filename dpyname...    extract entries into file" },
  98.     { "help",     1, 4, do_help,
  99.     "help [topic]                   print help" },
  100.     { "info",     1, 4, do_info,
  101.     "info                           print information about entries" },
  102.     { "list",     1, 4, do_list,
  103.     "list [dpyname...]              list entries" },
  104.     { "merge",    1, 5, do_merge,
  105.     "merge filename...              merge entries from files" },
  106.     { "nextract", 2, 8, do_extract,
  107.     "nextract filename dpyname...   numerically extract entries" },
  108.     { "nlist",    2, 5, do_list,
  109.     "nlist [dpyname...]             numerically list entries" },
  110.     { "nmerge",   2, 6, do_merge,
  111.     "nmerge filename...             numerically merge entries" },
  112.     { "quit",     1, 4, do_quit,
  113.     "quit                           abort changes and exit program" },
  114.     { "remove",   1, 6, do_remove,
  115.     "remove dpyname...              remove entries" },
  116.     { "source",   1, 6, do_source,
  117.     "source filename                read commands from file" },
  118.     { "?",        1, 1, do_questionmark,
  119.     "?                              list available commands" },
  120.     { NULL,       0, 0, NULL, NULL },
  121. };
  122.  
  123. #define COMMAND_NAMES_PADDED_WIDTH 10    /* wider than anything above */
  124.  
  125.  
  126. static Bool okay_to_use_stdin = True;    /* set to false after using */
  127.  
  128. static char *hex_table[] = {        /* for printing hex digits */
  129.     "00", "01", "02", "03", "04", "05", "06", "07", 
  130.     "08", "09", "0a", "0b", "0c", "0d", "0e", "0f", 
  131.     "10", "11", "12", "13", "14", "15", "16", "17", 
  132.     "18", "19", "1a", "1b", "1c", "1d", "1e", "1f", 
  133.     "20", "21", "22", "23", "24", "25", "26", "27", 
  134.     "28", "29", "2a", "2b", "2c", "2d", "2e", "2f", 
  135.     "30", "31", "32", "33", "34", "35", "36", "37", 
  136.     "38", "39", "3a", "3b", "3c", "3d", "3e", "3f", 
  137.     "40", "41", "42", "43", "44", "45", "46", "47", 
  138.     "48", "49", "4a", "4b", "4c", "4d", "4e", "4f", 
  139.     "50", "51", "52", "53", "54", "55", "56", "57", 
  140.     "58", "59", "5a", "5b", "5c", "5d", "5e", "5f", 
  141.     "60", "61", "62", "63", "64", "65", "66", "67", 
  142.     "68", "69", "6a", "6b", "6c", "6d", "6e", "6f", 
  143.     "70", "71", "72", "73", "74", "75", "76", "77", 
  144.     "78", "79", "7a", "7b", "7c", "7d", "7e", "7f", 
  145.     "80", "81", "82", "83", "84", "85", "86", "87", 
  146.     "88", "89", "8a", "8b", "8c", "8d", "8e", "8f", 
  147.     "90", "91", "92", "93", "94", "95", "96", "97", 
  148.     "98", "99", "9a", "9b", "9c", "9d", "9e", "9f", 
  149.     "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", 
  150.     "a8", "a9", "aa", "ab", "ac", "ad", "ae", "af", 
  151.     "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7", 
  152.     "b8", "b9", "ba", "bb", "bc", "bd", "be", "bf", 
  153.     "c0", "c1", "c2", "c3", "c4", "c5", "c6", "c7", 
  154.     "c8", "c9", "ca", "cb", "cc", "cd", "ce", "cf", 
  155.     "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", 
  156.     "d8", "d9", "da", "db", "dc", "dd", "de", "df", 
  157.     "e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7", 
  158.     "e8", "e9", "ea", "eb", "ec", "ed", "ee", "ef", 
  159.     "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", 
  160.     "f8", "f9", "fa", "fb", "fc", "fd", "fe", "ff", 
  161. };
  162.  
  163. static unsigned int hexvalues[256];    /* for parsing hex input */
  164.  
  165. static int original_umask = 0;        /* for restoring */
  166.  
  167.  
  168. /*
  169.  * private utility procedures
  170.  */
  171.  
  172. static void prefix (fn, n)
  173.     char *fn;
  174.     int n;
  175. {
  176.     fprintf (stderr, "%s: %s:%d:  ", ProgramName, fn, n);
  177. }
  178.  
  179. static void baddisplayname (dpy, cmd)
  180.     char *dpy, *cmd;
  181. {
  182.     fprintf (stderr, "bad display name \"%s\" in \"%s\" command\n",
  183.          dpy, cmd);
  184. }
  185.  
  186. static void badcommandline (cmd)
  187.     char *cmd;
  188. {
  189.     fprintf (stderr, "bad \"%s\" command line\n", cmd);
  190. }
  191.  
  192. static char *skip_space (s)
  193.     register char *s;
  194. {
  195.     if (!s) return NULL;
  196.  
  197.     for ( ; *s && isascii(*s) && isspace(*s); s++)
  198.     ;
  199.     return s;
  200. }
  201.  
  202.  
  203. static char *skip_nonspace (s)
  204.     register char *s;
  205. {
  206.     if (!s) return NULL;
  207.  
  208.     /* put quoting into loop if need be */
  209.     for ( ; *s && isascii(*s) && !isspace(*s); s++)
  210.     ;
  211.     return s;
  212. }
  213.  
  214. static char **split_into_words (src, argcp)  /* argvify string */
  215.     char *src;
  216.     int *argcp;
  217. {
  218.     char *jword;
  219.     char savec;
  220.     char **argv;
  221.     int cur, total;
  222.  
  223.     *argcp = 0;
  224. #define WORDSTOALLOC 4            /* most lines are short */
  225.     argv = (char **) malloc (WORDSTOALLOC * sizeof (char *));
  226.     if (!argv) return NULL;
  227.     cur = 0;
  228.     total = WORDSTOALLOC;
  229.  
  230.     /*
  231.      * split the line up into separate, nul-terminated tokens; the last
  232.      * "token" will point to the empty string so that it can be bashed into
  233.      * a null pointer.
  234.      */
  235.  
  236.     do {
  237.     jword = skip_space (src);
  238.     src = skip_nonspace (jword);
  239.     savec = *src;
  240.     *src = '\0';
  241.     if (cur == total) {
  242.         total += WORDSTOALLOC;
  243.         argv = (char **) realloc (argv, total * sizeof (char *));
  244.         if (!argv) return NULL;
  245.     }
  246.     argv[cur++] = jword;
  247.     if (savec) src++;        /* if not last on line advance */
  248.     } while (jword != src);
  249.  
  250.     argv[--cur] = NULL;            /* smash empty token to end list */
  251.     *argcp = cur;
  252.     return argv;
  253. }
  254.  
  255.  
  256. static FILE *open_file (filenamep, mode, usedstdp, srcfn, srcln, cmd)
  257.     char **filenamep;
  258.     char *mode;
  259.     Bool *usedstdp;
  260.     char *srcfn;
  261.     int srcln;
  262.     char *cmd;
  263. {
  264.     FILE *fp;
  265.  
  266.     if (strcmp (*filenamep, "-") == 0) {
  267.     *usedstdp = True;
  268.                     /* select std descriptor to use */
  269.     if (mode[0] == 'r') {
  270.         if (okay_to_use_stdin) {
  271.         okay_to_use_stdin = False;
  272.         *filenamep = stdin_filename;
  273.         return stdin;
  274.         } else {
  275.         prefix (srcfn, srcln);
  276.         fprintf (stderr, "%s:  stdin already in use\n", cmd);
  277.         return NULL;
  278.         }
  279.     } else {
  280.         *filenamep = stdout_filename;
  281.         return stdout;        /* always okay to use stdout */
  282.     }
  283.     }
  284.  
  285.     fp = fopen (*filenamep, mode);
  286.     if (!fp) {
  287.     prefix (srcfn, srcln);
  288.     fprintf (stderr, "%s:  unable to open file %s\n", cmd, *filenamep);
  289.     }
  290.     return fp;
  291. }
  292.  
  293. static int getinput (fp)
  294.     FILE *fp;
  295. {
  296.     register int c;
  297.  
  298.     while ((c = getc (fp)) != EOF && isascii(c) && c != '\n' && isspace(c)) ;
  299.     return c;
  300. }
  301.  
  302. static int get_short (fp, sp)        /* for reading numeric input */
  303.     FILE *fp;
  304.     unsigned short *sp;
  305. {
  306.     int c;
  307.     int i;
  308.     unsigned short us = 0;
  309.  
  310.     /*
  311.      * read family:  written with %04x
  312.      */
  313.     for (i = 0; i < 4; i++) {
  314.     switch (c = getinput (fp)) {
  315.       case EOF:
  316.       case '\n':
  317.         return 0;
  318.     }
  319.     if (c < 0 || c > 255) return 0;
  320.     us = (us * 16) + hexvalues[c];    /* since msb */
  321.     }
  322.     *sp = us;
  323.     return 1;
  324. }
  325.  
  326. static int get_bytes (fp, n, ptr)    /* for reading numeric input */
  327.     FILE *fp;
  328.     unsigned int n;
  329.     char **ptr;
  330. {
  331.     char *s;
  332.     register char *cp;
  333.     int c1, c2;
  334.  
  335.     cp = s = malloc (n);
  336.     if (!cp) return 0;
  337.  
  338.     while (n > 0) {
  339.     if ((c1 = getinput (fp)) == EOF || c1 == '\n' ||
  340.         (c2 = getinput (fp)) == EOF || c2 == '\n') {
  341.         free (s);
  342.         return 0;
  343.     }
  344.     *cp = (char) ((hexvalues[c1] * 16) + hexvalues[c2]);
  345.     cp++;
  346.     n--;
  347.     }
  348.  
  349.     *ptr = s;
  350.     return 1;
  351. }
  352.  
  353.  
  354. static Xauth *read_numeric (fp)
  355.     FILE *fp;
  356. {
  357.     Xauth *auth;
  358.  
  359.     auth = (Xauth *) malloc (sizeof (Xauth));
  360.     if (!auth) goto bad;
  361.     auth->family = 0;
  362.     auth->address = NULL;
  363.     auth->address_length = 0;
  364.     auth->number = NULL;
  365.     auth->number_length = 0;
  366.     auth->name = NULL;
  367.     auth->name_length = 0;
  368.     auth->data = NULL;
  369.     auth->data_length = 0;
  370.  
  371.     if (!get_short (fp, (unsigned short *) &auth->family))
  372.       goto bad;
  373.     if (!get_short (fp, (unsigned short *) &auth->address_length))
  374.       goto bad;
  375.     if (!get_bytes (fp, (unsigned int) auth->address_length, &auth->address))
  376.       goto bad;
  377.     if (!get_short (fp, (unsigned short *) &auth->number_length))
  378.       goto bad;
  379.     if (!get_bytes (fp, (unsigned int) auth->number_length, &auth->number))
  380.       goto bad;
  381.     if (!get_short (fp, (unsigned short *) &auth->name_length))
  382.       goto bad;
  383.     if (!get_bytes (fp, (unsigned int) auth->name_length, &auth->name))
  384.       goto bad;
  385.     if (!get_short (fp, (unsigned short *) &auth->data_length))
  386.       goto bad;
  387.     if (!get_bytes (fp, (unsigned int) auth->data_length, &auth->data))
  388.       goto bad;
  389.     
  390.     switch (getinput (fp)) {        /* get end of line */
  391.       case EOF:
  392.       case '\n':
  393.     return auth;
  394.     }
  395.  
  396.   bad:
  397.     if (auth) XauDisposeAuth (auth);    /* won't free null pointers */
  398.     return NULL;
  399. }
  400.  
  401. static int read_auth_entries (fp, numeric, headp, tailp)
  402.     FILE *fp;
  403.     Bool numeric;
  404.     AuthList **headp, **tailp;
  405. {
  406.     Xauth *((*readfunc)()) = (numeric ? read_numeric : XauReadAuth);
  407.     Xauth *auth;
  408.     AuthList *head, *tail;
  409.     int n;
  410.  
  411.     head = tail = NULL;
  412.     n = 0;
  413.                     /* put all records into linked list */
  414.     while ((auth = ((*readfunc) (fp))) != NULL) {
  415.     AuthList *l = (AuthList *) malloc (sizeof (AuthList));
  416.     if (!l) {
  417.         fprintf (stderr,
  418.              "%s:  unable to alloc entry reading auth file\n",
  419.              ProgramName);
  420.         exit (1);
  421.     }
  422.     l->next = NULL;
  423.     l->auth = auth;
  424.     if (tail)             /* if not first time through append */
  425.       tail->next = l;
  426.     else
  427.       head = l;            /* first time through, so assign */
  428.     tail = l;
  429.     n++;
  430.     }
  431.     *headp = head;
  432.     *tailp = tail;
  433.     return n;
  434. }
  435.  
  436. static Bool get_displayname_auth (displayname, auth)
  437.     char *displayname;
  438.     Xauth *auth;            /* fill in */
  439. {
  440.     int family;
  441.     char *host = NULL, *rest = NULL;
  442.     int dpynum, scrnum;
  443.     char *cp;
  444.     int len;
  445.     extern char *get_address_info();
  446.     Xauth proto;
  447.     int prelen = 0;
  448.  
  449.     /*
  450.      * check to see if the display name is of the form "host/unix:"
  451.      * which is how the list routine prints out local connections
  452.      */
  453.     cp = index (displayname, '/');
  454.     if (cp && strncmp (cp, "/unix:", 6) == 0)
  455.       prelen = (cp - displayname);
  456.  
  457.     if (!parse_displayname (displayname + ((prelen > 0) ? prelen + 1 : 0),
  458.                 &family, &host, &dpynum, &scrnum, &rest)) {
  459.     return False;
  460.     }
  461.  
  462.     proto.family = family;
  463.     proto.address = get_address_info (family, displayname, prelen, host, &len);
  464.     if (proto.address) {
  465.     char buf[40];            /* want to hold largest display num */
  466.  
  467.     proto.address_length = len;
  468.     buf[0] = '\0';
  469.     sprintf (buf, "%d", dpynum);
  470.     proto.number_length = strlen (buf);
  471.     if (proto.number_length <= 0) {
  472.         free (proto.address);
  473.         proto.address = NULL;
  474.     } else {
  475.         proto.number = copystring (buf, proto.number_length);
  476.     }
  477.     }
  478.  
  479.     if (host) free (host);
  480.     if (rest) free (rest);
  481.  
  482.     if (proto.address) {
  483.     auth->family = proto.family;
  484.     auth->address = proto.address;
  485.     auth->address_length = proto.address_length;
  486.     auth->number = proto.number;
  487.     auth->number_length = proto.number_length;
  488.     auth->name = NULL;
  489.     auth->name_length = 0;
  490.     auth->data = NULL;
  491.     auth->data_length = 0;
  492.     return True;
  493.     } else {
  494.     return False;
  495.     }
  496. }
  497.  
  498. static int cvthexkey (hexstr, ptrp)    /* turn hex key string into octets */
  499.     char *hexstr;
  500.     char **ptrp;
  501. {
  502.     int i;
  503.     int len = 0;
  504.     char *retval, *s;
  505.     unsigned char *us;
  506.     char c;
  507.     char savec = '\0';
  508.  
  509.     /* count */
  510.     for (s = hexstr; *s; s++) {
  511.     if (!isascii(*s)) return -1;
  512.     if (isspace(*s)) continue;
  513.     if (!isxdigit(*s)) return -1;
  514.     len++;
  515.     }
  516.  
  517.     /* if odd then there was an error */
  518.     if ((len & 1) == 1) return -1;
  519.  
  520.  
  521.     /* now we know that the input is good */
  522.     len >>= 1;
  523.     retval = malloc (len);
  524.     if (!retval) {
  525.     fprintf (stderr, "%s:  unable to allocate %d bytes for hexkey\n",
  526.          ProgramName, len);
  527.     return -1;
  528.     }
  529.  
  530.     for (us = (unsigned char *) retval, i = len; i > 0; hexstr++) {
  531.     c = *hexstr;
  532.     if (isspace(c)) continue;     /* already know it is ascii */
  533.     if (isupper(c))
  534.         c = tolower(c);
  535.     if (savec) {
  536. #define atoh(c) ((c) - (((c) >= '0' && (c) <= '9') ? '0' : ('a'-10)))
  537.         *us = (unsigned char)((atoh(savec) << 4) + atoh(c));
  538. #undef atoh
  539.         savec = 0;        /* ready for next character */
  540.         us++;
  541.         i--;
  542.     } else {
  543.         savec = c;
  544.     }
  545.     }
  546.     *ptrp = retval;
  547.     return len;
  548. }
  549.  
  550. static int dispatch_command (inputfilename, lineno, argc, argv, tab, statusp)
  551.     char *inputfilename;
  552.     int lineno;
  553.     int argc;
  554.     char **argv;
  555.     CommandTable *tab;
  556.     int *statusp;
  557. {
  558.     CommandTable *ct;
  559.     char *cmd;
  560.     int n;
  561.                     /* scan table for command */
  562.     cmd = argv[0];
  563.     n = strlen (cmd);
  564.     for (ct = tab; ct->name; ct++) {
  565.                     /* look for unique prefix */
  566.     if (n >= ct->minlen && n <= ct->maxlen &&
  567.         strncmp (cmd, ct->name, n) == 0) {
  568.         *statusp = (*(ct->processfunc))(inputfilename, lineno, argc, argv);
  569.         return 1;
  570.     }
  571.     }
  572.  
  573.     *statusp = 1;
  574.     return 0;
  575. }
  576.  
  577.  
  578. static AuthList *xauth_head = NULL;    /* list of auth entries */
  579. static Bool xauth_existed = False;    /* if was present at initialize */
  580. static Bool xauth_modified = False;    /* if added, removed, or merged */
  581. static Bool xauth_allowed = True;    /* if allowed to write auth file */
  582. static char *xauth_filename = NULL;
  583. static Bool dieing = False;
  584.  
  585. #ifdef SIGNALRETURNSINT
  586. #define _signal_t int
  587. #else
  588. #define _signal_t void
  589. #endif
  590.  
  591. /* ARGSUSED */
  592. static _signal_t die (sig)
  593.     int sig;
  594. {
  595.     dieing = True;
  596.     exit (auth_finalize ());
  597.     /* NOTREACHED */
  598. #ifdef SIGNALRETURNSINT
  599.     return -1;                /* for picky compilers */
  600. #endif
  601. }
  602.  
  603. static _signal_t catchsig (sig)
  604.     int sig;
  605. {
  606. #ifdef SYSV
  607.     if (sig > 0) signal (sig, die);    /* re-establish signal handler */
  608. #endif
  609.     if (verbose && xauth_modified) printf ("\r\n");
  610.     die (sig);
  611.     /* NOTREACHED */
  612. #ifdef SIGNALRETURNSINT
  613.     return -1;                /* for picky compilers */
  614. #endif
  615. }
  616.  
  617. static void register_signals ()
  618. {
  619.     signal (SIGINT, catchsig);
  620.     signal (SIGTERM, catchsig);
  621.     signal (SIGHUP, catchsig);
  622.     return;
  623. }
  624.  
  625.  
  626. /*
  627.  * public procedures for parsing lines of input
  628.  */
  629.  
  630. int auth_initialize (authfilename)
  631.     char *authfilename;
  632. {
  633.     int n;
  634.     AuthList *head, *tail;
  635.     FILE *authfp;
  636.     Bool exists;
  637.  
  638.     register_signals ();
  639.  
  640.     bzero ((char *) hexvalues, sizeof hexvalues);
  641.     hexvalues['0'] = 0;
  642.     hexvalues['1'] = 1;
  643.     hexvalues['2'] = 2;
  644.     hexvalues['3'] = 3;
  645.     hexvalues['4'] = 4;
  646.     hexvalues['5'] = 5;
  647.     hexvalues['6'] = 6;
  648.     hexvalues['7'] = 7;
  649.     hexvalues['8'] = 8;
  650.     hexvalues['9'] = 9;
  651.     hexvalues['a'] = hexvalues['A'] = 0xa;
  652.     hexvalues['b'] = hexvalues['B'] = 0xb;
  653.     hexvalues['c'] = hexvalues['C'] = 0xc;
  654.     hexvalues['d'] = hexvalues['D'] = 0xd;
  655.     hexvalues['e'] = hexvalues['E'] = 0xe;
  656.     hexvalues['f'] = hexvalues['F'] = 0xf;
  657.  
  658.     if (break_locks && verbose) {
  659.     printf ("Attempting to break locks on authority file %s\n",
  660.         authfilename);
  661.     }
  662.  
  663.     if (ignore_locks) {
  664.     if (break_locks) XauUnlockAuth (authfilename);
  665.     } else {
  666.     n = XauLockAuth (authfilename, XAUTH_DEFAULT_RETRIES,
  667.              XAUTH_DEFAULT_TIMEOUT, 
  668.              (break_locks ? 0L : XAUTH_DEFAULT_DEADTIME));
  669.     if (n != LOCK_SUCCESS) {
  670.         char *reason = "unknown error";
  671.         switch (n) {
  672.           case LOCK_ERROR:
  673.         reason = "error";
  674.         break;
  675.           case LOCK_TIMEOUT:
  676.         reason = "timeout";
  677.         break;
  678.         }
  679.         fprintf (stderr, "%s:  %s in locking authority file %s\n",
  680.              ProgramName, reason, authfilename);
  681.         return -1;
  682.     }
  683.     }
  684.  
  685.     /* these checks can only be done reliably after the file is locked */
  686.     exists = (access (authfilename, F_OK) == 0);
  687.     if (exists && access (authfilename, W_OK) != 0) {
  688.     fprintf (stderr,
  689.      "%s:  %s not writable, changes will be ignored\n",
  690.          ProgramName, authfilename);
  691.     xauth_allowed = False;
  692.     }
  693.  
  694.     original_umask = umask (0077);    /* disallow non-owner access */
  695.  
  696.     authfp = fopen (authfilename, "r");
  697.     if (!authfp) {
  698.     int olderrno = errno;
  699.  
  700.                     /* if file there then error */
  701.     if (access (authfilename, F_OK) == 0) {     /* then file does exist! */
  702.         errno = olderrno;
  703.         return -1;
  704.     }                /* else ignore it */
  705.     fprintf (stderr, 
  706.          "%s:  creating new authority file %s\n",
  707.          ProgramName, authfilename);
  708.     } else {
  709.     xauth_existed = True;
  710.     n = read_auth_entries (authfp, False, &head, &tail);
  711.     (void) fclose (authfp);
  712.     if (n < 0) {
  713.         fprintf (stderr,
  714.              "%s:  unable to read auth entries from file \"%s\"\n",
  715.              ProgramName, authfilename);
  716.         return -1;
  717.     }
  718.     xauth_head = head;
  719.     }
  720.  
  721.     n = strlen (authfilename);
  722.     xauth_filename = malloc (n + 1);
  723.     if (xauth_filename) strcpy (xauth_filename, authfilename);
  724.     xauth_modified = False;
  725.  
  726.     if (verbose) {
  727.     printf ("%s authority file %s\n", 
  728.         ignore_locks ? "Ignoring locks on" : "Using", authfilename);
  729.     }
  730.     return 0;
  731. }
  732.  
  733. static int write_auth_file (tmpnam)
  734.     char *tmpnam;
  735. {
  736.     FILE *fp;
  737.     AuthList *list;
  738.  
  739.     /*
  740.      * xdm and auth spec assumes auth file is 12 or fewer characters
  741.      */
  742.     strcpy (tmpnam, xauth_filename);
  743.     strcat (tmpnam, "-n");        /* for new */
  744.     (void) unlink (tmpnam);
  745.     fp = fopen (tmpnam, "w");        /* umask is still set to 0077 */
  746.     if (!fp) {
  747.     fprintf (stderr, "%s:  unable to open tmp file \"%s\"\n",
  748.          ProgramName, tmpnam);
  749.     return -1;
  750.     } 
  751.  
  752.     /*
  753.      * Write MIT-MAGIC-COOKIE-1 first, because R4 Xlib knows
  754.      * only that and uses the first authorization it finds.
  755.      */
  756.     for (list = xauth_head; list; list = list->next) {
  757.     if (list->auth->name_length == 18
  758.         && strncmp(list->auth->name, "MIT-MAGIC-COOKIE-1", 18) == 0)
  759.     {
  760.         XauWriteAuth (fp, list->auth);
  761.     }
  762.     }
  763.     for (list = xauth_head; list; list = list->next) {
  764.     if (list->auth->name_length != 18
  765.         || strncmp(list->auth->name, "MIT-MAGIC-COOKIE-1", 18) != 0)
  766.     {
  767.         XauWriteAuth (fp, list->auth);
  768.     }
  769.     }
  770.  
  771.     (void) fclose (fp);
  772.     return 0;
  773. }
  774.  
  775. int auth_finalize ()
  776. {
  777.     char tmpnam[1024];            /* large filename size */
  778.  
  779.     if (xauth_modified) {
  780.     if (dieing) {
  781.         if (verbose) {
  782.         printf ("Aborting changes to authority file %s\n",
  783.             xauth_filename);
  784.         }
  785.     } else if (!xauth_allowed) {
  786.         fprintf (stderr, 
  787.              "%s:  %s not writable, changes ignored\n",
  788.              ProgramName, xauth_filename);
  789.     } else {
  790.         if (verbose) {
  791.         printf ("%s authority file %s\n", 
  792.             ignore_locks ? "Ignoring locks and writing" :
  793.             "Writing", xauth_filename);
  794.         }
  795.         tmpnam[0] = '\0';
  796.         if (write_auth_file (tmpnam) == -1) {
  797.         fprintf (stderr,
  798.              "%s:  unable to write authority file %s\n",
  799.              ProgramName, tmpnam);
  800.         } else {
  801.         (void) unlink (xauth_filename);
  802.         if (link (tmpnam, xauth_filename) == -1) {
  803.             fprintf (stderr,
  804.              "%s:  unable to link authority file %s, use %s\n",
  805.                  ProgramName, xauth_filename, tmpnam);
  806.         } else {
  807.             (void) unlink (tmpnam);
  808.         }
  809.         }
  810.     }
  811.     }
  812.  
  813.     if (!ignore_locks) {
  814.     XauUnlockAuth (xauth_filename);
  815.     }
  816.     (void) umask (original_umask);
  817.     return 0;
  818. }
  819.  
  820. int process_command (inputfilename, lineno, argc, argv)
  821.     char *inputfilename;
  822.     int lineno;
  823.     int argc;
  824.     char **argv;
  825. {
  826.     int status;
  827.  
  828.     if (argc < 1 || !argv || !argv[0]) return 1;
  829.  
  830.     if (dispatch_command (inputfilename, lineno, argc, argv,
  831.               command_table, &status))
  832.       return status;
  833.  
  834.     prefix (inputfilename, lineno);
  835.     fprintf (stderr, "unknown command \"%s\"\n", argv[0]);
  836.     return 1;
  837. }
  838.  
  839.  
  840. /*
  841.  * utility routines
  842.  */
  843.  
  844. static void fprintfhex (fp, len, cp)
  845.     register FILE *fp;
  846.     unsigned int len;
  847.     char *cp;
  848. {
  849.     unsigned char *ucp = (unsigned char *) cp;
  850.  
  851.     for (; len > 0; len--, ucp++) {
  852.     register char *s = hex_table[*ucp];
  853.     putc (s[0], fp);
  854.     putc (s[1], fp);
  855.     }
  856.     return;
  857. }
  858.  
  859. dump_numeric (fp, auth)
  860.     register FILE *fp;
  861.     register Xauth *auth;
  862. {
  863.     fprintf (fp, "%04x", auth->family);  /* unsigned short */
  864.     fprintf (fp, " %04x ", auth->address_length);  /* short */
  865.     fprintfhex (fp, auth->address_length, auth->address);
  866.     fprintf (fp, " %04x ", auth->number_length);  /* short */
  867.     fprintfhex (fp, auth->number_length, auth->number);
  868.     fprintf (fp, " %04x ", auth->name_length);  /* short */
  869.     fprintfhex (fp, auth->name_length, auth->name);
  870.     fprintf (fp, " %04x ", auth->data_length);  /* short */
  871.     fprintfhex (fp, auth->data_length, auth->data);
  872.     putc ('\n', fp);
  873.     return;
  874. }
  875.  
  876. /* ARGSUSED */
  877. static int dump_entry (inputfilename, lineno, auth, data)
  878.     char *inputfilename;
  879.     int lineno;
  880.     Xauth *auth;
  881.     char *data;
  882. {
  883.     struct _list_data *ld = (struct _list_data *) data;
  884.     FILE *fp = ld->fp;
  885.  
  886.     if (ld->numeric) {
  887.     dump_numeric (fp, auth);
  888.     } else {
  889.     char *dpyname = NULL;
  890.  
  891.     switch (auth->family) {
  892.       case FamilyLocal:
  893.         fwrite (auth->address, sizeof (char), auth->address_length, fp);
  894.         fprintf (fp, "/unix");
  895.         break;
  896.       case FamilyInternet:
  897.       case FamilyDECnet:
  898.         dpyname = get_hostname (auth);
  899.         if (dpyname) {
  900.         fprintf (fp, "%s", dpyname);
  901.         break;
  902.         }
  903.         /* else fall through to default */
  904.       default:
  905.         fprintf (fp, "#%04x#", auth->family);
  906.         fprintfhex (fp, auth->address_length, auth->address);
  907.         putc ('#', fp);
  908.     }
  909.     putc (':', fp);
  910.     fwrite (auth->number, sizeof (char), auth->number_length, fp);
  911.     putc (' ', fp);
  912.     putc (' ', fp);
  913.     fwrite (auth->name, sizeof (char), auth->name_length, fp);
  914.     putc (' ', fp);
  915.     putc (' ', fp);
  916.     if (!strncmp(auth->name, SECURERPC, auth->name_length))
  917.         fwrite (auth->data, sizeof (char), auth->data_length, fp);
  918.     else
  919.         fprintfhex (fp, auth->data_length, auth->data);
  920.     putc ('\n', fp);
  921.     }
  922.     return 0;
  923. }
  924.  
  925. static int extract_entry (inputfilename, lineno, auth, data)
  926.     char *inputfilename;
  927.     int lineno;
  928.     Xauth *auth;
  929.     char *data;
  930. {
  931.     struct _extract_data *ed = (struct _extract_data *) data;
  932.  
  933.     if (!ed->fp) {
  934.     ed->fp = open_file (&ed->filename, "w", &ed->used_stdout,
  935.                 inputfilename, lineno, ed->cmd);
  936.     if (!ed->fp) {
  937.         prefix (inputfilename, lineno);
  938.         fprintf (stderr,
  939.              "unable to open extraction file \"%s\"\n",
  940.              ed->filename);
  941.         return -1;
  942.     }
  943.     }
  944.     (*(ed->numeric ? dump_numeric : XauWriteAuth)) (ed->fp, auth);
  945.     ed->nwritten++;
  946.  
  947.     return 0;
  948. }
  949.  
  950.  
  951. static int match_auth_dpy (a, b)
  952.     register Xauth *a, *b;
  953. {
  954.     return ((a->family == b->family &&
  955.          a->address_length == b->address_length &&
  956.          a->number_length == b->number_length &&
  957.          bcmp (a->address, b->address, a->address_length) == 0 &&
  958.          bcmp (a->number, b->number, a->number_length) == 0) ? 1 : 0);
  959. }
  960.  
  961. /* return non-zero iff display and authorization type are the same */
  962.  
  963. static int match_auth (a, b)
  964.     register Xauth *a, *b;
  965. {
  966.     return ((match_auth_dpy(a, b)
  967.          && a->name_length == b->name_length
  968.          && bcmp(a->name, b->name, a->name_length) == 0) ? 1 : 0);
  969. }
  970.  
  971.  
  972. static int merge_entries (firstp, second, nnewp, nreplp)
  973.     AuthList **firstp, *second;
  974.     int *nnewp, *nreplp;
  975. {
  976.     AuthList *a, *b, *first, *tail;
  977.     int n = 0, nnew = 0, nrepl = 0;
  978.  
  979.     if (!second) return 0;
  980.  
  981.     if (!*firstp) {            /* if nothing to merge into */
  982.     *firstp = second;
  983.     for (tail = *firstp, n = 1; tail->next; n++, tail = tail->next) ;
  984.     *nnewp = n;
  985.     *nreplp = 0;
  986.     return n;
  987.     }
  988.  
  989.     first = *firstp;
  990.     /*
  991.      * find end of first list and stick second list on it
  992.      */
  993.     for (tail = first; tail->next; tail = tail->next) ;
  994.     tail->next = second;
  995.  
  996.     /*
  997.      * run down list freeing duplicate entries; if an entry is okay, then
  998.      * bump the tail up to include it, otherwise, cut the entry out of
  999.      * the chain.
  1000.      */
  1001.     for (b = second; b; ) {
  1002.     AuthList *next = b->next;    /* in case we free it */
  1003.  
  1004.     a = first;
  1005.     for (;;) {
  1006.         if (match_auth (a->auth, b->auth)) {  /* found a duplicate */
  1007.         AuthList tmp;        /* swap it in for old one */
  1008.         tmp = *a;
  1009.         *a = *b;
  1010.         *b = tmp;
  1011.         a->next = b->next;
  1012.         XauDisposeAuth (b->auth);
  1013.         free ((char *) b);
  1014.         b = NULL;
  1015.         tail->next = next;
  1016.         nrepl++;
  1017.         nnew--;
  1018.         break;
  1019.         }
  1020.         if (a == tail) break;    /* if have looked at left side */
  1021.         a = a->next;
  1022.     }
  1023.     if (b) {            /* if we didn't remove it */
  1024.         tail = b;            /* bump end of first list */
  1025.     }
  1026.     b = next;
  1027.     n++;
  1028.     nnew++;
  1029.     }
  1030.  
  1031.     *nnewp = nnew;
  1032.     *nreplp = nrepl;
  1033.     return n;
  1034.  
  1035. }
  1036.  
  1037.  
  1038. static int iterdpy (inputfilename, lineno, start,
  1039.             argc, argv, yfunc, nfunc, data)
  1040.     char *inputfilename;
  1041.     int lineno;
  1042.     int start;
  1043.     int argc;
  1044.     char *argv[];
  1045.     int (*yfunc)(), (*nfunc)();
  1046.     char *data;
  1047. {
  1048.     int i;
  1049.     int status;
  1050.     int errors = 0;
  1051.     Xauth proto;
  1052.     AuthList *l, *next;
  1053.  
  1054.     /*
  1055.      * iterate
  1056.      */
  1057.     for (i = start; i < argc; i++) {
  1058.     char *displayname = argv[i];
  1059.     proto.address = proto.number = NULL;
  1060.     if (!get_displayname_auth (displayname, &proto)) {
  1061.         prefix (inputfilename, lineno);
  1062.         baddisplayname (displayname, argv[0]);
  1063.         errors++;
  1064.         continue;
  1065.     }
  1066.     status = 0;
  1067.     for (l = xauth_head; l; l = next) {
  1068.         next = l->next;
  1069.         if (match_auth_dpy (&proto, l->auth)) {
  1070.         if (yfunc) {
  1071.             status = (*yfunc) (inputfilename, lineno,
  1072.                        l->auth, data);
  1073.             if (status < 0) break;
  1074.         }
  1075.         } else {
  1076.         if (nfunc) {
  1077.             status = (*nfunc) (inputfilename, lineno,
  1078.                        l->auth, data);
  1079.             if (status < 0) break;
  1080.         }
  1081.         }
  1082.     }
  1083.     if (proto.address) free (proto.address);
  1084.     if (proto.number) free (proto.number);
  1085.     if (status < 0) {
  1086.         errors -= status;        /* since status is negative */
  1087.         break;
  1088.     }
  1089.     }
  1090.  
  1091.     return errors;
  1092. }
  1093.  
  1094. /* ARGSUSED */
  1095. static int remove_entry (inputfilename, lineno, auth, data)
  1096.     char *inputfilename;
  1097.     int lineno;
  1098.     Xauth *auth;
  1099.     char *data;
  1100. {
  1101.     int *nremovedp = (int *) data;
  1102.     AuthList **listp = &xauth_head;
  1103.     AuthList *list;
  1104.  
  1105.     /*
  1106.      * unlink the auth we were asked to
  1107.      */
  1108.     while ((list = *listp)->auth != auth)
  1109.     listp = &list->next;
  1110.     *listp = list->next;
  1111.     XauDisposeAuth (list->auth);                    /* free the auth */
  1112.     free (list);                    /* free the link */
  1113.     xauth_modified = True;
  1114.     (*nremovedp)++;
  1115.     return 1;
  1116. }
  1117.  
  1118. /*
  1119.  * action routines
  1120.  */
  1121.  
  1122. /*
  1123.  * help
  1124.  */
  1125. int print_help (fp, cmd, prefix)
  1126.     FILE *fp;
  1127.     char *cmd;
  1128.     char *prefix;
  1129. {
  1130.     CommandTable *ct;
  1131.     int n = 0;
  1132.  
  1133.     if (!prefix) prefix = "";
  1134.  
  1135.     if (!cmd) {                /* if no cmd, print all help */
  1136.     for (ct = command_table; ct->name; ct++) {
  1137.         fprintf (fp, "%s%s\n", prefix, ct->helptext);
  1138.         n++;
  1139.     }
  1140.     } else {
  1141.     int len = strlen (cmd);
  1142.     for (ct = command_table; ct->name; ct++) {
  1143.         if (strncmp (cmd, ct->name, len) == 0) {
  1144.         fprintf (fp, "%s%s\n", prefix, ct->helptext);
  1145.         n++;
  1146.         }
  1147.     }
  1148.     }
  1149.     
  1150.     return n;
  1151. }
  1152.  
  1153. static int do_help (inputfilename, lineno, argc, argv)
  1154.     char *inputfilename;
  1155.     int lineno;
  1156.     int argc;
  1157.     char **argv;
  1158. {
  1159.     char *cmd = (argc > 1 ? argv[1] : NULL);
  1160.     int n;
  1161.  
  1162.     n = print_help (stdout, cmd, "    ");  /* a nice amount */
  1163.  
  1164.     if (n < 0 || (n == 0 && !cmd)) {
  1165.     prefix (inputfilename, lineno);
  1166.     fprintf (stderr, "internal error with help");
  1167.     if (cmd) {
  1168.         fprintf (stderr, " on command \"%s\"", cmd);
  1169.     }
  1170.     fprintf (stderr, "\n");
  1171.     return 1;
  1172.     }
  1173.  
  1174.     if (n == 0) {
  1175.     prefix (inputfilename, lineno);
  1176.     /* already know that cmd is set in this case */
  1177.     fprintf (stderr, "no help for noexistent command \"%s\"\n", cmd);
  1178.     }
  1179.  
  1180.     return 0;
  1181. }
  1182.  
  1183. /*
  1184.  * questionmark
  1185.  */
  1186. /* ARGSUSED */
  1187. static int do_questionmark (inputfilename, lineno, argc, argv)
  1188.     char *inputfilename;
  1189.     int lineno;
  1190.     int argc;
  1191.     char **argv;
  1192. {
  1193.     CommandTable *ct;
  1194.     int i;
  1195. #define WIDEST_COLUMN 72
  1196.     int col = WIDEST_COLUMN;
  1197.  
  1198.     printf ("Commands:\n");
  1199.     for (ct = command_table; ct->name; ct++) {
  1200.     if ((col + ct->maxlen) > WIDEST_COLUMN) {
  1201.         if (ct != command_table) {
  1202.         putc ('\n', stdout);
  1203.         }
  1204.         fputs ("        ", stdout);
  1205.         col = 8;            /* length of string above */
  1206.     }
  1207.     fputs (ct->name, stdout);
  1208.     col += ct->maxlen;
  1209.     for (i = ct->maxlen; i < COMMAND_NAMES_PADDED_WIDTH; i++) {
  1210.         putc (' ', stdout);
  1211.         col++;
  1212.     }
  1213.     }
  1214.     if (col != 0) {
  1215.     putc ('\n', stdout);
  1216.     }
  1217.  
  1218.     /* allow bad lines since this is help */
  1219.     return 0;
  1220. }
  1221.  
  1222. /*
  1223.  * list [displayname ...]
  1224.  */
  1225. static int do_list (inputfilename, lineno, argc, argv)
  1226.     char *inputfilename;
  1227.     int lineno;
  1228.     int argc;
  1229.     char **argv;
  1230. {
  1231.     struct _list_data ld;
  1232.  
  1233.     ld.fp = stdout;
  1234.     ld.numeric = (argv[0][0] == 'n');
  1235.  
  1236.     if (argc == 1) {
  1237.     register AuthList *l;
  1238.  
  1239.     if (xauth_head) {
  1240.         for (l = xauth_head; l; l = l->next) {
  1241.         dump_entry (inputfilename, lineno, l->auth, (char *) &ld);
  1242.         }
  1243.     }
  1244.     return 0;
  1245.     }
  1246.  
  1247.     return iterdpy (inputfilename, lineno, 1, argc, argv,
  1248.             dump_entry, NULL, (char *) &ld);
  1249. }
  1250.  
  1251. /*
  1252.  * merge filename [filename ...]
  1253.  */
  1254. static int do_merge (inputfilename, lineno, argc, argv)
  1255.     char *inputfilename;
  1256.     int lineno;
  1257.     int argc;
  1258.     char **argv;
  1259. {
  1260.     int i;
  1261.     int errors = 0;
  1262.     AuthList *head, *tail, *listhead, *listtail;
  1263.     int nentries, nnew, nrepl;
  1264.     Bool numeric = False;
  1265.  
  1266.     if (argc < 2) {
  1267.     prefix (inputfilename, lineno);
  1268.     badcommandline (argv[0]);
  1269.     return 1;
  1270.     }
  1271.  
  1272.     if (argv[0][0] == 'n') numeric = True;
  1273.     listhead = listtail = NULL;
  1274.  
  1275.     for (i = 1; i < argc; i++) {
  1276.     char *filename = argv[i];
  1277.     FILE *fp;
  1278.     Bool used_stdin = False;
  1279.  
  1280.     fp = open_file (&filename, "r", &used_stdin, inputfilename, lineno,
  1281.             argv[0]);
  1282.     if (!fp) {
  1283.         errors++;
  1284.         continue;
  1285.     }
  1286.  
  1287.     head = tail = NULL;
  1288.     nentries = read_auth_entries (fp, numeric, &head, &tail);
  1289.     if (nentries == 0) {
  1290.         prefix (inputfilename, lineno);
  1291.         fprintf (stderr, "unable to read any entries from file \"%s\"\n",
  1292.              filename);
  1293.         errors++;
  1294.     } else {            /* link it in */
  1295.         add_to_list (listhead, listtail, head);
  1296.      }
  1297.  
  1298.     if (!used_stdin) (void) fclose (fp);
  1299.     }
  1300.  
  1301.     /*
  1302.      * if we have new entries, merge them in (freeing any duplicates)
  1303.      */
  1304.     if (listhead) {
  1305.     nentries = merge_entries (&xauth_head, listhead, &nnew, &nrepl);
  1306.     if (verbose) 
  1307.       printf ("%d entries read in:  %d new, %d replacement%s\n", 
  1308.             nentries, nnew, nrepl, nrepl != 1 ? "s" : "");
  1309.     if (nentries > 0) xauth_modified = True;
  1310.     }
  1311.  
  1312.     return 0;
  1313. }
  1314.  
  1315. /*
  1316.  * extract filename displayname [displayname ...]
  1317.  */
  1318. static int do_extract (inputfilename, lineno, argc, argv)
  1319.     char *inputfilename;
  1320.     int lineno;
  1321.     int argc;
  1322.     char **argv;
  1323. {
  1324.     int errors;
  1325.     struct _extract_data ed;
  1326.  
  1327.     if (argc < 3) {
  1328.     prefix (inputfilename, lineno);
  1329.     badcommandline (argv[0]);
  1330.     return 1;
  1331.     }
  1332.  
  1333.     ed.fp = NULL;
  1334.     ed.filename = argv[1];
  1335.     ed.numeric = (argv[0][0] == 'n');
  1336.     ed.nwritten = 0;
  1337.     ed.cmd = argv[0];
  1338.  
  1339.     errors = iterdpy (inputfilename, lineno, 2, argc, argv, 
  1340.               extract_entry, NULL, (char *) &ed);
  1341.  
  1342.     if (!ed.fp) {
  1343.     fprintf (stderr, 
  1344.          "No matches found, authority file \"%s\" not written\n",
  1345.          ed.filename);
  1346.     } else {
  1347.     if (verbose) {
  1348.         printf ("%d entries written to \"%s\"\n", 
  1349.             ed.nwritten, ed.filename);
  1350.     }
  1351.     if (!ed.used_stdout) {
  1352.         (void) fclose (ed.fp);
  1353.     }
  1354.     }
  1355.  
  1356.     return errors;
  1357. }
  1358.  
  1359.  
  1360. /*
  1361.  * add displayname protocolname hexkey
  1362.  */
  1363. static int do_add (inputfilename, lineno, argc, argv)
  1364.     char *inputfilename;
  1365.     int lineno;
  1366.     int argc;
  1367.     char **argv;
  1368.     int n, nnew, nrepl;
  1369.     int len;
  1370.     char *dpyname;
  1371.     char *protoname;
  1372.     char *hexkey;
  1373.     char *key;
  1374.     Xauth *auth;
  1375.     AuthList *list;
  1376.  
  1377.     if (argc != 4 || !argv[1] || !argv[2] || !argv[3]) {
  1378.     prefix (inputfilename, lineno);
  1379.     badcommandline (argv[0]);
  1380.     return 1;
  1381.     }
  1382.  
  1383.     dpyname = argv[1];
  1384.     protoname = argv[2];
  1385.     hexkey = argv[3];
  1386.  
  1387.     len = strlen(hexkey);
  1388.     if (hexkey[0] == '"' && hexkey[len-1] == '"') {
  1389.     key = malloc(len-1);
  1390.     strncpy(key, hexkey+1, len-2);
  1391.     len -= 2;
  1392.     } else if (!strcmp(protoname, SECURERPC)) {
  1393.     key = malloc(len+1);
  1394.     strcpy(key, hexkey);
  1395.     } else {
  1396.     len = cvthexkey (hexkey, &key);
  1397.     if (len < 0) {
  1398.         prefix (inputfilename, lineno);
  1399.         fprintf (stderr,
  1400.              "key contains odd number of or non-hex characters\n");
  1401.         return 1;
  1402.     }
  1403.     }
  1404.  
  1405.     auth = (Xauth *) malloc (sizeof (Xauth));
  1406.     if (!auth) {
  1407.     prefix (inputfilename, lineno);
  1408.     fprintf (stderr, "unable to allocate %d bytes for Xauth structure\n",
  1409.          sizeof (Xauth));
  1410.     free (key);
  1411.     return 1;
  1412.     }
  1413.  
  1414.     if (!get_displayname_auth (dpyname, auth)) {
  1415.     prefix (inputfilename, lineno);
  1416.     baddisplayname (dpyname, argv[0]);
  1417.     free (auth);
  1418.     free (key);
  1419.     return 1;
  1420.     }
  1421.  
  1422.     /*
  1423.      * allow an abbreviation for common protocol names
  1424.      */
  1425.     if (strcmp (protoname, DEFAULT_PROTOCOL_ABBREV) == 0) {
  1426.     protoname = DEFAULT_PROTOCOL;
  1427.     }
  1428.  
  1429.     auth->name_length = strlen (protoname);
  1430.     auth->name = copystring (protoname, auth->name_length);
  1431.     if (!auth->name) {
  1432.     prefix (inputfilename, lineno);
  1433.     fprintf (stderr, "unable to allocate %d character protocol name\n",
  1434.          auth->name_length);
  1435.     free (auth);
  1436.     free (key);
  1437.     return 1;
  1438.     }
  1439.     auth->data_length = len;
  1440.     auth->data = key;
  1441.  
  1442.     list = (AuthList *) malloc (sizeof (AuthList));
  1443.     if (!list) {
  1444.     prefix (inputfilename, lineno);
  1445.     fprintf (stderr, "unable to allocate %d bytes for auth list\n",
  1446.          sizeof (AuthList));
  1447.     free (auth);
  1448.     free (key);
  1449.     free (auth->name);
  1450.     return 1;
  1451.     }
  1452.  
  1453.     list->next = NULL;
  1454.     list->auth = auth;
  1455.  
  1456.     /*
  1457.      * merge it in; note that merge will deal with allocation
  1458.      */
  1459.     n = merge_entries (&xauth_head, list, &nnew, &nrepl);
  1460.     if (n <= 0) {
  1461.     prefix (inputfilename, lineno);
  1462.     fprintf (stderr, "unable to merge in added record\n");
  1463.     return 1;
  1464.     }
  1465.  
  1466.     xauth_modified = True;
  1467.     return 0;
  1468. }
  1469.  
  1470. /*
  1471.  * remove displayname
  1472.  */
  1473. static int do_remove (inputfilename, lineno, argc, argv)
  1474.     char *inputfilename;
  1475.     int lineno;
  1476.     int argc;
  1477.     char **argv;
  1478. {
  1479.     int nremoved = 0;
  1480.     int errors;
  1481.  
  1482.     if (argc < 2) {
  1483.     prefix (inputfilename, lineno);
  1484.     badcommandline (argv[0]);
  1485.     return 1;
  1486.     }
  1487.  
  1488.     errors = iterdpy (inputfilename, lineno, 1, argc, argv,
  1489.               remove_entry, NULL, (char *) &nremoved);
  1490.     if (verbose) printf ("%d entries removed\n", nremoved);
  1491.     return errors;
  1492. }
  1493.  
  1494. /*
  1495.  * info
  1496.  */
  1497. static int do_info (inputfilename, lineno, argc, argv)
  1498.     char *inputfilename;
  1499.     int lineno;
  1500.     int argc;
  1501.     char **argv;
  1502. {
  1503.     int n;
  1504.     AuthList *l;
  1505.  
  1506.     if (argc != 1) {
  1507.     prefix (inputfilename, lineno);
  1508.     badcommandline (argv[0]);
  1509.     return 1;
  1510.     }
  1511.  
  1512.     for (l = xauth_head, n = 0; l; l = l->next, n++) ;
  1513.  
  1514.     printf ("Authority file:       %s\n",
  1515.         xauth_filename ? xauth_filename : "(none)");
  1516.     printf ("File new:             %s\n", xauth_existed ? No : Yes);
  1517.     printf ("File locked:          %s\n", ignore_locks ? No : Yes);
  1518.     printf ("Number of entries:    %d\n", n);
  1519.     printf ("Changes honored:      %s\n", xauth_allowed ? Yes : No);
  1520.     printf ("Changes made:         %s\n", xauth_modified ? Yes : No);
  1521.     printf ("Current input:        %s:%d\n", inputfilename, lineno);
  1522.     return 0;
  1523. }
  1524.  
  1525.  
  1526. /*
  1527.  * exit
  1528.  */
  1529. static Bool alldone = False;
  1530.  
  1531. /* ARGSUSED */
  1532. static int do_exit (inputfilename, lineno, argc, argv)
  1533.     char *inputfilename;
  1534.     int lineno;
  1535.     int argc;
  1536.     char **argv;
  1537. {
  1538.     /* allow bogus stuff */
  1539.     alldone = True;
  1540.     return 0;
  1541. }
  1542.  
  1543. /*
  1544.  * quit
  1545.  */
  1546. /* ARGSUSED */
  1547. static int do_quit (inputfilename, lineno, argc, argv)
  1548.     char *inputfilename;
  1549.     int lineno;
  1550.     int argc;
  1551.     char **argv;
  1552. {
  1553.     /* allow bogus stuff */
  1554.     die (0);
  1555.     /* NOTREACHED */
  1556.     return -1;                /* for picky compilers */
  1557. }
  1558.  
  1559.  
  1560. /*
  1561.  * source filename
  1562.  */
  1563. static int do_source (inputfilename, lineno, argc, argv)
  1564.     char *inputfilename;
  1565.     int lineno;
  1566.     int argc;
  1567.     char **argv;
  1568. {
  1569.     char *script;
  1570.     char buf[BUFSIZ];
  1571.     FILE *fp;
  1572.     Bool used_stdin = False;
  1573.     int len;
  1574.     int errors = 0, status;
  1575.     int sublineno = 0;
  1576.     char **subargv;
  1577.     int subargc;
  1578.     Bool prompt = False;        /* only true if reading from tty */
  1579.  
  1580.     if (argc != 2 || !argv[1]) {
  1581.     prefix (inputfilename, lineno);
  1582.     badcommandline (argv[0]);
  1583.     return 1;
  1584.     }
  1585.  
  1586.     script = argv[1];
  1587.  
  1588.     fp = open_file (&script, "r", &used_stdin, inputfilename, lineno, argv[0]);
  1589.     if (!fp) {
  1590.     return 1;
  1591.     }
  1592.  
  1593.     if (verbose && used_stdin && isatty (fileno (fp))) prompt = True;
  1594.  
  1595.     while (!alldone) {
  1596.     buf[0] = '\0';
  1597.     if (prompt) {
  1598.         printf ("xauth> ");
  1599.         fflush (stdout);
  1600.     }
  1601.     if (fgets (buf, sizeof buf, fp) == NULL) break;
  1602.     sublineno++;
  1603.     len = strlen (buf);
  1604.     if (len == 0 || buf[0] == '#') continue;
  1605.     if (buf[len-1] != '\n') {
  1606.         prefix (script, sublineno);
  1607.         fprintf (stderr, "line too long\n");
  1608.         errors++;
  1609.         break;
  1610.     }
  1611.     buf[--len] = '\0';        /* remove new line */
  1612.     subargv = split_into_words (buf, &subargc);
  1613.     if (subargv) {
  1614.         status = process_command (script, sublineno, subargc, subargv);
  1615.         free ((char *) subargv);
  1616.         errors += status;
  1617.     } else {
  1618.         prefix (script, sublineno);
  1619.         fprintf (stderr, "unable to break line into words\n");
  1620.         errors++;
  1621.     }
  1622.     }
  1623.  
  1624.     if (!used_stdin) {
  1625.     (void) fclose (fp);
  1626.     }
  1627.     return errors;
  1628. }
  1629.