void initializeArgHandler(void) { struct cmd_syndesc *cptr; cmd_SetBeforeProc(MyBeforeProc, NULL); cptr = cmd_CreateSyntax(NULL, argHandler, NULL, 0, "Backup database server"); cmd_AddParm(cptr, "-database", CMD_SINGLE, CMD_OPTIONAL, "database directory"); cmd_AddParm(cptr, "-cellservdb", CMD_SINGLE, CMD_OPTIONAL, "cell configuration directory"); cmd_AddParm(cptr, "-resetdb", CMD_FLAG, CMD_OPTIONAL, "truncate the database"); cmd_AddParm(cptr, "-noauth", CMD_FLAG, CMD_OPTIONAL, "run without authentication"); cmd_AddParm(cptr, "-smallht", CMD_FLAG, CMD_OPTIONAL, "use small hash tables"); cmd_AddParm(cptr, "-servers", CMD_LIST, CMD_OPTIONAL, "list of ubik database servers"); cmd_AddParm(cptr, "-ubikbuffers", CMD_SINGLE, CMD_OPTIONAL, "the number of ubik buffers"); cmd_AddParm(cptr, "-auditlog", CMD_SINGLE, CMD_OPTIONAL, "audit log path"); cmd_AddParm(cptr, "-p", CMD_SINGLE, CMD_OPTIONAL, "number of processes"); cmd_AddParm(cptr, "-rxbind", CMD_FLAG, CMD_OPTIONAL, "bind the Rx socket (primary interface only)"); cmd_AddParm(cptr, "-audit-interface", CMD_SINGLE, CMD_OPTIONAL, "audit interface (file or sysvmq)"); cmd_AddParm(cptr, "-transarc-logs", CMD_FLAG, CMD_OPTIONAL, "enable Transarc style logging"); }
int main(int argc, char **argv) { /*main */ char *targv[MAXV]; /*Ptr to parsed argv stuff */ afs_int32 targc; /*Num parsed arguments */ afs_int32 code; /*Return code */ struct cmd_syndesc *ts; /*Ptr to parsed command line */ int i; #ifdef AFS_AIX32_ENV /* * The following signal action for AIX is necessary so that in case of a * crash (i.e. core is generated) we can include the user's data section * in the core dump. Unfortunately, by default, only a partial core is * generated which, in many cases, isn't too useful. */ struct sigaction nsa; sigemptyset(&nsa.sa_mask); nsa.sa_handler = SIG_DFL; nsa.sa_flags = SA_FULLDUMP; sigaction(SIGSEGV, &nsa, NULL); #endif Lock_Init(&dispatchLock); InitErrTabs(); /* init all the error tables which may be used */ /* setup the default backup dir */ DefaultConfDir = AFSDIR_SERVER_BACKUP_DIRPATH; /* Get early warning if the command is interacive mode or not */ interact = (((argc < 2) || (argv[1][0] == '-')) ? 1 : 0); cmd_SetBeforeProc(MyBeforeProc, NULL); ts = cmd_CreateSyntax("dump", bc_DumpCmd, NULL, "start dump"); cmd_AddParm(ts, "-volumeset", CMD_SINGLE, CMD_OPTIONAL, "volume set name"); cmd_AddParm(ts, "-dump", CMD_SINGLE, CMD_OPTIONAL, "dump level name"); cmd_AddParm(ts, "-portoffset", CMD_SINGLE, CMD_OPTIONAL, "TC port offset"); cmd_AddParm(ts, "-at", CMD_LIST, CMD_OPTIONAL, "Date/time to start dump"); cmd_AddParm(ts, "-append", CMD_FLAG, CMD_OPTIONAL, "append to existing dump set"); cmd_AddParm(ts, "-dryrun", CMD_FLAG, CMD_OPTIONAL, "list what would be done, don't do it"); cmd_AddParmAlias(ts, 5, "-n"); cmd_AddParm(ts, "-file", CMD_SINGLE, CMD_OPTIONAL, "load file"); if (!interact) add_std_args(ts); ts = cmd_CreateSyntax("volrestore", bc_VolRestoreCmd, NULL, "restore volume"); cmd_AddParm(ts, "-server", CMD_SINGLE, CMD_REQUIRED, "destination machine"); cmd_AddParm(ts, "-partition", CMD_SINGLE, CMD_REQUIRED, "destination partition"); cmd_AddParm(ts, "-volume", CMD_LIST, CMD_REQUIRED, "volume(s) to restore"); cmd_AddParm(ts, "-extension", CMD_SINGLE, CMD_OPTIONAL, "new volume name extension"); cmd_AddParm(ts, "-date", CMD_LIST, CMD_OPTIONAL, "date from which to restore"); cmd_AddParm(ts, "-portoffset", CMD_LIST, CMD_OPTIONAL, "TC port offsets"); cmd_AddParm(ts, "-dryrun", CMD_FLAG, CMD_OPTIONAL, "list what would be done, don't do it"); cmd_AddParmAlias(ts, 6, "-n"); cmd_AddParm(ts, "-usedump", CMD_SINGLE, CMD_OPTIONAL, "specify the dumpID to restore from"); if (!interact) add_std_args(ts); ts = cmd_CreateSyntax("diskrestore", bc_DiskRestoreCmd, NULL, "restore partition"); cmd_AddParm(ts, "-server", CMD_SINGLE, CMD_REQUIRED, "machine to restore"); cmd_AddParm(ts, "-partition", CMD_SINGLE, CMD_REQUIRED, "partition to restore"); cmd_AddParm(ts, "-portoffset", CMD_LIST, CMD_OPTIONAL, "TC port offset"); cmd_Seek(ts, 8); cmd_AddParm(ts, "-newserver", CMD_SINGLE, CMD_OPTIONAL, "destination machine"); cmd_AddParm(ts, "-newpartition", CMD_SINGLE, CMD_OPTIONAL, "destination partition"); cmd_AddParm(ts, "-extension", CMD_SINGLE, CMD_OPTIONAL, "new volume name extension"); cmd_AddParm(ts, "-dryrun", CMD_FLAG, CMD_OPTIONAL, "list what would be done, don't do it"); cmd_AddParmAlias(ts, 11, "-n"); if (!interact) add_std_args(ts); cmd_CreateSyntax("quit", bc_QuitCmd, NULL, "leave the program"); ts = cmd_CreateSyntax("volsetrestore", bc_VolsetRestoreCmd, NULL, "restore a set of volumes"); cmd_AddParm(ts, "-name", CMD_SINGLE, CMD_OPTIONAL, "volume set name"); cmd_AddParm(ts, "-file", CMD_SINGLE, CMD_OPTIONAL, "file name"); cmd_AddParm(ts, "-portoffset", CMD_LIST, CMD_OPTIONAL, "TC port offset"); cmd_AddParm(ts, "-extension", CMD_SINGLE, CMD_OPTIONAL, "new volume name extension"); cmd_AddParm(ts, "-dryrun", CMD_FLAG, CMD_OPTIONAL, "list what would be done, don't do it"); cmd_AddParmAlias(ts, 4, "-n"); if (!interact) add_std_args(ts); ts = cmd_CreateSyntax("addhost", bc_AddHostCmd, NULL, "add host to config"); cmd_AddParm(ts, "-tapehost", CMD_SINGLE, CMD_REQUIRED, "tape machine name"); cmd_AddParm(ts, "-portoffset", CMD_SINGLE, CMD_OPTIONAL, "TC port offset"); if (!interact) add_std_args(ts); ts = cmd_CreateSyntax("delhost", bc_DeleteHostCmd, NULL, "delete host to config"); cmd_AddParm(ts, "-tapehost", CMD_SINGLE, CMD_REQUIRED, "tape machine name"); cmd_AddParm(ts, "-portoffset", CMD_SINGLE, CMD_OPTIONAL, "TC port offset"); if (!interact) add_std_args(ts); ts = cmd_CreateSyntax("listhosts", bc_ListHostsCmd, NULL, "list config hosts"); if (!interact) add_std_args(ts); cmd_CreateSyntax("jobs", bc_JobsCmd, NULL, "list running jobs"); ts = cmd_CreateSyntax("kill", bc_KillCmd, NULL, "kill running job"); cmd_AddParm(ts, "-id", CMD_SINGLE, CMD_REQUIRED, "job ID or dump set name"); ts = cmd_CreateSyntax("listvolsets", bc_ListVolSetCmd, NULL, "list volume sets"); cmd_AddParm(ts, "-name", CMD_SINGLE, CMD_OPTIONAL, "volume set name"); if (!interact) add_std_args(ts); ts = cmd_CreateSyntax("listdumps", bc_ListDumpScheduleCmd, NULL, "list dump schedules"); if (!interact) add_std_args(ts); ts = cmd_CreateSyntax("addvolset", bc_AddVolSetCmd, NULL, "create a new volume set"); cmd_AddParm(ts, "-name", CMD_SINGLE, CMD_REQUIRED, "volume set name"); cmd_AddParm(ts, "-temporary", CMD_FLAG, CMD_OPTIONAL, "temporary volume set"); if (!interact) add_std_args(ts); ts = cmd_CreateSyntax("status", bc_GetTapeStatusCmd, NULL, "get tape coordinator status"); cmd_AddParm(ts, "-portoffset", CMD_SINGLE, CMD_OPTIONAL, "TC port offset"); if (!interact) add_std_args(ts); ts = cmd_CreateSyntax("delvolset", bc_DeleteVolSetCmd, NULL, "delete a volume set"); cmd_AddParm(ts, "-name", CMD_LIST, CMD_REQUIRED, "volume set name"); if (!interact) add_std_args(ts); ts = cmd_CreateSyntax("addvolentry", bc_AddVolEntryCmd, NULL, "add a new volume entry"); cmd_AddParm(ts, "-name", CMD_SINGLE, CMD_REQUIRED, "volume set name"); cmd_AddParm(ts, "-server", CMD_SINGLE, CMD_REQUIRED, "machine name"); cmd_AddParm(ts, "-partition", CMD_SINGLE, CMD_REQUIRED, "partition name"); cmd_AddParm(ts, "-volumes", CMD_SINGLE, CMD_REQUIRED, "volume name (regular expression)"); if (!interact) add_std_args(ts); ts = cmd_CreateSyntax("delvolentry", bc_DeleteVolEntryCmd, NULL, "delete a volume set sub-entry"); cmd_AddParm(ts, "-name", CMD_SINGLE, CMD_REQUIRED, "volume set name"); cmd_AddParm(ts, "-entry", CMD_SINGLE, CMD_REQUIRED, "volume set index"); if (!interact) add_std_args(ts); ts = cmd_CreateSyntax("adddump", bc_AddDumpCmd, NULL, "add dump schedule"); cmd_AddParm(ts, "-dump", CMD_LIST, CMD_REQUIRED, "dump level name"); cmd_AddParm(ts, "-expires", CMD_LIST, CMD_OPTIONAL, "expiration date"); if (!interact) add_std_args(ts); ts = cmd_CreateSyntax("deldump", bc_DeleteDumpCmd, NULL, "delete dump schedule"); cmd_AddParm(ts, "-dump", CMD_SINGLE, CMD_REQUIRED, "dump level name"); if (!interact) add_std_args(ts); ts = cmd_CreateSyntax("labeltape", bc_LabelTapeCmd, NULL, "label a tape"); cmd_AddParm(ts, "-name", CMD_SINGLE, CMD_OPTIONAL, "AFS tape name, defaults to NULL"); cmd_AddParm(ts, "-size", CMD_SINGLE, CMD_OPTIONAL, "tape size in Kbytes, defaults to size in tapeconfig"); cmd_AddParm(ts, "-portoffset", CMD_SINGLE, CMD_OPTIONAL, "TC port offset"); cmd_AddParm(ts, "-pname", CMD_SINGLE, CMD_OPTIONAL, "permanent tape name"); if (!interact) add_std_args(ts); ts = cmd_CreateSyntax("readlabel", bc_ReadLabelCmd, NULL, "read the label on tape"); cmd_AddParm(ts, "-portoffset", CMD_SINGLE, CMD_OPTIONAL, "TC port offset"); if (!interact) add_std_args(ts); ts = cmd_CreateSyntax("scantape", bc_ScanDumpsCmd, NULL, "dump information recovery from tape"); cmd_AddParm(ts, "-dbadd", CMD_FLAG, CMD_OPTIONAL, "add information to the database"); cmd_AddParm(ts, "-portoffset", CMD_SINGLE, CMD_OPTIONAL, "TC port offset"); if (!interact) add_std_args(ts); ts = cmd_CreateSyntax("volinfo", bc_dblookupCmd, NULL, "query the backup database"); cmd_AddParm(ts, "-volume", CMD_SINGLE, CMD_REQUIRED, "volume name"); if (!interact) add_std_args(ts); ts = cmd_CreateSyntax("setexp", bc_SetExpCmd, NULL, "set/clear dump expiration dates"); cmd_AddParm(ts, "-dump", CMD_LIST, CMD_REQUIRED, "dump level name"); cmd_AddParm(ts, "-expires", CMD_LIST, CMD_OPTIONAL, "expiration date"); if (!interact) add_std_args(ts); ts = cmd_CreateSyntax("savedb", bc_saveDbCmd, NULL, "save backup database"); cmd_AddParm(ts, "-portoffset", CMD_SINGLE, CMD_OPTIONAL, "TC port offset"); cmd_AddParm(ts, "-archive", CMD_LIST, CMD_OPTIONAL, "date time"); if (!interact) add_std_args(ts); ts = cmd_CreateSyntax("restoredb", bc_restoreDbCmd, NULL, "restore backup database"); cmd_AddParm(ts, "-portoffset", CMD_SINGLE, CMD_OPTIONAL, "TC port offset"); if (!interact) add_std_args(ts); ts = cmd_CreateSyntax("dumpinfo", bc_dumpInfoCmd, NULL, "provide information about a dump in the database"); cmd_AddParm(ts, "-ndumps", CMD_SINGLE, CMD_OPTIONAL, "no. of dumps"); cmd_AddParm(ts, "-id", CMD_SINGLE, CMD_OPTIONAL, "dump id"); cmd_AddParm(ts, "-verbose", CMD_FLAG, CMD_OPTIONAL, "detailed description"); if (!interact) add_std_args(ts); ts = cmd_CreateSyntax("dbverify", bc_dbVerifyCmd, NULL, "check ubik database integrity"); cmd_AddParm(ts, "-detail", CMD_FLAG, CMD_OPTIONAL, "additional details"); if (!interact) add_std_args(ts); ts = cmd_CreateSyntax("deletedump", bc_deleteDumpCmd, NULL, "delete dumps from the database"); cmd_AddParm(ts, "-dumpid", CMD_LIST, CMD_OPTIONAL, "dump id"); cmd_AddParm(ts, "-from", CMD_LIST, CMD_OPTIONAL, "date time"); cmd_AddParm(ts, "-to", CMD_LIST, CMD_OPTIONAL, "date time"); cmd_AddParm(ts, "-port", CMD_SINGLE, CMD_OPTIONAL, "TC port offset"); cmd_AddParm(ts, "-groupid", CMD_SINGLE, CMD_OPTIONAL, "group ID"); cmd_AddParm(ts, "-dbonly", CMD_FLAG, CMD_OPTIONAL, "delete the dump from the backup database only"); cmd_AddParm(ts, "-force", CMD_FLAG, CMD_OPTIONAL, "always delete from backup database"); cmd_AddParm(ts, "-noexecute", CMD_FLAG, CMD_OPTIONAL|CMD_HIDDEN, ""); cmd_AddParm(ts, "-dryrun", CMD_FLAG, CMD_OPTIONAL, "list the dumps, don't delete anything"); cmd_AddParmAlias(ts, 8, "-n"); if (!interact) add_std_args(ts); ts = cmd_CreateSyntax("interactive", bc_interactCmd, NULL, "enter interactive mode"); add_std_args(ts); /* * Now execute the command. */ targc = 0; targv[targc++] = argv[0]; if (interact) targv[targc++] = "interactive"; for (i = 1; i < argc; i++) targv[targc++] = argv[i]; code = doDispatch(targc, targv, 1); if (!interact || !bcInit) { /* Non-interactive mode */ if (code) exit(-1); if (bcInit) code = bc_WaitForNoJobs(); /* wait for any jobs to finish */ exit(code); /* and exit */ } /* Iterate on command lines, interpreting user commands (interactive mode) */ while (1) { int ret; printf("backup> "); fflush(stdout); while ((ret = LWP_GetLine(lineBuffer, sizeof(lineBuffer))) == 0) printf("%s: Command line too long\n", whoami); /* line too long */ if (ret == -1) return 0; /* Got EOF */ if (!LineIsBlank(lineBuffer)) { code = cmd_ParseLine(lineBuffer, targv, &targc, MAXV); if (code) afs_com_err(whoami, code, "; Can't parse line: '%s'", afs_error_message(code)); else { doDispatch(targc, targv, 1); cmd_FreeArgv(targv); } } } } /*main */
/* * Split arguments into FUSE and afsd/libcmd arguments. To determine whether an * argument is meant for FUSE or for the cmd interface, we pass the given * argument to cmd_Dispatch, and see if our beforeProc is run (which we set to * fuafsd_cmd_check). If it was run, the argument is acceptable to cmd; if it * was not run, cmd doesn't know what to do with the argument, so we assume the * argument is meant for FUSE. We can tell if fuafsd_cmd_check was run by the * global fuafsd_cmd_accept bool, which is set to true when fuafsd_cmd_check is * run. */ static void split_args(const struct fuse_args *args) { int i; cmd_SetBeforeProc(fuafsd_cmd_check, NULL); nullfd = open("/dev/null", O_WRONLY); stderr_save = dup(2); if (nullfd < 0 || stderr_save < 0) { perror("open/dup"); exit(1); } for (i = 0; args->argv[i]; ++i) { int code; char *arg = args->argv[i]; char *argv[3] = {args->argv[0], arg, NULL}; if (fuafsd_cmd_accept) { fuse_opt_add_arg(&afsd_args, arg); fuafsd_cmd_accept = 0; continue; } /* redirect stderr to null, so libcmd doesn't print out * an error message for unknown options */ if (dup2(nullfd, 2) < 0) { perror("dup2"); exit(1); } code = cmd_Dispatch(2, argv); if (dup2(stderr_save, 2) < 0) { perror("dup2"); exit(1); } /* fuafsd_cmd_check should prevent the dispatch from succeeding; * the only way we should be able to succeed is if -help was * specified, so just exit */ if (code == 0) { exit(1); } if (fuafsd_cmd_accept || code == CMD_TOOFEW) { /* libcmd accepted the argument; must go to afsd */ fuse_opt_add_arg(&afsd_args, arg); if (code == CMD_TOOFEW) { /* flag takes another argument; get the next one, too */ fuafsd_cmd_accept = 1; } else { fuafsd_cmd_accept = 0; } } else { /* libcmd doesn't recognize the argument; give it to FUSE */ fuse_opt_add_arg(&fuse_args, arg); } } if (close(nullfd) < 0) { perror("close"); } if (close(stderr_save) < 0) { perror("close"); } cmd_SetBeforeProc(NULL, NULL); }