X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=ndmp-src%2Fndmjob_args.c;fp=ndmp-src%2Fndmjob_args.c;h=dc0e473a253ef53f975bd39c64549c3efd1a2974;hb=fd48f3e498442f0cbff5f3606c7c403d0566150e;hp=0000000000000000000000000000000000000000;hpb=96f35b20267e8b1a1c846d476f27fcd330e0b018;p=debian%2Famanda diff --git a/ndmp-src/ndmjob_args.c b/ndmp-src/ndmjob_args.c new file mode 100644 index 0000000..dc0e473 --- /dev/null +++ b/ndmp-src/ndmjob_args.c @@ -0,0 +1,972 @@ +/* + * Copyright (c) 1998,1999,2000 + * Traakan, Inc., Los Altos, CA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice unmodified, this list of conditions, and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Project: NDMJOB + * Ident: $Id: $ + * + * Description: + * + */ + + +#include "ndmjob.h" + + +char *help_text[] = { + "ndmjob -v -- print version and configuration info", + "ndmjob OPTIONS ... FILES ...", + " FILES can be FILEPATH or NEWFILEPATH=OLDFILEPATH with", + " '=' quoted by backslash.", + "Modes (exactly one required)", +#ifndef NDMOS_OPTION_NO_CONTROL_AGENT + " -c -- create a backup", + " -t -- list contents on a backup", + " -x -- extract from a backup", + " -l -- list media labels", + " -q -- query agent(s)", + " -Z -- clean up zee mess (put robot right)", + " -o init-labels -- init media labels", +#endif /* !NDMOS_OPTION_NO_CONTROL_AGENT */ +#ifndef NDMOS_EFFECT_NO_SERVER_AGENTS + " -o daemon -- launch session for incomming connections", + " -o test-daemon -- launch session for incomming connections, exit when stdin is closed", + " -o tape-size=SIZE -- specify the length, in bytes of the simulated tape", +#endif /* !NDMOS_EFFECT_NO_SERVER_AGENTS */ +#ifndef NDMOS_OPTION_NO_CONTROL_AGENT + " -o rewind -- rewind tape in drive, need -T and -f", + " -o eject -- eject tape in drive, need -T and -f", + " -o move -- cmd ROBOT to move tape, need -o from/to-addr", + " -o import=ELEMADDR -- cmd ROBOT to import tape from door to slot", + " -o export=ELEMADDR -- cmd ROBOT to export tape from slot to door", + " -o load=ELEMADDR -- cmd ROBOT to load tape from slot to drive", + " -o unload[=ELEMADDR]-- cmd ROBOT to unload tape, sometimes auto", + " -o init-elem-status -- cmd ROBOT to rescan tape slots", + " -o test-tape -- test TAPE agent NDMP_TAPE functions", + " -o test-mover -- test TAPE agent NDMP_MOVER functions", + " -o test-data -- test DATA agent NDMP_DATA functions", + " -o time-limit=N", + " -- check for reply within specified seconds (default 360)", + " -o swap-connect -- perform DATA LISTEN & MOVER CONNECT", +#if 0 + " -p -- pass DATA->DATA (ndmpcopy)", + " -P -- pass TAPE->TAPE", + " -o c-partial -- partial backup", + " -o c-full -- full backup", + " -o x-restore -- extract restoring", +#endif +#endif /* !NDMOS_OPTION_NO_CONTROL_AGENT */ + "General and Logging parameters", + " --MACRO -- expand MACRO from ndmjob-args file", + " -d N -- set debug level to N (default 0, max 9)", + " -L FILE -- set log file (default stderr, includes debug)", + " -n -- no-op, just show how args were handled", + " -v -- verbose, same messages as -d1 to standard out", + " -S -- Perform DATA listen and MOVER CONNECT", + " -p PORT -- NDMP port to listen on (for -o daemon)", + " -o no-time-stamps -- log w/o time stamps, makes diff(1)s easier", + " -o config-file=PATH", + " -- set config file ($NDMJOB_CONFIG, /usr/local/etc/ndmjob.conf)", +#ifndef NDMOS_OPTION_NO_CONTROL_AGENT + "CONTROL of DATA agent parameters", + " -D AGENT -- data agent (see AGENT below)", + " -B TYPE -- set backup format (default tar)", + " -C DIR -- change directory on data agent before operation", + " -e PATN -- exclude files matching pattern", + " -E NAME=VAL -- add to data agent environment", + " -F FILE -- add FILE arg (used to not confuse arg processing)", + " -o load-files=PATHNAME", + " -- load FILES from the specified PATHANME", + " -o import=ELEMADDR -- cmd ROBOT to import tape from door to slot", + + " -I FILE -- set output index file, enable FILEHIST (default to log)", + " -J FILE -- set input index file (default none)", + " -U USER -- user rights to use on data agent", + " -o rules=RULES -- apply RULES to job (see RULES below)", + "CONTROL of TAPE agent parameters", + " -T AGENT -- tape agent if different than -D (see AGENT below)", + " -b N -- block size in 512-byte records (default 20)", + " -f TAPE -- tape drive device name", + " -o tape-timeout=SECONDS", + " -- how long to retry opening drive (await tape)", + " -o use-eject=N", + " -- use eject when unloading tapes (default 0)", + " -o tape-tcp=hostname:port -- send the data directly to that tcp port.", + "CONTROL of ROBOT agent parameters", + " -R AGENT -- robot agent if different than -T (see AGENT below)", + " -m MEDIA -- add entry to media table (see below)", + " -o tape-addr=ELEMADDR", + " -- robot element address of drive (default first)", + " -o tape-scsi=SCSI", + " -- tape drive SCSI target (see below)", + " -o robot-timeout=SECONDS", + " -- how long to retry moving tapes (await robot)", + " -r SCSI -- tape robot target (see below)", + "", + "Definitions:", + " AGENT HOST[:PORT][/FLAGS][,USERNAME,PASSWORD]", + " FLAGS [234][ntm] 2->v2 3->v3 4->v4 n->AUTH_NONE t->TEXT m->MD5", + " AGENT . (resident)", + " SCSI DEVICE[,[CNUM,]SID[,LUN]]", + " MEDIA [TAPE-LABEL][+SKIP-FILEMARKS][@ELEMADDR][/WINDOW-SIZE]", + "", + "RULES:", +#endif /* !NDMOS_OPTION_NO_CONTROL_AGENT */ + 0 +}; + + +int +process_args (int argc, char *argv[]) +{ + int c; + char options[100]; + char ** pp; + char * p; + char * op; + char * av[1000]; + int ac = 0; + + progname = argv[0]; + + if (argc == 2 && strcmp (argv[1], "-help") == 0) { + help(); + exit(0); + } + + if (argc == 2 && strcmp (argv[1], "-v") == 0) { + ndmjob_version_info (); + exit(0); + } + + if (argc < 2) + usage(); + + o_config_file = g_strdup_printf("%s/ndmjob.conf", amdatadir); + if ((p = getenv ("NDMJOB_CONF")) != 0) { + o_config_file = p; + } + + op = options; + for (pp = help_text; *pp; pp++) { + p = *pp; + + if (strncmp (p, " -", 3) != 0) + continue; + if (p[3] == 'o') + continue; /* don't include o: repeatedly */ + *op++ = p[3]; + if (p[5] != ' ') + *op++ = ':'; + } + *op++ = 'o'; /* include o: once */ + *op++ = ':'; + *op = 0; + + ac = copy_args_expanding_macros (argc, argv, + av, sizeof(av)/sizeof(av[0])); + + while ((c = getopt (ac, av, options)) != EOF) { + switch (c) { + case 'o': + handle_long_option (optarg); + break; + +#ifndef NDMOS_OPTION_NO_CONTROL_AGENT + case 'c': /* -c -- create a backup */ + set_job_mode (NDM_JOB_OP_BACKUP); + break; + + case 't': /* -t -- list contents on a backup */ + set_job_mode (NDM_JOB_OP_TOC); + break; + + case 'x': /* -x -- extract from a backup */ + set_job_mode (NDM_JOB_OP_EXTRACT); + break; + + case 'l': /* -l -- list media labels */ + set_job_mode (NDM_JOB_OP_LIST_LABELS); + break; + + case 'q': /* -q -- query agent(s) */ + set_job_mode (NDM_JOB_OP_QUERY_AGENTS); + break; + + case 'Z': /* -Z -- clean up zee mess */ + set_job_mode (NDM_JOB_OP_REMEDY_ROBOT); + break; + + case 'B': /* -B TYPE -- set backup format (default tar) */ + if (B_bu_type) { + error_byebye ("more than one of -B"); + } + B_bu_type = optarg; + break; + + case 'b': /* -b N -- block size in 512-byte records (20) */ + { + long b = strtol(optarg, NULL, 10); + if (b < 1 || b > 200 || (!b && EINVAL == errno)) { + error_byebye ("bad -b option"); + } + b_bsize = (int) b; + break; + } + + case 'p': /* -p N -- port number for daemon mode (10000) */ + { + long p = strtol(optarg, NULL, 10); + if (p < 1 || p > 65535 || (!p && EINVAL == errno)) { + error_byebye ("bad -p option"); + } + p_ndmp_port = (int) p; + break; + } + + case 'C': /* -C DIR -- change directory on data agent */ +#if 0 + /* allow second to override first. make recover easier */ + if (C_chdir) { + error_byebye ("more than one of -C"); + } +#endif + C_chdir = optarg; + break; + + case 'D': /* -D AGENT -- data agent (see below) */ + if (AGENT_GIVEN(D_data_agent)) { + error_byebye ("more than one of -D"); + } + if (ndmagent_from_str (&D_data_agent, optarg)) { + error_byebye ("bad -D argument"); + } + break; +#endif /* !NDMOS_OPTION_NO_CONTROL_AGENT */ + + case 'd': /* -d N -- set debug level to N */ + d_debug = atoi(optarg); + break; + +#ifndef NDMOS_OPTION_NO_CONTROL_AGENT + case 'E': /* -E NAME=VAL -- add to data agent environment */ + if (n_E_environment >= NDM_MAX_ENV) { + error_byebye ("too many of -E"); + } + { + char * p; + + p = optarg; + E_environment[n_E_environment].name = p; + while (*p && *p != '=') p++; + if (*p != '=') { + error_byebye ("missing value in -E"); + } + *p++ = 0; + E_environment[n_E_environment].value = p; + n_E_environment++; + } + break; + + case 'e': /* -e PATN -- exclude files matching pattern */ + if (n_e_exclude_pattern >= MAX_EXCLUDE_PATTERN) { + error_byebye ("too many of -e"); + } + e_exclude_pattern[n_e_exclude_pattern++] = optarg; + break; + + case 'F': /* -F FILE -- add to list of files */ + if (n_file_arg >= MAX_FILE_ARG) { + error_byebye ("too many FILE args"); + } + if (strchr(optarg, '=')) { + char *p = strchr(optarg, '='); + *p++ = 0; + file_arg[n_file_arg] = p; + file_arg_new[n_file_arg] = optarg; + n_file_arg++; + } else { + file_arg[n_file_arg] = optarg; + file_arg_new[n_file_arg] = 0; + n_file_arg++; + } + + break; + + case 'f': /* -f TAPE -- tape drive device name */ + if (f_tape_device) { + error_byebye ("more than one of -f"); + } + f_tape_device = optarg; + break; + + case 'I': /* -I FILE -- output index, enab FILEHIST */ + if (I_index_file) { + error_byebye ("more than one of -I"); + } + I_index_file = optarg; + break; + + case 'J': /* -J FILE -- input index */ + if (J_index_file) { + error_byebye ("more than one of -J"); + } + J_index_file = optarg; + break; + + case 'L': /* -L FILE -- set log file (def stderr, incl. dbg) */ + if (L_log_file) { + error_byebye ("more than one of -L"); + } + L_log_file = optarg; + if (d_debug < 2) d_debug = 2; + break; + + case 'm': /* -m MEDIA -- add entry to media table (see below) */ + if (n_m_media >= NDM_MAX_MEDIA) { + error_byebye ("too many of -m"); + } + if (ndmmedia_from_str (&m_media[n_m_media], optarg)) { + error_byebye ("bad -m argument: %s", optarg); + } + n_m_media++; + break; +#endif /* !NDMOS_OPTION_NO_CONTROL_AGENT */ + + case 'n': /* -n -- no-op, show how args were handled */ + n_noop++; + break; + +#ifndef NDMOS_OPTION_NO_CONTROL_AGENT + case 'R': /* -R AGENT -- robot agent if different than -T */ + if (AGENT_GIVEN(R_robot_agent)) { + error_byebye ("more than one of -R"); + } + if (ndmagent_from_str (&R_robot_agent, optarg)) { + error_byebye ("bad -R argument"); + } + break; + + case 'r': /* -r SCSI -- tape robot target (see below) */ + if (ROBOT_GIVEN()) { + error_byebye ("more than one of -r"); + } + if (ndmscsi_target_from_str (&r_robot_target, optarg)) { + error_byebye ("bad -r argument"); + } + break; + + case 'T': /* -T AGENT -- tape agent if different than -D */ + if (AGENT_GIVEN(T_tape_agent)) { + error_byebye ("more than one of -T"); + } + if (ndmagent_from_str (&T_tape_agent, optarg)) { + error_byebye ("bad -T argument"); + } + break; + + case 'U': /* -U USER -- user rights to use on data agent */ + if (U_user) { + error_byebye ("more than one of -U"); + } + U_user = optarg; + break; +#endif /* !NDMOS_OPTION_NO_CONTROL_AGENT */ + + case 'v': /* -v -- verbose */ + v_verbose++; + break; + + default: + usage(); + break; + } + } + + if (n_noop && d_debug > 1) { + int i; + + for (i = 0; i < ac; i++) { + printf (" av[%d] = '%s'\n", i, av[i]); + } + } + + if (!the_mode) { +#ifndef NDMOS_OPTION_NO_CONTROL_AGENT + printf ("must specify one of -[ctxlqZ] or other mode\n"); +#else /* !NDMOS_OPTION_NO_CONTROL_AGENT */ + printf ("must specify -o daemon\n"); +#endif /* !NDMOS_OPTION_NO_CONTROL_AGENT */ + usage(); + } + +#ifndef NDMOS_OPTION_NO_CONTROL_AGENT + for (c = optind; c < ac; c++) { + if (n_file_arg >= MAX_FILE_ARG) { + error_byebye ("too many file args"); + } + if (strchr(av[c], '=')) { + char *p = strchr(av[c], '='); + *p++ = 0; + file_arg[n_file_arg] = p; + file_arg_new[n_file_arg] = av[c]; + } else { + file_arg[n_file_arg] = av[c]; + file_arg_new[n_file_arg] = 0; + } + n_file_arg++; + } + + if (o_load_files_file) { + char buf[2048]; + FILE *fp; + static struct load_file_entry { + struct load_file_entry *next; + char name[1]; + } *load_files_list = 0; + + /* clean up old load_files_list */ + while (load_files_list) { + struct load_file_entry *p; + p = load_files_list; + load_files_list = p->next; + p->next = 0; + free(p); + } + + fp = fopen(o_load_files_file, "r"); + if (!fp) { + perror (o_load_files_file); + error_byebye ("can't open load_files file %s", + o_load_files_file); + /* no return */ + } + while (fgets (buf, sizeof buf, fp) != NULL) { + char *bp = buf, *p, *ep; + int len, slen; + struct load_file_entry *lfe; + + bp = buf; + while (*bp && isspace(*bp)) + bp++; + ep = bp; + while (*ep && (*ep != '\n') && (*ep != '\r')) + ep++; + *ep = 0; + if (bp >= ep) + continue; + + if (n_file_arg >= MAX_FILE_ARG) { + error_byebye ("too many FILE args"); + } + + /* allocate memory */ + slen = (ep-bp)+2; + len = sizeof(struct load_file_entry)+(ep-bp)+1; + lfe = malloc(len); + if (lfe == 0) { + error_byebye ("can't allocate entry for load_files file line %s", + bp); + /* no return */ + } + lfe->next = 0; + + /* see if we have destination */ + if ((p = strchr(bp, '=')) != 0) { + int plen; + char ch = *p; + *p = 0; + + /* double conversion -- assume the strings shrink */ + plen = (p-bp); + ndmcstr_to_str(p, &lfe->name[plen+2], slen-plen-2); + ndmcstr_to_str(bp, lfe->name, plen+1); + file_arg[n_file_arg] = &lfe->name[plen+2]; + file_arg_new[n_file_arg] = lfe->name; + *p = ch; + } else { + /* simple conversion copy */ + ndmcstr_to_str(bp, lfe->name, slen-1); + file_arg[n_file_arg] = lfe->name; + file_arg_new[n_file_arg] = 0; + } + n_file_arg++; + + /* link into list */ + lfe->next = load_files_list; + load_files_list = lfe; + } + + fclose (fp); + } /* end of load_files option */ + + if (!B_bu_type) + B_bu_type = "tar"; + + /* + * A quirk of the NDMP protocol is that the robot + * should be accessed over a different connection + * than the TAPE agent. (See the Workflow document). + */ + if (ROBOT_GIVEN()) { + if (!AGENT_GIVEN(R_robot_agent)) { + if (AGENT_GIVEN(T_tape_agent)) + R_robot_agent = T_tape_agent; + else + R_robot_agent = D_data_agent; + + if (!AGENT_GIVEN(R_robot_agent)) { + error_byebye ("-r given, can't determine -R"); + } + } + } else if (AGENT_GIVEN(R_robot_agent)) { + if (the_mode != NDM_JOB_OP_QUERY_AGENTS) { + error_byebye ("-R but no -r"); + } + } +#endif /* !NDMOS_OPTION_NO_CONTROL_AGENT */ + + return 0; +} + +struct ndmp_enum_str_table mode_long_name_table[] = { +#ifndef NDMOS_OPTION_NO_CONTROL_AGENT + { "init-labels", NDM_JOB_OP_INIT_LABELS }, + { "test-tape", NDM_JOB_OP_TEST_TAPE }, + { "test-mover", NDM_JOB_OP_TEST_MOVER }, + { "test-data", NDM_JOB_OP_TEST_DATA }, + { "eject", NDM_JOB_OP_EJECT_TAPE }, + { "rewind", NDM_JOB_OP_REWIND_TAPE }, + { "move", NDM_JOB_OP_MOVE_TAPE }, + { "import", NDM_JOB_OP_IMPORT_TAPE }, + { "export", NDM_JOB_OP_EXPORT_TAPE }, + { "load", NDM_JOB_OP_LOAD_TAPE }, + { "unload", NDM_JOB_OP_UNLOAD_TAPE }, + { "init-elem-status", NDM_JOB_OP_INIT_ELEM_STATUS }, + { "-c", NDM_JOB_OP_BACKUP }, + { "-t", NDM_JOB_OP_TOC }, + { "-x", NDM_JOB_OP_EXTRACT }, + { "-l", NDM_JOB_OP_LIST_LABELS }, + { "-q", NDM_JOB_OP_QUERY_AGENTS }, + { "-Z", NDM_JOB_OP_REMEDY_ROBOT }, +#endif /* !NDMOS_OPTION_NO_CONTROL_AGENT */ +#ifndef NDMOS_EFFECT_NO_SERVER_AGENTS + { "daemon", NDM_JOB_OP_DAEMON }, + { "test-daemon", NDM_JOB_OP_TEST_DAEMON }, +#endif /* !NDMOS_EFFECT_NO_SERVER_AGENTS */ + { 0 } +}; + + +int +handle_long_option (char *str) +{ + char * name; + char * value; + int mode; + + name = str; + for (value = str; *value; value++) + if (*value == '=') + break; + if (*value) + *value++ = 0; + else + value = 0; + + if (ndmp_enum_from_str (&mode, name, mode_long_name_table)) { + set_job_mode (mode); +#ifndef NDMOS_OPTION_NO_CONTROL_AGENT + if (value) { + switch (mode) { + default: /* value part ignored */ + break; + + case NDM_JOB_OP_LOAD_TAPE: + case NDM_JOB_OP_EXPORT_TAPE: + o_from_addr = atoi(value); + break; + case NDM_JOB_OP_UNLOAD_TAPE: + case NDM_JOB_OP_IMPORT_TAPE: + o_to_addr = atoi(value); + break; + } + } + } else if (strcmp (name, "swap-connect") == 0) { + /* value part ignored */ + o_swap_connect++; + } else if (strcmp (name, "time-limit") == 0) { + if (!value) { + o_time_limit = 5*60; + } else { + o_time_limit = atoi(value); + } + } else if (strcmp (name, "use-eject") == 0) { + if (!value) { + o_use_eject = 1; + } else { + o_use_eject = atoi(value); + } + } else if (strcmp (name, "tape-addr") == 0 && value) { + o_tape_addr = atoi(value); + } else if (strcmp (name, "from-addr") == 0 && value) { + o_from_addr = atoi(value); + } else if (strcmp (name, "to-addr") == 0 && value) { + o_to_addr = atoi(value); + } else if (strcmp (name, "tape-timeout") == 0 && value) { + o_tape_timeout = atoi(value); + } else if (strcmp (name, "robot-timeout") == 0 && value) { + o_robot_timeout = atoi(value); + } else if (strcmp (name, "tape-scsi") == 0 && value) { + if (ndmscsi_target_from_str (&o_tape_scsi, value)) { + error_byebye ("bad -otape-scsi argument"); + } + } else if (strcmp (name, "rules") == 0 && value) { + if (!value) + error_byebye ("missing RULES in -o rules"); + o_rules = value; + } else if (strcmp (name, "load-files") == 0 && value) { + o_load_files_file = value; +#endif /* !NDMOS_OPTION_NO_CONTROL_AGENT */ + } else if (strcmp (name, "no-time-stamps") == 0) { + /* value part ignored */ + o_no_time_stamps++; + } else if (strcmp (name, "config-file") == 0 && value) { + o_config_file = value; + } else if (strcmp (name, "tape-tcp") == 0 && value) { + o_tape_tcp = value; + } else if (strcmp (name, "tape-limit") == 0) { + if (!value) { + error_byebye ("tape-limit argument is required"); + } else { + o_tape_limit = atoi(value); + } + } else { + if (value) value[-1] = '='; + error_byebye ("unknown/bad long option -o%s", str); + } + + if (value) value[-1] = '='; + return 0; +} + +void +set_job_mode (int mode) +{ + if (the_mode) { + printf ("more than one -[ctxlqZ] or other mode"); + usage(); + } + the_mode = mode; +} + +void +usage (void) +{ + error_byebye ("bad usage, use -help"); +} + +void +help (void) +{ + char * p; + char ** pp; + + for (pp = help_text; *pp; pp++) { + p = *pp; + printf ("%s\n", p); + } +#ifndef NDMOS_OPTION_NO_CONTROL_AGENT + help_rules(); +#endif /* !NDMOS_OPTION_NO_CONTROL_AGENT */ +} + +void +ndmjob_version_info (void) +{ + char vbuf[100]; + char abuf[100]; + char obuf[5]; + + *vbuf = 0; +#ifndef NDMOS_OPTION_NO_NDMP2 + strcat (vbuf, " NDMPv2"); +#endif /* !NDMOS_OPTION_NO_NDMP2 */ +#ifndef NDMOS_OPTION_NO_NDMP3 + strcat (vbuf, " NDMPv3"); +#endif /* !NDMOS_OPTION_NO_NDMP3 */ +#ifndef NDMOS_OPTION_NO_NDMP4 + strcat (vbuf, " NDMPv4"); +#endif /* !NDMOS_OPTION_NO_NDMP4 */ + + *abuf = 0; +#ifndef NDMOS_OPTION_NO_CONTROL_AGENT + strcat (abuf, " CONTROL"); +#endif /* !NDMOS_OPTION_NO_CONTROL_AGENT */ +#ifndef NDMOS_OPTION_NO_DATA_AGENT + strcat (abuf, " DATA"); +#endif /* !NDMOS_OPTION_NO_DATA_AGENT */ +#ifndef NDMOS_OPTION_NO_TAPE_AGENT + strcat (abuf, " TAPE"); +#endif /* !NDMOS_OPTION_NO_TAPE_AGENT */ +#ifndef NDMOS_OPTION_NO_ROBOT_AGENT + strcat (abuf, " ROBOT"); +#endif /* !NDMOS_OPTION_NO_ROBOT_AGENT */ + + obuf[0] = (char)(NDMOS_ID >> 24); + obuf[1] = (char)(NDMOS_ID >> 16); + obuf[2] = (char)(NDMOS_ID >> 8); + obuf[3] = (char)(NDMOS_ID >> 0); + obuf[4] = 0; + + printf ("%s (%s)\n", + NDMOS_CONST_PRODUCT_NAME, + NDMOS_CONST_VENDOR_NAME); + + printf (" Rev %s LIB:%d.%d/%s OS:%s (%s)\n", + NDMOS_CONST_PRODUCT_REVISION, + NDMJOBLIB_VERSION, NDMJOBLIB_RELEASE, + NDMOS_CONST_NDMJOBLIB_REVISION, + NDMOS_CONST_NDMOS_REVISION, + obuf); + + printf (" Agents: %s\n", abuf); + printf (" Protocols:%s\n", vbuf); +} + + +void +dump_settings (void) +{ + int i; + char buf[100]; + + *buf = 0; /* shuts up -Wall */ + i = 0; /* shuts up -Wall */ +#ifndef NDMOS_OPTION_NO_CONTROL_AGENT + switch (the_mode) { + case 'x': + printf ("mode = x (extract)\n"); + break; + + case 'c': + printf ("mode = c (create)\n"); + break; + + case 't': + printf ("mode = t (table-of-contents)\n"); + break; + + case 'q': + printf ("mode = q (query-agents)\n"); + break; + + default: + printf ("mode = %c (unknown)\n", the_mode); + break; + } +#endif /* !NDMOS_OPTION_NO_CONTROL_AGENT */ + + if (v_verbose) + printf ("verbose %d\n", v_verbose); + else + printf ("not verbose\n"); + +#ifndef NDMOS_OPTION_NO_CONTROL_AGENT + printf ("blocksize = %d (%dkb, %db)\n", + b_bsize, b_bsize/2, b_bsize*512); +#endif /* !NDMOS_OPTION_NO_CONTROL_AGENT */ + + if (d_debug) + printf ("debug %d\n", d_debug); + else + printf ("no debug\n"); + +#ifndef NDMOS_OPTION_NO_CONTROL_AGENT + printf ("Data agent %s\n", D_data_agent.host); + if (AGENT_GIVEN(T_tape_agent)) + printf ("Tape agent %s\n", T_tape_agent.host); + else + printf ("Tape agent same as data agent\n"); + + printf ("tape device %s\n", f_tape_device); + + printf ("tape format %s\n", B_bu_type); + + if (C_chdir) + printf ("Chdir %s\n", C_chdir); + else + printf ("Chdir / (default)\n"); +#endif /* !NDMOS_OPTION_NO_CONTROL_AGENT */ + + if (L_log_file) + printf ("Log to file %s\n", L_log_file); + else + printf ("Log to stderr (default)\n"); + +#ifndef NDMOS_OPTION_NO_CONTROL_AGENT + if (I_index_file) { + if (strcmp (I_index_file, "-") == 0) { + printf ("Index to log, enable FILEHIST\n"); + } else { + printf ("Index to file %s, enable FILEHIST\n", + I_index_file); + } + } else { + printf ("Index off (default), no FILEHIST\n"); + } + + printf ("%d media entries\n", n_m_media); + for (i = 0; i < n_m_media; i++) { + ndmmedia_to_str (&m_media[i], buf); + printf (" %2d: %s\n", i, buf); + } + + printf ("%d excludes\n", n_e_exclude_pattern); + for (i = 0; i < n_e_exclude_pattern; i++) { + printf (" %2d: %s\n", i, e_exclude_pattern[i]); + } + + printf ("%d environment values\n", n_E_environment); + for (i = 0; i < n_E_environment; i++) { + printf (" %2d: %s=%s\n", i, + E_environment[i].name, E_environment[i].value); + } + + printf ("%d files\n", n_file_arg); + for (i = 0; i < n_file_arg; i++) { + printf (" %2d: @%-8lld %s\n", i, + nlist[i].fh_info.valid ? nlist[i].fh_info.value : NDMP9_INVALID_U_QUAD, + file_arg[i]); + } +#endif /* !NDMOS_OPTION_NO_CONTROL_AGENT */ + + return; +} + +int +copy_args_expanding_macros (int argc, char *argv[], char *av[], int max_ac) +{ + int i, ac = 0, rc; + char * arg; + char * p; + char env_name[50]; + + /* expand macros */ + for (i = 0; i < argc; i++) { + arg = argv[i]; + + if (strncmp (arg, "--", 2) != 0 || arg[2] == 0) { + av[ac++] = arg; + continue; + } + + sprintf (env_name, "NDMJOB_%s", arg+2); + if ((p = getenv (env_name)) != 0) { + ac += snarf_macro (&av[ac], p); + continue; + } + + rc = lookup_and_snarf (&av[ac], arg+2); + if (rc < 0) { + error_byebye ("bad arg macro --%s", arg+2); + } + ac += rc; + } + + av[ac] = 0; + + return ac; +} + +int +lookup_and_snarf (char *av[], char *name) +{ + FILE * fp; + char buf[512]; + char * argfile; + int ac = 0; + int found = 0; + + argfile = o_config_file; + assert (argfile); + + fp = fopen (argfile, "r"); + if (!fp) { + perror (argfile); + error_byebye ("can't open config file %s", argfile); + } + + while (ndmstz_getstanza (fp, buf, sizeof buf) >= 0) { + if (buf[0] == '-' && buf[1] == '-' + && strcmp (buf+2, name) == 0) { + found = 1; + break; + } + } + + if (found) { + while (ndmstz_getline (fp, buf, sizeof buf) >= 0) { + if (*buf == 0) + continue; + ac += snarf_macro (&av[ac], buf); + } + } + + fclose (fp); + + if (!found) + return -1; + + return ac; +} + +int +snarf_macro (char *av[], char *val) +{ + char * p; + int ac = 0; + char * tmp_av[100]; + int tmp_ac = 0; + + p = NDMOS_API_STRDUP (val); + if (!p) { + error_byebye ("bad strdup macro"); + } + for (;;) { + while (isspace((int)*p)) p++; + if (*p == 0) break; + tmp_av[tmp_ac++] = p; + while (*p && !isspace((int)*p)) p++; + if (*p) *p++ = 0; + } + + ac = copy_args_expanding_macros (tmp_ac, tmp_av, av, 100); + + return ac; +}