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

  1. /*
  2.  * $XConsortium: process.c,v 1.41 92/01/22 23:39:12 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.     char buf[2];
  334.  
  335.     cp = s = malloc (n);
  336.     if (!cp) return 0;
  337.  
  338.     while (n > 0) {
  339.     if ((buf[0] = getinput (fp)) == EOF || buf[0] == '\n' ||
  340.         (buf[1] = getinput (fp)) == EOF || buf[1] == '\n') {
  341.         free (s);
  342.         return 0;
  343.     }
  344.     *cp = (char) ((hexvalues[(unsigned int)buf[0]] * 16) + 
  345.               hexvalues[(unsigned int)buf[1]]);
  346.     cp++;
  347.     n--;
  348.     }
  349.  
  350.     *ptr = s;
  351.     return 1;
  352. }
  353.  
  354.  
  355. static Xauth *read_numeric (fp)
  356.     FILE *fp;
  357. {
  358.     Xauth *auth;
  359.  
  360.     auth = (Xauth *) malloc (sizeof (Xauth));
  361.     if (!auth) goto bad;
  362.     auth->family = 0;
  363.     auth->address = NULL;
  364.     auth->address_length = 0;
  365.     auth->number = NULL;
  366.     auth->number_length = 0;
  367.     auth->name = NULL;
  368.     auth->name_length = 0;
  369.     auth->data = NULL;
  370.     auth->data_length = 0;
  371.  
  372.     if (!get_short (fp, (unsigned short *) &auth->family))
  373.       goto bad;
  374.     if (!get_short (fp, (unsigned short *) &auth->address_length))
  375.       goto bad;
  376.     if (!get_bytes (fp, (unsigned int) auth->address_length, &auth->address))
  377.       goto bad;
  378.     if (!get_short (fp, (unsigned short *) &auth->number_length))
  379.       goto bad;
  380.     if (!get_bytes (fp, (unsigned int) auth->number_length, &auth->number))
  381.       goto bad;
  382.     if (!get_short (fp, (unsigned short *) &auth->name_length))
  383.       goto bad;
  384.     if (!get_bytes (fp, (unsigned int) auth->name_length, &auth->name))
  385.       goto bad;
  386.     if (!get_short (fp, (unsigned short *) &auth->data_length))
  387.       goto bad;
  388.     if (!get_bytes (fp, (unsigned int) auth->data_length, &auth->data))
  389.       goto bad;
  390.     
  391.     switch (getinput (fp)) {        /* get end of line */
  392.       case EOF:
  393.       case '\n':
  394.     return auth;
  395.     }
  396.  
  397.   bad:
  398.     if (auth) XauDisposeAuth (auth);    /* won't free null pointers */
  399.     return NULL;
  400. }
  401.  
  402. static int read_auth_entries (fp, numeric, headp, tailp)
  403.     FILE *fp;
  404.     Bool numeric;
  405.     AuthList **headp, **tailp;
  406. {
  407.     Xauth *((*readfunc)()) = (numeric ? read_numeric : XauReadAuth);
  408.     Xauth *auth;
  409.     AuthList *head, *tail;
  410.     int n;
  411.  
  412.     head = tail = NULL;
  413.     n = 0;
  414.                     /* put all records into linked list */
  415.     while ((auth = ((*readfunc) (fp))) != NULL) {
  416.     AuthList *l = (AuthList *) malloc (sizeof (AuthList));
  417.     if (!l) {
  418.         fprintf (stderr,
  419.              "%s:  unable to alloc entry reading auth file\n",
  420.              ProgramName);
  421.         exit (1);
  422.     }
  423.     l->next = NULL;
  424.     l->auth = auth;
  425.     if (tail)             /* if not first time through append */
  426.       tail->next = l;
  427.     else
  428.       head = l;            /* first time through, so assign */
  429.     tail = l;
  430.     n++;
  431.     }
  432.     *headp = head;
  433.     *tailp = tail;
  434.     return n;
  435. }
  436.  
  437. static Bool get_displayname_auth (displayname, auth)
  438.     char *displayname;
  439.     Xauth *auth;            /* fill in */
  440. {
  441.     int family;
  442.     char *host = NULL, *rest = NULL;
  443.     int dpynum, scrnum;
  444.     char *cp;
  445.     int len;
  446.     extern char *get_address_info();
  447.     Xauth proto;
  448.     int prelen = 0;
  449.  
  450.     /*
  451.      * check to see if the display name is of the form "host/unix:"
  452.      * which is how the list routine prints out local connections
  453.      */
  454.     cp = index (displayname, '/');
  455.     if (cp && strncmp (cp, "/unix:", 6) == 0)
  456.       prelen = (cp - displayname);
  457.  
  458.     if (!parse_displayname (displayname + ((prelen > 0) ? prelen + 1 : 0),
  459.                 &family, &host, &dpynum, &scrnum, &rest)) {
  460.     return False;
  461.     }
  462.  
  463.     proto.family = family;
  464.     proto.address = get_address_info (family, displayname, prelen, host, &len);
  465.     if (proto.address) {
  466.     char buf[40];            /* want to hold largest display num */
  467.  
  468.     proto.address_length = len;
  469.     buf[0] = '\0';
  470.     sprintf (buf, "%d", dpynum);
  471.     proto.number_length = strlen (buf);
  472.     if (proto.number_length <= 0) {
  473.         free (proto.address);
  474.         proto.address = NULL;
  475.     } else {
  476.         proto.number = copystring (buf, proto.number_length);
  477.     }
  478.     }
  479.  
  480.     if (host) free (host);
  481.     if (rest) free (rest);
  482.  
  483.     if (proto.address) {
  484.     auth->family = proto.family;
  485.     auth->address = proto.address;
  486.     auth->address_length = proto.address_length;
  487.     auth->number = proto.number;
  488.     auth->number_length = proto.number_length;
  489.     auth->name = NULL;
  490.     auth->name_length = 0;
  491.     auth->data = NULL;
  492.     auth->data_length = 0;
  493.     return True;
  494.     } else {
  495.     return False;
  496.     }
  497. }
  498.  
  499. static int cvthexkey (hexstr, ptrp)    /* turn hex key string into octets */
  500.     char *hexstr;
  501.     char **ptrp;
  502. {
  503.     int i;
  504.     int len = 0;
  505.     char *retval, *s;
  506.     unsigned char *us;
  507.     char c;
  508.     char savec = '\0';
  509.  
  510.     /* count */
  511.     for (s = hexstr; *s; s++) {
  512.     if (!isascii(*s)) return -1;
  513.     if (isspace(*s)) continue;
  514.     if (!isxdigit(*s)) return -1;
  515.     len++;
  516.     }
  517.  
  518.     /* if odd then there was an error */
  519.     if ((len & 1) == 1) return -1;
  520.  
  521.  
  522.     /* now we know that the input is good */
  523.     len >>= 1;
  524.     retval = malloc (len);
  525.     if (!retval) {
  526.     fprintf (stderr, "%s:  unable to allocate %d bytes for hexkey\n",
  527.          ProgramName, len);
  528.     return -1;
  529.     }
  530.  
  531.     for (us = (unsigned char *) retval, i = len; i > 0; hexstr++) {
  532.     c = *hexstr;
  533.     if (isspace(c)) continue;     /* already know it is ascii */
  534.     if (isupper(c))
  535.         c = tolower(c);
  536.     if (savec) {
  537. #define atoh(c) ((c) - (((c) >= '0' && (c) <= '9') ? '0' : ('a'-10)))
  538.         *us = (unsigned char)((atoh(savec) << 4) + atoh(c));
  539. #undef atoh
  540.         savec = 0;        /* ready for next character */
  541.         us++;
  542.         i--;
  543.     } else {
  544.         savec = c;
  545.     }
  546.     }
  547.     *ptrp = retval;
  548.     return len;
  549. }
  550.  
  551. static int dispatch_command (inputfilename, lineno, argc, argv, tab, statusp)
  552.     char *inputfilename;
  553.     int lineno;
  554.     int argc;
  555.     char **argv;
  556.     CommandTable *tab;
  557.     int *statusp;
  558. {
  559.     CommandTable *ct;
  560.     char *cmd;
  561.     int n;
  562.                     /* scan table for command */
  563.     cmd = argv[0];
  564.     n = strlen (cmd);
  565.     for (ct = tab; ct->name; ct++) {
  566.                     /* look for unique prefix */
  567.     if (n >= ct->minlen && n <= ct->maxlen &&
  568.         strncmp (cmd, ct->name, n) == 0) {
  569.         *statusp = (*(ct->processfunc))(inputfilename, lineno, argc, argv);
  570.         return 1;
  571.     }
  572.     }
  573.  
  574.     *statusp = 1;
  575.     return 0;
  576. }
  577.  
  578.  
  579. static AuthList *xauth_head = NULL;    /* list of auth entries */
  580. static Bool xauth_existed = False;    /* if was present at initialize */
  581. static Bool xauth_modified = False;    /* if added, removed, or merged */
  582. static Bool xauth_allowed = True;    /* if allowed to write auth file */
  583. static char *xauth_filename = NULL;
  584. static Bool dieing = False;
  585.  
  586. #ifdef SIGNALRETURNSINT
  587. #define _signal_t int
  588. #else
  589. #define _signal_t void
  590. #endif
  591.  
  592. /* ARGSUSED */
  593. static _signal_t die (sig)
  594.     int sig;
  595. {
  596.     dieing = True;
  597.     exit (auth_finalize ());
  598.     /* NOTREACHED */
  599. #ifdef SIGNALRETURNSINT
  600.     return -1;                /* for picky compilers */
  601. #endif
  602. }
  603.  
  604. static _signal_t catchsig (sig)
  605.     int sig;
  606. {
  607. #ifdef SYSV
  608.     if (sig > 0) signal (sig, die);    /* re-establish signal handler */
  609. #endif
  610.     if (verbose && xauth_modified) printf ("\r\n");
  611.     die (sig);
  612.     /* NOTREACHED */
  613. #ifdef SIGNALRETURNSINT
  614.     return -1;                /* for picky compilers */
  615. #endif
  616. }
  617.  
  618. static void register_signals ()
  619. {
  620.     signal (SIGINT, catchsig);
  621.     signal (SIGTERM, catchsig);
  622.     signal (SIGHUP, catchsig);
  623.     return;
  624. }
  625.  
  626.  
  627. /*
  628.  * public procedures for parsing lines of input
  629.  */
  630.  
  631. int auth_initialize (authfilename)
  632.     char *authfilename;
  633. {
  634.     int n;
  635.     AuthList *head, *tail;
  636.     FILE *authfp;
  637.     Bool exists;
  638.  
  639.     register_signals ();
  640.  
  641.     bzero ((char *) hexvalues, sizeof hexvalues);
  642.     hexvalues['0'] = 0;
  643.     hexvalues['1'] = 1;
  644.     hexvalues['2'] = 2;
  645.     hexvalues['3'] = 3;
  646.     hexvalues['4'] = 4;
  647.     hexvalues['5'] = 5;
  648.     hexvalues['6'] = 6;
  649.     hexvalues['7'] = 7;
  650.     hexvalues['8'] = 8;
  651.     hexvalues['9'] = 9;
  652.     hexvalues['a'] = hexvalues['A'] = 0xa;
  653.     hexvalues['b'] = hexvalues['B'] = 0xb;
  654.     hexvalues['c'] = hexvalues['C'] = 0xc;
  655.     hexvalues['d'] = hexvalues['D'] = 0xd;
  656.     hexvalues['e'] = hexvalues['E'] = 0xe;
  657.     hexvalues['f'] = hexvalues['F'] = 0xf;
  658.  
  659.     if (break_locks && verbose) {
  660.     printf ("Attempting to break locks on authority file %s\n",
  661.         authfilename);
  662.     }
  663.  
  664.     if (ignore_locks) {
  665.     if (break_locks) XauUnlockAuth (authfilename);
  666.     } else {
  667.     n = XauLockAuth (authfilename, XAUTH_DEFAULT_RETRIES,
  668.              XAUTH_DEFAULT_TIMEOUT, 
  669.              (break_locks ? 0L : XAUTH_DEFAULT_DEADTIME));
  670.     if (n != LOCK_SUCCESS) {
  671.         char *reason = "unknown error";
  672.         switch (n) {
  673.           case LOCK_ERROR:
  674.         reason = "error";
  675.         break;
  676.           case LOCK_TIMEOUT:
  677.         reason = "timeout";
  678.         break;
  679.         }
  680.         fprintf (stderr, "%s:  %s in locking authority file %s\n",
  681.              ProgramName, reason, authfilename);
  682.         return -1;
  683.     }
  684.     }
  685.  
  686.     /* these checks can only be done reliably after the file is locked */
  687.     exists = (access (authfilename, F_OK) == 0);
  688.     if (exists && access (authfilename, W_OK) != 0) {
  689.     fprintf (stderr,
  690.      "%s:  %s not writable, changes will be ignored\n",
  691.          ProgramName, authfilename);
  692.     xauth_allowed = False;
  693.     }
  694.  
  695.     original_umask = umask (0077);    /* disallow non-owner access */
  696.  
  697.     authfp = fopen (authfilename, "r");
  698.     if (!authfp) {
  699.     int olderrno = errno;
  700.  
  701.                     /* if file there then error */
  702.     if (access (authfilename, F_OK) == 0) {     /* then file does exist! */
  703.         errno = olderrno;
  704.         return -1;
  705.     }                /* else ignore it */
  706.     fprintf (stderr, 
  707.          "%s:  creating new authority file %s\n",
  708.          ProgramName, authfilename);
  709.     } else {
  710.     xauth_existed = True;
  711.     n = read_auth_entries (authfp, False, &head, &tail);
  712.     (void) fclose (authfp);
  713.     if (n < 0) {
  714.         fprintf (stderr,
  715.              "%s:  unable to read auth entries from file \"%s\"\n",
  716.              ProgramName, authfilename);
  717.         return -1;
  718.     }
  719.     xauth_head = head;
  720.     }
  721.  
  722.     n = strlen (authfilename);
  723.     xauth_filename = malloc (n + 1);
  724.     if (xauth_filename) strcpy (xauth_filename, authfilename);
  725.     xauth_modified = False;
  726.  
  727.     if (verbose) {
  728.     printf ("%s authority file %s\n", 
  729.         ignore_locks ? "Ignoring locks on" : "Using", authfilename);
  730.     }
  731.     return 0;
  732. }
  733.  
  734. static int write_auth_file (tmpnam)
  735.     char *tmpnam;
  736. {
  737.     FILE *fp;
  738.     AuthList *list;
  739.  
  740.     /*
  741.      * xdm and auth spec assumes auth file is 12 or fewer characters
  742.      */
  743.     strcpy (tmpnam, xauth_filename);
  744.     strcat (tmpnam, "-n");        /* for new */
  745.     (void) unlink (tmpnam);
  746.     fp = fopen (tmpnam, "w");        /* umask is still set to 0077 */
  747.     if (!fp) {
  748.     fprintf (stderr, "%s:  unable to open tmp file \"%s\"\n",
  749.          ProgramName, tmpnam);
  750.     return -1;
  751.     } 
  752.  
  753.     /*
  754.      * Write MIT-MAGIC-COOKIE-1 first, because R4 Xlib knows
  755.      * only that and uses the first authorization it finds.
  756.      */
  757.     for (list = xauth_head; list; list = list->next) {
  758.     if (list->auth->name_length == 18
  759.         && strncmp(list->auth->name, "MIT-MAGIC-COOKIE-1", 18) == 0)
  760.     {
  761.         XauWriteAuth (fp, list->auth);
  762.     }
  763.     }
  764.     for (list = xauth_head; list; list = list->next) {
  765.     if (list->auth->name_length != 18
  766.         || strncmp(list->auth->name, "MIT-MAGIC-COOKIE-1", 18) != 0)
  767.     {
  768.         XauWriteAuth (fp, list->auth);
  769.     }
  770.     }
  771.  
  772.     (void) fclose (fp);
  773.     return 0;
  774. }
  775.  
  776. int auth_finalize ()
  777. {
  778.     char tmpnam[1024];            /* large filename size */
  779.  
  780.     if (xauth_modified) {
  781.     if (dieing) {
  782.         if (verbose) {
  783.         printf ("Aborting changes to authority file %s\n",
  784.             xauth_filename);
  785.         }
  786.     } else if (!xauth_allowed) {
  787.         fprintf (stderr, 
  788.              "%s:  %s not writable, changes ignored\n",
  789.              ProgramName, xauth_filename);
  790.     } else {
  791.         if (verbose) {
  792.         printf ("%s authority file %s\n", 
  793.             ignore_locks ? "Ignoring locks and writing" :
  794.             "Writing", xauth_filename);
  795.         }
  796.         tmpnam[0] = '\0';
  797.         if (write_auth_file (tmpnam) == -1) {
  798.         fprintf (stderr,
  799.              "%s:  unable to write authority file %s\n",
  800.              ProgramName, tmpnam);
  801.         } else {
  802.         (void) unlink (xauth_filename);
  803.         if (link (tmpnam, xauth_filename) == -1) {
  804.             fprintf (stderr,
  805.              "%s:  unable to link authority file %s, use %s\n",
  806.                  ProgramName, xauth_filename, tmpnam);
  807.         } else {
  808.             (void) unlink (tmpnam);
  809.         }
  810.         }
  811.     }
  812.     }
  813.  
  814.     if (!ignore_locks) {
  815.     XauUnlockAuth (xauth_filename);
  816.     }
  817.     (void) umask (original_umask);
  818.     return 0;
  819. }
  820.  
  821. int process_command (inputfilename, lineno, argc, argv)
  822.     char *inputfilename;
  823.     int lineno;
  824.     int argc;
  825.     char **argv;
  826. {
  827.     int status;
  828.  
  829.     if (argc < 1 || !argv || !argv[0]) return 1;
  830.  
  831.     if (dispatch_command (inputfilename, lineno, argc, argv,
  832.               command_table, &status))
  833.       return status;
  834.  
  835.     prefix (inputfilename, lineno);
  836.     fprintf (stderr, "unknown command \"%s\"\n", argv[0]);
  837.     return 1;
  838. }
  839.  
  840.  
  841. /*
  842.  * utility routines
  843.  */
  844.  
  845. static void fprintfhex (fp, len, cp)
  846.     register FILE *fp;
  847.     unsigned int len;
  848.     char *cp;
  849. {
  850.     unsigned char *ucp = (unsigned char *) cp;
  851.  
  852.     for (; len > 0; len--, ucp++) {
  853.     register char *s = hex_table[*ucp];
  854.     putc (s[0], fp);
  855.     putc (s[1], fp);
  856.     }
  857.     return;
  858. }
  859.  
  860. dump_numeric (fp, auth)
  861.     register FILE *fp;
  862.     register Xauth *auth;
  863. {
  864.     fprintf (fp, "%04x", auth->family);  /* unsigned short */
  865.     fprintf (fp, " %04x ", auth->address_length);  /* short */
  866.     fprintfhex (fp, auth->address_length, auth->address);
  867.     fprintf (fp, " %04x ", auth->number_length);  /* short */
  868.     fprintfhex (fp, auth->number_length, auth->number);
  869.     fprintf (fp, " %04x ", auth->name_length);  /* short */
  870.     fprintfhex (fp, auth->name_length, auth->name);
  871.     fprintf (fp, " %04x ", auth->data_length);  /* short */
  872.     fprintfhex (fp, auth->data_length, auth->data);
  873.     putc ('\n', fp);
  874.     return;
  875. }
  876.  
  877. /* ARGSUSED */
  878. static int dump_entry (inputfilename, lineno, auth, data)
  879.     char *inputfilename;
  880.     int lineno;
  881.     Xauth *auth;
  882.     char *data;
  883. {
  884.     struct _list_data *ld = (struct _list_data *) data;
  885.     FILE *fp = ld->fp;
  886.  
  887.     if (ld->numeric) {
  888.     dump_numeric (fp, auth);
  889.     } else {
  890.     char *dpyname = NULL;
  891.  
  892.     switch (auth->family) {
  893.       case FamilyLocal:
  894.         fwrite (auth->address, sizeof (char), auth->address_length, fp);
  895.         fprintf (fp, "/unix");
  896.         break;
  897.       case FamilyInternet:
  898.       case FamilyDECnet:
  899.         dpyname = get_hostname (auth);
  900.         if (dpyname) {
  901.         fprintf (fp, "%s", dpyname);
  902.         break;
  903.         }
  904.         /* else fall through to default */
  905.       default:
  906.         fprintf (fp, "#%04x#", auth->family);
  907.         fprintfhex (fp, auth->address_length, auth->address);
  908.         putc ('#', fp);
  909.     }
  910.     putc (':', fp);
  911.     fwrite (auth->number, sizeof (char), auth->number_length, fp);
  912.     putc (' ', fp);
  913.     putc (' ', fp);
  914.     fwrite (auth->name, sizeof (char), auth->name_length, fp);
  915.     putc (' ', fp);
  916.     putc (' ', fp);
  917.     if (!strncmp(auth->name, SECURERPC, auth->name_length))
  918.         fwrite (auth->data, sizeof (char), auth->data_length, fp);
  919.     else
  920.         fprintfhex (fp, auth->data_length, auth->data);
  921.     putc ('\n', fp);
  922.     }
  923.     return 0;
  924. }
  925.  
  926. static int extract_entry (inputfilename, lineno, auth, data)
  927.     char *inputfilename;
  928.     int lineno;
  929.     Xauth *auth;
  930.     char *data;
  931. {
  932.     struct _extract_data *ed = (struct _extract_data *) data;
  933.  
  934.     if (!ed->fp) {
  935.     ed->fp = open_file (&ed->filename, "w", &ed->used_stdout,
  936.                 inputfilename, lineno, ed->cmd);
  937.     if (!ed->fp) {
  938.         prefix (inputfilename, lineno);
  939.         fprintf (stderr,
  940.              "unable to open extraction file \"%s\"\n",
  941.              ed->filename);
  942.         return -1;
  943.     }
  944.     }
  945.     (*(ed->numeric ? dump_numeric : XauWriteAuth)) (ed->fp, auth);
  946.     ed->nwritten++;
  947.  
  948.     return 0;
  949. }
  950.  
  951.  
  952. static int match_auth_dpy (a, b)
  953.     register Xauth *a, *b;
  954. {
  955.     return ((a->family == b->family &&
  956.          a->address_length == b->address_length &&
  957.          a->number_length == b->number_length &&
  958.          bcmp (a->address, b->address, a->address_length) == 0 &&
  959.          bcmp (a->number, b->number, a->number_length) == 0) ? 1 : 0);
  960. }
  961.  
  962. /* return non-zero iff display and authorization type are the same */
  963.  
  964. static int match_auth (a, b)
  965.     register Xauth *a, *b;
  966. {
  967.     return ((match_auth_dpy(a, b)
  968.          && a->name_length == b->name_length
  969.          && bcmp(a->name, b->name, a->name_length) == 0) ? 1 : 0);
  970. }
  971.  
  972.  
  973. static int merge_entries (firstp, second, nnewp, nreplp)
  974.     AuthList **firstp, *second;
  975.     int *nnewp, *nreplp;
  976. {
  977.     AuthList *a, *b, *first, *tail;
  978.     int n = 0, nnew = 0, nrepl = 0;
  979.  
  980.     if (!second) return 0;
  981.  
  982.     if (!*firstp) {            /* if nothing to merge into */
  983.     *firstp = second;
  984.     for (tail = *firstp, n = 1; tail->next; n++, tail = tail->next) ;
  985.     *nnewp = n;
  986.     *nreplp = 0;
  987.     return n;
  988.     }
  989.  
  990.     first = *firstp;
  991.     /*
  992.      * find end of first list and stick second list on it
  993.      */
  994.     for (tail = first; tail->next; tail = tail->next) ;
  995.     tail->next = second;
  996.  
  997.     /*
  998.      * run down list freeing duplicate entries; if an entry is okay, then
  999.      * bump the tail up to include it, otherwise, cut the entry out of
  1000.      * the chain.
  1001.      */
  1002.     for (b = second; b; ) {
  1003.     AuthList *next = b->next;    /* in case we free it */
  1004.  
  1005.     a = first;
  1006.     for (;;) {
  1007.         if (match_auth (a->auth, b->auth)) {  /* found a duplicate */
  1008.         AuthList tmp;        /* swap it in for old one */
  1009.         tmp = *a;
  1010.         *a = *b;
  1011.         *b = tmp;
  1012.         a->next = b->next;
  1013.         XauDisposeAuth (b->auth);
  1014.         free ((char *) b);
  1015.         b = NULL;
  1016.         tail->next = next;
  1017.         nrepl++;
  1018.         nnew--;
  1019.         break;
  1020.         }
  1021.         if (a == tail) break;    /* if have looked at left side */
  1022.         a = a->next;
  1023.     }
  1024.     if (b) {            /* if we didn't remove it */
  1025.         tail = b;            /* bump end of first list */
  1026.     }
  1027.     b = next;
  1028.     n++;
  1029.     nnew++;
  1030.     }
  1031.  
  1032.     *nnewp = nnew;
  1033.     *nreplp = nrepl;
  1034.     return n;
  1035.  
  1036. }
  1037.  
  1038.  
  1039. static int iterdpy (inputfilename, lineno, start,
  1040.             argc, argv, yfunc, nfunc, data)
  1041.     char *inputfilename;
  1042.     int lineno;
  1043.     int start;
  1044.     int argc;
  1045.     char *argv[];
  1046.     int (*yfunc)(), (*nfunc)();
  1047.     char *data;
  1048. {
  1049.     int i;
  1050.     int status;
  1051.     int errors = 0;
  1052.     Xauth proto;
  1053.     AuthList *l, *next;
  1054.  
  1055.     /*
  1056.      * iterate
  1057.      */
  1058.     for (i = start; i < argc; i++) {
  1059.     char *displayname = argv[i];
  1060.     proto.address = proto.number = NULL;
  1061.     if (!get_displayname_auth (displayname, &proto)) {
  1062.         prefix (inputfilename, lineno);
  1063.         baddisplayname (displayname, argv[0]);
  1064.         errors++;
  1065.         continue;
  1066.     }
  1067.     status = 0;
  1068.     for (l = xauth_head; l; l = next) {
  1069.         next = l->next;
  1070.         if (match_auth_dpy (&proto, l->auth)) {
  1071.         if (yfunc) {
  1072.             status = (*yfunc) (inputfilename, lineno,
  1073.                        l->auth, data);
  1074.             if (status < 0) break;
  1075.         }
  1076.         } else {
  1077.         if (nfunc) {
  1078.             status = (*nfunc) (inputfilename, lineno,
  1079.                        l->auth, data);
  1080.             if (status < 0) break;
  1081.         }
  1082.         }
  1083.     }
  1084.     if (proto.address) free (proto.address);
  1085.     if (proto.number) free (proto.number);
  1086.     if (status < 0) {
  1087.         errors -= status;        /* since status is negative */
  1088.         break;
  1089.     }
  1090.     }
  1091.  
  1092.     return errors;
  1093. }
  1094.  
  1095. /* ARGSUSED */
  1096. static int remove_entry (inputfilename, lineno, auth, data)
  1097.     char *inputfilename;
  1098.     int lineno;
  1099.     Xauth *auth;
  1100.     char *data;
  1101. {
  1102.     int *nremovedp = (int *) data;
  1103.     AuthList **listp = &xauth_head;
  1104.     AuthList *list;
  1105.  
  1106.     /*
  1107.      * unlink the auth we were asked to
  1108.      */
  1109.     while ((list = *listp)->auth != auth)
  1110.     listp = &list->next;
  1111.     *listp = list->next;
  1112.     XauDisposeAuth (list->auth);                    /* free the auth */
  1113.     free (list);                    /* free the link */
  1114.     xauth_modified = True;
  1115.     (*nremovedp)++;
  1116.     return 1;
  1117. }
  1118.  
  1119. /*
  1120.  * action routines
  1121.  */
  1122.  
  1123. /*
  1124.  * help
  1125.  */
  1126. int print_help (fp, cmd, prefix)
  1127.     FILE *fp;
  1128.     char *cmd;
  1129.     char *prefix;
  1130. {
  1131.     CommandTable *ct;
  1132.     int n = 0;
  1133.  
  1134.     if (!prefix) prefix = "";
  1135.  
  1136.     if (!cmd) {                /* if no cmd, print all help */
  1137.     for (ct = command_table; ct->name; ct++) {
  1138.         fprintf (fp, "%s%s\n", prefix, ct->helptext);
  1139.         n++;
  1140.     }
  1141.     } else {
  1142.     int len = strlen (cmd);
  1143.     for (ct = command_table; ct->name; ct++) {
  1144.         if (strncmp (cmd, ct->name, len) == 0) {
  1145.         fprintf (fp, "%s%s\n", prefix, ct->helptext);
  1146.         n++;
  1147.         }
  1148.     }
  1149.     }
  1150.     
  1151.     return n;
  1152. }
  1153.  
  1154. static int do_help (inputfilename, lineno, argc, argv)
  1155.     char *inputfilename;
  1156.     int lineno;
  1157.     int argc;
  1158.     char **argv;
  1159. {
  1160.     char *cmd = (argc > 1 ? argv[1] : NULL);
  1161.     int n;
  1162.  
  1163.     n = print_help (stdout, cmd, "    ");  /* a nice amount */
  1164.  
  1165.     if (n < 0 || (n == 0 && !cmd)) {
  1166.     prefix (inputfilename, lineno);
  1167.     fprintf (stderr, "internal error with help");
  1168.     if (cmd) {
  1169.         fprintf (stderr, " on command \"%s\"", cmd);
  1170.     }
  1171.     fprintf (stderr, "\n");
  1172.     return 1;
  1173.     }
  1174.  
  1175.     if (n == 0) {
  1176.     prefix (inputfilename, lineno);
  1177.     /* already know that cmd is set in this case */
  1178.     fprintf (stderr, "no help for noexistent command \"%s\"\n", cmd);
  1179.     }
  1180.  
  1181.     return 0;
  1182. }
  1183.  
  1184. /*
  1185.  * questionmark
  1186.  */
  1187. /* ARGSUSED */
  1188. static int do_questionmark (inputfilename, lineno, argc, argv)
  1189.     char *inputfilename;
  1190.     int lineno;
  1191.     int argc;
  1192.     char **argv;
  1193. {
  1194.     CommandTable *ct;
  1195.     int i;
  1196. #define WIDEST_COLUMN 72
  1197.     int col = WIDEST_COLUMN;
  1198.  
  1199.     printf ("Commands:\n");
  1200.     for (ct = command_table; ct->name; ct++) {
  1201.     if ((col + ct->maxlen) > WIDEST_COLUMN) {
  1202.         if (ct != command_table) {
  1203.         putc ('\n', stdout);
  1204.         }
  1205.         fputs ("        ", stdout);
  1206.         col = 8;            /* length of string above */
  1207.     }
  1208.     fputs (ct->name, stdout);
  1209.     col += ct->maxlen;
  1210.     for (i = ct->maxlen; i < COMMAND_NAMES_PADDED_WIDTH; i++) {
  1211.         putc (' ', stdout);
  1212.         col++;
  1213.     }
  1214.     }
  1215.     if (col != 0) {
  1216.     putc ('\n', stdout);
  1217.     }
  1218.  
  1219.     /* allow bad lines since this is help */
  1220.     return 0;
  1221. }
  1222.  
  1223. /*
  1224.  * list [displayname ...]
  1225.  */
  1226. static int do_list (inputfilename, lineno, argc, argv)
  1227.     char *inputfilename;
  1228.     int lineno;
  1229.     int argc;
  1230.     char **argv;
  1231. {
  1232.     struct _list_data ld;
  1233.  
  1234.     ld.fp = stdout;
  1235.     ld.numeric = (argv[0][0] == 'n');
  1236.  
  1237.     if (argc == 1) {
  1238.     register AuthList *l;
  1239.  
  1240.     if (xauth_head) {
  1241.         for (l = xauth_head; l; l = l->next) {
  1242.         dump_entry (inputfilename, lineno, l->auth, (char *) &ld);
  1243.         }
  1244.     }
  1245.     return 0;
  1246.     }
  1247.  
  1248.     return iterdpy (inputfilename, lineno, 1, argc, argv,
  1249.             dump_entry, NULL, (char *) &ld);
  1250. }
  1251.  
  1252. /*
  1253.  * merge filename [filename ...]
  1254.  */
  1255. static int do_merge (inputfilename, lineno, argc, argv)
  1256.     char *inputfilename;
  1257.     int lineno;
  1258.     int argc;
  1259.     char **argv;
  1260. {
  1261.     int i;
  1262.     int errors = 0;
  1263.     AuthList *head, *tail, *listhead, *listtail;
  1264.     int nentries, nnew, nrepl;
  1265.     Bool numeric = False;
  1266.  
  1267.     if (argc < 2) {
  1268.     prefix (inputfilename, lineno);
  1269.     badcommandline (argv[0]);
  1270.     return 1;
  1271.     }
  1272.  
  1273.     if (argv[0][0] == 'n') numeric = True;
  1274.     listhead = listtail = NULL;
  1275.  
  1276.     for (i = 1; i < argc; i++) {
  1277.     char *filename = argv[i];
  1278.     FILE *fp;
  1279.     Bool used_stdin = False;
  1280.  
  1281.     fp = open_file (&filename, "r", &used_stdin, inputfilename, lineno,
  1282.             argv[0]);
  1283.     if (!fp) {
  1284.         errors++;
  1285.         continue;
  1286.     }
  1287.  
  1288.     head = tail = NULL;
  1289.     nentries = read_auth_entries (fp, numeric, &head, &tail);
  1290.     if (nentries == 0) {
  1291.         prefix (inputfilename, lineno);
  1292.         fprintf (stderr, "unable to read any entries from file \"%s\"\n",
  1293.              filename);
  1294.         errors++;
  1295.     } else {            /* link it in */
  1296.         add_to_list (listhead, listtail, head);
  1297.      }
  1298.  
  1299.     if (!used_stdin) (void) fclose (fp);
  1300.     }
  1301.  
  1302.     /*
  1303.      * if we have new entries, merge them in (freeing any duplicates)
  1304.      */
  1305.     if (listhead) {
  1306.     nentries = merge_entries (&xauth_head, listhead, &nnew, &nrepl);
  1307.     if (verbose) 
  1308.       printf ("%d entries read in:  %d new, %d replacement%s\n", 
  1309.             nentries, nnew, nrepl, nrepl != 1 ? "s" : "");
  1310.     if (nentries > 0) xauth_modified = True;
  1311.     }
  1312.  
  1313.     return 0;
  1314. }
  1315.  
  1316. /*
  1317.  * extract filename displayname [displayname ...]
  1318.  */
  1319. static int do_extract (inputfilename, lineno, argc, argv)
  1320.     char *inputfilename;
  1321.     int lineno;
  1322.     int argc;
  1323.     char **argv;
  1324. {
  1325.     int errors;
  1326.     struct _extract_data ed;
  1327.  
  1328.     if (argc < 3) {
  1329.     prefix (inputfilename, lineno);
  1330.     badcommandline (argv[0]);
  1331.     return 1;
  1332.     }
  1333.  
  1334.     ed.fp = NULL;
  1335.     ed.filename = argv[1];
  1336.     ed.numeric = (argv[0][0] == 'n');
  1337.     ed.nwritten = 0;
  1338.     ed.cmd = argv[0];
  1339.  
  1340.     errors = iterdpy (inputfilename, lineno, 2, argc, argv, 
  1341.               extract_entry, NULL, (char *) &ed);
  1342.  
  1343.     if (!ed.fp) {
  1344.     fprintf (stderr, 
  1345.          "No matches found, authority file \"%s\" not written\n",
  1346.          ed.filename);
  1347.     } else {
  1348.     if (verbose) {
  1349.         printf ("%d entries written to \"%s\"\n", 
  1350.             ed.nwritten, ed.filename);
  1351.     }
  1352.     if (!ed.used_stdout) {
  1353.         (void) fclose (ed.fp);
  1354.     }
  1355.     }
  1356.  
  1357.     return errors;
  1358. }
  1359.  
  1360.  
  1361. /*
  1362.  * add displayname protocolname hexkey
  1363.  */
  1364. static int do_add (inputfilename, lineno, argc, argv)
  1365.     char *inputfilename;
  1366.     int lineno;
  1367.     int argc;
  1368.     char **argv;
  1369.     int n, nnew, nrepl;
  1370.     int len;
  1371.     char *dpyname;
  1372.     char *protoname;
  1373.     char *hexkey;
  1374.     char *key;
  1375.     Xauth *auth;
  1376.     AuthList *list;
  1377.  
  1378.     if (argc != 4 || !argv[1] || !argv[2] || !argv[3]) {
  1379.     prefix (inputfilename, lineno);
  1380.     badcommandline (argv[0]);
  1381.     return 1;
  1382.     }
  1383.  
  1384.     dpyname = argv[1];
  1385.     protoname = argv[2];
  1386.     hexkey = argv[3];
  1387.  
  1388.     len = strlen(hexkey);
  1389.     if (hexkey[0] == '"' && hexkey[len-1] == '"') {
  1390.     key = malloc(len-1);
  1391.     strncpy(key, hexkey+1, len-2);
  1392.     len -= 2;
  1393.     } else if (!strcmp(protoname, SECURERPC)) {
  1394.     key = malloc(len+1);
  1395.     strcpy(key, hexkey);
  1396.     } else {
  1397.     len = cvthexkey (hexkey, &key);
  1398.     if (len < 0) {
  1399.         prefix (inputfilename, lineno);
  1400.         fprintf (stderr,
  1401.              "key contains odd number of or non-hex characters\n");
  1402.         return 1;
  1403.     }
  1404.     }
  1405.  
  1406.     auth = (Xauth *) malloc (sizeof (Xauth));
  1407.     if (!auth) {
  1408.     prefix (inputfilename, lineno);
  1409.     fprintf (stderr, "unable to allocate %d bytes for Xauth structure\n",
  1410.          sizeof (Xauth));
  1411.     free (key);
  1412.     return 1;
  1413.     }
  1414.  
  1415.     if (!get_displayname_auth (dpyname, auth)) {
  1416.     prefix (inputfilename, lineno);
  1417.     baddisplayname (dpyname, argv[0]);
  1418.     free (auth);
  1419.     free (key);
  1420.     return 1;
  1421.     }
  1422.  
  1423.     /*
  1424.      * allow an abbreviation for common protocol names
  1425.      */
  1426.     if (strcmp (protoname, DEFAULT_PROTOCOL_ABBREV) == 0) {
  1427.     protoname = DEFAULT_PROTOCOL;
  1428.     }
  1429.  
  1430.     auth->name_length = strlen (protoname);
  1431.     auth->name = copystring (protoname, auth->name_length);
  1432.     if (!auth->name) {
  1433.     prefix (inputfilename, lineno);
  1434.     fprintf (stderr, "unable to allocate %d character protocol name\n",
  1435.          auth->name_length);
  1436.     free (auth);
  1437.     free (key);
  1438.     return 1;
  1439.     }
  1440.     auth->data_length = len;
  1441.     auth->data = key;
  1442.  
  1443.     list = (AuthList *) malloc (sizeof (AuthList));
  1444.     if (!list) {
  1445.     prefix (inputfilename, lineno);
  1446.     fprintf (stderr, "unable to allocate %d bytes for auth list\n",
  1447.          sizeof (AuthList));
  1448.     free (auth);
  1449.     free (key);
  1450.     free (auth->name);
  1451.     return 1;
  1452.     }
  1453.  
  1454.     list->next = NULL;
  1455.     list->auth = auth;
  1456.  
  1457.     /*
  1458.      * merge it in; note that merge will deal with allocation
  1459.      */
  1460.     n = merge_entries (&xauth_head, list, &nnew, &nrepl);
  1461.     if (n <= 0) {
  1462.     prefix (inputfilename, lineno);
  1463.     fprintf (stderr, "unable to merge in added record\n");
  1464.     return 1;
  1465.     }
  1466.  
  1467.     xauth_modified = True;
  1468.     return 0;
  1469. }
  1470.  
  1471. /*
  1472.  * remove displayname
  1473.  */
  1474. static int do_remove (inputfilename, lineno, argc, argv)
  1475.     char *inputfilename;
  1476.     int lineno;
  1477.     int argc;
  1478.     char **argv;
  1479. {
  1480.     int nremoved = 0;
  1481.     int errors;
  1482.  
  1483.     if (argc < 2) {
  1484.     prefix (inputfilename, lineno);
  1485.     badcommandline (argv[0]);
  1486.     return 1;
  1487.     }
  1488.  
  1489.     errors = iterdpy (inputfilename, lineno, 1, argc, argv,
  1490.               remove_entry, NULL, (char *) &nremoved);
  1491.     if (verbose) printf ("%d entries removed\n", nremoved);
  1492.     return errors;
  1493. }
  1494.  
  1495. /*
  1496.  * info
  1497.  */
  1498. static int do_info (inputfilename, lineno, argc, argv)
  1499.     char *inputfilename;
  1500.     int lineno;
  1501.     int argc;
  1502.     char **argv;
  1503. {
  1504.     int n;
  1505.     AuthList *l;
  1506.  
  1507.     if (argc != 1) {
  1508.     prefix (inputfilename, lineno);
  1509.     badcommandline (argv[0]);
  1510.     return 1;
  1511.     }
  1512.  
  1513.     for (l = xauth_head, n = 0; l; l = l->next, n++) ;
  1514.  
  1515.     printf ("Authority file:       %s\n",
  1516.         xauth_filename ? xauth_filename : "(none)");
  1517.     printf ("File new:             %s\n", xauth_existed ? No : Yes);
  1518.     printf ("File locked:          %s\n", ignore_locks ? No : Yes);
  1519.     printf ("Number of entries:    %d\n", n);
  1520.     printf ("Changes honored:      %s\n", xauth_allowed ? Yes : No);
  1521.     printf ("Changes made:         %s\n", xauth_modified ? Yes : No);
  1522.     printf ("Current input:        %s:%d\n", inputfilename, lineno);
  1523.     return 0;
  1524. }
  1525.  
  1526.  
  1527. /*
  1528.  * exit
  1529.  */
  1530. static Bool alldone = False;
  1531.  
  1532. /* ARGSUSED */
  1533. static int do_exit (inputfilename, lineno, argc, argv)
  1534.     char *inputfilename;
  1535.     int lineno;
  1536.     int argc;
  1537.     char **argv;
  1538. {
  1539.     /* allow bogus stuff */
  1540.     alldone = True;
  1541.     return 0;
  1542. }
  1543.  
  1544. /*
  1545.  * quit
  1546.  */
  1547. /* ARGSUSED */
  1548. static int do_quit (inputfilename, lineno, argc, argv)
  1549.     char *inputfilename;
  1550.     int lineno;
  1551.     int argc;
  1552.     char **argv;
  1553. {
  1554.     /* allow bogus stuff */
  1555.     die (0);
  1556.     /* NOTREACHED */
  1557.     return -1;                /* for picky compilers */
  1558. }
  1559.  
  1560.  
  1561. /*
  1562.  * source filename
  1563.  */
  1564. static int do_source (inputfilename, lineno, argc, argv)
  1565.     char *inputfilename;
  1566.     int lineno;
  1567.     int argc;
  1568.     char **argv;
  1569. {
  1570.     char *script;
  1571.     char buf[BUFSIZ];
  1572.     FILE *fp;
  1573.     Bool used_stdin = False;
  1574.     int len;
  1575.     int errors = 0, status;
  1576.     int sublineno = 0;
  1577.     char **subargv;
  1578.     int subargc;
  1579.     Bool prompt = False;        /* only true if reading from tty */
  1580.  
  1581.     if (argc != 2 || !argv[1]) {
  1582.     prefix (inputfilename, lineno);
  1583.     badcommandline (argv[0]);
  1584.     return 1;
  1585.     }
  1586.  
  1587.     script = argv[1];
  1588.  
  1589.     fp = open_file (&script, "r", &used_stdin, inputfilename, lineno, argv[0]);
  1590.     if (!fp) {
  1591.     return 1;
  1592.     }
  1593.  
  1594.     if (verbose && used_stdin && isatty (fileno (fp))) prompt = True;
  1595.  
  1596.     while (!alldone) {
  1597.     buf[0] = '\0';
  1598.     if (prompt) {
  1599.         printf ("xauth> ");
  1600.         fflush (stdout);
  1601.     }
  1602.     if (fgets (buf, sizeof buf, fp) == NULL) break;
  1603.     sublineno++;
  1604.     len = strlen (buf);
  1605.     if (len == 0 || buf[0] == '#') continue;
  1606.     if (buf[len-1] != '\n') {
  1607.         prefix (script, sublineno);
  1608.         fprintf (stderr, "line too long\n");
  1609.         errors++;
  1610.         break;
  1611.     }
  1612.     buf[--len] = '\0';        /* remove new line */
  1613.     subargv = split_into_words (buf, &subargc);
  1614.     if (subargv) {
  1615.         status = process_command (script, sublineno, subargc, subargv);
  1616.         free ((char *) subargv);
  1617.         errors += status;
  1618.     } else {
  1619.         prefix (script, sublineno);
  1620.         fprintf (stderr, "unable to break line into words\n");
  1621.         errors++;
  1622.     }
  1623.     }
  1624.  
  1625.     if (!used_stdin) {
  1626.     (void) fclose (fp);
  1627.     }
  1628.     return errors;
  1629. }
  1630.