home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume21 / amd / part07 / get_args.c < prev    next >
C/C++ Source or Header  |  1990-04-10  |  10KB  |  515 lines

  1. /*
  2.  * $Id: get_args.c,v 5.1.1.2 90/01/11 17:06:42 jsp Exp Locker: jsp $
  3.  *
  4.  * Copyright (c) 1990 Jan-Simon Pendry
  5.  * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
  6.  * Copyright (c) 1990 The Regents of the University of California.
  7.  * All rights reserved.
  8.  *
  9.  * This code is derived from software contributed to Berkeley by
  10.  * Jan-Simon Pendry at Imperial College, London.
  11.  *
  12.  * Redistribution and use in source and binary forms are permitted
  13.  * provided that the above copyright notice and this paragraph are
  14.  * duplicated in all such forms and that any documentation,
  15.  * advertising materials, and other materials related to such
  16.  * distribution and use acknowledge that the software was developed
  17.  * by Imperial College of Science, Technology and Medicine, London, UK.
  18.  * The names of the College and University may not be used to endorse
  19.  * or promote products derived from this software without specific
  20.  * prior written permission.
  21.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  22.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  23.  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  24.  *
  25.  *    %W% (Berkeley) %G%
  26.  */
  27.  
  28. /*
  29.  * Argument decode
  30.  */
  31.  
  32. #include "am.h"
  33. #ifdef HAS_SYSLOG
  34. #include <syslog.h>
  35. #endif
  36. #include <sys/stat.h>
  37.  
  38. extern int optind;
  39. extern char *optarg;
  40.  
  41. #if defined(DEBUG) && defined(PARANOID)
  42. char **gargv;
  43. #endif
  44. int restart_existing_mounts;
  45. int print_pid;
  46. int normalize_hosts;
  47. char *karch;            /* Kernel architecture */
  48. char *cluster;            /* Cluster name */
  49. #ifdef HAS_YP_MAPS
  50. char *domain;            /* YP domain */
  51. #endif
  52. #ifdef UPDATE_MTAB
  53. char *mtab;
  54. #endif
  55. FILE *logfp = stderr;        /* Log errors to stderr initially */
  56. #ifdef HAS_SYSLOG
  57. int syslogging;
  58. #endif
  59. int afs_timeo = -1;
  60. int afs_retrans = -1;
  61. int am_timeo = AM_TTL;
  62. int am_timeo_w = AM_TTL_W;
  63. int xlog_level = 0;
  64. int xlog_level_init = ~0;
  65.  
  66. struct opt_tab {
  67.     char *opt;
  68.     int flag;
  69. };
  70.  
  71. /*
  72.  * List of log options
  73.  */
  74. static struct opt_tab xlog_opt[] = {
  75.     { "all", XLOG_ALL },        /* All messages */
  76. #ifdef DEBUG
  77.     { "debug", XLOG_DEBUG },    /* Debug messages */
  78. #endif
  79.     { "error", XLOG_ERROR },    /* Non-fatal system errors */
  80.     { "fatal", XLOG_FATAL },    /* Fatal errors */
  81.     { "info", XLOG_INFO },        /* Information */
  82.     { "map", XLOG_MAP },        /* Map errors */
  83.     { "stats", XLOG_STATS },    /* Additional statistical information */
  84.     { "user", XLOG_USER },        /* Non-fatal user errors */
  85.     { "warn", XLOG_WARNING },    /* Warnings */
  86.     { "warning", XLOG_WARNING },    /* Warnings */
  87.     { 0, 0 }
  88. };
  89.  
  90. #ifdef DEBUG
  91. /*
  92.  * List of debug options.
  93.  */
  94. static struct opt_tab dbg_opt[] = {
  95.     { "all", D_ALL },        /* All */
  96.     { "amq", D_AMQ },        /* Register for AMQ program */
  97.     { "daemon", D_DAEMON },        /* Enter daemon mode */
  98.     { "full", D_FULL },        /* Program trace */
  99.     { "mem", D_MEM },        /* Trace memory allocations */
  100.     { "mtab", D_MTAB },        /* Use local mtab file */
  101.     { "str", D_STR },        /* Debug string munging */
  102.     { "test", D_TEST },        /* Full debug - but no daemon */
  103.     { "trace", D_TRACE },        /* Protocol trace */
  104.     { 0, 0 }
  105. };
  106.  
  107. int debug_flags = D_AMQ            /* Register AMQ */
  108.          |D_DAEMON        /* Enter daemon mode */
  109.          ;
  110. #endif
  111.  
  112. static void show_opts(ch, opts)
  113. int ch;
  114. struct opt_tab *opts;
  115. {
  116.     /*
  117.      * Display current debug options
  118.      */
  119.     int i;
  120.     int s = '{';
  121.     fprintf(stderr, "\t[-%c {no}", ch);
  122.     for (i = 0; opts[i].opt; i++) {
  123.         fprintf(stderr, "%c%s", s, opts[i].opt);
  124.         s = ',';
  125.     }
  126.     fputs("}]\n", stderr);
  127. }
  128.  
  129. static int option(s, optb, flags)
  130. char *s;
  131. struct opt_tab *optb;
  132. int *flags;
  133. {
  134.     char *p = s;
  135.     int errs = 0;
  136.  
  137.     while (p && *p) {
  138.         int neg;
  139.         char *opt;
  140.         struct opt_tab *dp;
  141.  
  142.         s = p;
  143.         p = strchr(p, ',');
  144.         if (p)
  145.             *p = '\0';
  146.  
  147.         if (s[0] == 'n' && s[1] == 'o') {
  148.             opt = s + 2;
  149.             neg = 1;
  150.         } else {
  151.             opt = s;
  152.             neg = 0;
  153.         }
  154.  
  155.         /*
  156.          * Scan the array of debug options to find the
  157.          * corresponding flag value.  If it is found
  158.          * then set (or clear) the flag (depending on
  159.          * whether the option was prefixed with "no").
  160.          */
  161.         for (dp = optb; dp->opt; dp++) {
  162.             if (strcmp(opt, dp->opt) == 0) {
  163.                 if (neg)
  164.                     *flags &= ~dp->flag;
  165.                 else
  166.                     *flags |= dp->flag;
  167.                 break;
  168.             }
  169.         }
  170.  
  171.         if (dp->opt == 0) {
  172.             /*
  173.              * This will log to stderr when parsing the command line
  174.              * since any -l option will not yet have taken effect.
  175.              */
  176.             plog(XLOG_USER, "option \"%s\" not recognised", s);
  177.             errs++;
  178.         }
  179.         /*
  180.          * Put the comma back
  181.          */
  182.         if (p)
  183.             *p++ = ',';
  184.     }
  185.  
  186.     return errs;
  187. }
  188.  
  189. /*
  190.  * Switch on/off logging options
  191.  */
  192. int switch_option(opt)
  193. char *opt;
  194. {
  195.     int xl = xlog_level;
  196.     int rc = option(opt, xlog_opt, &xl);
  197.     if (rc) {
  198.         rc = EINVAL;
  199.     } else {
  200.         /*
  201.          * Keep track of initial log level, and
  202.          * don't allow options to be turned off.
  203.          */
  204.         if (xlog_level_init == ~0)
  205.             xlog_level_init = xl;
  206.         else
  207.             xl |= xlog_level_init;
  208.         xlog_level = xl;
  209.     }
  210.     return rc;
  211. }
  212.  
  213. #ifdef DEBUG
  214. /*
  215.  * Switch on/off debug options
  216.  */
  217. int debug_option(opt)
  218. char *opt;
  219. {
  220.     return option(opt, dbg_opt, &debug_flags);
  221. }
  222. #endif
  223.  
  224. /*
  225.  * Change current logfile
  226.  */
  227. int switch_to_logfile(logfile)
  228. char *logfile;
  229. {
  230.     FILE *new_logfp = stderr;
  231.  
  232.     if (logfile) {
  233. #ifdef HAS_SYSLOG
  234.         syslogging = 0;
  235. #endif
  236.         if (strcmp(logfile, "/dev/stderr") == 0)
  237.             new_logfp = stderr;
  238.         else if (strcmp(logfile, "syslog") == 0) {
  239. #ifdef HAS_SYSLOG
  240.             syslogging = 1;
  241.             new_logfp = stderr;
  242. #ifdef LOG_CONS
  243.             openlog(progname, LOG_PID|LOG_CONS|LOG_NOWAIT,
  244.                 LOG_DAEMON);
  245. #else
  246.             /* 4.2 compat mode - XXX */
  247.             openlog(progname, LOG_PID);
  248. #endif
  249. #else
  250.             plog(XLOG_WARNING, "syslog option not supported, logging unchanged");
  251. #endif
  252.         } else {
  253.             (void) umask(orig_umask);
  254.             new_logfp = fopen(logfile, "a");
  255.             umask(0);
  256.         }
  257.     }
  258.  
  259.     /*
  260.      * If we couldn't open a new file, then continue using the old.
  261.      */
  262.     if (!new_logfp && logfile) {
  263.         plog(XLOG_USER, "%s: Can't open logfile: %m", logfile);
  264.         return 1;
  265.     }
  266.     /*
  267.      * Close the previous file
  268.      */
  269.     if (logfp && logfp != stderr)
  270.         (void) fclose(logfp);
  271.     logfp = new_logfp;
  272.     return 0;
  273. }
  274.  
  275. void get_args(c, v)
  276. int c;
  277. char *v[];
  278. {
  279.     int opt_ch;
  280.     int usage = 0;
  281.     char *logfile = 0;
  282.     char *sub_domain = 0;
  283.  
  284. #if defined(DEBUG) && defined(PARANOID)
  285.     gargv = v;
  286.     progname = v[0];        /* Use argv[0] to try to solve Piete's problem */
  287. #else
  288.     if (v[0]) {
  289.         progname = strrchr(v[0], '/');
  290.         if (progname && progname[1])
  291.             progname++;
  292.         else
  293.             progname = v[0];
  294.     }
  295. #endif
  296.     if (!progname)
  297.         progname = "amd";
  298.  
  299.     while ((opt_ch = getopt(c, v, "mnprva:c:d:k:l:t:w:x:y:D:")) != EOF)
  300.     switch (opt_ch) {
  301.     case 'a':
  302.         if (*optarg != '/') {
  303.             fprintf(stderr, "%s: -a option must begin with a '/'\n",
  304.                     progname);
  305.             exit(1);
  306.         }
  307.         auto_dir = optarg;
  308.         break;
  309.  
  310.     case 'c':
  311.         am_timeo = atoi(optarg);
  312.         if (am_timeo <= 0)
  313.             am_timeo = AM_TTL;
  314.         break;
  315.  
  316.     case 'd':
  317.         sub_domain = optarg;
  318.         break;
  319.  
  320.     case 'k':
  321.         karch = optarg;
  322.         break;
  323.  
  324.     case 'l':
  325.         logfile = optarg;
  326.         break;
  327.  
  328.     case 'm':
  329.         plog(XLOG_USER, "The -m option is no longer supported.");
  330.         plog(XLOG_USER, "... Use `ypcat -k am.master` on the command line instead");
  331.         break;
  332.  
  333.     case 'n':
  334.         normalize_hosts = 1;
  335.         break;
  336.  
  337.     case 'p':
  338.         print_pid = 1;
  339.         break;
  340.  
  341.     case 'r':
  342.         restart_existing_mounts = 1;
  343.         break;
  344.  
  345.     case 't':
  346.         /* timeo.retrans */
  347.         { char *dot = strchr(optarg, '.');
  348.           if (dot) *dot = '\0';
  349.           if (*optarg) {
  350.             afs_timeo = atoi(optarg);
  351.           }
  352.           if (dot) {
  353.               afs_retrans = atoi(dot+1);
  354.             *dot = '.';
  355.           }
  356.         }
  357.         break;
  358.  
  359.     case 'v':
  360.         { char buf[256];
  361.           show_rcs_info(version, buf);
  362.           fputs(buf, stderr);
  363.         }
  364.         fprintf(stderr,
  365.             " for a%s %s running %s (%s-endian)\n",
  366.                     strchr("aeiou", arch[0]) ? "n" : "",
  367.                     arch, op_sys, endian);
  368.         fputs("Map support for: ", stderr);
  369.         mapc_showtypes(stderr);
  370.         fputs(".\n", stderr);
  371.         exit(0);
  372.         break;
  373.  
  374.     case 'w':
  375.         am_timeo_w = atoi(optarg);
  376.         if (am_timeo_w <= 0)
  377.             am_timeo_w = AM_TTL_W;
  378.         break;
  379.  
  380.     case 'x':
  381.         usage += switch_option(optarg);
  382.         break;
  383.  
  384.     case 'y':
  385. #ifdef HAS_YP_MAPS
  386.         domain = optarg;
  387. #else
  388.         plog(XLOG_USER, "-y: option ignored.  No YP support available.");
  389. #endif
  390.         break;
  391.  
  392.     case 'C':
  393.         cluster = optarg;
  394.         break;
  395.  
  396.     case 'D':
  397. #ifdef DEBUG
  398.         usage += debug_option(optarg);
  399. #else
  400.         fprintf(stderr, "%s: not compiled with DEBUG option -- sorry.\n", progname);
  401. #endif
  402.         break;
  403.  
  404.     default:
  405.         usage = 1;
  406.         break;
  407.     }
  408.  
  409.     if (xlog_level == 0) {
  410.         /* Take copy to avoid writable-strings problem */
  411.         char *dfstr = strdup(XLOG_DEFSTR);
  412.         usage += switch_option(dfstr);
  413.         free((voidp) dfstr);
  414. #ifdef DEBUG
  415.         usage += switch_option("debug");
  416. #endif
  417.     } else {
  418. #ifdef DEBUG
  419.         usage += switch_option("debug");
  420. #endif
  421.     }
  422.  
  423.     if (usage)
  424.         goto show_usage;
  425.  
  426.     while (optind <= c-2) {
  427.         char *dir = v[optind++];
  428.         char *map = v[optind++];
  429.         char *opts = "";
  430.         if (v[optind] && *v[optind] == '-')
  431.             opts = &v[optind++][1];
  432.  
  433.         root_newmap(dir, opts, map);
  434.     }
  435.  
  436.     if (optind == c) {
  437. #ifdef hpux
  438.         /*
  439.          * HP-UX can't handle ./mtab
  440.          * That system is sick - really.
  441.          */
  442. #ifdef    DEBUG
  443.         debug_option("nomtab");
  444. #endif    /* DEBUG */
  445. #endif    /* hpux */
  446.  
  447.         /*
  448.          * Append domain name to hostname.
  449.          * sub_domain overrides hostdomain
  450.          * if given.
  451.          */
  452.         if (sub_domain)
  453.             hostdomain = sub_domain;
  454.         if (*hostdomain == '.')
  455.             hostdomain++;
  456.         strcat(hostd,  ".");
  457.         strcat(hostd, hostdomain);
  458.  
  459. #ifdef UPDATE_MTAB
  460. #ifdef DEBUG
  461.         if (debug_flags & D_MTAB)
  462.             mtab = DEBUG_MTAB;
  463.         else
  464. #endif /* DEBUG */
  465.         mtab = MOUNTED;
  466. #else
  467. #ifdef DEBUG
  468.         { if (debug_flags & D_MTAB) {
  469.             dlog("-D mtab option ignored");
  470.         } }
  471. #endif /* DEBUG */
  472. #endif /* UPDATE_MTAB */
  473.  
  474.         if (switch_to_logfile(logfile) != 0)
  475.             plog(XLOG_USER, "Cannot switch logfile");
  476.  
  477.         /*
  478.          * If the kernel architecture was not specified
  479.          * then use the machine architecture.
  480.          */
  481.         if (karch == 0)
  482.             karch = arch;
  483.  
  484.         if (cluster == 0)
  485.             cluster = hostdomain;
  486.  
  487.         if (afs_timeo <= 0)
  488.             afs_timeo = AFS_TIMEO;
  489.         if (afs_retrans <= 0)
  490.             afs_retrans = AFS_RETRANS;
  491.         if (afs_retrans <= 0)
  492.             afs_retrans = 3;    /* XXX */
  493.         return;
  494.     }
  495.  
  496. show_usage:
  497.     fprintf(stderr,
  498. "Usage: %s [-mnprv] [-a mnt_point] [-c cache_time] [-d domain]\n\
  499. \t[-k kernel_arch] [-l logfile|\"syslog\"] [-t afs_timeout]\n\
  500. \t[-w wait_timeout] [-C cluster_name]", progname);
  501.  
  502. #ifdef HAS_YP_MAPS
  503.     fputs(" [-y yp-domain]\n", stderr);
  504. #else
  505.     fputc('\n', stderr);
  506. #endif
  507.  
  508.     show_opts('x', xlog_opt);
  509. #ifdef DEBUG
  510.     show_opts('D', dbg_opt);
  511. #endif
  512.     fprintf(stderr, "\t{directory mapname [-map_options]} ...\n");
  513.     exit(1);
  514. }
  515.