2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
10 #include <afsconfig.h>
11 #include <afs/param.h>
19 #include <rx/rx_globals.h>
21 #include <afs/bubasics.h>
22 #include <afs/afsutil.h>
24 #include <afs/cellconfig.h>
29 #include <afs/afsint.h>
30 #include <afs/volser.h> /*VLDB_MAXSERVERS */
31 #include <afs/com_err.h>
34 #include <afs/kautils.h>
35 #include <afs/vlserver.h>
38 #include <afs/tcdata.h>
40 #include "bc.h" /*Backup Coordinator structs and defs */
41 #include "bucoord_internal.h"
42 #include "bucoord_prototypes.h"
44 int localauth
, interact
, nobutcauth
;
48 * Global configuration information for the Backup Coordinator.
50 struct bc_config
*bc_globalConfig
; /*Ptr to global BC configuration info */
52 struct ubik_client
*cstruct
; /* Ptr to Ubik client structure */
53 time_t tokenExpires
; /* The token's expiration time */
55 static const char *DefaultConfDir
; /*Default backup config directory */
56 static int bcInit
= 0; /* backupInit called yet ? */
57 char *whoami
= "backup";
59 /* dummy routine for the audit work. It should do nothing since audits */
60 /* occur at the server level and bos is not a server. */
68 * Initialize all the error tables that may be used by com_err
74 initialize_ACFG_error_table();
75 initialize_KA_error_table();
76 initialize_RXK_error_table();
77 initialize_CMD_error_table();
78 initialize_VL_error_table();
79 initialize_BUTM_error_table();
80 initialize_VOLS_error_table();
81 initialize_BUTC_error_table();
82 initialize_BUTX_error_table();
83 initialize_BUDB_error_table();
84 initialize_BUCD_error_table();
85 initialize_KTC_error_table();
89 * got to account for the errors which are volume related but
90 * not dealt with by standard errno and com_err stuff.
93 bc_HandleMisc(afs_int32 code
)
95 if (((code
<= VMOVED
) && (code
>= VSALVAGE
)) || (code
< 0)) {
98 fprintf(STDERR
, "Possible communication failure\n");
101 fprintf(STDERR
, "Volume needs salvage\n");
104 fprintf(STDERR
, "Bad vnode number quoted\n");
108 "Volume not attached, does not exist, or not on line\n");
111 fprintf(STDERR
, "Volume already exists\n");
114 fprintf(STDERR
, "Volume is not in service\n");
117 fprintf(STDERR
, "Volume is off line\n");
120 fprintf(STDERR
, "Volume is already on line\n");
123 fprintf(STDERR
, "Partition is full\n");
126 fprintf(STDERR
, "Volume max quota exceeded\n");
129 fprintf(STDERR
, "Volume temporarily unavailable\n");
132 fprintf(STDERR
, "Volume has moved to another server\n");
141 /* Return true if line is all whitespace */
143 LineIsBlank(char *aline
)
147 while ((tc
= *aline
++))
148 if ((tc
!= ' ') && (tc
!= '\t') && (tc
!= '\n'))
156 * initialize configuration information that is stored as text blocks
160 bc_InitTextConfig(void)
162 udbClientTextP ctPtr
;
165 extern struct bc_config
*bc_globalConfig
;
167 mkdir(DefaultConfDir
, 777); /* temporary */
169 /* initialize the client text structures */
170 ctPtr
= &bc_globalConfig
->configText
[0];
172 for (i
= 0; i
< TB_NUM
; i
++) {
173 memset(ctPtr
, 0, sizeof(*ctPtr
));
175 ctPtr
->textVersion
= -1;
182 /*----------------------------------------------------------------------------
186 * Routine that is called when the backup coordinator is invoked, responsible for
187 * basic initialization and some command line parsing.
190 * Zero (but may exit the entire program on error!)
193 * Nothing interesting.
196 * Initializes this program.
197 *----------------------------------------------------------------------------
204 static int initd
= 0; /* ever called? */
206 PROCESS pid
; /* LWP process ID */
209 initialize_CMD_error_table();
211 /* don't run more than once */
213 afs_com_err(whoami
, 0, "Backup already initialized.");
218 code
= bc_InitConfig((char *)DefaultConfDir
);
220 afs_com_err(whoami
, code
,
221 "Can't initialize from config files in directory '%s'",
229 code
= LWP_InitializeProcessSupport(LWP_NORMAL_PRIORITY
, &pid
);
231 afs_com_err(whoami
, code
, "; Can't initialize LWP");
235 code
= rx_Init(htons(0));
237 afs_com_err(whoami
, code
, "; Can't initialize Rx");
241 rx_SetRxDeadTime(60);
243 /* VLDB initialization */
244 code
= vldbClientInit(0, localauth
, tcell
, &cstruct
, &tokenExpires
);
248 /* Backup database initialization */
249 code
= udbClientInit(0, localauth
, tcell
);
253 /* setup status monitoring thread */
256 LWP_CreateProcess(statusWatcher
, 20480, LWP_NORMAL_PRIORITY
,
257 (void *)2, "statusWatcher", &watcherPid
);
259 afs_com_err(whoami
, code
, "; Can't create status monitor task");
266 /*----------------------------------------------------------------------------
270 * Make sure we mark down when we need to exit the Backup Coordinator.
271 * Specifically, we don't want to continue when our help and apropos
272 * routines are called from the command line.
275 * as : Ptr to the command syntax descriptor.
281 * This routine is called right before each of the Backup Coordinator
282 * opcode routines are invoked.
284 *----------------------------------------------------------------------------
288 MyBeforeProc(struct cmd_syndesc
*as
, void *arock
)
292 /* Handling the command line opcode */
294 localauth
= ((as
&& as
->parms
[14].items
) ? 1 : 0);
295 nobutcauth
= ((as
&& as
->parms
[16].items
) ? 1 : 0);
296 if (as
&& as
->parms
[15].items
)
297 strcpy(tcell
, as
->parms
[15].items
->data
);
303 afs_com_err(whoami
, code
, "; Can't initialize backup");
307 /* Get initial information from the database */
308 code
= bc_InitTextConfig();
310 afs_com_err(whoami
, code
,
311 "; Can't obtain configuration text from backup database");
323 #include "AFS_component_version_number.c"
325 #define MAXRECURSION 20
326 extern int dontExecute
; /* declared in commands.c */
327 extern char *loadFile
; /* declared in commands.c */
328 char lineBuffer
[1024]; /* Line typed in by user or read from load file */
331 * This will dispatch a command. It holds a recursive loop for the
332 * "dump -file" option. This option reads backup commands from a file.
334 * Cannot put this code on other side of cmd_Dispatch call (in
335 * commands.c) because when make a dispatch call when in a dispatch
336 * call, environment is mucked up.
338 * To avoid multiple processes stepping on each other in the dispatch code,
339 * put a lock around it so only 1 process gets in at a time.
342 struct Lock dispatchLock
; /* lock on the Dispatch call */
343 #define lock_Dispatch() ObtainWriteLock(&dispatchLock)
344 #define unlock_Dispatch() ReleaseWriteLock(&dispatchLock)
347 doDispatch(afs_int32 targc
,
349 afs_int32 dispatchCount
) /* to prevent infinite recursion */
357 int noExecute
; /* local capy of global variable */
358 char *internalLoadFile
;
363 code
= cmd_Dispatch(targc
, targv
);
364 internalLoadFile
= loadFile
;
368 if (internalLoadFile
) { /* Load a file in */
369 if (dispatchCount
> MAXRECURSION
) { /* Beware recursive loops. */
370 afs_com_err(whoami
, 0, "Potential recursion: will not load file %s",
376 fd
= fopen(internalLoadFile
, "r"); /* Open the load file */
378 afs_com_err(whoami
, errno
, "; Cannot open file %s", internalLoadFile
);
383 noExecute
= dontExecute
;
385 printf("Would have executed the following commands:\n");
388 while (fgets(lineBuffer
, sizeof(lineBuffer
) - 1, fd
)) { /* Get commands from file */
391 i
= strlen(lineBuffer
) - 1;
392 if (lineBuffer
[i
] == '\n') /* Drop return at end of line */
393 lineBuffer
[i
] = '\0';
396 printf(" %s\n", lineBuffer
); /* echo */
398 printf("------> %s\n", lineBuffer
); /* echo */
400 if (!LineIsBlank(lineBuffer
) && /* Skip if blank line */
401 (lineBuffer
[0] != '#') && /* or comment */
402 (!noExecute
)) { /* or no execute */
403 c
= cmd_ParseLine(lineBuffer
, sargv
, &sargc
, MAXV
);
405 afs_com_err(whoami
, c
, "; Can't parse line");
407 doDispatch(sargc
, sargv
, dispatchCount
+ 1); /* Recursive - ignore error */
408 cmd_FreeArgv(sargv
); /* Free up arguments */
417 if (internalLoadFile
)
418 free(internalLoadFile
);
423 bc_interactCmd(struct cmd_syndesc
*as
, void *arock
)
430 add_std_args(struct cmd_syndesc
*ts
)
433 cmd_AddParm(ts
, "-localauth", CMD_FLAG
, CMD_OPTIONAL
,
434 "local authentication");
435 cmd_AddParm(ts
, "-cell", CMD_SINGLE
, CMD_OPTIONAL
, "cell name");
436 cmd_AddParm(ts
, "-nobutcauth", CMD_FLAG
, CMD_OPTIONAL
,
437 "no authentication to butc");
441 main(int argc
, char **argv
)
443 char *targv
[MAXV
]; /*Ptr to parsed argv stuff */
444 afs_int32 targc
; /*Num parsed arguments */
445 afs_int32 code
; /*Return code */
446 struct cmd_syndesc
*ts
; /*Ptr to parsed command line */
452 * The following signal action for AIX is necessary so that in case of a
453 * crash (i.e. core is generated) we can include the user's data section
454 * in the core dump. Unfortunately, by default, only a partial core is
455 * generated which, in many cases, isn't too useful.
457 struct sigaction nsa
;
459 sigemptyset(&nsa
.sa_mask
);
460 nsa
.sa_handler
= SIG_DFL
;
461 nsa
.sa_flags
= SA_FULLDUMP
;
462 sigaction(SIGSEGV
, &nsa
, NULL
);
464 Lock_Init(&dispatchLock
);
465 InitErrTabs(); /* init all the error tables which may be used */
467 /* setup the default backup dir */
468 DefaultConfDir
= AFSDIR_SERVER_BACKUP_DIRPATH
;
469 /* Get early warning if the command is interacive mode or not */
474 if (argv
[1][0] == '-') {
476 if (strcmp(argv
[1], "-help") == 0) {
482 cmd_SetBeforeProc(MyBeforeProc
, NULL
);
484 ts
= cmd_CreateSyntax("dump", bc_DumpCmd
, NULL
, 0, "start dump");
485 cmd_AddParm(ts
, "-volumeset", CMD_SINGLE
, CMD_OPTIONAL
,
487 cmd_AddParm(ts
, "-dump", CMD_SINGLE
, CMD_OPTIONAL
, "dump level name");
488 cmd_AddParm(ts
, "-portoffset", CMD_SINGLE
, CMD_OPTIONAL
,
490 cmd_AddParm(ts
, "-at", CMD_LIST
, CMD_OPTIONAL
, "Date/time to start dump");
491 cmd_AddParm(ts
, "-append", CMD_FLAG
, CMD_OPTIONAL
,
492 "append to existing dump set");
493 cmd_AddParm(ts
, "-dryrun", CMD_FLAG
, CMD_OPTIONAL
,
494 "list what would be done, don't do it");
495 cmd_AddParmAlias(ts
, 5, "-n");
496 cmd_AddParm(ts
, "-file", CMD_SINGLE
, CMD_OPTIONAL
, "load file");
500 ts
= cmd_CreateSyntax("volrestore", bc_VolRestoreCmd
, NULL
, 0,
502 cmd_AddParm(ts
, "-server", CMD_SINGLE
, CMD_REQUIRED
,
503 "destination machine");
504 cmd_AddParm(ts
, "-partition", CMD_SINGLE
, CMD_REQUIRED
,
505 "destination partition");
506 cmd_AddParm(ts
, "-volume", CMD_LIST
, CMD_REQUIRED
,
507 "volume(s) to restore");
508 cmd_AddParm(ts
, "-extension", CMD_SINGLE
, CMD_OPTIONAL
,
509 "new volume name extension");
510 cmd_AddParm(ts
, "-date", CMD_LIST
, CMD_OPTIONAL
,
511 "date from which to restore");
512 cmd_AddParm(ts
, "-portoffset", CMD_LIST
, CMD_OPTIONAL
, "TC port offsets");
513 cmd_AddParm(ts
, "-dryrun", CMD_FLAG
, CMD_OPTIONAL
,
514 "list what would be done, don't do it");
515 cmd_AddParmAlias(ts
, 6, "-n");
516 cmd_AddParm(ts
, "-usedump", CMD_SINGLE
, CMD_OPTIONAL
,
517 "specify the dumpID to restore from");
521 ts
= cmd_CreateSyntax("diskrestore", bc_DiskRestoreCmd
, NULL
, 0,
522 "restore partition");
523 cmd_AddParm(ts
, "-server", CMD_SINGLE
, CMD_REQUIRED
,
524 "machine to restore");
525 cmd_AddParm(ts
, "-partition", CMD_SINGLE
, CMD_REQUIRED
,
526 "partition to restore");
527 cmd_AddParm(ts
, "-portoffset", CMD_LIST
, CMD_OPTIONAL
, "TC port offset");
529 cmd_AddParm(ts
, "-newserver", CMD_SINGLE
, CMD_OPTIONAL
,
530 "destination machine");
531 cmd_AddParm(ts
, "-newpartition", CMD_SINGLE
, CMD_OPTIONAL
,
532 "destination partition");
533 cmd_AddParm(ts
, "-extension", CMD_SINGLE
, CMD_OPTIONAL
,
534 "new volume name extension");
535 cmd_AddParm(ts
, "-dryrun", CMD_FLAG
, CMD_OPTIONAL
,
536 "list what would be done, don't do it");
537 cmd_AddParmAlias(ts
, 11, "-n");
541 cmd_CreateSyntax("quit", bc_QuitCmd
, NULL
, 0, "leave the program");
543 ts
= cmd_CreateSyntax("volsetrestore", bc_VolsetRestoreCmd
, NULL
, 0,
544 "restore a set of volumes");
545 cmd_AddParm(ts
, "-name", CMD_SINGLE
, CMD_OPTIONAL
, "volume set name");
546 cmd_AddParm(ts
, "-file", CMD_SINGLE
, CMD_OPTIONAL
, "file name");
547 cmd_AddParm(ts
, "-portoffset", CMD_LIST
, CMD_OPTIONAL
, "TC port offset");
548 cmd_AddParm(ts
, "-extension", CMD_SINGLE
, CMD_OPTIONAL
,
549 "new volume name extension");
550 cmd_AddParm(ts
, "-dryrun", CMD_FLAG
, CMD_OPTIONAL
,
551 "list what would be done, don't do it");
552 cmd_AddParmAlias(ts
, 4, "-n");
556 ts
= cmd_CreateSyntax("addhost", bc_AddHostCmd
, NULL
, 0, "add host to config");
557 cmd_AddParm(ts
, "-tapehost", CMD_SINGLE
, CMD_REQUIRED
,
558 "tape machine name");
559 cmd_AddParm(ts
, "-portoffset", CMD_SINGLE
, CMD_OPTIONAL
,
564 ts
= cmd_CreateSyntax("delhost", bc_DeleteHostCmd
, NULL
, 0,
565 "delete host to config");
566 cmd_AddParm(ts
, "-tapehost", CMD_SINGLE
, CMD_REQUIRED
,
567 "tape machine name");
568 cmd_AddParm(ts
, "-portoffset", CMD_SINGLE
, CMD_OPTIONAL
,
573 ts
= cmd_CreateSyntax("listhosts", bc_ListHostsCmd
, NULL
, 0,
574 "list config hosts");
578 cmd_CreateSyntax("jobs", bc_JobsCmd
, NULL
, 0, "list running jobs");
580 ts
= cmd_CreateSyntax("kill", bc_KillCmd
, NULL
, 0, "kill running job");
581 cmd_AddParm(ts
, "-id", CMD_SINGLE
, CMD_REQUIRED
,
582 "job ID or dump set name");
584 ts
= cmd_CreateSyntax("listvolsets", bc_ListVolSetCmd
, NULL
, 0,
586 cmd_AddParm(ts
, "-name", CMD_SINGLE
, CMD_OPTIONAL
, "volume set name");
590 ts
= cmd_CreateSyntax("listdumps", bc_ListDumpScheduleCmd
, NULL
, 0,
591 "list dump schedules");
595 ts
= cmd_CreateSyntax("addvolset", bc_AddVolSetCmd
, NULL
, 0,
596 "create a new volume set");
597 cmd_AddParm(ts
, "-name", CMD_SINGLE
, CMD_REQUIRED
, "volume set name");
598 cmd_AddParm(ts
, "-temporary", CMD_FLAG
, CMD_OPTIONAL
,
599 "temporary volume set");
603 ts
= cmd_CreateSyntax("status", bc_GetTapeStatusCmd
, NULL
, 0,
604 "get tape coordinator status");
605 cmd_AddParm(ts
, "-portoffset", CMD_SINGLE
, CMD_OPTIONAL
,
610 ts
= cmd_CreateSyntax("delvolset", bc_DeleteVolSetCmd
, NULL
, 0,
611 "delete a volume set");
612 cmd_AddParm(ts
, "-name", CMD_LIST
, CMD_REQUIRED
, "volume set name");
616 ts
= cmd_CreateSyntax("addvolentry", bc_AddVolEntryCmd
, NULL
, 0,
617 "add a new volume entry");
618 cmd_AddParm(ts
, "-name", CMD_SINGLE
, CMD_REQUIRED
, "volume set name");
619 cmd_AddParm(ts
, "-server", CMD_SINGLE
, CMD_REQUIRED
, "machine name");
620 cmd_AddParm(ts
, "-partition", CMD_SINGLE
, CMD_REQUIRED
, "partition name");
621 cmd_AddParm(ts
, "-volumes", CMD_SINGLE
, CMD_REQUIRED
,
622 "volume name (regular expression)");
626 ts
= cmd_CreateSyntax("delvolentry", bc_DeleteVolEntryCmd
, NULL
, 0,
627 "delete a volume set sub-entry");
628 cmd_AddParm(ts
, "-name", CMD_SINGLE
, CMD_REQUIRED
, "volume set name");
629 cmd_AddParm(ts
, "-entry", CMD_SINGLE
, CMD_REQUIRED
, "volume set index");
633 ts
= cmd_CreateSyntax("adddump", bc_AddDumpCmd
, NULL
, 0, "add dump schedule");
634 cmd_AddParm(ts
, "-dump", CMD_LIST
, CMD_REQUIRED
, "dump level name");
635 cmd_AddParm(ts
, "-expires", CMD_LIST
, CMD_OPTIONAL
, "expiration date");
639 ts
= cmd_CreateSyntax("deldump", bc_DeleteDumpCmd
, NULL
, 0,
640 "delete dump schedule");
641 cmd_AddParm(ts
, "-dump", CMD_SINGLE
, CMD_REQUIRED
, "dump level name");
645 ts
= cmd_CreateSyntax("labeltape", bc_LabelTapeCmd
, NULL
, 0, "label a tape");
646 cmd_AddParm(ts
, "-name", CMD_SINGLE
, CMD_OPTIONAL
,
647 "AFS tape name, defaults to NULL");
648 cmd_AddParm(ts
, "-size", CMD_SINGLE
, CMD_OPTIONAL
,
649 "tape size in Kbytes, defaults to size in tapeconfig");
650 cmd_AddParm(ts
, "-portoffset", CMD_SINGLE
, CMD_OPTIONAL
,
652 cmd_AddParm(ts
, "-pname", CMD_SINGLE
, CMD_OPTIONAL
,
653 "permanent tape name");
657 ts
= cmd_CreateSyntax("readlabel", bc_ReadLabelCmd
, NULL
, 0,
658 "read the label on tape");
659 cmd_AddParm(ts
, "-portoffset", CMD_SINGLE
, CMD_OPTIONAL
,
664 ts
= cmd_CreateSyntax("scantape", bc_ScanDumpsCmd
, NULL
, 0,
665 "dump information recovery from tape");
666 cmd_AddParm(ts
, "-dbadd", CMD_FLAG
, CMD_OPTIONAL
,
667 "add information to the database");
668 cmd_AddParm(ts
, "-portoffset", CMD_SINGLE
, CMD_OPTIONAL
,
673 ts
= cmd_CreateSyntax("volinfo", bc_dblookupCmd
, NULL
, 0,
674 "query the backup database");
675 cmd_AddParm(ts
, "-volume", CMD_SINGLE
, CMD_REQUIRED
, "volume name");
679 ts
= cmd_CreateSyntax("setexp", bc_SetExpCmd
, NULL
, 0,
680 "set/clear dump expiration dates");
681 cmd_AddParm(ts
, "-dump", CMD_LIST
, CMD_REQUIRED
, "dump level name");
682 cmd_AddParm(ts
, "-expires", CMD_LIST
, CMD_OPTIONAL
, "expiration date");
686 ts
= cmd_CreateSyntax("savedb", bc_saveDbCmd
, NULL
, 0, "save backup database");
687 cmd_AddParm(ts
, "-portoffset", CMD_SINGLE
, CMD_OPTIONAL
,
689 cmd_AddParm(ts
, "-archive", CMD_LIST
, CMD_OPTIONAL
, "date time");
693 ts
= cmd_CreateSyntax("restoredb", bc_restoreDbCmd
, NULL
, 0,
694 "restore backup database");
695 cmd_AddParm(ts
, "-portoffset", CMD_SINGLE
, CMD_OPTIONAL
,
700 ts
= cmd_CreateSyntax("dumpinfo", bc_dumpInfoCmd
, NULL
, 0,
701 "provide information about a dump in the database");
702 cmd_AddParm(ts
, "-ndumps", CMD_SINGLE
, CMD_OPTIONAL
, "no. of dumps");
703 cmd_AddParm(ts
, "-id", CMD_SINGLE
, CMD_OPTIONAL
, "dump id");
704 cmd_AddParm(ts
, "-verbose", CMD_FLAG
, CMD_OPTIONAL
,
705 "detailed description");
709 ts
= cmd_CreateSyntax("dbverify", bc_dbVerifyCmd
, NULL
, 0,
710 "check ubik database integrity");
711 cmd_AddParm(ts
, "-detail", CMD_FLAG
, CMD_OPTIONAL
, "additional details");
715 ts
= cmd_CreateSyntax("deletedump", bc_deleteDumpCmd
, NULL
, 0,
716 "delete dumps from the database");
717 cmd_AddParm(ts
, "-dumpid", CMD_LIST
, CMD_OPTIONAL
, "dump id");
718 cmd_AddParm(ts
, "-from", CMD_LIST
, CMD_OPTIONAL
, "date time");
719 cmd_AddParm(ts
, "-to", CMD_LIST
, CMD_OPTIONAL
, "date time");
720 cmd_AddParm(ts
, "-portoffset", CMD_SINGLE
, CMD_OPTIONAL
, "TC port offset");
721 cmd_AddParmAlias(ts
, 3, "-port");
722 cmd_AddParm(ts
, "-groupid", CMD_SINGLE
, CMD_OPTIONAL
, "group ID");
723 cmd_AddParm(ts
, "-dbonly", CMD_FLAG
, CMD_OPTIONAL
,
724 "delete the dump from the backup database only");
725 cmd_AddParm(ts
, "-force", CMD_FLAG
, CMD_OPTIONAL
,
726 "always delete from backup database");
727 cmd_AddParm(ts
, "-noexecute", CMD_FLAG
, CMD_OPTIONAL
|CMD_HIDDEN
, "");
728 cmd_AddParm(ts
, "-dryrun", CMD_FLAG
, CMD_OPTIONAL
,
729 "list the dumps, don't delete anything");
730 cmd_AddParmAlias(ts
, 8, "-n");
735 ts
= cmd_CreateSyntax("interactive", bc_interactCmd
, NULL
, 0,
736 "enter interactive mode");
740 * Now execute the command.
744 targv
[targc
++] = argv
[0];
746 targv
[targc
++] = "interactive";
747 for (i
= 1; i
< argc
; i
++)
748 targv
[targc
++] = argv
[i
];
750 code
= doDispatch(targc
, targv
, 1);
752 if (!interact
|| !bcInit
) { /* Non-interactive mode */
756 code
= bc_WaitForNoJobs(); /* wait for any jobs to finish */
757 exit(code
); /* and exit */
760 /* Iterate on command lines, interpreting user commands (interactive mode) */
768 while ((ret
= LWP_GetLine(lineBuffer
, sizeof(lineBuffer
))) == 0)
769 printf("%s: Command line too long\n", whoami
); /* line too long */
772 return 0; /* Got EOF */
774 if (!LineIsBlank(lineBuffer
)) {
775 code
= cmd_ParseLine(lineBuffer
, targv
, &targc
, MAXV
);
777 afs_com_err(whoami
, code
, "; Can't parse line: '%s'",
778 afs_error_message(code
));
780 doDispatch(targc
, targv
, 1);