1 /*
2 * Copyright (c) 1998,1999,2000
3 * Traakan, Inc., Los Altos, CA
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice unmodified, this list of conditions, and the following
11 * disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29 /*
30 * Project: NDMJOB
31 * Ident: $Id: $
32 *
33 * Description:
34 *
35 */
36
37
38 #include "ndmjob.h"
39
40
41 char *help_text[] = {
42 "ndmjob -v -- print version and configuration info",
43 "ndmjob OPTIONS ... FILES ...",
44 " FILES can be FILEPATH or NEWFILEPATH=OLDFILEPATH with",
45 " '=' quoted by backslash.",
46 "Modes (exactly one required)",
47 #ifndef NDMOS_OPTION_NO_CONTROL_AGENT
48 " -c -- create a backup",
49 " -t -- list contents on a backup",
50 " -x -- extract from a backup",
51 " -l -- list media labels",
52 " -q -- query agent(s)",
53 " -Z -- clean up zee mess (put robot right)",
54 " -o init-labels -- init media labels",
55 #endif /* !NDMOS_OPTION_NO_CONTROL_AGENT */
56 #ifndef NDMOS_EFFECT_NO_SERVER_AGENTS
57 " -o daemon -- launch session for incoming connections",
58 " -o test-daemon -- launch session for incoming connections, exit when stdin is closed",
59 " -o tape-size=SIZE -- specify the length, in bytes of the simulated tape",
60 #endif /* !NDMOS_EFFECT_NO_SERVER_AGENTS */
61 #ifndef NDMOS_OPTION_NO_CONTROL_AGENT
62 " -o rewind -- rewind tape in drive, need -T and -f",
63 " -o eject -- eject tape in drive, need -T and -f",
64 " -o move -- cmd ROBOT to move tape, need -o from/to-addr",
65 " -o import=ELEMADDR -- cmd ROBOT to import tape from door to slot",
66 " -o export=ELEMADDR -- cmd ROBOT to export tape from slot to door",
67 " -o load=ELEMADDR -- cmd ROBOT to load tape from slot to drive",
68 " -o unload[=ELEMADDR]-- cmd ROBOT to unload tape, sometimes auto",
69 " -o init-elem-status -- cmd ROBOT to rescan tape slots",
70 " -o test-tape -- test TAPE agent NDMP_TAPE functions",
71 " -o test-mover -- test TAPE agent NDMP_MOVER functions",
72 " -o test-data -- test DATA agent NDMP_DATA functions",
73 " -o time-limit=N",
74 " -- check for reply within specified seconds (default 360)",
75 " -o swap-connect -- perform DATA LISTEN & MOVER CONNECT",
76 #if 0
77 " -p -- pass DATA->DATA (ndmpcopy)",
78 " -P -- pass TAPE->TAPE",
79 " -o c-partial -- partial backup",
80 " -o c-full -- full backup",
81 " -o x-restore -- extract restoring",
82 #endif
83 #endif /* !NDMOS_OPTION_NO_CONTROL_AGENT */
84 "General and Logging parameters",
85 " --MACRO -- expand MACRO from ndmjob-args file",
86 " -d N -- set debug level to N (default 0, max 9)",
87 " -L FILE -- set log file (default stderr, includes debug)",
88 " -n -- no-op, just show how args were handled",
89 " -v -- verbose, same messages as -d1 to standard out",
90 " -S -- Perform DATA listen and MOVER CONNECT",
91 " -p PORT -- NDMP port to listen on (for -o daemon)",
92 " -o no-time-stamps -- log w/o time stamps, makes diff(1)s easier",
93 " -o config-file=PATH",
94 " -- set config file ($NDMJOB_CONFIG, /usr/local/etc/ndmjob.conf)",
95 #ifndef NDMOS_OPTION_NO_CONTROL_AGENT
96 "CONTROL of DATA agent parameters",
97 " -D AGENT -- data agent (see AGENT below)",
98 " -B TYPE -- set backup format (default tar)",
99 " -C DIR -- change directory on data agent before operation",
100 " -e PATN -- exclude files matching pattern",
101 " -E NAME=VAL -- add to data agent environment",
102 " -F FILE -- add FILE arg (used to not confuse arg processing)",
103 " -o load-files=PATHNAME",
104 " -- load FILES from the specified PATHANME",
105 " -o import=ELEMADDR -- cmd ROBOT to import tape from door to slot",
106
107 " -I FILE -- set output index file, enable FILEHIST (default to log)",
108 " -J FILE -- set input index file (default none)",
109 " -U USER -- user rights to use on data agent",
110 " -o rules=RULES -- apply RULES to job (see RULES below)",
111 "CONTROL of TAPE agent parameters",
112 " -T AGENT -- tape agent if different than -D (see AGENT below)",
113 " -b N -- block size in 512-byte records (default 20)",
114 " -f TAPE -- tape drive device name",
115 " -o tape-timeout=SECONDS",
116 " -- how long to retry opening drive (await tape)",
117 " -o use-eject=N",
118 " -- use eject when unloading tapes (default 0)",
119 " -o tape-tcp=hostname:port -- send the data directly to that tcp port.",
120 " -o D-agent-fd=<fd> -- file descriptor to read the -D agent.",
121 "CONTROL of ROBOT agent parameters",
122 " -R AGENT -- robot agent if different than -T (see AGENT below)",
123 " -m MEDIA -- add entry to media table (see below)",
124 " -o tape-addr=ELEMADDR",
125 " -- robot element address of drive (default first)",
126 " -o tape-scsi=SCSI",
127 " -- tape drive SCSI target (see below)",
128 " -o robot-timeout=SECONDS",
129 " -- how long to retry moving tapes (await robot)",
130 " -r SCSI -- tape robot target (see below)",
131 "",
132 "Definitions:",
133 " AGENT HOST[:PORT][/FLAGS][,USERNAME,PASSWORD]",
134 " FLAGS [234][ntm] 2->v2 3->v3 4->v4 n->AUTH_NONE t->TEXT m->MD5",
135 " AGENT . (resident)",
136 " SCSI DEVICE[,[CNUM,]SID[,LUN]]",
137 " MEDIA [TAPE-LABEL][+SKIP-FILEMARKS][@ELEMADDR][/WINDOW-SIZE]",
138 "",
139 "RULES:",
140 #endif /* !NDMOS_OPTION_NO_CONTROL_AGENT */
141 0
142 };
143
144
145 int
process_args(int argc,char * argv[])146 process_args (int argc, char *argv[])
147 {
148 int c;
149 char options[100];
150 char ** pp;
151 char * p;
152 char * op;
153 char ** av;
154 int ac = 0;
155
156 progname = argv[0];
157 av = malloc((argc+1000) * sizeof(char *));
158
159 if (argc == 2 && strcmp (argv[1], "-help") == 0) {
160 help();
161 exit(0);
162 }
163
164 if (argc == 2 && strcmp (argv[1], "-v") == 0) {
165 ndmjob_version_info ();
166 exit(0);
167 }
168
169 if (argc < 2)
170 usage();
171
172 o_config_file = g_strdup_printf("%s/ndmjob.conf", amdatadir);
173 if ((p = getenv ("NDMJOB_CONF")) != 0) {
174 o_config_file = p;
175 }
176
177 op = options;
178 for (pp = help_text; *pp; pp++) {
179 p = *pp;
180
181 if (strncmp (p, " -", 3) != 0)
182 continue;
183 if (p[3] == 'o')
184 continue; /* don't include o: repeatedly */
185 *op++ = p[3];
186 if (p[5] != ' ')
187 *op++ = ':';
188 }
189 *op++ = 'o'; /* include o: once */
190 *op++ = ':';
191 *op = 0;
192
193 ac = copy_args_expanding_macros (argc, argv,
194 av, sizeof(av)/sizeof(av[0]));
195
196 while ((c = getopt (ac, av, options)) != EOF) {
197 switch (c) {
198 case 'o':
199 handle_long_option (optarg);
200 break;
201
202 #ifndef NDMOS_OPTION_NO_CONTROL_AGENT
203 case 'c': /* -c -- create a backup */
204 set_job_mode (NDM_JOB_OP_BACKUP);
205 break;
206
207 case 't': /* -t -- list contents on a backup */
208 set_job_mode (NDM_JOB_OP_TOC);
209 break;
210
211 case 'x': /* -x -- extract from a backup */
212 set_job_mode (NDM_JOB_OP_EXTRACT);
213 break;
214
215 case 'l': /* -l -- list media labels */
216 set_job_mode (NDM_JOB_OP_LIST_LABELS);
217 break;
218
219 case 'q': /* -q -- query agent(s) */
220 set_job_mode (NDM_JOB_OP_QUERY_AGENTS);
221 break;
222
223 case 'Z': /* -Z -- clean up zee mess */
224 set_job_mode (NDM_JOB_OP_REMEDY_ROBOT);
225 break;
226
227 case 'B': /* -B TYPE -- set backup format (default tar) */
228 if (B_bu_type) {
229 error_byebye ("more than one of -B");
230 }
231 B_bu_type = optarg;
232 break;
233
234 case 'b': /* -b N -- block size in 512-byte records (20) */
235 {
236 long b = strtol(optarg, NULL, 10);
237 if (b < 1 || b > 200 || (!b && EINVAL == errno)) {
238 error_byebye ("bad -b option");
239 }
240 b_bsize = (int) b;
241 break;
242 }
243
244 case 'p': /* -p N -- port number for daemon mode (10000) */
245 {
246 long p = strtol(optarg, NULL, 10);
247 if (p < 1 || p > 65535 || (!p && EINVAL == errno)) {
248 error_byebye ("bad -p option");
249 }
250 p_ndmp_port = (int) p;
251 break;
252 }
253
254 case 'C': /* -C DIR -- change directory on data agent */
255 #if 0
256 /* allow second to override first. make recover easier */
257 if (C_chdir) {
258 error_byebye ("more than one of -C");
259 }
260 #endif
261 C_chdir = optarg;
262 break;
263
264 case 'D': /* -D AGENT -- data agent (see below) */
265 if (AGENT_GIVEN(D_data_agent)) {
266 error_byebye ("more than one of -D");
267 }
268 if (ndmagent_from_str (&D_data_agent, optarg)) {
269 error_byebye ("bad -D argument");
270 }
271 break;
272 #endif /* !NDMOS_OPTION_NO_CONTROL_AGENT */
273
274 case 'd': /* -d N -- set debug level to N */
275 d_debug = atoi(optarg);
276 break;
277
278 #ifndef NDMOS_OPTION_NO_CONTROL_AGENT
279 case 'E': /* -E NAME=VAL -- add to data agent environment */
280 if (n_E_environment >= NDM_MAX_ENV) {
281 error_byebye ("too many of -E");
282 }
283 {
284 char * p;
285
286 p = optarg;
287 E_environment[n_E_environment].name = p;
288 while (*p && *p != '=') p++;
289 if (*p != '=') {
290 error_byebye ("missing value in -E");
291 }
292 *p++ = 0;
293 E_environment[n_E_environment].value = p;
294 n_E_environment++;
295 }
296 break;
297
298 case 'e': /* -e PATN -- exclude files matching pattern */
299 if (n_e_exclude_pattern >= MAX_EXCLUDE_PATTERN) {
300 error_byebye ("too many of -e");
301 }
302 e_exclude_pattern[n_e_exclude_pattern++] = optarg;
303 break;
304
305 case 'F': /* -F FILE -- add to list of files */
306 if (n_file_arg >= MAX_FILE_ARG) {
307 error_byebye ("too many FILE args");
308 }
309 if (strchr(optarg, '=')) {
310 char *p = strchr(optarg, '=');
311 *p++ = 0;
312 file_arg[n_file_arg] = p;
313 file_arg_new[n_file_arg] = optarg;
314 n_file_arg++;
315 } else {
316 file_arg[n_file_arg] = optarg;
317 file_arg_new[n_file_arg] = 0;
318 n_file_arg++;
319 }
320
321 break;
322
323 case 'f': /* -f TAPE -- tape drive device name */
324 if (f_tape_device) {
325 error_byebye ("more than one of -f");
326 }
327 f_tape_device = optarg;
328 break;
329
330 case 'I': /* -I FILE -- output index, enab FILEHIST */
331 if (I_index_file) {
332 error_byebye ("more than one of -I");
333 }
334 I_index_file = optarg;
335 break;
336
337 case 'J': /* -J FILE -- input index */
338 if (J_index_file) {
339 error_byebye ("more than one of -J");
340 }
341 J_index_file = optarg;
342 break;
343
344 case 'L': /* -L FILE -- set log file (def stderr, incl. dbg) */
345 if (L_log_file) {
346 error_byebye ("more than one of -L");
347 }
348 L_log_file = optarg;
349 if (d_debug < 2) d_debug = 2;
350 break;
351
352 case 'm': /* -m MEDIA -- add entry to media table (see below) */
353 if (n_m_media >= NDM_MAX_MEDIA) {
354 error_byebye ("too many of -m");
355 }
356 if (ndmmedia_from_str (&m_media[n_m_media], optarg)) {
357 error_byebye ("bad -m argument: %s", optarg);
358 }
359 n_m_media++;
360 break;
361 #endif /* !NDMOS_OPTION_NO_CONTROL_AGENT */
362
363 case 'n': /* -n -- no-op, show how args were handled */
364 n_noop++;
365 break;
366
367 #ifndef NDMOS_OPTION_NO_CONTROL_AGENT
368 case 'R': /* -R AGENT -- robot agent if different than -T */
369 if (AGENT_GIVEN(R_robot_agent)) {
370 error_byebye ("more than one of -R");
371 }
372 if (ndmagent_from_str (&R_robot_agent, optarg)) {
373 error_byebye ("bad -R argument");
374 }
375 break;
376
377 case 'r': /* -r SCSI -- tape robot target (see below) */
378 if (ROBOT_GIVEN()) {
379 error_byebye ("more than one of -r");
380 }
381 if (ndmscsi_target_from_str (&r_robot_target, optarg)) {
382 error_byebye ("bad -r argument");
383 }
384 break;
385
386 case 'T': /* -T AGENT -- tape agent if different than -D */
387 if (AGENT_GIVEN(T_tape_agent)) {
388 error_byebye ("more than one of -T");
389 }
390 if (ndmagent_from_str (&T_tape_agent, optarg)) {
391 error_byebye ("bad -T argument");
392 }
393 break;
394
395 case 'U': /* -U USER -- user rights to use on data agent */
396 if (U_user) {
397 error_byebye ("more than one of -U");
398 }
399 U_user = optarg;
400 break;
401 #endif /* !NDMOS_OPTION_NO_CONTROL_AGENT */
402
403 case 'v': /* -v -- verbose */
404 v_verbose++;
405 break;
406
407 default:
408 usage();
409 break;
410 }
411 }
412
413 if (n_noop && d_debug > 1) {
414 int i;
415
416 for (i = 0; i < ac; i++) {
417 printf (" av[%d] = '%s'\n", i, av[i]);
418 }
419 }
420
421 if (!the_mode) {
422 #ifndef NDMOS_OPTION_NO_CONTROL_AGENT
423 printf ("must specify one of -[ctxlqZ] or other mode\n");
424 #else /* !NDMOS_OPTION_NO_CONTROL_AGENT */
425 printf ("must specify -o daemon\n");
426 #endif /* !NDMOS_OPTION_NO_CONTROL_AGENT */
427 usage();
428 }
429
430 #ifndef NDMOS_OPTION_NO_CONTROL_AGENT
431 for (c = optind; c < ac; c++) {
432 if (n_file_arg >= MAX_FILE_ARG) {
433 error_byebye ("too many file args");
434 }
435 if (strchr(av[c], '=')) {
436 char *p = strchr(av[c], '=');
437 *p++ = 0;
438 file_arg[n_file_arg] = p;
439 file_arg_new[n_file_arg] = av[c];
440 } else {
441 file_arg[n_file_arg] = av[c];
442 file_arg_new[n_file_arg] = 0;
443 }
444 n_file_arg++;
445 }
446
447 if (o_load_files_file) {
448 char buf[2048];
449 FILE *fp;
450 static struct load_file_entry {
451 struct load_file_entry *next;
452 char name[1];
453 } *load_files_list = 0;
454
455 /* clean up old load_files_list */
456 while (load_files_list) {
457 struct load_file_entry *p;
458 p = load_files_list;
459 load_files_list = p->next;
460 p->next = 0;
461 free(p);
462 }
463
464 fp = fopen(o_load_files_file, "r");
465 if (!fp) {
466 perror (o_load_files_file);
467 error_byebye ("can't open load_files file %s",
468 o_load_files_file);
469 /* no return */
470 }
471 while (fgets (buf, sizeof buf, fp) != NULL) {
472 char *bp = buf, *p, *ep;
473 int len, slen;
474 struct load_file_entry *lfe;
475
476 bp = buf;
477 while (*bp && isspace(*bp))
478 bp++;
479 ep = bp;
480 while (*ep && (*ep != '\n') && (*ep != '\r'))
481 ep++;
482 *ep = 0;
483 if (bp >= ep)
484 continue;
485
486 if (n_file_arg >= MAX_FILE_ARG) {
487 error_byebye ("too many FILE args");
488 }
489
490 /* allocate memory */
491 slen = (ep-bp)+2;
492 len = sizeof(struct load_file_entry)+(ep-bp)+1;
493 lfe = malloc(len);
494 if (lfe == 0) {
495 error_byebye ("can't allocate entry for load_files file line %s",
496 bp);
497 /* no return */
498 }
499 lfe->next = 0;
500
501 /* see if we have destination */
502 if ((p = strchr(bp, '=')) != 0) {
503 int plen;
504 char ch = *p;
505 *p = 0;
506
507 /* double conversion -- assume the strings shrink */
508 plen = (p-bp);
509 ndmcstr_to_str(p, &lfe->name[plen+2], slen-plen-2);
510 ndmcstr_to_str(bp, lfe->name, plen+1);
511 file_arg[n_file_arg] = &lfe->name[plen+2];
512 file_arg_new[n_file_arg] = lfe->name;
513 *p = ch;
514 } else {
515 /* simple conversion copy */
516 ndmcstr_to_str(bp, lfe->name, slen-1);
517 file_arg[n_file_arg] = lfe->name;
518 file_arg_new[n_file_arg] = 0;
519 }
520 n_file_arg++;
521
522 /* link into list */
523 lfe->next = load_files_list;
524 load_files_list = lfe;
525 }
526
527 fclose (fp);
528 } /* end of load_files option */
529
530 if (!B_bu_type)
531 B_bu_type = "tar";
532
533 /*
534 * A quirk of the NDMP protocol is that the robot
535 * should be accessed over a different connection
536 * than the TAPE agent. (See the Workflow document).
537 */
538 if (ROBOT_GIVEN()) {
539 if (!AGENT_GIVEN(R_robot_agent)) {
540 if (AGENT_GIVEN(T_tape_agent))
541 R_robot_agent = T_tape_agent;
542 else
543 R_robot_agent = D_data_agent;
544
545 if (!AGENT_GIVEN(R_robot_agent)) {
546 error_byebye ("-r given, can't determine -R");
547 }
548 }
549 } else if (AGENT_GIVEN(R_robot_agent)) {
550 if (the_mode != NDM_JOB_OP_QUERY_AGENTS) {
551 error_byebye ("-R but no -r");
552 }
553 }
554 #endif /* !NDMOS_OPTION_NO_CONTROL_AGENT */
555
556 return 0;
557 }
558
559 struct ndmp_enum_str_table mode_long_name_table[] = {
560 #ifndef NDMOS_OPTION_NO_CONTROL_AGENT
561 { "init-labels", NDM_JOB_OP_INIT_LABELS },
562 { "test-tape", NDM_JOB_OP_TEST_TAPE },
563 { "test-mover", NDM_JOB_OP_TEST_MOVER },
564 { "test-data", NDM_JOB_OP_TEST_DATA },
565 { "eject", NDM_JOB_OP_EJECT_TAPE },
566 { "rewind", NDM_JOB_OP_REWIND_TAPE },
567 { "move", NDM_JOB_OP_MOVE_TAPE },
568 { "import", NDM_JOB_OP_IMPORT_TAPE },
569 { "export", NDM_JOB_OP_EXPORT_TAPE },
570 { "load", NDM_JOB_OP_LOAD_TAPE },
571 { "unload", NDM_JOB_OP_UNLOAD_TAPE },
572 { "init-elem-status", NDM_JOB_OP_INIT_ELEM_STATUS },
573 { "-c", NDM_JOB_OP_BACKUP },
574 { "-t", NDM_JOB_OP_TOC },
575 { "-x", NDM_JOB_OP_EXTRACT },
576 { "-l", NDM_JOB_OP_LIST_LABELS },
577 { "-q", NDM_JOB_OP_QUERY_AGENTS },
578 { "-Z", NDM_JOB_OP_REMEDY_ROBOT },
579 #endif /* !NDMOS_OPTION_NO_CONTROL_AGENT */
580 #ifndef NDMOS_EFFECT_NO_SERVER_AGENTS
581 { "daemon", NDM_JOB_OP_DAEMON },
582 { "test-daemon", NDM_JOB_OP_TEST_DAEMON },
583 #endif /* !NDMOS_EFFECT_NO_SERVER_AGENTS */
584 { 0 }
585 };
586
587
588 int
handle_long_option(char * str)589 handle_long_option (char *str)
590 {
591 char * name;
592 char * value;
593 int mode;
594
595 name = str;
596 for (value = str; *value; value++)
597 if (*value == '=')
598 break;
599 if (*value)
600 *value++ = 0;
601 else
602 value = 0;
603
604 if (ndmp_enum_from_str (&mode, name, mode_long_name_table)) {
605 set_job_mode (mode);
606 #ifndef NDMOS_OPTION_NO_CONTROL_AGENT
607 if (value) {
608 switch (mode) {
609 default: /* value part ignored */
610 break;
611
612 case NDM_JOB_OP_LOAD_TAPE:
613 case NDM_JOB_OP_EXPORT_TAPE:
614 o_from_addr = atoi(value);
615 break;
616 case NDM_JOB_OP_UNLOAD_TAPE:
617 case NDM_JOB_OP_IMPORT_TAPE:
618 o_to_addr = atoi(value);
619 break;
620 }
621 }
622 } else if (strcmp (name, "swap-connect") == 0) {
623 /* value part ignored */
624 o_swap_connect++;
625 } else if (strcmp (name, "time-limit") == 0) {
626 if (!value) {
627 o_time_limit = 5*60;
628 } else {
629 o_time_limit = atoi(value);
630 }
631 } else if (strcmp (name, "use-eject") == 0) {
632 if (!value) {
633 o_use_eject = 1;
634 } else {
635 o_use_eject = atoi(value);
636 }
637 } else if (strcmp (name, "tape-addr") == 0 && value) {
638 o_tape_addr = atoi(value);
639 } else if (strcmp (name, "from-addr") == 0 && value) {
640 o_from_addr = atoi(value);
641 } else if (strcmp (name, "to-addr") == 0 && value) {
642 o_to_addr = atoi(value);
643 } else if (strcmp (name, "tape-timeout") == 0 && value) {
644 o_tape_timeout = atoi(value);
645 } else if (strcmp (name, "robot-timeout") == 0 && value) {
646 o_robot_timeout = atoi(value);
647 } else if (strcmp (name, "tape-scsi") == 0 && value) {
648 if (ndmscsi_target_from_str (&o_tape_scsi, value)) {
649 error_byebye ("bad -otape-scsi argument");
650 }
651 } else if (strcmp (name, "rules") == 0 && value) {
652 if (!value)
653 error_byebye ("missing RULES in -o rules");
654 o_rules = value;
655 } else if (strcmp (name, "load-files") == 0 && value) {
656 o_load_files_file = value;
657 #endif /* !NDMOS_OPTION_NO_CONTROL_AGENT */
658 } else if (strcmp (name, "no-time-stamps") == 0) {
659 /* value part ignored */
660 o_no_time_stamps++;
661 } else if (strcmp (name, "config-file") == 0 && value) {
662 o_config_file = value;
663 } else if (strcmp (name, "tape-tcp") == 0 && value) {
664 o_tape_tcp = value;
665 } else if (strcmp (name, "D-agent-fd") == 0 && value) {
666 char d_agent[1025];
667 int fd = atoi(value);
668 int size;
669
670 if (AGENT_GIVEN(D_data_agent)) {
671 error_byebye ("more than one of -D or -D-agent-fd");
672 }
673
674 size = full_read(fd, d_agent, 1024);
675 d_agent[size] = '\0';
676 if (size > 0 && d_agent[size-1] == '\n')
677 d_agent[size-1] = '\0';
678 close(fd);
679 if (ndmagent_from_str (&D_data_agent, d_agent)) {
680 error_byebye ("bad -D-agent-fd argument");
681 }
682 } else if (strcmp (name, "tape-limit") == 0) {
683 if (!value) {
684 error_byebye ("tape-limit argument is required");
685 } else {
686 o_tape_limit = atoi(value);
687 }
688 } else {
689 if (value) value[-1] = '=';
690 error_byebye ("unknown/bad long option -o%s", str);
691 }
692
693 if (value) value[-1] = '=';
694 return 0;
695 }
696
697 void
set_job_mode(int mode)698 set_job_mode (int mode)
699 {
700 if (the_mode) {
701 printf ("more than one -[ctxlqZ] or other mode");
702 usage();
703 }
704 the_mode = mode;
705 }
706
707 void
usage(void)708 usage (void)
709 {
710 error_byebye ("bad usage, use -help");
711 }
712
713 void
help(void)714 help (void)
715 {
716 char * p;
717 char ** pp;
718
719 for (pp = help_text; *pp; pp++) {
720 p = *pp;
721 printf ("%s\n", p);
722 }
723 #ifndef NDMOS_OPTION_NO_CONTROL_AGENT
724 help_rules();
725 #endif /* !NDMOS_OPTION_NO_CONTROL_AGENT */
726 }
727
728 void
ndmjob_version_info(void)729 ndmjob_version_info (void)
730 {
731 char vbuf[100];
732 char abuf[100];
733 char obuf[5];
734
735 *vbuf = 0;
736 #ifndef NDMOS_OPTION_NO_NDMP2
737 strcat (vbuf, " NDMPv2");
738 #endif /* !NDMOS_OPTION_NO_NDMP2 */
739 #ifndef NDMOS_OPTION_NO_NDMP3
740 strcat (vbuf, " NDMPv3");
741 #endif /* !NDMOS_OPTION_NO_NDMP3 */
742 #ifndef NDMOS_OPTION_NO_NDMP4
743 strcat (vbuf, " NDMPv4");
744 #endif /* !NDMOS_OPTION_NO_NDMP4 */
745
746 *abuf = 0;
747 #ifndef NDMOS_OPTION_NO_CONTROL_AGENT
748 strcat (abuf, " CONTROL");
749 #endif /* !NDMOS_OPTION_NO_CONTROL_AGENT */
750 #ifndef NDMOS_OPTION_NO_DATA_AGENT
751 strcat (abuf, " DATA");
752 #endif /* !NDMOS_OPTION_NO_DATA_AGENT */
753 #ifndef NDMOS_OPTION_NO_TAPE_AGENT
754 strcat (abuf, " TAPE");
755 #endif /* !NDMOS_OPTION_NO_TAPE_AGENT */
756 #ifndef NDMOS_OPTION_NO_ROBOT_AGENT
757 strcat (abuf, " ROBOT");
758 #endif /* !NDMOS_OPTION_NO_ROBOT_AGENT */
759
760 obuf[0] = (char)(NDMOS_ID >> 24);
761 obuf[1] = (char)(NDMOS_ID >> 16);
762 obuf[2] = (char)(NDMOS_ID >> 8);
763 obuf[3] = (char)(NDMOS_ID >> 0);
764 obuf[4] = 0;
765
766 printf ("%s (%s)\n",
767 NDMOS_CONST_PRODUCT_NAME,
768 NDMOS_CONST_VENDOR_NAME);
769
770 printf (" Rev %s LIB:%d.%d/%s OS:%s (%s)\n",
771 NDMOS_CONST_PRODUCT_REVISION,
772 NDMJOBLIB_VERSION, NDMJOBLIB_RELEASE,
773 NDMOS_CONST_NDMJOBLIB_REVISION,
774 NDMOS_CONST_NDMOS_REVISION,
775 obuf);
776
777 printf (" Agents: %s\n", abuf);
778 printf (" Protocols:%s\n", vbuf);
779 }
780
781
782 void
dump_settings(void)783 dump_settings (void)
784 {
785 int i;
786 char buf[100];
787
788 *buf = 0; /* shuts up -Wall */
789 i = 0; /* shuts up -Wall */
790 #ifndef NDMOS_OPTION_NO_CONTROL_AGENT
791 switch (the_mode) {
792 case 'x':
793 printf ("mode = x (extract)\n");
794 break;
795
796 case 'c':
797 printf ("mode = c (create)\n");
798 break;
799
800 case 't':
801 printf ("mode = t (table-of-contents)\n");
802 break;
803
804 case 'q':
805 printf ("mode = q (query-agents)\n");
806 break;
807
808 default:
809 printf ("mode = %c (unknown)\n", the_mode);
810 break;
811 }
812 #endif /* !NDMOS_OPTION_NO_CONTROL_AGENT */
813
814 if (v_verbose)
815 printf ("verbose %d\n", v_verbose);
816 else
817 printf ("not verbose\n");
818
819 #ifndef NDMOS_OPTION_NO_CONTROL_AGENT
820 printf ("blocksize = %d (%dkb, %db)\n",
821 b_bsize, b_bsize/2, b_bsize*512);
822 #endif /* !NDMOS_OPTION_NO_CONTROL_AGENT */
823
824 if (d_debug)
825 printf ("debug %d\n", d_debug);
826 else
827 printf ("no debug\n");
828
829 #ifndef NDMOS_OPTION_NO_CONTROL_AGENT
830 printf ("Data agent %s\n", D_data_agent.host);
831 if (AGENT_GIVEN(T_tape_agent))
832 printf ("Tape agent %s\n", T_tape_agent.host);
833 else
834 printf ("Tape agent same as data agent\n");
835
836 printf ("tape device %s\n", f_tape_device);
837
838 printf ("tape format %s\n", B_bu_type);
839
840 if (C_chdir)
841 printf ("Chdir %s\n", C_chdir);
842 else
843 printf ("Chdir / (default)\n");
844 #endif /* !NDMOS_OPTION_NO_CONTROL_AGENT */
845
846 if (L_log_file)
847 printf ("Log to file %s\n", L_log_file);
848 else
849 printf ("Log to stderr (default)\n");
850
851 #ifndef NDMOS_OPTION_NO_CONTROL_AGENT
852 if (I_index_file) {
853 if (strcmp (I_index_file, "-") == 0) {
854 printf ("Index to log, enable FILEHIST\n");
855 } else {
856 printf ("Index to file %s, enable FILEHIST\n",
857 I_index_file);
858 }
859 } else {
860 printf ("Index off (default), no FILEHIST\n");
861 }
862
863 printf ("%d media entries\n", n_m_media);
864 for (i = 0; i < n_m_media; i++) {
865 ndmmedia_to_str (&m_media[i], buf);
866 printf (" %2d: %s\n", i, buf);
867 }
868
869 printf ("%d excludes\n", n_e_exclude_pattern);
870 for (i = 0; i < n_e_exclude_pattern; i++) {
871 printf (" %2d: %s\n", i, e_exclude_pattern[i]);
872 }
873
874 printf ("%d environment values\n", n_E_environment);
875 for (i = 0; i < n_E_environment; i++) {
876 printf (" %2d: %s=%s\n", i,
877 E_environment[i].name, E_environment[i].value);
878 }
879
880 printf ("%d files\n", n_file_arg);
881 for (i = 0; i < n_file_arg; i++) {
882 printf (" %2d: @%-8lld %s\n", i,
883 nlist[i].fh_info.valid ? nlist[i].fh_info.value : NDMP9_INVALID_U_QUAD,
884 file_arg[i]);
885 }
886 #endif /* !NDMOS_OPTION_NO_CONTROL_AGENT */
887
888 return;
889 }
890
891 int
copy_args_expanding_macros(int argc,char * argv[],char * av[],int max_ac)892 copy_args_expanding_macros (int argc, char *argv[], char *av[], int max_ac)
893 {
894 int i, ac = 0, rc;
895 char * arg;
896 char * p;
897 char env_name[50];
898
899 /* expand macros */
900 for (i = 0; i < argc; i++) {
901 arg = argv[i];
902
903 if (strncmp (arg, "--", 2) != 0 || arg[2] == 0) {
904 av[ac++] = arg;
905 continue;
906 }
907
908 sprintf (env_name, "NDMJOB_%s", arg+2);
909 if ((p = getenv (env_name)) != 0) {
910 ac += snarf_macro (&av[ac], p);
911 continue;
912 }
913
914 rc = lookup_and_snarf (&av[ac], arg+2);
915 if (rc < 0) {
916 error_byebye ("bad arg macro --%s", arg+2);
917 }
918 ac += rc;
919 }
920
921 av[ac] = 0;
922
923 return ac;
924 }
925
926 int
lookup_and_snarf(char * av[],char * name)927 lookup_and_snarf (char *av[], char *name)
928 {
929 FILE * fp;
930 char buf[512];
931 char * argfile;
932 int ac = 0;
933 int found = 0;
934
935 argfile = o_config_file;
936 assert (argfile);
937
938 fp = fopen (argfile, "r");
939 if (!fp) {
940 perror (argfile);
941 error_byebye ("can't open config file %s", argfile);
942 }
943
944 while (ndmstz_getstanza (fp, buf, sizeof buf) >= 0) {
945 if (buf[0] == '-' && buf[1] == '-'
946 && strcmp (buf+2, name) == 0) {
947 found = 1;
948 break;
949 }
950 }
951
952 if (found) {
953 while (ndmstz_getline (fp, buf, sizeof buf) >= 0) {
954 if (*buf == 0)
955 continue;
956 ac += snarf_macro (&av[ac], buf);
957 }
958 }
959
960 fclose (fp);
961
962 if (!found)
963 return -1;
964
965 return ac;
966 }
967
968 int
snarf_macro(char * av[],char * val)969 snarf_macro (char *av[], char *val)
970 {
971 char * p;
972 int ac = 0;
973 char * tmp_av[100];
974 int tmp_ac = 0;
975
976 p = NDMOS_API_STRDUP (val);
977 if (!p) {
978 error_byebye ("bad strdup macro");
979 }
980 for (;;) {
981 while (isspace((int)*p)) p++;
982 if (*p == 0) break;
983 tmp_av[tmp_ac++] = p;
984 while (*p && !isspace((int)*p)) p++;
985 if (*p) *p++ = 0;
986 }
987
988 ac = copy_args_expanding_macros (tmp_ac, tmp_av, av, 100);
989
990 return ac;
991 }
992