/* * 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 incoming connections", " -o test-daemon -- launch session for incoming 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.", " -o D-agent-fd= -- file descriptor to read the -D agent.", "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; int ac = 0; progname = argv[0]; av = malloc((argc+1000) * sizeof(char *)); 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, G_N_ELEMENTS(av)); 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, "D-agent-fd") == 0 && value) { char d_agent[1025]; int fd = atoi(value); int size; if (AGENT_GIVEN(D_data_agent)) { error_byebye ("more than one of -D or -D-agent-fd"); } size = full_read(fd, d_agent, 1024); d_agent[size] = '\0'; if (size > 0 && d_agent[size-1] == '\n') d_agent[size-1] = '\0'; close(fd); if (ndmagent_from_str (&D_data_agent, d_agent)) { error_byebye ("bad -D-agent-fd argument"); } } 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; }