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