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