/*
* 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=<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;
}