2
0

process.c 35 KB

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