1 /* ***********************************************************
  2    *                                                         *
  3    * Copyright, (C) Honeywell Bull Inc., 1987                *
  4    *                                                         *
  5    * Copyright, (C) Honeywell Information Systems Inc., 1985 *
  6    *                                                         *
  7    *********************************************************** */
  8 
  9 
 10 /* HISTORY COMMENTS:
 11   1) change(86-10-31,Rohs), approve(87-07-13,MCR7580), audit(87-07-13,Leskiw),
 12      install(87-08-07,MR12.1-1072):
 13      Created.
 14   2) change(87-10-31,Flegel), approve(87-10-31,MCR7787),
 15      audit(88-01-26,DGHowe), install(88-02-24,MR12.2-1028):
 16      Added support for control_args to accomodate new queueing strategy.
 17   3) change(87-12-12,Flegel), approve(87-12-12,MCR7819),
 18      audit(88-01-26,DGHowe), install(88-02-24,MR12.2-1028):
 19      Added control arguments for a wider scope of request capabilities.
 20   4) change(89-02-15,Lee), approve(89-02-14,MCR8061), audit(89-02-27,Vu),
 21      install(89-04-24,MR12.3-1034):
 22      phx21250 (MOWSE 11) - fixed typo "requesst" in bft_fetch message.
 23                                                    END HISTORY COMMENTS */
 24 
 25 /* COMPILER: Lattice C, V2.15 */
 26 
 27 /***************************************************************
 28 
 29      BFT ARGUMENT ANAYLSER
 30 
 31      SYNTAX:     BFT KEY {path1 {path2...path1N path2N}} {/Control_args}
 32 
 33      PARAMETERS: argc - the number of arguments on the command
 34                         line. (input)
 35                  argv - a pointer to an array of pointers to
 36                         strings which contain the arguments
 37                         that follow the fetch keyword. (input)
 38 
 39      FUNCTION:   Parses the BFT command line for a valid keyword.
 40                  If one is found then the appropriate routine is
 41                  called to parse the remainder of the command
 42                  for filenames. If the command if syntactically
 43                  correct, then a call to the appropriate BFT
 44                  minor capability is made.
 45 
 46 *****************************************************************/
 47 
 48 #include <stdio.h>
 49 #include <mowse.h>
 50 #include <bft.h>
 51 
 52 #define CANCEL_SW     0x001
 53 #define DISPLAY_SW    0x002
 54 #define FETCH_SW      0x004
 55 #define LOAD_SW       0x008
 56 #define RECOVER_SW    0x010
 57 #define STORE_SW      0x020
 58 #define UNLOAD_SW     0x040
 59 
 60 /* ERROR MESSAGE */
 61 
 62 #define NAME          "BFT"
 63 #define USAGE_CANCEL  "\n   Usage: bft cancel request_id {request_id ...}\n"
 64 #define USAGE_UNLOAD  "\n   Usage: bft unload\n"
 65 #define USAGE_RECOVER "\n   Usage: bft unload\n"
 66 #define USAGE_BFT     "\n   Usage: bft KEY {path1 {path2...path1N path2N}} {/Control_args}\n"
 67 #define USAGE_FETCH   "\n   Usage: bft FETCH {path1 {path2...path1N path2N}} {/Control_args}\n"
 68 #define USAGE_STORE   "\n   Usage: bft STORE {path1 {path2...path1N path2N}} {/Control_args}\n"
 69 #define USAGE_KEYS    "\n     (s)tore, (f)etch, (c)ancel, (ls) list, (l)oad, (u)nload, (r)ecover\n"
 70 
 71 /* GLOBAL REFERENCE */
 72 
 73 int  argp;                            /* Current position in argument list */
 74 int  argcount;                        /* Argument count */
 75 char **argval;                        /* Arguments */
 76 char *arg;                            /* Current argument */
 77 long flags;                           /* Transfer modes */
 78 int  priority;                        /* Transfer priority level */
 79 int  control_sw;                      /* Argument parsing control */
 80 
 81 char *find_option ();                 /* Locates a control_arg option */
 82 char *stripquote();                   /* function to remove surrounding quotes */
 83 char *upper();                        /* function to convert string to upper case */
 84 int  bft_cancel ();
 85 int  bft_fetch ();
 86 int  bft_load ();
 87 int  bft_display ();
 88 int  bft_recover ();
 89 int  bft_store ();
 90 int  bft_unload ();
 91 
 92 /*^L*/
 93 
 94 main (argc, argv)
 95 
 96 int  argc;                            /* number of args on the command line */
 97 char **argv;                          /* pointer to the args */
 98 {
 99 int  code;                            /* Error code */
100 int  (*key_procedure)();              /* Key function handler */
101 
102 /* Initialize */
103 
104   code = 0;
105   flags = 0;
106   priority = 3;
107   control_sw = 0;
108 
109   argcount = argc;
110   argval = argv;
111   flags = 0;
112 
113 /* How many args are there ? */
114 
115   if (argcount < 1)
116   {
117     fprintf (stderr, "%s: Wrong number of arguments.\n%s", NAME, USAGE_BFT);
118     return;
119   }
120 
121 /* Extract the keyword */
122 
123   argp = 0;
124   if ((code = get_arg (0)) != 0)
125   {
126     bfterror (code, USAGE_BFT, NULL);
127     return;
128   }
129 
130 /* This argument MUST be a keywrd, otherwise what are we to do ? */
131 
132   if      (!strcmp (argval[argp],"cancel")  || !strcmp (argval[argp],"c"))
133   {
134     control_sw |= CANCEL_SW;
135     key_procedure = bft_cancel;
136   }
137   else if (!strcmp (argval[argp],"fetch")   || !strcmp (argval[argp],"f"))
138   {
139     control_sw |= FETCH_SW;
140     key_procedure = bft_fetch;
141   }
142   else if (!strcmp (argval[argp],"load")    || !strcmp (argval[argp],"l") || !strcmp (argval[argp],"ld"))
143   {
144     control_sw |= LOAD_SW;
145     key_procedure = bft_load;
146   }
147   else if (!strcmp (argval[argp],"list")    || !strcmp (argval[argp],"ls"))
148   {
149     control_sw |= DISPLAY_SW;
150     key_procedure = bft_display;
151   }
152   else if (!strcmp (argval[argp],"recover") || !strcmp (argval[argp],"r"))
153   {
154     control_sw |= RECOVER_SW;
155     key_procedure = bft_recover;
156   }
157   else if (!strcmp (argval[argp],"store")   || !strcmp (argval[argp],"s"))
158   {
159     control_sw |= STORE_SW;
160     key_procedure = bft_store;
161   }
162   else if (!strcmp (argval[argp],"unload")  || !strcmp (argval[argp],"u") || !strcmp (argval[argp],"uld"))
163   {
164     control_sw |= UNLOAD_SW;
165     key_procedure = bft_unload;
166   }
167   else
168   {
169     fprintf (stderr, "BFT: Keyword not accepted: %s.%s", arg, USAGE_KEYS);
170     return;
171   }
172 
173 /* Parse through control arguments */
174 
175   if ((code = parse_args ()) != 0)
176   {
177     bfterror (code, USAGE_BFT, NULL);
178     return;
179   }
180 
181 /* We made it here, so call the handler, skipt the first real argument as it is the keyword */
182 
183   argp = 0;
184   get_arg (0);
185   (*key_procedure) ();
186 }
187 /*^L*/
188 /***************************************************************
189 
190      BFT_CANCEL
191 
192      SYNTAX:     bft cancel REQUEST_IDENTIFIER {REQUEST_IDENTIFIER ...}
193                  bft c      REQUEST_IDENTIFIER {REQUEST_IDENTIFIER ...}
194 
195      PARAMETERS: None.
196 
197      FUNCTION:   Cancel an element from the request queue.
198 
199 *****************************************************************/
200 
201 bft_cancel ()
202 {
203 int  code;                             /* Error code */
204 char id[PATHNAMESIZE];                 /* Request id */
205 int  passed;                           /* Count of satisfied requests */
206 char request_type;                     /* Cancellation request type */
207 
208 
209   passed = 0;
210 
211 /* Repeat until all args are exhausted */
212 
213   while (argp < argcount - 1)
214   {
215     if (code = get_arg (1))
216     {
217       bfterror (code, arg, NULL);
218       if (passed > 0)
219         printf ("BFT: %d reques%s submitted for cancellation.\n", passed, ((passed == 1) ? "t" : "ts"));
220       return (code);
221     }
222 
223 /* Verify and cancel the request */
224 
225     if (arg[0] != '/')
226     {
227       strncpy (id, arg, PATHNAMESIZE);
228       code = bftcan (BFT_PATH_ID, stripquote (id));
229     }
230     else
231     {
232       request_type = arg[1];
233 
234       arg = find_option ();
235       if (arg == NULL)
236         code = BFT_EXPECTING;
237       else
238       {
239         strncpy (id, arg, PATHNAMESIZE);
240 
241         if (request_type == 'I')
242           code = bftcan (BFT_TIME_ID, stripquote (id));
243         else if (request_type == 'E')
244           code = bftcan (BFT_ENTRY_ID, stripquote (id));
245       }
246     }
247 
248 /* Something went wrong */
249 
250     if (code != 0)
251     {
252       bfterror (code, "Executing bft cancel.", NULL);
253       if (passed > 0)
254         printf ("BFT: %d reques%s submitted for cancellation.\n", passed, ((passed == 1) ? "t" : "ts"));
255       return (code);
256     }
257     else
258       passed += 1;
259   }
260 
261   if (passed > 0)
262     printf ("BFT: %d reques%s submitted for cancellation.\n", passed, ((passed == 1) ? "t" : "ts"));
263 
264   return (0);
265 }
266 /*^L*/
267 /***************************************************************
268 
269      BFT_DISPLAY
270 
271      SYNTAX:     BFT LIST {/Control_args}
272                  BFT LS   {/Control_args}
273 
274      PARAMETERS: None.
275 
276      FUNCTION:   Display the request queues.
277 
278 *****************************************************************/
279 
280 bft_display ()
281 {
282   fprintf (stderr, "BFT: PC version of BFT does not implement queue list.  Use Multics list.\n");
283 }
284 /*^L*/
285 /***************************************************************
286 
287      BFT_FETCH
288 
289      SYNTAX:     bft fetch file1 {file2...file1N file2N} {/Control_args}
290                  bft f     file1 {file2...file1N file2N} {/Control_args}
291 
292      PARAMETERS: None.
293 
294      FUNCTION:   parses the BFT command line after the "fetch"
295                  keyword for a source and destination filename.
296                  If only one filename is given then it is taken
297                  as both the source and destination filename.
298                  If the syntax is correct then the bft fetch
299                  minor capability is called.
300 
301 *****************************************************************/
302 
303 bft_fetch ()
304 {
305 char mu_path[MAXARGSTRING];           /* holds arguments to be passed to execap  */
306 char pc_path[PATHNAMESIZE];           /* source file name */
307 int  passed;                          /* Number of requests submitted */
308 int  code;
309 
310   passed = 0;
311 
312 /* Repeat until all args are exhausted */
313 
314   while (argp < argcount - 1)
315   {
316 
317 /* Get Multics path */
318 
319     if (code = get_arg (0))
320     {
321       bfterror (code, USAGE_FETCH, NULL);
322       if (passed > 0)
323         printf ("BFT: %d reques%s submitted for fetching.\n", passed, ((passed == 1) ? "t" : "ts"));
324       return (code);
325     }
326 
327     strncpy (mu_path, arg, PATHNAMESIZE);
328     strncpy (pc_path, "===", PATHNAMESIZE);
329 
330 /* Get the Multics path, if it was specified */
331 
332     code = get_arg (0);
333     if ((code != 0)&&(code != BFT_NOARG))
334     {
335       bfterror (code, arg, NULL);
336       if (passed > 0)
337         printf ("BFT: %d reques%s submitted for fetching.\n", passed, ((passed == 1) ? "t" : "ts"));
338       return (code);
339     }
340     else if (code == 0)
341       strcpy (pc_path, arg);
342 
343 /* expand the destination filename to a pathname for the fetch */
344 
345     getpath (pc_path);
346 
347     code = bftfetch (stripquote (mu_path), pc_path, flags, priority);
348     if (code != 0)
349     {
350       bfterror (code, pc_path, NULL);
351       if (passed > 0)
352         printf ("BFT: %d reques%s submitted for fetching.\n", passed, ((passed == 1) ? "t" : "ts"));
353       return (code);
354     }
355     else
356       passed += 1;
357   }
358 
359   /* RL: phx21250 - fixed display message typo "requesst" for singular form */
360   if (passed > 0)
361     printf ("BFT: %d reques%s submitted for fetching.\n", passed, ((passed == 1) ? "t" : "ts"));
362 
363   return (0);
364 }
365 /*^L*/
366 /***************************************************************
367 
368      BFT_LOAD
369 
370      SYNTAX:     bft load
371 
372      PARAMETERS: none
373 
374      FUNCTION:   Because of the difference in nature of loading
375                  an application between Multics and the PC, this
376                  merely tells the user that (s)he must use "bft_load"
377                  command.
378 
379 *****************************************************************/
380 
381 bft_load ()
382 {
383 
384 /* Inform the user of the bft_load command*/
385 
386   printf ("BFT: load is not implemented.  Use bft_load.\n");
387 }
388 /*^L*/
389 /**************************************************************
390 
391      BFT_RECOVER
392 
393      SYNTAX:     bft recover
394                  bft r
395 
396      PARAMETERS: None.
397 
398      FUNCTION:   Initiates the appropriate recover procedures
399                  by emitting a message to the Multics bft to
400                  begin recovery procedures.
401 
402 *****************************************************************/
403 
404 bft_recover ()
405 {
406 int code;
407 
408 /* call the recover fetch entry point */
409 
410   if ((code = bftrecfe ()) != 0)
411     return (bfterror (code, "Recovering fetch requests.", NULL));
412 
413 /* call the recover store entry point */
414 
415   if ((code = bftrecst ()) != 0)
416     return (bfterror (code, "Recovering store requests.", NULL));
417 }
418 /*^L*/
419 /***************************************************************
420 
421      BFT_STORE
422 
423      SYNTAX:     bft store file1 {file2...file1N file2N} {/Control_args}
424                  bft s     file1 {file2...file1N file2N} {/Control_args}
425 
426      PARAMETERS: None.
427 
428      FUNCTION:   Parses the BFT command line after the "store"
429                  keyword for a source and destination filename
430                  if only one filename is given then it is taken
431                  as both the source and destination filename.
432                  If the syntax is correct then the bft store
433                  minor capability is called with the filenames.
434 
435 *****************************************************************/
436 
437 bft_store ()
438 {
439 char mu_path[MAXARGSTRING];           /* holds arguments to be passed to execap  */
440 char pc_path[PATHNAMESIZE];           /* source file name */
441 int  passed;                          /* Number of requests submitted */
442 int  code;
443 
444 
445   passed = 0;
446 
447 /* Repeat until there are no argument */
448 
449   while (argp < argcount - 1)
450   {
451 
452 /* Get PC path */
453 
454     if ((code = get_arg (0)) != 0)
455     {
456       bfterror (code, USAGE_STORE, NULL);
457       if (passed > 0)
458         printf ("BFT: %d reques%s submitted for storing.\n", passed, ((passed == 1) ? "t" : "ts"));
459       return (code);
460     }
461 
462     strncpy (pc_path, arg, PATHNAMESIZE);
463     strncpy (mu_path, "===", PATHNAMESIZE);
464 
465 /* Get the Multics path, if it was specified */
466 
467     code = get_arg (0);
468     if ((code != 0)&&(code != BFT_NOARG))
469     {
470       bfterror (code, arg, NULL);
471       if (passed > 0)
472         printf ("BFT: %d reques%s submitted for storing.\n", passed, ((passed == 1) ? "t" : "ts"));
473       return (code);
474     }
475     else if (code == 0)
476       strcpy (mu_path, arg);
477 
478 /* expand the destination filename to a pathname for the fetch */
479 
480     getpath (pc_path);
481 
482     code = bftstore (pc_path, stripquote (mu_path), flags, priority);
483     if (code != 0)
484     {
485       bfterror (code, pc_path, NULL);
486       if (passed > 0)
487         printf ("BFT: %d reques%s submitted for storing.\n", passed, ((passed == 1) ? "t" : "ts"));
488       return (code);
489     }
490     else
491       passed += 1;
492   }
493 
494   if (passed > 0)
495     printf ("BFT: %d reques%s submitted for storing.\n", passed, ((passed == 1) ? "t" : "ts"));
496 
497   return (0);
498 }
499 
500 /*^L*/
501 /***************************************************************
502 
503      BFT_UNLOAD
504 
505      SYNTAX:     bft unload
506                  bft u
507 
508      PARAMETERS: None.
509 
510      FUNCTION:   Unloads bft from MOWSE.
511 
512 *****************************************************************/
513 
514 bft_unload ()
515 {
516 int code;
517 
518 
519 /* unload the BFT major capability */
520 
521   if ((code = bftunld ()) != 0)
522     return (bfterror (code, "Unloading.", NULL));
523 }
524 /*^L*/
525 /***************************************************************
526 
527      FIND_OPTION
528 
529      PARAMETERS: None.
530 
531      FUNCTION:   Returns a pointer to the option string to an argument.
532                  This is either the [2] character in the current arg,
533                  or the next arg.
534 
535 *****************************************************************/
536 
537 char *find_option ()
538 {
539 
540   if (arg[2] != 0)
541     return (&(arg[2]));
542 
543   argp += 1;
544   arg = argval[argp];
545 
546   if (arg[0] == '/')
547     return (NULL);
548   else if (argp < argcount)
549     return (arg);
550   else
551     return (NULL);
552 }
553 /*^L*/
554 /***************************************************************
555 
556      GET_ARG
557 
558      PARAMETERS: SPECIAL - If the special control_args are to be
559                            treated as a regular arg.
560 
561      FUNCTION:   Sets arg and argp to the next valid non-control
562                  argument.  If "special" is set to True, then accept
563                  "/C STR" control arguments as a non-control argument.
564 
565 *****************************************************************/
566 
567 get_arg (special)
568 
569 int  special;                         /* Accept "/C STR" */
570 {
571 int  queue;                           /* Priority queue */
572 int  code;
573 
574 
575 /* Process all control args until a non-control arg is found */
576 
577   while (1)
578   {
579     argp += 1;
580 
581     if (argp >= argcount)
582       return (BFT_NOARG);
583 
584 /* Is this an argument, no then return 0 */
585 
586     arg = argval[argp];
587     if (arg[0] != '/')
588       return (0);
589 
590 /* Else check for special cases */
591 
592     switch (toupper (arg[1]))
593     {
594       case 'E':                       /* These are special */
595       case 'I':
596         if (special)                  /* Caller wants one of these */
597           return (0);
598         else                          /* Skip the param */
599           find_option ();
600         break;
601 
602       case 'N':                       /* Skip param */
603       case 'F':
604       case 'Q':
605         find_option ();
606         break;
607 
608       default:                        /* No param */
609         break;
610     }
611   }
612 }
613 /*^L*/
614 /***************************************************************
615 
616      PARSE_ARGS
617 
618      PARAMETERS: None.
619 
620      FUNCTION:   Processes a control argument.
621 
622                  Acceptable control args:
623 
624                     /F ascii | binary   - file type {ascii}
625                     /N on | off         - notify {off}
626                     /Q N                - priority {3}
627 
628                  Control arguments skipped (as they are really "single"
629                  arguments):
630 
631                     /E NAME             - Request entry
632                     /I NAME             - Request ID
633 
634 *****************************************************************/
635 
636 parse_args ()
637 
638 {
639 int  code;
640 int  queue;                           /* Transfer priority */
641 
642   code = 0;
643 
644   for (argp = 1; argp < argcount; argp++)
645   {
646     arg = argval[argp];
647 
648     if (arg[0] == '/')
649     {
650       switch (toupper (arg[1]))
651       {
652         case 'F':                                         /* File_type */
653           if (!(control_sw & STORE_SW || control_sw & FETCH_SW))
654             code = BFT_INCOMPATIBLE;
655           else if ((arg = find_option ()) == NULL)
656             code = BFT_EXPECTING;
657           else if (!strcmp (upper (arg), "ASCII"))
658             flags &= ~BFT_BINARY;
659           else if (!strcmp (upper (arg), "BINARY"))
660             flags |= BFT_BINARY;
661           else
662             code = BFT_BADOPT;
663           break;
664 
665         case 'N':                                         /* Notify */
666           if (!(control_sw & STORE_SW || control_sw & FETCH_SW))
667             code = BFT_INCOMPATIBLE;
668           else if ((arg = find_option ()) == NULL)
669             code = BFT_EXPECTING;
670           else if (!strcmp (upper (arg), "OFF"))
671             flags &= ~BFT_NOTIFY;
672           else if (!strcmp (upper (arg), "ON"))
673             flags |= BFT_NOTIFY;
674           else
675             code = BFT_BADOPT;
676           break;
677 
678         case 'Q':                                         /* Queue */
679           if (!(control_sw & STORE_SW || control_sw & FETCH_SW))
680             code = BFT_INCOMPATIBLE;
681           else if ((arg = find_option ()) == NULL)
682             code = BFT_EXPECTING;
683           else if (strlen (arg) != 1)
684             code = BFT_BADOPT;
685           else if (!isdigit (arg[0]))
686             code = BFT_BADOPT;
687           else
688           {
689             queue = (int) (arg[0] - '0');
690             if ((queue < BFT_MIN_PRIORITY) || (queue > BFT_MAX_PRIORITY))
691               code = BFT_INVALID_PRIORITY;
692             else
693               priority = queue;
694           }
695           break;
696 
697         case 'I':                                         /* ID */
698           if (!(control_sw & CANCEL_SW))
699             code = BFT_INCOMPATIBLE;
700           break;
701 
702         case 'E':                                         /* Entry */
703           if (!(control_sw & CANCEL_SW))
704             code = BFT_INCOMPATIBLE;
705           break;
706 
707         default:                                          /* Error */
708           code = BFT_BADARG;
709           break;
710       }
711 
712       if (code != 0)
713         return (code);
714     }
715   }
716 
717   return (0);
718 }
719 /*^L*/
720 /***************************************************************
721 
722      UPPER
723 
724      PARAMETERS: STRING - string to convert to upper.
725 
726      FUNCTION:   Convert a character string to upper case.
727 
728 *****************************************************************/
729 
730 char *upper (str)
731 
732 char *str;
733 {
734 int  i;
735 
736   for (i = 0; str[i]; i++)
737     str[i] = toupper (str[i]);
738 
739   return (str);
740 }