880936a106476f1d3c5a7e33963ba63da5aed62e
[openafs.git] / src / bozo / bos.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  *
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
8  */
9
10 #include <afsconfig.h>
11 #include <afs/param.h>
12 #include <afs/stds.h>
13
14 #include <afs/procmgmt.h>
15 #include <roken.h>
16 #include <afs/opr.h>
17
18 #include <hcrypto/ui.h>
19
20 #include "bnode.h"
21 #include <afs/afsutil.h>
22 #include <afs/cellconfig.h>
23 #include <rx/rx.h>
24 #include <rx/xdr.h>
25 #include <afs/auth.h>
26 #include <afs/cellconfig.h>
27 #include <afs/cmd.h>
28 #include <afs/com_err.h>
29 #include <ubik.h>
30 #include <afs/ktime.h>
31 #include <afs/kautils.h>
32 #include <afs/afsint.h>
33 #include <afs/volser.h>
34
35 static int IStatServer(struct cmd_syndesc *as, int int32p);
36 static int DoStat(char *aname, struct rx_connection *aconn,
37                   int aint32p, int firstTime);
38
39 #include "bosint.h"
40 #include "bnode_internal.h"
41 #include "bosprototypes.h"
42
43 /* command offsets for bos salvage command */
44 #define MRAFS_OFFSET  10
45 #define ADDPARMOFFSET 27
46
47 /* MR-AFS salvage parameters */
48 struct MRAFSSalvageParms {
49     afs_int32 Optdebug;
50     afs_int32 Optnowrite;
51     afs_int32 Optforce;
52     afs_int32 Optoktozap;
53     afs_int32 Optrootfiles;
54     afs_int32 Optsalvagedirs;
55     afs_int32 Optblockreads;
56     afs_int32 OptListResidencies;
57     afs_int32 OptSalvageRemote;
58     afs_int32 OptSalvageArchival;
59     afs_int32 OptIgnoreCheck;
60     afs_int32 OptForceOnLine;
61     afs_int32 OptUseRootDirACL;
62     afs_int32 OptTraceBadLinkCounts;
63     afs_int32 OptDontAskFS;
64     afs_int32 OptLogLevel;
65     afs_int32 OptRxDebug;
66     afs_uint32 OptResidencies;
67 };
68
69 /* dummy routine for the audit work.  It should do nothing since audits */
70 /* occur at the server level and bos is not a server. */
71 int osi_audit(void )
72 {
73     return 0;
74 }
75
76 /* keep those lines small */
77 static char *
78 em(afs_int32 acode)
79 {
80     if (acode == -1)
81         return "communications failure (-1)";
82     else if (acode == -3)
83         return "communications timeout (-3)";
84     else
85         return (char *)afs_error_message(acode);
86 }
87
88 /* make ctime easier to use */
89 static char *
90 DateOf(time_t atime)
91 {
92     static char tbuffer[30];
93     char *tp;
94     tp = ctime(&atime);
95     if (tp) {
96         strlcpy(tbuffer, tp, sizeof(tbuffer));
97         tbuffer[24] = 0;        /* get rid of new line */
98     } else
99         strcpy(tbuffer, "BAD TIME");
100     return tbuffer;
101 }
102
103
104 /* use the syntax descr to get a connection, authenticated appropriately.
105  * aencrypt is set if we want to encrypt the data on the wire.
106  */
107 static struct rx_connection *
108 GetConn(struct cmd_syndesc *as, int aencrypt)
109 {
110     struct hostent *th;
111     char *hostname;
112     char *cellname = NULL;
113     const char *confdir;
114     afs_int32 code;
115     struct rx_connection *tconn;
116     afs_int32 addr;
117     struct afsconf_dir *tdir = NULL;
118     afsconf_secflags secFlags;
119     struct rx_securityClass *sc;
120     afs_int32 scIndex;
121
122     hostname = as->parms[0].items->data;
123     th = hostutil_GetHostByName(hostname);
124     if (!th) {
125         printf("bos: can't find address for host '%s'\n", hostname);
126         exit(1);
127     }
128     memcpy(&addr, th->h_addr, sizeof(afs_int32));
129
130     if (aencrypt)
131         secFlags = AFSCONF_SECOPTS_ALWAYSENCRYPT;
132     else
133         secFlags = AFSCONF_SECOPTS_FALLBACK_NULL;
134
135
136     if (as->parms[ADDPARMOFFSET + 2].items) { /* -localauth */
137         secFlags |= AFSCONF_SECOPTS_LOCALAUTH;
138         confdir = AFSDIR_SERVER_ETC_DIRPATH;
139     } else {
140         confdir = AFSDIR_CLIENT_ETC_DIRPATH;
141     }
142
143     if (as->parms[ADDPARMOFFSET + 1].items) { /* -noauth */
144         secFlags |= AFSCONF_SECOPTS_NOAUTH;
145     } else {
146         /* If we're running with -noauth, we don't need a configuration
147          * directory */
148         tdir = afsconf_Open(confdir);
149         if (tdir == NULL) {
150             printf("bos: can't open cell database (%s)\n", confdir);
151             exit(1);
152         }
153     }
154
155     if (as->parms[ADDPARMOFFSET].items) /* -cell */
156         cellname = as->parms[ADDPARMOFFSET].items->data;
157
158     code = afsconf_PickClientSecObj(tdir, secFlags, NULL, cellname,
159                                     &sc, &scIndex, NULL);
160     if (code) {
161         afs_com_err("bos", code, "(configuring connection security)");
162         exit(1);
163     }
164
165     if (scIndex == RX_SECIDX_NULL)
166         fprintf(stderr, "bos: running unauthenticated\n");
167
168     tconn =
169         rx_NewConnection(addr, htons(AFSCONF_NANNYPORT), 1, sc, scIndex);
170     if (!tconn) {
171         fprintf(stderr, "bos: could not create rx connection\n");
172         exit(1);
173     }
174     rxs_Release(sc);
175
176     return tconn;
177 }
178
179 static int
180 SetAuth(struct cmd_syndesc *as, void *arock)
181 {
182     afs_int32 code;
183     struct rx_connection *tconn;
184     afs_int32 flag;
185     char *tp;
186
187     tconn = GetConn(as, 0);
188     tp = as->parms[1].items->data;
189     if (strcmp(tp, "on") == 0)
190         flag = 0;               /* auth req.: noauthflag is false */
191     else if (strcmp(tp, "off") == 0)
192         flag = 1;
193     else {
194         printf
195             ("bos: illegal authentication specifier '%s', must be 'off' or 'on'.\n",
196              tp);
197         return 1;
198     }
199     code = BOZO_SetNoAuthFlag(tconn, flag);
200     if (code)
201         afs_com_err("bos", code, "(failed to set authentication flag)");
202     return 0;
203 }
204
205 /* take a name (e.g. foo/bar, and a dir e.g. /usr/afs/bin, and construct
206  * /usr/afs/bin/bar */
207 static int
208 ComputeDestDir(char *aname, char *adir, char *aresult, afs_int32 alen)
209 {
210     char *tp;
211
212     strcpy(aresult, adir);
213     tp = strrchr(aname, '/');
214     if (!tp) {
215         /* no '/' in name */
216         strcat(aresult, "/");
217         strcat(aresult, aname);
218     } else {
219         /* tp points at the / character */
220         strcat(aresult, tp);
221     }
222     return 0;
223 }
224
225 /* copy data from fd afd to rx call acall */
226 static int
227 CopyBytes(int afd, struct rx_call *acall)
228 {
229     afs_int32 code;
230     afs_int32 len;
231     char tbuffer[256];
232
233     while (1) {
234         len = read(afd, tbuffer, sizeof(tbuffer));
235         if (len < 0)
236             return errno;
237         if (len == 0)
238             return 0;           /* all done */
239         code = rx_Write(acall, tbuffer, len);
240         if (code != len)
241             return -1;
242     }
243 }
244
245 static int
246 Prune(struct cmd_syndesc *as, void *arock)
247 {
248     afs_int32 code;
249     struct rx_connection *tconn;
250     afs_int32 flags;
251
252     tconn = GetConn(as, 0);
253     flags = 0;
254     if (as->parms[1].items)
255         flags |= BOZO_PRUNEBAK;
256     if (as->parms[2].items)
257         flags |= BOZO_PRUNEOLD;
258     if (as->parms[3].items)
259         flags |= BOZO_PRUNECORE;
260     if (as->parms[4].items)
261         flags |= 0xff;
262     code = BOZO_Prune(tconn, flags);
263     if (code)
264         afs_com_err("bos", code, "(failed to prune server files)");
265     return code;
266 }
267
268 static int
269 Exec(struct cmd_syndesc *as, void *arock)
270 {
271     struct rx_connection *tconn;
272     afs_int32 code;
273
274     tconn = GetConn(as, 0);
275     code = BOZO_Exec(tconn, as->parms[1].items->data);
276     if (code)
277         printf("bos: failed to execute command (%s)\n", em(code));
278     return code;
279 }
280
281 static int
282 GetDate(struct cmd_syndesc *as, void *arock)
283 {
284     afs_int32 code;
285     char tbuffer[256];
286     char destDir[256];
287     afs_int32 time, bakTime, oldTime;
288     struct rx_connection *tconn;
289     struct cmd_item *ti;
290
291     tconn = GetConn(as, 0);
292     if (!as->parms[1].items) {
293         printf("bos: no files to check\n");
294         return 1;
295     }
296
297     /* compute dest dir or file; default MUST be canonical form of dir path */
298     if (as->parms[2].items)
299         strcpy(destDir, as->parms[2].items->data);
300     else
301         strcpy(destDir, AFSDIR_CANONICAL_SERVER_BIN_DIRPATH);
302
303     for (ti = as->parms[1].items; ti; ti = ti->next) {
304         /* check date for each file */
305         ComputeDestDir(ti->data, destDir, tbuffer, sizeof(tbuffer));
306         code = BOZO_GetDates(tconn, tbuffer, &time, &bakTime, &oldTime);
307         if (code) {
308             printf("bos: failed to check date on %s (%s)\n", ti->data,
309                    em(code));
310             return 1;
311         } else {
312             printf("File %s ", tbuffer);
313             if (time == 0)
314                 printf("does not exist, ");
315             else
316                 printf("dated %s, ", DateOf(time));
317             if (bakTime == 0)
318                 printf("no .BAK file, ");
319             else
320                 printf(".BAK file dated %s, ", DateOf(bakTime));
321             if (oldTime == 0)
322                 printf("no .OLD file.");
323             else
324                 printf(".OLD file dated %s.", DateOf(oldTime));
325             printf("\n");
326         }
327     }
328     return 0;
329 }
330
331 static int
332 UnInstall(struct cmd_syndesc *as, void *arock)
333 {
334     afs_int32 code;
335     char tbuffer[256];
336     char destDir[256];
337     struct cmd_item *ti;
338     struct rx_connection *tconn;
339
340     tconn = GetConn(as, 0);
341     if (!as->parms[1].items) {
342         printf("bos: no files to uninstall\n");
343         return 1;
344     }
345
346     /* compute dest dir or file; default MUST be canonical form of dir path */
347     if (as->parms[2].items)
348         strcpy(destDir, as->parms[2].items->data);
349     else
350         strcpy(destDir, AFSDIR_CANONICAL_SERVER_BIN_DIRPATH);
351
352     for (ti = as->parms[1].items; ti; ti = ti->next) {
353         /* uninstall each file */
354         ComputeDestDir(ti->data, destDir, tbuffer, sizeof(tbuffer));
355         code = BOZO_UnInstall(tconn, tbuffer);
356         if (code) {
357             printf("bos: failed to uninstall %s (%s)\n", ti->data, em(code));
358             return 1;
359         } else
360             printf("bos: uninstalled file %s\n", ti->data);
361     }
362     return 0;
363 }
364
365 static afs_int32
366 GetServerGoal(struct rx_connection *aconn, char *aname)
367 {
368     char buffer[500];
369     char *tp;
370     afs_int32 code;
371     struct bozo_status istatus;
372
373     tp = buffer;
374     code = BOZO_GetInstanceInfo(aconn, aname, &tp, &istatus);
375     if (code) {
376         printf("bos: failed to get instance info for '%s' (%s)\n", aname,
377                em(code));
378         /* if we can't get the answer, assume its running */
379         return BSTAT_NORMAL;
380     }
381     if (istatus.goal == 0)
382         return BSTAT_SHUTDOWN;
383     else
384         return BSTAT_NORMAL;
385 }
386
387 static int
388 Install(struct cmd_syndesc *as, void *arock)
389 {
390     struct rx_connection *tconn;
391     afs_int32 code;
392     struct cmd_item *ti;
393     struct stat tstat;
394     char tbuffer[256];
395     int fd;
396     struct rx_call *tcall;
397     char destDir[256];
398
399     tconn = GetConn(as, 0);
400     if (!as->parms[1].items) {
401         printf("bos: no files to install\n");
402         return 1;
403     }
404
405     /* compute dest dir or file; default MUST be canonical form of dir path */
406     if (as->parms[2].items)
407         strcpy(destDir, as->parms[2].items->data);
408     else
409         strcpy(destDir, AFSDIR_CANONICAL_SERVER_BIN_DIRPATH);
410
411     for (ti = as->parms[1].items; ti; ti = ti->next) {
412         /* install each file */
413         fd = open(ti->data, O_RDONLY);
414         if (fd < 0) {
415             /* better to quit on error than continue for install command */
416             printf("bos: can't find file '%s', quitting\n", ti->data);
417             return 1;
418         }
419         code = fstat(fd, &tstat);
420         if (code) {
421             printf("bos: failed to stat file %s, errno is %d\n", ti->data,
422                    errno);
423             return 1;
424         }
425         /* compute destination dir */
426         ComputeDestDir(ti->data, destDir, tbuffer, sizeof(tbuffer));
427         tcall = rx_NewCall(tconn);
428         code =
429             StartBOZO_Install(tcall, tbuffer, tstat.st_size,
430                               (afs_int32) tstat.st_mode, tstat.st_mtime);
431         if (code == 0) {
432             code = CopyBytes(fd, tcall);
433         }
434         code = rx_EndCall(tcall, code);
435         if (code) {
436             printf("bos: failed to install %s (%s)\n", ti->data, em(code));
437             return 1;
438         } else
439             printf("bos: installed file %s\n", ti->data);
440     }
441     return 0;
442 }
443
444 static int
445 Shutdown(struct cmd_syndesc *as, void *arock)
446 {
447     struct rx_connection *tconn;
448     afs_int32 code;
449     struct cmd_item *ti;
450
451     tconn = GetConn(as, 0);
452     if (as->parms[1].items == 0) {
453         code = BOZO_ShutdownAll(tconn);
454         if (code)
455             printf("bos: failed to shutdown servers (%s)\n", em(code));
456     } else {
457         for (ti = as->parms[1].items; ti; ti = ti->next) {
458             code = BOZO_SetTStatus(tconn, ti->data, BSTAT_SHUTDOWN);
459             if (code)
460                 printf("bos: failed to shutdown instance %s (%s)\n", ti->data,
461                        em(code));
462         }
463     }
464     if (as->parms[8].items) {
465         code = BOZO_WaitAll(tconn);
466         if (code)
467             printf("bos: can't wait for processes to shutdown (%s)\n",
468                    em(code));
469     }
470     return 0;
471 }
472
473 static int
474 BlockScannerCmd(struct cmd_syndesc *as, void *arock)
475 {
476     afs_int32 code;
477     struct rx_connection *tconn;
478     char BlockCommand[] = "/usr/afs/bin/scanner -block";
479
480     tconn = GetConn(as, 0);
481     code = BOZO_Exec(tconn, BlockCommand);
482     if (code)
483         printf
484             ("bos: failed to block scanner from making migration requests (%s)\n",
485              em(code));
486     return 0;
487 }
488
489 static int
490 UnBlockScannerCmd(struct cmd_syndesc *as, void *arock)
491 {
492     afs_int32 code;
493     struct rx_connection *tconn;
494     char UnBlockCommand[] = "/usr/afs/bin/scanner -unblock";
495
496     tconn = GetConn(as, 0);
497     code = BOZO_Exec(tconn, UnBlockCommand);
498     if (code)
499         printf
500             ("bos: failed to allow scanner daemon to make migration requests again (%s)\n",
501              em(code));
502     return 0;
503 }
504
505 static int
506 GetRestartCmd(struct cmd_syndesc *as, void *arock)
507 {
508     afs_int32 code;
509     struct ktime generalTime, newBinaryTime;
510     char messageBuffer[256];
511     struct rx_connection *tconn;
512     char *hostp;
513
514     hostp = as->parms[0].items->data;   /* host name for messages */
515     tconn = GetConn(as, 0);
516
517     code = BOZO_GetRestartTime(tconn, 1, (struct bozo_netKTime *) &generalTime);
518     if (code) {
519         printf("bos: failed to retrieve restart information (%s)\n",
520                em(code));
521         return code;
522     }
523     code = BOZO_GetRestartTime(tconn, 2, (struct bozo_netKTime *) &newBinaryTime);
524     if (code) {
525         printf("bos: failed to retrieve restart information (%s)\n",
526                em(code));
527         return code;
528     }
529
530     code = ktime_DisplayString(&generalTime, messageBuffer);
531     if (code) {
532         printf("bos: failed to decode restart time (%s)\n", em(code));
533         return code;
534     }
535     printf("Server %s restarts %s\n", hostp, messageBuffer);
536
537     code = ktime_DisplayString(&newBinaryTime, messageBuffer);
538     if (code) {
539         printf("bos: failed to decode restart time (%s)\n", em(code));
540         return code;
541     }
542     printf("Server %s restarts for new binaries %s\n", hostp, messageBuffer);
543
544     /* all done now */
545     return 0;
546 }
547
548 static int
549 SetRestartCmd(struct cmd_syndesc *as, void *arock)
550 {
551     afs_int32 count = 0;
552     afs_int32 code;
553     struct ktime restartTime;
554     afs_int32 type = 0 ;
555     struct rx_connection *tconn;
556
557     count = 0;
558     tconn = GetConn(as, 0);
559     if (as->parms[2].items) {
560         count++;
561         type = 1;
562     }
563     if (as->parms[3].items) {
564         count++;
565         type = 2;
566     }
567     if (count > 1) {
568         printf("bos: can't specify more than one restart time at a time\n");
569         return -1;
570     }
571     if (count == 0)
572         type = 1;               /* by default set general restart time */
573
574     if ((code = ktime_ParsePeriodic(as->parms[1].items->data, &restartTime))) {
575         printf("bos: failed to parse '%s' as periodic restart time(%s)\n",
576                as->parms[1].items->data, em(code));
577         return code;
578     }
579
580     code = BOZO_SetRestartTime(tconn, type, (struct bozo_netKTime *) &restartTime);
581     if (code) {
582         printf("bos: failed to set restart time at server (%s)\n", em(code));
583         return code;
584     }
585     return 0;
586 }
587
588 static int
589 Startup(struct cmd_syndesc *as, void *arock)
590 {
591     struct rx_connection *tconn;
592     afs_int32 code;
593     struct cmd_item *ti;
594
595     tconn = GetConn(as, 0);
596     if (as->parms[1].items == 0) {
597         code = BOZO_StartupAll(tconn);
598         if (code)
599             printf("bos: failed to startup servers (%s)\n", em(code));
600     } else {
601         for (ti = as->parms[1].items; ti; ti = ti->next) {
602             code = BOZO_SetTStatus(tconn, ti->data, BSTAT_NORMAL);
603             if (code)
604                 printf("bos: failed to start instance %s (%s)\n", ti->data,
605                        em(code));
606         }
607     }
608     return 0;
609 }
610
611 static int
612 Restart(struct cmd_syndesc *as, void *arock)
613 {
614     struct rx_connection *tconn;
615     afs_int32 code;
616     struct cmd_item *ti;
617
618     tconn = GetConn(as, 0);
619     if (as->parms[2].items) {
620         /* this is really a rebozo command */
621         if (as->parms[1].items) {
622             /* specified specific things to restart, can't do this at the same
623              * time */
624             printf
625                 ("bos: can't specify both '-bos' and specific servers to restart.\n");
626             return 1;
627         }
628         /* otherwise do a rebozo */
629         code = BOZO_ReBozo(tconn);
630         if (code)
631             printf("bos: failed to restart bosserver (%s)\n", em(code));
632         return code;
633     }
634     if (as->parms[1].items == 0) {
635         if (as->parms[3].items) {       /* '-all' */
636             code = BOZO_RestartAll(tconn);
637             if (code)
638                 printf("bos: failed to restart servers (%s)\n", em(code));
639         } else
640             printf("bos: To restart all processes please specify '-all'\n");
641     } else {
642         if (as->parms[3].items) {
643             printf("bos: Can't use '-all' along with individual instances\n");
644         } else {
645             for (ti = as->parms[1].items; ti; ti = ti->next) {
646                 code = BOZO_Restart(tconn, ti->data);
647                 if (code)
648                     printf("bos: failed to restart instance %s (%s)\n",
649                            ti->data, em(code));
650             }
651         }
652     }
653     return 0;
654 }
655
656 static int
657 SetCellName(struct cmd_syndesc *as, void *arock)
658 {
659     struct rx_connection *tconn;
660     afs_int32 code;
661
662     tconn = GetConn(as, 0);
663     code = BOZO_SetCellName(tconn, as->parms[1].items->data);
664     if (code)
665         printf("bos: failed to set cell (%s)\n", em(code));
666     return 0;
667 }
668
669 static int
670 AddHost(struct cmd_syndesc *as, void *arock)
671 {
672     struct rx_connection *tconn;
673     afs_int32 code;
674     struct cmd_item *ti;
675     char name[MAXHOSTCHARS];
676
677     tconn = GetConn(as, 0);
678     for (ti = as->parms[1].items; ti; ti = ti->next) {
679         if (as->parms[2].items) {
680             if (strlen(ti->data) > MAXHOSTCHARS - 3) {
681                 fprintf(stderr, "bos: host name too long\n");
682                 return E2BIG;
683             }
684             name[0] = '[';
685             strcpy(&name[1], ti->data);
686             strcat((char *)&name, "]");
687             code = BOZO_AddCellHost(tconn, name);
688         } else
689             code = BOZO_AddCellHost(tconn, ti->data);
690         if (code)
691             printf("bos: failed to add host %s (%s)\n", ti->data, em(code));
692     }
693     return 0;
694 }
695
696 static int
697 RemoveHost(struct cmd_syndesc *as, void *arock)
698 {
699     struct rx_connection *tconn;
700     afs_int32 code;
701     struct cmd_item *ti;
702
703     tconn = GetConn(as, 0);
704     for (ti = as->parms[1].items; ti; ti = ti->next) {
705         code = BOZO_DeleteCellHost(tconn, ti->data);
706         if (code)
707             printf("bos: failed to delete host %s (%s)\n", ti->data,
708                    em(code));
709     }
710     return 0;
711 }
712
713 static int
714 ListHosts(struct cmd_syndesc *as, void *arock)
715 {
716     struct rx_connection *tconn;
717     afs_int32 code;
718     char tbuffer[256];
719     char *tp;
720     afs_int32 i;
721
722     tp = tbuffer;
723     tconn = GetConn(as, 0);
724     code = BOZO_GetCellName(tconn, &tp);
725     if (code) {
726         printf("bos: failed to get cell name (%s)\n", em(code));
727         exit(1);
728     }
729     printf("Cell name is %s\n", tbuffer);
730     for (i = 0;; i++) {
731         code = BOZO_GetCellHost(tconn, i, &tp);
732         if (code == BZDOM)
733             break;
734         if (code != 0) {
735             printf("bos: failed to get cell host %d (%s)\n", i, em(code));
736             exit(1);
737         }
738         printf("    Host %d is %s\n", i + 1, tbuffer);
739     }
740     return 0;
741 }
742
743 static int
744 AddKey(struct cmd_syndesc *as, void *arock)
745 {
746     struct rx_connection *tconn;
747     afs_int32 code;
748     struct ktc_encryptionKey tkey;
749     afs_int32 temp;
750     char buf[BUFSIZ], ver[BUFSIZ];
751
752     tconn = GetConn(as, 1);
753     memset(&tkey, 0, sizeof(struct ktc_encryptionKey));
754
755     if (as->parms[1].items) {
756         if (strlcpy(buf, as->parms[1].items->data, sizeof(buf)) >= sizeof(buf)) {
757             fprintf(stderr, "Key data too long for buffer\n");
758             exit(1);
759         }
760     } else {
761         /* prompt for key */
762         code = UI_UTIL_read_pw_string(buf, sizeof(buf), "input key: ", 0);
763         if (code || strlen(buf) == 0) {
764             fprintf(stderr, "Bad key: \n");
765             exit(1);
766         }
767         code = UI_UTIL_read_pw_string(ver, sizeof(ver), "Retype input key: ", 0);
768         if (code || strlen(ver) == 0) {
769             fprintf(stderr, "Bad key: \n");
770             exit(1);
771         }
772         if (strcmp(ver, buf) != 0) {
773             fprintf(stderr, "\nInput key mismatch\n");
774             exit(1);
775         }
776
777     }
778
779     temp = atoi(as->parms[2].items->data);
780     if (temp == 999) {
781         /* bcrypt key */
782 /*
783         strcpy((char *)&tkey, as->parms[1].items->data);
784 */
785         strcpy((char *)&tkey, buf);
786     } else {                    /* kerberos key */
787         char *tcell;
788         if (as->parms[ADDPARMOFFSET].items) {
789             tcell = strdup(as->parms[ADDPARMOFFSET].items->data);
790             if (tcell == NULL) {
791                 fprintf(stderr, "bos: Unable to allocate memory for cellname\n");
792                 exit(1);
793             }
794
795             /* string to key needs upper-case cell names */
796
797             /* I don't believe this is true.  The string to key function
798              * actually expands the cell name, then LOWER-CASES it.  Perhaps it
799              * didn't use to??? */
800             ucstring(tcell, tcell, strlen(tcell));
801         } else
802             tcell = NULL;       /* no cell specified, use current */
803 /*
804         ka_StringToKey(as->parms[1].items->data, tcell, &tkey);
805 */
806         ka_StringToKey(buf, tcell, &tkey);
807
808         if (tcell)
809             free(tcell);
810     }
811     code = BOZO_AddKey(tconn, temp, ktc_to_bozoptr(&tkey));
812     if (code) {
813         printf("bos: failed to set key %d (%s)\n", temp, em(code));
814         exit(1);
815     }
816     return 0;
817 }
818
819 static int
820 RemoveKey(struct cmd_syndesc *as, void *arock)
821 {
822     struct rx_connection *tconn;
823     afs_int32 code;
824     afs_int32 temp;
825     struct cmd_item *ti;
826
827     tconn = GetConn(as, 0);
828     for (ti = as->parms[1].items; ti; ti = ti->next) {
829         temp = atoi(ti->data);
830         code = BOZO_DeleteKey(tconn, temp);
831         if (code) {
832             printf("bos: failed to delete key %d (%s)\n", temp, em(code));
833             exit(1);
834         }
835     }
836     return 0;
837 }
838
839 static int
840 ListKeys(struct cmd_syndesc *as, void *arock)
841 {
842     struct rx_connection *tconn;
843     afs_int32 code;
844     struct ktc_encryptionKey tkey;
845     afs_int32 kvno;
846     struct bozo_keyInfo keyInfo;
847     int everWorked;
848     afs_int32 i;
849
850     tconn = GetConn(as, 1);
851     everWorked = 0;
852     for (i = 0;; i++) {
853         code = BOZO_ListKeys(tconn, i, &kvno, ktc_to_bozoptr(&tkey), &keyInfo);
854         if (code)
855             break;
856         everWorked = 1;
857         /* first check if key is returned */
858         if ((!ka_KeyIsZero((char *)&tkey, sizeof(tkey)))
859             && (as->parms[1].items)) {
860             printf("key %d is '", kvno);
861             ka_PrintBytes((char *)&tkey, sizeof(tkey));
862             printf("'\n");
863         } else {
864             if (keyInfo.keyCheckSum == 0)       /* shouldn't happen */
865                 printf("key version is %d\n", kvno);
866             else
867                 printf("key %d has cksum %u\n", kvno, keyInfo.keyCheckSum);
868         }
869     }
870     if (everWorked) {
871         printf("Keys last changed on %s.\n", DateOf(keyInfo.mod_sec));
872     }
873     if (code != BZDOM)
874         printf("bos: %s error encountered while listing keys\n", em(code));
875     else
876         printf("All done.\n");
877     return 0;
878 }
879
880 static int
881 AddSUser(struct cmd_syndesc *as, void *arock)
882 {
883     struct rx_connection *tconn;
884     afs_int32 code;
885     int failed;
886     struct cmd_item *ti;
887
888     failed = 0;
889     tconn = GetConn(as, 0);
890     for (ti = as->parms[1].items; ti; ti = ti->next) {
891         code = BOZO_AddSUser(tconn, ti->data);
892         if (code) {
893             printf("bos: failed to add user '%s' (%s)\n", ti->data, em(code));
894             failed = 1;
895         }
896     }
897     return failed;
898 }
899
900 static int
901 RemoveSUser(struct cmd_syndesc *as, void *arock)
902 {
903     struct rx_connection *tconn;
904     struct cmd_item *ti;
905     afs_int32 code;
906     int failed;
907
908     failed = 0;
909     tconn = GetConn(as, 0);
910     for (ti = as->parms[1].items; ti; ti = ti->next) {
911         code = BOZO_DeleteSUser(tconn, ti->data);
912         if (code) {
913             printf("bos: failed to delete user '%s', ", ti->data);
914             if (code == ENOENT)
915                 printf("(no such user)\n");
916             else
917                 printf("(%s)\n", em(code));
918             failed = 1;
919         }
920     }
921     return failed;
922 }
923
924 #define NPERLINE    10          /* dudes to print per line */
925 static int
926 ListSUsers(struct cmd_syndesc *as, void *arock)
927 {
928     struct rx_connection *tconn;
929     int i;
930     afs_int32 code;
931     char tbuffer[256];
932     char *tp;
933     int lastNL, printGreeting;
934
935     tconn = GetConn(as, 0);
936     lastNL = 0;
937     printGreeting = 1;
938     for (i = 0;; i++) {
939         tp = tbuffer;
940         code = BOZO_ListSUsers(tconn, i, &tp);
941         if (code)
942             break;
943         if (printGreeting) {
944             printGreeting = 0;  /* delay until after first call succeeds */
945             printf("SUsers are: ");
946         }
947         printf("%s ", tbuffer);
948         if ((i % NPERLINE) == NPERLINE - 1) {
949             printf("\n");
950             lastNL = 1;
951         } else
952             lastNL = 0;
953     }
954     if (code != 1) {
955         /* a real error code, instead of scanned past end */
956         printf("bos: failed to retrieve super-user list (%s)\n", em(code));
957         return code;
958     }
959     if (lastNL == 0)
960         printf("\n");
961     return 0;
962 }
963
964 static int
965 StatServer(struct cmd_syndesc *as, void *arock)
966 {
967     struct rx_connection *tconn;
968     afs_int32 code;
969     int i;
970     char ibuffer[BOZO_BSSIZE];
971     char *tp;
972     int int32p;
973
974     /* int32p==1 is obsolete, smaller, printout */
975     int32p = (as->parms[2].items != 0 ? 2 : 0);
976
977     /* no parms does something pretty different */
978     if (as->parms[1].items)
979         return IStatServer(as, int32p);
980
981     tconn = GetConn(as, 0);
982     for (i = 0;; i++) {
983         /* for each instance */
984         tp = ibuffer;
985         code = BOZO_EnumerateInstance(tconn, i, &tp);
986         if (code == BZDOM)
987             break;
988         if (code) {
989             printf("bos: failed to contact host's bosserver (%s).\n",
990                    em(code));
991             break;
992         }
993         DoStat(ibuffer, tconn, int32p, (i == 0));       /* print status line */
994     }
995     return 0;
996 }
997
998 static int
999 CreateServer(struct cmd_syndesc *as, void *arock)
1000 {
1001     struct rx_connection *tconn;
1002     afs_int32 code;
1003     char *parms[6];
1004     struct cmd_item *ti;
1005     int i;
1006     char *type, *name, *notifier = NONOTIFIER;
1007
1008     tconn = GetConn(as, 0);
1009     for (i = 0; i < 6; i++)
1010         parms[i] = "";
1011     for (i = 0, ti = as->parms[3].items; (ti && i < 6); ti = ti->next, i++) {
1012         parms[i] = ti->data;
1013     }
1014     name = as->parms[1].items->data;
1015     type = as->parms[2].items->data;
1016     if ((ti = as->parms[4].items)) {
1017         notifier = ti->data;
1018     }
1019     code =
1020         BOZO_CreateBnode(tconn, type, name, parms[0], parms[1], parms[2],
1021                          parms[3], parms[4], notifier);
1022     if (code) {
1023         printf
1024             ("bos: failed to create new server instance %s of type '%s' (%s)\n",
1025              name, type, em(code));
1026     }
1027     return code;
1028 }
1029
1030 static int
1031 DeleteServer(struct cmd_syndesc *as, void *arock)
1032 {
1033     struct rx_connection *tconn;
1034     afs_int32 code;
1035     struct cmd_item *ti;
1036
1037     code = 0;
1038     tconn = GetConn(as, 0);
1039     for (ti = as->parms[1].items; ti; ti = ti->next) {
1040         code = BOZO_DeleteBnode(tconn, ti->data);
1041         if (code) {
1042             if (code == BZBUSY)
1043                 printf("bos: can't delete running instance '%s'\n", ti->data);
1044             else
1045                 printf("bos: failed to delete instance '%s' (%s)\n", ti->data,
1046                        em(code));
1047         }
1048     }
1049     return code;
1050 }
1051
1052 static int
1053 StartServer(struct cmd_syndesc *as, void *arock)
1054 {
1055     struct rx_connection *tconn;
1056     afs_int32 code;
1057     struct cmd_item *ti;
1058
1059     code = 0;
1060     tconn = GetConn(as, 0);
1061     for (ti = as->parms[1].items; ti; ti = ti->next) {
1062         code = BOZO_SetStatus(tconn, ti->data, BSTAT_NORMAL);
1063         if (code)
1064             printf("bos: failed to start instance '%s' (%s)\n", ti->data,
1065                    em(code));
1066     }
1067     return code;
1068 }
1069
1070 static int
1071 StopServer(struct cmd_syndesc *as, void *arock)
1072 {
1073     struct rx_connection *tconn;
1074     afs_int32 code;
1075     struct cmd_item *ti;
1076
1077     code = 0;
1078     tconn = GetConn(as, 0);
1079     for (ti = as->parms[1].items; ti; ti = ti->next) {
1080         code = BOZO_SetStatus(tconn, ti->data, BSTAT_SHUTDOWN);
1081         if (code)
1082             printf("bos: failed to change stop instance '%s' (%s)\n",
1083                    ti->data, em(code));
1084     }
1085     if (as->parms[8].items) {
1086         code = BOZO_WaitAll(tconn);
1087         if (code)
1088             printf("bos: can't wait for processes to shutdown (%s)\n",
1089                    em(code));
1090     }
1091     return code;
1092 }
1093
1094 #define PARMBUFFERSSIZE 32
1095
1096 static afs_int32
1097 DoSalvage(struct rx_connection * aconn, char * aparm1, char * aparm2,
1098           char * aoutName, afs_int32 showlog, char * parallel,
1099           char * atmpDir, char * orphans, int dafs,
1100           struct MRAFSSalvageParms * mrafsParm)
1101 {
1102     afs_int32 code;
1103     char *parms[6];
1104     char buffer;
1105     char tbuffer[BOZO_BSSIZE];
1106     struct bozo_status istatus;
1107     struct rx_call *tcall;
1108     char *tp;
1109     FILE *outFile;
1110     int closeIt;
1111     char partName[20];          /* canonical name for partition */
1112     char pbuffer[PARMBUFFERSSIZE];
1113     afs_int32 partNumber;
1114     char *notifier = NONOTIFIER;
1115     int count;
1116
1117     /* if a partition was specified, canonicalize the name, since
1118      * the salvager has a stupid partition ID parser */
1119     if (aparm1) {
1120         partNumber = volutil_GetPartitionID(aparm1);
1121         if (partNumber < 0) {
1122             printf("bos: could not parse partition ID '%s'\n", aparm1);
1123             return EINVAL;
1124         }
1125         tp = volutil_PartitionName(partNumber);
1126         if (!tp) {
1127             printf("bos: internal error parsing partition ID '%s'\n", aparm1);
1128             return EINVAL;
1129         }
1130         strcpy(partName, tp);
1131     } else
1132         partName[0] = 0;
1133
1134     /* open the file name */
1135     if (aoutName) {
1136         outFile = fopen(aoutName, "w");
1137         if (!outFile) {
1138             printf("bos: can't open specified SalvageLog file '%s'\n",
1139                    aoutName);
1140             return ENOENT;
1141         }
1142         closeIt = 1;            /* close this file later */
1143     } else {
1144         outFile = stdout;
1145         closeIt = 0;            /* don't close this file later */
1146     }
1147
1148     for (code = 2; code < 6; code++)
1149         parms[code] = "";
1150     if (!aparm2)
1151         aparm2 = "";
1152
1153     /* MUST pass canonical (wire-format) salvager path to bosserver */
1154     if (*aparm2 != 0) {
1155         /* single volume salvage */
1156         if (dafs) {
1157             /* for DAFS, we call the salvagserver binary with special options.
1158              * in this mode, it simply uses SALVSYNC to tell the currently
1159              * running salvageserver to offline and salvage the volume in question */
1160             strncpy(tbuffer, AFSDIR_CANONICAL_SERVER_SALSRV_FILEPATH, BOZO_BSSIZE);
1161
1162             if ((strlen(tbuffer) + 9 + strlen(partName) + 1 + strlen(aparm2) +
1163                  1) > BOZO_BSSIZE) {
1164                 printf("bos: command line too big\n");
1165                 return (E2BIG);
1166             }
1167
1168             strcat(tbuffer, " -client ");
1169             strcat(tbuffer, partName);
1170             strcat(tbuffer, " ");
1171             strcat(tbuffer, aparm2);
1172         } else {
1173             strncpy(tbuffer, AFSDIR_CANONICAL_SERVER_SALVAGER_FILEPATH, BOZO_BSSIZE);
1174
1175             if ((strlen(tbuffer) + 1 + strlen(partName) + 1 + strlen(aparm2) +
1176                  1) > BOZO_BSSIZE) {
1177                 printf("bos: command line too big\n");
1178                 return (E2BIG);
1179             }
1180
1181             strcat(tbuffer, " ");
1182             strcat(tbuffer, partName);
1183             strcat(tbuffer, " ");
1184             strcat(tbuffer, aparm2);
1185         }
1186     } else {
1187         /* partition salvage */
1188         strncpy(tbuffer, AFSDIR_CANONICAL_SERVER_SALVAGER_FILEPATH, BOZO_BSSIZE);
1189         if ((strlen(tbuffer) + 4 + strlen(partName) + 1) > BOZO_BSSIZE) {
1190             printf("bos: command line too big\n");
1191             return (E2BIG);
1192         }
1193         strcat(tbuffer, " -force ");
1194         strcat(tbuffer, partName);
1195     }
1196
1197     /* For DAFS, specifying a single volume does not result in a standard
1198      * salvager call.  Instead, it simply results in a SALVSYNC call to the
1199      * online salvager daemon.  This interface does not give us the same rich
1200      * set of call flags.  Thus, we skip these steps for DAFS single-volume
1201      * calls */
1202     if (!dafs || (*aparm2 == 0)) {
1203         /* add the parallel option if given */
1204         if (parallel != NULL) {
1205             if ((strlen(tbuffer) + 11 + strlen(parallel) + 1) > BOZO_BSSIZE) {
1206                 printf("bos: command line too big\n");
1207                 return (E2BIG);
1208             }
1209             strcat(tbuffer, " -parallel ");
1210             strcat(tbuffer, parallel);
1211         }
1212
1213         /* add the tmpdir option if given */
1214         if (atmpDir != NULL) {
1215             if ((strlen(tbuffer) + 9 + strlen(atmpDir) + 1) > BOZO_BSSIZE) {
1216                 printf("bos: command line too big\n");
1217                 return (E2BIG);
1218             }
1219             strcat(tbuffer, " -tmpdir ");
1220             strcat(tbuffer, atmpDir);
1221         }
1222
1223         /* add the orphans option if given */
1224         if (orphans != NULL) {
1225             if ((strlen(tbuffer) + 10 + strlen(orphans) + 1) > BOZO_BSSIZE) {
1226                 printf("bos: command line too big\n");
1227                 return (E2BIG);
1228             }
1229             strcat(tbuffer, " -orphans ");
1230             strcat(tbuffer, orphans);
1231         }
1232
1233         if (mrafsParm->Optdebug)
1234             strcat(tbuffer, " -debug");
1235         if (mrafsParm->Optnowrite)
1236             strcat(tbuffer, " -nowrite");
1237         if (mrafsParm->Optforce)
1238             strcat(tbuffer, " -force");
1239         if (mrafsParm->Optoktozap)
1240             strcat(tbuffer, " -oktozap");
1241         if (mrafsParm->Optrootfiles)
1242             strcat(tbuffer, " -rootfiles");
1243         if (mrafsParm->Optsalvagedirs)
1244             strcat(tbuffer, " -salvagedirs");
1245         if (mrafsParm->Optblockreads)
1246             strcat(tbuffer, " -blockreads");
1247         if (mrafsParm->OptListResidencies)
1248             strcat(tbuffer, " -ListResidencies");
1249         if (mrafsParm->OptSalvageRemote)
1250             strcat(tbuffer, " -SalvageRemote");
1251         if (mrafsParm->OptSalvageArchival)
1252             strcat(tbuffer, " -SalvageArchival");
1253         if (mrafsParm->OptIgnoreCheck)
1254             strcat(tbuffer, " -IgnoreCheck");
1255         if (mrafsParm->OptForceOnLine)
1256             strcat(tbuffer, " -ForceOnLine");
1257         if (mrafsParm->OptUseRootDirACL)
1258             strcat(tbuffer, " -UseRootDirACL");
1259         if (mrafsParm->OptTraceBadLinkCounts)
1260             strcat(tbuffer, " -TraceBadLinkCounts");
1261         if (mrafsParm->OptDontAskFS)
1262             strcat(tbuffer, " -DontAskFS");
1263         if (mrafsParm->OptLogLevel) {
1264             sprintf(pbuffer, " -LogLevel %ld", afs_printable_int32_ld(mrafsParm->OptLogLevel));
1265             strcat(tbuffer, pbuffer);
1266         }
1267         if (mrafsParm->OptRxDebug)
1268             strcat(tbuffer, " -rxdebug");
1269         if (mrafsParm->OptResidencies) {
1270             sprintf(pbuffer, " -Residencies %lu",
1271                     afs_printable_uint32_lu(mrafsParm->OptResidencies));
1272             strcat(tbuffer, pbuffer);
1273         }
1274     }
1275
1276     parms[0] = tbuffer;
1277     parms[1] = "now";           /* when to do it */
1278     code =
1279         BOZO_CreateBnode(aconn, "cron", "salvage-tmp", parms[0], parms[1],
1280                          parms[2], parms[3], parms[4], notifier);
1281     if (code) {
1282         printf("bos: failed to start 'salvager' (%s)\n", em(code));
1283         goto done;
1284     }
1285     /* now wait for bnode to disappear */
1286     count = 0;
1287     while (1) {
1288         IOMGR_Sleep(1);
1289         tp = tbuffer;
1290         code = BOZO_GetInstanceInfo(aconn, "salvage-tmp", &tp, &istatus);
1291         if (code)
1292             break;
1293         if ((++count % 5) == 0)
1294             printf("bos: waiting for salvage to complete.\n");
1295     }
1296     if (code != BZNOENT) {
1297         printf("bos: salvage failed (%s)\n", em(code));
1298         goto done;
1299     }
1300     code = 0;
1301
1302     /* now print the log file to the output file */
1303     printf("bos: salvage completed\n");
1304     if (aoutName || showlog) {
1305         fprintf(outFile, "SalvageLog:\n");
1306         tcall = rx_NewCall(aconn);
1307         /* MUST pass canonical (wire-format) salvager log path to bosserver */
1308         code =
1309             StartBOZO_GetLog(tcall, AFSDIR_CANONICAL_SERVER_SLVGLOG_FILEPATH);
1310         if (code) {
1311             rx_EndCall(tcall, code);
1312             goto done;
1313         }
1314         /* copy data */
1315         while (1) {
1316             code = rx_Read(tcall, &buffer, 1);
1317             if (code != 1)
1318                 break;
1319             putc(buffer, outFile);
1320             if (buffer == 0)
1321                 break;          /* the end delimeter */
1322         }
1323         code = rx_EndCall(tcall, 0);
1324         /* fall through into cleanup code */
1325     }
1326
1327   done:
1328     if (closeIt && outFile)
1329         fclose(outFile);
1330     return code;
1331 }
1332
1333 static int
1334 GetLogCmd(struct cmd_syndesc *as, void *arock)
1335 {
1336     struct rx_connection *tconn;
1337     struct rx_call *tcall;
1338     afs_int32 code;
1339     char buffer;
1340     int error;
1341
1342     printf("Fetching log file '%s'...\n", as->parms[1].items->data);
1343     tconn = GetConn(as, 0);
1344     tcall = rx_NewCall(tconn);
1345     code = StartBOZO_GetLog(tcall, as->parms[1].items->data);
1346     if (code) {
1347         rx_EndCall(tcall, code);
1348         goto done;
1349     }
1350     /* copy data */
1351     error = 0;
1352     while (1) {
1353         code = rx_Read(tcall, &buffer, 1);
1354         if (code != 1) {
1355             error = EIO;
1356             break;
1357         }
1358         if (buffer == 0)
1359             break;              /* the end delimeter */
1360         putchar(buffer);
1361     }
1362     code = rx_EndCall(tcall, error);
1363     /* fall through into cleanup code */
1364
1365   done:
1366     if (code)
1367         afs_com_err("bos", code, "(while reading log)");
1368     return code;
1369 }
1370
1371 static int
1372 IsDAFS(struct rx_connection *aconn)
1373 {
1374     char buffer[BOZO_BSSIZE];
1375     char *tp;
1376     struct bozo_status istatus;
1377     afs_int32 code;
1378
1379     tp = &buffer[0];
1380
1381     code = BOZO_GetInstanceInfo(aconn, "dafs", &tp, &istatus);
1382     if (code) {
1383         /* no dafs bnode; cannot be dafs */
1384         return 0;
1385     }
1386     if (istatus.goal) {
1387         /* dafs bnode is running; we must be dafs */
1388         return 1;
1389     }
1390
1391     /* At this point, either we have neither a dafs nor fs bnode running, or
1392      * we have an fs bnode running but the dafs bnode is stopped.
1393      *
1394      * If an fs bnode is running, we are obviously not DAFS. If an fs bnode
1395      * is not running and a dafs bnode is not running... it's not certain if
1396      * we are DAFS or not DAFS. Just return 0 in that case; it shouldn't much
1397      * matter what we return, anyway */
1398     return 0;
1399 }
1400
1401 static int
1402 SalvageCmd(struct cmd_syndesc *as, void *arock)
1403 {
1404     struct rx_connection *tconn;
1405     afs_int32 code, rc, i;
1406     char *outName;
1407     char tname[BOZO_BSSIZE];
1408     afs_int32 newID;
1409     extern struct ubik_client *cstruct;
1410     afs_int32 curGoal, showlog = 0, dafs = 0, mrafs = 0;
1411     char *parallel;
1412     char *tmpDir;
1413     char *orphans;
1414     char *tp;
1415     char * serviceName;
1416     struct MRAFSSalvageParms mrafsParm;
1417
1418     memset(&mrafsParm, 0, sizeof(mrafsParm));
1419
1420     /* parm 0 is machine name, 1 is partition, 2 is volume, 3 is -all flag */
1421     tconn = GetConn(as, 0);
1422
1423     tp = &tname[0];
1424
1425     /* find out whether fileserver is running demand attach fs */
1426     if (IsDAFS(tconn)) {
1427         dafs = 1;
1428         serviceName = "dafs";
1429         /* Find out whether fileserver is running MR-AFS (has a scanner instance) */
1430         /* XXX this should really be done some other way, potentially by RPC */
1431         if ((code = BOZO_GetInstanceParm(tconn, serviceName, 4, &tp) == 0))
1432             mrafs = 1;
1433     } else {
1434         serviceName = "fs";
1435         /* Find out whether fileserver is running MR-AFS (has a scanner instance) */
1436         /* XXX this should really be done some other way, potentially by RPC */
1437         if ((code = BOZO_GetInstanceParm(tconn, serviceName, 3, &tp) == 0))
1438             mrafs = 1;
1439     }
1440
1441     /* we can do a volume, a partition or the whole thing, but not mixtures
1442      * thereof */
1443     if (!as->parms[1].items && as->parms[2].items) {
1444         printf("bos: must specify partition to salvage individual volume.\n");
1445         return -1;
1446     }
1447     if (as->parms[5].items && as->parms[3].items) {
1448         printf("bos: can not specify both -file and -showlog.\n");
1449         return -1;
1450     }
1451     if (as->parms[4].items && (as->parms[1].items || as->parms[2].items)) {
1452         printf("bos: can not specify -all with other flags.\n");
1453         return -1;
1454     }
1455
1456     /* get the output file name, if any */
1457     if (as->parms[3].items)
1458         outName = as->parms[3].items->data;
1459     else
1460         outName = NULL;
1461
1462     if (as->parms[5].items)
1463         showlog = 1;
1464
1465     /* parallel option */
1466     parallel = NULL;
1467     if (as->parms[6].items)
1468         parallel = as->parms[6].items->data;
1469
1470     /* get the tmpdir filename if any */
1471     tmpDir = NULL;
1472     if (as->parms[7].items)
1473         tmpDir = as->parms[7].items->data;
1474
1475     /* -orphans option */
1476     orphans = NULL;
1477     if (as->parms[8].items) {
1478         if (mrafs) {
1479             printf("Can't specify -orphans for MR-AFS fileserver\n");
1480             return EINVAL;
1481         }
1482         orphans = as->parms[8].items->data;
1483     }
1484
1485     if (dafs) {
1486         if (!as->parms[9].items) { /* -forceDAFS flag */
1487             printf("This is a demand attach fileserver.  Are you sure you want to proceed with a manual salvage?\n");
1488             printf("must specify -forceDAFS flag in order to proceed.\n");
1489             return EINVAL;
1490         }
1491     }
1492
1493     if (mrafs) {
1494         if (as->parms[MRAFS_OFFSET].items)
1495             mrafsParm.Optdebug = 1;
1496         if (as->parms[MRAFS_OFFSET + 1].items)
1497             mrafsParm.Optnowrite = 1;
1498         if (as->parms[MRAFS_OFFSET + 2].items)
1499             mrafsParm.Optforce = 1;
1500         if (as->parms[MRAFS_OFFSET + 3].items)
1501             mrafsParm.Optoktozap = 1;
1502         if (as->parms[MRAFS_OFFSET + 4].items)
1503             mrafsParm.Optrootfiles = 1;
1504         if (as->parms[MRAFS_OFFSET + 5].items)
1505             mrafsParm.Optsalvagedirs = 1;
1506         if (as->parms[MRAFS_OFFSET + 6].items)
1507             mrafsParm.Optblockreads = 1;
1508         if (as->parms[MRAFS_OFFSET + 7].items)
1509             mrafsParm.OptListResidencies = 1;
1510         if (as->parms[MRAFS_OFFSET + 8].items)
1511             mrafsParm.OptSalvageRemote = 1;
1512         if (as->parms[MRAFS_OFFSET + 9].items)
1513             mrafsParm.OptSalvageArchival = 1;
1514         if (as->parms[MRAFS_OFFSET + 10].items)
1515             mrafsParm.OptIgnoreCheck = 1;
1516         if (as->parms[MRAFS_OFFSET + 11].items)
1517             mrafsParm.OptForceOnLine = 1;
1518         if (as->parms[MRAFS_OFFSET + 12].items)
1519             mrafsParm.OptUseRootDirACL = 1;
1520         if (as->parms[MRAFS_OFFSET + 13].items)
1521             mrafsParm.OptTraceBadLinkCounts = 1;
1522         if (as->parms[MRAFS_OFFSET + 14].items)
1523             mrafsParm.OptDontAskFS = 1;
1524         if (as->parms[MRAFS_OFFSET + 15].items)
1525             mrafsParm.OptLogLevel =
1526                 atoi(as->parms[MRAFS_OFFSET + 15].items->data);
1527         if (as->parms[MRAFS_OFFSET + 16].items)
1528             mrafsParm.OptRxDebug = 1;
1529         if (as->parms[MRAFS_OFFSET + 17].items) {
1530             if (as->parms[MRAFS_OFFSET + 8].items
1531                 || as->parms[MRAFS_OFFSET + 9].items) {
1532                 printf
1533                     ("Can't specify -Residencies with -SalvageRemote or -SalvageArchival\n");
1534                 return EINVAL;
1535             }
1536             code =
1537                 util_GetUInt32(as->parms[MRAFS_OFFSET + 17].items->data,
1538                                &mrafsParm.OptResidencies);
1539             if (code) {
1540                 printf("bos: '%s' is not a valid residency mask.\n",
1541                        as->parms[MRAFS_OFFSET + 17].items->data);
1542                 return code;
1543             }
1544         }
1545     } else {
1546         int stop = 0;
1547
1548         for (i = MRAFS_OFFSET; i < ADDPARMOFFSET; i++) {
1549             if (as->parms[i].items) {
1550                 printf(" %s only possible for MR-AFS fileserver.\n",
1551                        as->parms[i].name);
1552                 stop = 1;
1553             }
1554         }
1555         if (stop)
1556             exit(1);
1557     }
1558
1559     if (as->parms[4].items) {
1560         /* salvage whole enchilada */
1561         curGoal = GetServerGoal(tconn, serviceName);
1562         if (curGoal == BSTAT_NORMAL) {
1563             printf("bos: shutting down '%s'.\n", serviceName);
1564             code = BOZO_SetTStatus(tconn, serviceName, BSTAT_SHUTDOWN);
1565             if (code) {
1566                 printf("bos: failed to stop '%s' (%s)\n", serviceName, em(code));
1567                 return code;
1568             }
1569             code = BOZO_WaitAll(tconn); /* wait for shutdown to complete */
1570             if (code)
1571                 printf
1572                     ("bos: failed to wait for file server shutdown, continuing.\n");
1573         }
1574         /* now do the salvage operation */
1575         printf("Starting salvage.\n");
1576         rc = DoSalvage(tconn, NULL, NULL, outName, showlog, parallel, tmpDir,
1577                        orphans, dafs, &mrafsParm);
1578         if (curGoal == BSTAT_NORMAL) {
1579             printf("bos: restarting %s.\n", serviceName);
1580             code = BOZO_SetTStatus(tconn, serviceName, BSTAT_NORMAL);
1581             if (code) {
1582                 printf("bos: failed to restart '%s' (%s)\n", serviceName, em(code));
1583                 return code;
1584             }
1585         }
1586         if (rc)
1587             return rc;
1588     } else if (!as->parms[2].items) {
1589         if (!as->parms[1].items) {
1590             printf
1591                 ("bos: must specify -all switch to salvage all partitions.\n");
1592             return -1;
1593         }
1594         if (volutil_GetPartitionID(as->parms[1].items->data) < 0) {
1595             /* can't parse volume ID, so complain before shutting down
1596              * file server.
1597              */
1598             printf("bos: can't interpret %s as partition ID.\n",
1599                    as->parms[1].items->data);
1600             return -1;
1601         }
1602         curGoal = GetServerGoal(tconn, serviceName);
1603         /* salvage a whole partition (specified by parms[1]) */
1604         if (curGoal == BSTAT_NORMAL) {
1605             printf("bos: shutting down '%s'.\n", serviceName);
1606             code = BOZO_SetTStatus(tconn, serviceName, BSTAT_SHUTDOWN);
1607             if (code) {
1608                 printf("bos: can't stop '%s' (%s)\n", serviceName, em(code));
1609                 return code;
1610             }
1611             code = BOZO_WaitAll(tconn); /* wait for shutdown to complete */
1612             if (code)
1613                 printf
1614                     ("bos: failed to wait for file server shutdown, continuing.\n");
1615         }
1616         /* now do the salvage operation */
1617         printf("Starting salvage.\n");
1618         rc = DoSalvage(tconn, as->parms[1].items->data, NULL, outName,
1619                        showlog, parallel, tmpDir, orphans, dafs, &mrafsParm);
1620         if (curGoal == BSTAT_NORMAL) {
1621             printf("bos: restarting '%s'.\n", serviceName);
1622             code = BOZO_SetTStatus(tconn, serviceName, BSTAT_NORMAL);
1623             if (code) {
1624                 printf("bos: failed to restart '%s' (%s)\n", serviceName, em(code));
1625                 return code;
1626             }
1627         }
1628         if (rc)
1629             return rc;
1630     } else {
1631         /* salvage individual volume (don't shutdown fs first), just use
1632          * single-shot cron bnode.  Must leave server running when using this
1633          * option, since salvager will ask file server for the volume */
1634         char *tmpname;
1635         afs_int32 err;
1636         const char *confdir;
1637         int localauth;
1638
1639         if (as->parms[ADDPARMOFFSET].items)
1640             tmpname = as->parms[ADDPARMOFFSET].items->data;
1641         else
1642             tmpname = NULL;
1643
1644         localauth = (as->parms[ADDPARMOFFSET + 2].items != 0);
1645         confdir =
1646             (localauth ? AFSDIR_SERVER_ETC_DIRPATH :
1647              AFSDIR_CLIENT_ETC_DIRPATH);
1648
1649         code = vsu_ClientInit(confdir, tmpname,
1650                               AFSCONF_SECOPTS_FALLBACK_NULL |
1651                               AFSCONF_SECOPTS_NOAUTH,
1652                               NULL, &cstruct);
1653
1654         if (code == 0) {
1655             newID = vsu_GetVolumeID(as->parms[2].items->data, cstruct, &err);
1656             if (newID == 0) {
1657                 printf("bos: can't interpret %s as volume name or ID\n",
1658                        as->parms[2].items->data);
1659                 return -1;
1660             }
1661             sprintf(tname, "%u", newID);
1662         } else {
1663             printf
1664                 ("bos: can't initialize volume system client (code %d), trying anyway.\n",
1665                  code);
1666             strncpy(tname, as->parms[2].items->data, sizeof(tname));
1667         }
1668         if (volutil_GetPartitionID(as->parms[1].items->data) < 0) {
1669             /* can't parse volume ID, so complain before shutting down
1670              * file server.
1671              */
1672             printf("bos: can't interpret %s as partition ID.\n",
1673                    as->parms[1].items->data);
1674             return -1;
1675         }
1676         printf("Starting salvage.\n");
1677         rc = DoSalvage(tconn, as->parms[1].items->data, tname, outName,
1678                        showlog, parallel, tmpDir, orphans, dafs, &mrafsParm);
1679         if (rc)
1680             return rc;
1681     }
1682     return 0;
1683 }
1684
1685 static int
1686 IStatServer(struct cmd_syndesc *as, int int32p)
1687 {
1688     struct rx_connection *tconn;
1689     struct cmd_item *ti;
1690     int firstTime = 1;
1691
1692     tconn = GetConn(as, 0);
1693     for (ti = as->parms[1].items; ti; ti = ti->next) {
1694         DoStat(ti->data, tconn, int32p, firstTime);
1695         firstTime = 0;
1696     }
1697     return 0;
1698 }
1699
1700 static int
1701 DoStat(IN char *aname,
1702        IN struct rx_connection *aconn,
1703        IN int aint32p,
1704        IN int firstTime)        /* true iff first instance in cmd */
1705 {
1706     afs_int32 temp;
1707     char buffer[500];
1708     afs_int32 code;
1709     afs_int32 i;
1710     struct bozo_status istatus;
1711     char *tp;
1712     char *is1, *is2, *is3, *is4;        /* instance strings */
1713
1714     tp = buffer;
1715     code = BOZO_GetInstanceInfo(aconn, aname, &tp, &istatus);
1716     if (code) {
1717         printf("bos: failed to get instance info for '%s' (%s)\n", aname,
1718                em(code));
1719         return -1;
1720     }
1721     if (firstTime && aint32p && (istatus.flags & BOZO_BADDIRACCESS))
1722         printf
1723             ("Bosserver reports inappropriate access on server directories\n");
1724     printf("Instance %s, ", aname);
1725     if (aint32p)
1726         printf("(type is %s) ", buffer);
1727     if (istatus.fileGoal == istatus.goal) {
1728         if (!istatus.goal)
1729             printf("disabled, ");
1730     } else {
1731         if (istatus.fileGoal)
1732             printf("temporarily disabled, ");
1733         else
1734             printf("temporarily enabled, ");
1735     }
1736
1737     if (istatus.flags & BOZO_ERRORSTOP)
1738         printf("stopped for too many errors, ");
1739     if (istatus.flags & BOZO_HASCORE)
1740         printf("has core file, ");
1741
1742     tp = buffer;
1743     code = BOZO_GetStatus(aconn, aname, &temp, &tp);
1744     if (code)
1745         printf("bos: failed to get status for instance '%s' (%s)\n", aname,
1746                em(code));
1747     else {
1748         printf("currently ");
1749         if (temp == BSTAT_NORMAL)
1750             printf("running normally.\n");
1751         else if (temp == BSTAT_SHUTDOWN)
1752             printf("shutdown.\n");
1753         else if (temp == BSTAT_STARTINGUP)
1754             printf("starting up.\n");
1755         else if (temp == BSTAT_SHUTTINGDOWN)
1756             printf("shutting down.\n");
1757         if (buffer[0] != 0) {
1758             printf("    Auxiliary status is: %s.\n", buffer);
1759         }
1760     }
1761
1762     /* are we done yet? */
1763     if (!aint32p)
1764         return 0;
1765
1766     if (istatus.procStartTime)
1767         printf("    Process last started at %s (%d proc starts)\n",
1768                DateOf(istatus.procStartTime), istatus.procStarts);
1769     if (istatus.lastAnyExit) {
1770         printf("    Last exit at %s\n", DateOf(istatus.lastAnyExit));
1771     }
1772     if (istatus.lastErrorExit) {
1773         is1 = is2 = is3 = is4 = NULL;
1774         printf("    Last error exit at %s, ", DateOf(istatus.lastErrorExit));
1775         code = BOZO_GetInstanceStrings(aconn, aname, &is1, &is2, &is3, &is4);
1776         /* don't complain about failing call, since could simply mean
1777          * interface mismatch.
1778          */
1779         if (code == 0) {
1780             if (*is1 != 0) {
1781                 /* non-null instance string */
1782                 printf("by %s, ", is1);
1783             }
1784             free(is1);
1785             free(is2);
1786             free(is3);
1787             free(is4);
1788         }
1789         if (istatus.errorSignal) {
1790             if (istatus.errorSignal == SIGTERM)
1791                 printf("due to shutdown request\n");
1792             else
1793                 printf("due to signal %d\n", istatus.errorSignal);
1794         } else
1795             printf("by exiting with code %d\n", istatus.errorCode);
1796     }
1797
1798     if (aint32p > 1) {
1799         /* try to display all the parms */
1800         for (i = 0;; i++) {
1801             tp = buffer;
1802             code = BOZO_GetInstanceParm(aconn, aname, i, &tp);
1803             if (code)
1804                 break;
1805             printf("    Command %d is '%s'\n", i + 1, buffer);
1806         }
1807         tp = buffer;
1808         code = BOZO_GetInstanceParm(aconn, aname, 999, &tp);
1809         if (!code) {
1810             /* Any type of failure is treated as not having a notifier program */
1811             printf("    Notifier  is '%s'\n", buffer);
1812         }
1813         printf("\n");
1814     }
1815     return 0;
1816 }
1817
1818 static int
1819 GetRestrict(struct cmd_syndesc *as, void *arock)
1820 {
1821     struct rx_connection *tconn;
1822     afs_int32 code, val;
1823
1824     tconn = GetConn(as, 0);
1825     code = BOZO_GetRestrictedMode(tconn, &val);
1826     if (code)
1827         printf("bos: failed to get restricted mode (%s)\n", em(code));
1828     else
1829         printf("Restricted mode is %s\n", val ? "on" : "off");
1830
1831     return 0;
1832 }
1833
1834 static int
1835 SetRestrict(struct cmd_syndesc *as, void *arock)
1836 {
1837     struct rx_connection *tconn;
1838     afs_int32 code, val;
1839
1840     tconn = GetConn(as, 0);
1841     util_GetInt32(as->parms[1].items->data, &val);
1842     code = BOZO_SetRestrictedMode(tconn, val);
1843     if (code)
1844         printf("bos: failed to set restricted mode (%s)\n", em(code));
1845     return 0;
1846 }
1847
1848 static void
1849 add_std_args(struct cmd_syndesc *ts)
1850 {
1851     cmd_Seek(ts, ADDPARMOFFSET);
1852     /* + 0 */ cmd_AddParm(ts, "-cell", CMD_SINGLE, CMD_OPTIONAL, "cell name");
1853     /* + 1 */ cmd_AddParm(ts, "-noauth", CMD_FLAG, CMD_OPTIONAL,
1854                           "don't authenticate");
1855     /* + 2 */ cmd_AddParm(ts, "-localauth", CMD_FLAG, CMD_OPTIONAL,
1856                           "create tickets from KeyFile");
1857 }
1858
1859 #include "AFS_component_version_number.c"
1860
1861 int
1862 main(int argc, char **argv)
1863 {
1864     afs_int32 code;
1865     struct cmd_syndesc *ts;
1866 #ifdef AFS_NT40_ENV
1867     __declspec(dllimport)
1868 #endif
1869     extern int afsconf_SawCell;
1870
1871 #ifdef  AFS_AIX32_ENV
1872     /*
1873      * The following signal action for AIX is necessary so that in case of a
1874      * crash (i.e. core is generated) we can include the user's data section
1875      * in the core dump. Unfortunately, by default, only a partial core is
1876      * generated which, in many cases, isn't too useful.
1877      */
1878     struct sigaction nsa;
1879
1880     sigemptyset(&nsa.sa_mask);
1881     nsa.sa_handler = SIG_DFL;
1882     nsa.sa_flags = SA_FULLDUMP;
1883     sigaction(SIGSEGV, &nsa, NULL);
1884     sigaction(SIGABRT, &nsa, NULL);
1885 #endif
1886
1887     /* start up rx */
1888     code = rx_Init(0);
1889     if (code) {
1890         printf("bos: could not initialize rx (%s)\n", em(code));
1891         exit(1);
1892     }
1893
1894     /* To resolve a AFSCELL environment "Note: ..." problem: Because bos calls ka_Init (why?) before any
1895      * checkup on the existance of a "-cell" option on the particular bos command we don't print the
1896      * message if a cell is passed in. Luckily the rest of the programs don't call these adhoc routines
1897      * and things work fine. Note that if the "-cell" isn't passed then we're still ok since later on
1898      * the proper routine (afsconf_GetCellInfo) is going to be called to do the right thing.
1899      */
1900     afsconf_SawCell = 1;        /* Means don't print warning if AFSCELL is set */
1901     ka_Init(0);
1902     afsconf_SawCell = 0;        /* Reset it */
1903     /* don't check error code, since fails sometimes when we're setting up a
1904      * system */
1905     initialize_CMD_error_table();
1906     initialize_BZ_error_table();
1907
1908     ts = cmd_CreateSyntax("start", StartServer, NULL, "start running a server");
1909     cmd_AddParm(ts, "-server", CMD_SINGLE, 0, "machine name");
1910     cmd_AddParm(ts, "-instance", CMD_LIST, 0, "server process name");
1911     add_std_args(ts);
1912
1913     ts = cmd_CreateSyntax("stop", StopServer, NULL, "halt a server instance");
1914     cmd_AddParm(ts, "-server", CMD_SINGLE, 0, "machine name");
1915     cmd_AddParm(ts, "-instance", CMD_LIST, 0, "server process name");
1916     cmd_Seek(ts, 8);
1917     cmd_AddParm(ts, "-wait", CMD_FLAG, CMD_OPTIONAL,
1918                 "wait for process to stop");
1919     add_std_args(ts);
1920
1921     ts = cmd_CreateSyntax("status", StatServer, NULL,
1922                           "show server instance status");
1923     cmd_AddParm(ts, "-server", CMD_SINGLE, 0, "machine name");
1924     cmd_AddParm(ts, "-instance", CMD_LIST, CMD_OPTIONAL,
1925                 "server process name");
1926     cmd_AddParm(ts, "-long", CMD_FLAG, CMD_OPTIONAL, "long status");
1927     add_std_args(ts);
1928
1929     ts = cmd_CreateSyntax("shutdown", Shutdown, NULL, "shutdown all processes");
1930     cmd_AddParm(ts, "-server", CMD_SINGLE, 0, "machine name");
1931     cmd_AddParm(ts, "-instance", CMD_LIST, CMD_OPTIONAL, "instances");
1932     cmd_Seek(ts, 8);
1933     cmd_AddParm(ts, "-wait", CMD_FLAG, CMD_OPTIONAL,
1934                 "wait for process to stop");
1935     add_std_args(ts);
1936
1937     ts = cmd_CreateSyntax("startup", Startup, NULL, "start all processes");
1938     cmd_AddParm(ts, "-server", CMD_SINGLE, 0, "machine name");
1939     cmd_AddParm(ts, "-instance", CMD_LIST, CMD_OPTIONAL, "instances");
1940     add_std_args(ts);
1941
1942     ts = cmd_CreateSyntax("restart", Restart, NULL, "restart processes");
1943     cmd_AddParm(ts, "-server", CMD_SINGLE, 0, "machine name");
1944     cmd_AddParm(ts, "-instance", CMD_LIST, CMD_OPTIONAL, "instances");
1945     cmd_AddParm(ts, "-bosserver", CMD_FLAG, CMD_OPTIONAL,
1946                 "restart bosserver");
1947     cmd_AddParm(ts, "-all", CMD_FLAG, CMD_OPTIONAL, "restart all processes");
1948     add_std_args(ts);
1949
1950 #ifndef OPBOS
1951
1952     ts = cmd_CreateSyntax("create", CreateServer, NULL,
1953                           "create a new server instance");
1954     cmd_AddParm(ts, "-server", CMD_SINGLE, 0, "machine name");
1955     cmd_AddParm(ts, "-instance", CMD_SINGLE, 0, "server process name");
1956     cmd_AddParm(ts, "-type", CMD_SINGLE, 0, "server type");
1957     cmd_AddParm(ts, "-cmd", CMD_LIST, 0, "command lines");
1958     cmd_AddParm(ts, "-notifier", CMD_SINGLE, CMD_OPTIONAL,
1959                 "Notifier program");
1960     add_std_args(ts);
1961
1962     ts = cmd_CreateSyntax("delete", DeleteServer, NULL,
1963                           "delete a server instance");
1964     cmd_AddParm(ts, "-server", CMD_SINGLE, 0, "machine name");
1965     cmd_AddParm(ts, "-instance", CMD_LIST, 0, "server process name");
1966     add_std_args(ts);
1967
1968     ts = cmd_CreateSyntax("adduser", AddSUser, NULL,
1969                           "add users to super-user list");
1970     cmd_AddParm(ts, "-server", CMD_SINGLE, 0, "machine name");
1971     cmd_AddParm(ts, "-user", CMD_LIST, 0, "user names");
1972     add_std_args(ts);
1973
1974     ts = cmd_CreateSyntax("removeuser", RemoveSUser, NULL,
1975                           "remove users from super-user list");
1976     cmd_AddParm(ts, "-server", CMD_SINGLE, 0, "machine name");
1977     cmd_AddParm(ts, "-user", CMD_LIST, 0, "user names");
1978     add_std_args(ts);
1979
1980     ts = cmd_CreateSyntax("listusers", ListSUsers, NULL, "list super-users");
1981     cmd_AddParm(ts, "-server", CMD_SINGLE, 0, "machine name");
1982     add_std_args(ts);
1983
1984     ts = cmd_CreateSyntax("addkey", AddKey, NULL,
1985                           "add keys to key dbase (kvno 999 is bcrypt)");
1986     cmd_AddParm(ts, "-server", CMD_SINGLE, 0, "machine name");
1987     cmd_AddParm(ts, "-key", CMD_SINGLE, CMD_OPTIONAL, "key");
1988     cmd_AddParm(ts, "-kvno", CMD_SINGLE, 0, "key version number");
1989     add_std_args(ts);
1990
1991     ts = cmd_CreateSyntax("removekey", RemoveKey, NULL,
1992                           "remove keys from key dbase");
1993     cmd_AddParm(ts, "-server", CMD_SINGLE, 0, "machine name");
1994     cmd_AddParm(ts, "-kvno", CMD_LIST, 0, "key version number");
1995     add_std_args(ts);
1996
1997     ts = cmd_CreateSyntax("listkeys", ListKeys, NULL, "list keys");
1998     cmd_AddParm(ts, "-server", CMD_SINGLE, 0, "machine name");
1999     cmd_AddParm(ts, "-showkey", CMD_FLAG, CMD_OPTIONAL,
2000                 "show the actual key rather than the checksum");
2001     add_std_args(ts);
2002
2003     ts = cmd_CreateSyntax("listhosts", ListHosts, NULL, "get cell host list");
2004     cmd_AddParm(ts, "-server", CMD_SINGLE, 0, "machine name");
2005     add_std_args(ts);
2006     cmd_CreateAlias(ts, "getcell");
2007
2008     ts = cmd_CreateSyntax("setcellname", SetCellName, NULL, "set cell name");
2009     cmd_AddParm(ts, "-server", CMD_SINGLE, 0, "machine name");
2010     cmd_AddParm(ts, "-name", CMD_SINGLE, 0, "cell name");
2011     add_std_args(ts);
2012
2013     ts = cmd_CreateSyntax("addhost", AddHost, NULL, "add host to cell dbase");
2014     cmd_AddParm(ts, "-server", CMD_SINGLE, 0, "machine name");
2015     cmd_AddParm(ts, "-host", CMD_LIST, 0, "host name");
2016     cmd_AddParm(ts, "-clone", CMD_FLAG, CMD_OPTIONAL, "vote doesn't count");
2017     add_std_args(ts);
2018
2019     ts = cmd_CreateSyntax("removehost", RemoveHost, NULL,
2020                           "remove host from cell dbase");
2021     cmd_AddParm(ts, "-server", CMD_SINGLE, 0, "machine name");
2022     cmd_AddParm(ts, "-host", CMD_LIST, 0, "host name");
2023     add_std_args(ts);
2024
2025     ts = cmd_CreateSyntax("setauth", SetAuth, NULL,
2026                           "set authentication required flag");
2027     cmd_AddParm(ts, "-server", CMD_SINGLE, 0, "machine name");
2028     cmd_AddParm(ts, "-authrequired", CMD_SINGLE, 0,
2029                 "on or off: authentication required for admin requests");
2030     add_std_args(ts);
2031
2032     ts = cmd_CreateSyntax("install", Install, NULL, "install program");
2033     cmd_AddParm(ts, "-server", CMD_SINGLE, 0, "machine name");
2034     cmd_AddParm(ts, "-file", CMD_LIST, 0, "files to install");
2035     cmd_AddParm(ts, "-dir", CMD_SINGLE, CMD_OPTIONAL, "destination dir");
2036     add_std_args(ts);
2037
2038     ts = cmd_CreateSyntax("uninstall", UnInstall, NULL, "uninstall program");
2039     cmd_AddParm(ts, "-server", CMD_SINGLE, 0, "machine name");
2040     cmd_AddParm(ts, "-file", CMD_LIST, 0, "files to uninstall");
2041     cmd_AddParm(ts, "-dir", CMD_SINGLE, CMD_OPTIONAL, "destination dir");
2042     add_std_args(ts);
2043
2044     ts = cmd_CreateSyntax("getlog", GetLogCmd, NULL, "examine log file");
2045     cmd_AddParm(ts, "-server", CMD_SINGLE, 0, "machine name");
2046     cmd_AddParm(ts, "-file", CMD_SINGLE, 0, "log file to examine");
2047     add_std_args(ts);
2048
2049     ts = cmd_CreateSyntax("getdate", GetDate, NULL, "get dates for programs");
2050     cmd_AddParm(ts, "-server", CMD_SINGLE, 0, "machine name");
2051     cmd_AddParm(ts, "-file", CMD_LIST, 0, "files to check");
2052     cmd_AddParm(ts, "-dir", CMD_SINGLE, CMD_OPTIONAL, "destination dir");
2053     add_std_args(ts);
2054
2055     ts = cmd_CreateSyntax("exec", Exec, NULL, "execute shell command on server");
2056     cmd_AddParm(ts, "-server", CMD_SINGLE, 0, "machine name");
2057     cmd_AddParm(ts, "-cmd", CMD_SINGLE, 0, "command to execute");
2058     add_std_args(ts);
2059
2060     ts = cmd_CreateSyntax("prune", Prune, NULL, "prune server files");
2061     cmd_AddParm(ts, "-server", CMD_SINGLE, 0, "machine name");
2062     cmd_AddParm(ts, "-bak", CMD_FLAG, CMD_OPTIONAL, "delete .BAK files");
2063     cmd_AddParm(ts, "-old", CMD_FLAG, CMD_OPTIONAL, "delete .OLD files");
2064     cmd_AddParm(ts, "-core", CMD_FLAG, CMD_OPTIONAL, "delete core files");
2065     cmd_AddParm(ts, "-all", CMD_FLAG, CMD_OPTIONAL, "delete all junk files");
2066     add_std_args(ts);
2067
2068     ts = cmd_CreateSyntax("setrestart", SetRestartCmd, NULL,
2069                           "set restart times");
2070     cmd_AddParm(ts, "-server", CMD_SINGLE, CMD_REQUIRED, "machine name");
2071     cmd_AddParm(ts, "-time", CMD_SINGLE, CMD_REQUIRED,
2072                 "time to restart server");
2073     cmd_AddParm(ts, "-general", CMD_FLAG, CMD_OPTIONAL,
2074                 "set general restart time");
2075     cmd_AddParm(ts, "-newbinary", CMD_FLAG, CMD_OPTIONAL,
2076                 "set new binary restart time");
2077     add_std_args(ts);
2078     cmd_CreateAlias(ts, "setr");
2079
2080     ts = cmd_CreateSyntax("getrestart", GetRestartCmd, NULL,
2081                           "get restart times");
2082     cmd_AddParm(ts, "-server", CMD_SINGLE, CMD_REQUIRED, "machine name");
2083     add_std_args(ts);
2084     cmd_CreateAlias(ts, "getr");
2085
2086     ts = cmd_CreateSyntax("salvage", SalvageCmd, NULL,
2087                           "salvage partition or volumes");
2088     cmd_AddParm(ts, "-server", CMD_SINGLE, 0, "machine name");
2089     cmd_AddParm(ts, "-partition", CMD_SINGLE, CMD_OPTIONAL,
2090                 "salvage partition");
2091     cmd_AddParm(ts, "-volume", CMD_SINGLE, CMD_OPTIONAL,
2092                 "salvage volume number or volume name");
2093     cmd_AddParm(ts, "-file", CMD_SINGLE, CMD_OPTIONAL,
2094                 "salvage log output file");
2095     cmd_AddParm(ts, "-all", CMD_FLAG, CMD_OPTIONAL, "salvage whole server");
2096     cmd_AddParm(ts, "-showlog", CMD_FLAG, CMD_OPTIONAL,
2097                 "display salvage log");
2098     cmd_AddParm(ts, "-parallel", CMD_SINGLE, CMD_OPTIONAL,
2099                 "# of max parallel partition salvaging");
2100     cmd_AddParm(ts, "-tmpdir", CMD_SINGLE, CMD_OPTIONAL,
2101                 "directory to place tmp files");
2102     cmd_AddParm(ts, "-orphans", CMD_SINGLE, CMD_OPTIONAL,
2103                 "ignore | remove | attach");
2104     cmd_AddParm(ts, "-forceDAFS", CMD_FLAG, CMD_OPTIONAL,
2105                 "(DAFS) force salvage of demand attach fileserver");
2106     cmd_AddParm(ts, "-debug", CMD_FLAG, CMD_OPTIONAL,
2107                 "(MR-AFS) Run in Debugging mode");
2108     cmd_AddParm(ts, "-nowrite", CMD_FLAG, CMD_OPTIONAL,
2109                 "(MR-AFS) Run readonly/test mode");
2110     cmd_AddParm(ts, "-force", CMD_FLAG, CMD_OPTIONAL,
2111                 "(MR-AFS) Force full salvaging");
2112     cmd_AddParm(ts, "-oktozap", CMD_FLAG, CMD_OPTIONAL,
2113                 "(MR-AFS) Give permission to destroy bogus file residencies/volumes - debugging flag");
2114     cmd_AddParm(ts, "-rootfiles", CMD_FLAG, CMD_OPTIONAL,
2115                 "(MR-AFS) Show files owned by root - debugging flag");
2116     cmd_AddParm(ts, "-salvagedirs", CMD_FLAG, CMD_OPTIONAL,
2117                 "(MR-AFS) Force rebuild/salvage of all directories");
2118     cmd_AddParm(ts, "-blockreads", CMD_FLAG, CMD_OPTIONAL,
2119                 "(MR-AFS) Read smaller blocks to handle IO/bad blocks");
2120     cmd_AddParm(ts, "-ListResidencies", CMD_FLAG, CMD_OPTIONAL,
2121                 "(MR-AFS) Just list affected file residencies - debugging flag");
2122     cmd_AddParm(ts, "-SalvageRemote", CMD_FLAG, CMD_OPTIONAL,
2123                 "(MR-AFS) Salvage storage systems that are not directly attached");
2124     cmd_AddParm(ts, "-SalvageArchival", CMD_FLAG, CMD_OPTIONAL,
2125                 "(MR-AFS) Salvage HSM storage systems");
2126     cmd_AddParm(ts, "-IgnoreCheck", CMD_FLAG, CMD_OPTIONAL,
2127                 "(MR-AFS) Don't perform VLDB safety check when deleting unreferenced files.  Only a good idea in single server cell.");
2128     cmd_AddParm(ts, "-ForceOnLine", CMD_FLAG, CMD_OPTIONAL,
2129                 "(MR-AFS) Force the volume to come online, even if it hasn't salvaged cleanly.");
2130     cmd_AddParm(ts, "-UseRootDirACL", CMD_FLAG, CMD_OPTIONAL,
2131                 "(MR-AFS) Use the root directory ACL for lost+found directory if it is created.");
2132     cmd_AddParm(ts, "-TraceBadLinkCounts", CMD_FLAG, CMD_OPTIONAL,
2133                 "(MR-AFS) Print out lines about volume reference count changes.");
2134     cmd_AddParm(ts, "-DontAskFS", CMD_FLAG, CMD_OPTIONAL,
2135                 "(MR-AFS) Don't ask fileserver to take volume offline.  THIS IS VERY DANGEROUS.");
2136     cmd_AddParm(ts, "-LogLevel", CMD_SINGLE, CMD_OPTIONAL,
2137                 "(MR-AFS) log level");
2138     cmd_AddParm(ts, "-rxdebug", CMD_FLAG, CMD_OPTIONAL,
2139                 "(MR-AFS) Write out rx debug information.");
2140     cmd_AddParm(ts, "-Residencies", CMD_SINGLE, CMD_OPTIONAL,
2141                 "(MR-AFS) Numeric mask of residencies to be included in the salvage.  Do not use with -SalvageRemote or -SalvageArchival");
2142     add_std_args(ts);
2143
2144     ts = cmd_CreateSyntax("blockscanner", BlockScannerCmd, NULL,
2145                           "block scanner daemon from making migration requests");
2146     cmd_AddParm(ts, "-server", CMD_SINGLE, CMD_REQUIRED, "machine name");
2147     add_std_args(ts);
2148
2149     ts = cmd_CreateSyntax("unblockscanner", UnBlockScannerCmd, NULL,
2150                           "allow scanner daemon to make migration requests again");
2151     cmd_AddParm(ts, "-server", CMD_SINGLE, CMD_REQUIRED, "machine name");
2152     add_std_args(ts);
2153
2154     ts = cmd_CreateSyntax("getrestricted", GetRestrict, NULL,
2155                           "get restrict mode");
2156     cmd_AddParm(ts, "-server", CMD_SINGLE, 0, "machine name");
2157     add_std_args(ts);
2158
2159     ts = cmd_CreateSyntax("setrestricted", SetRestrict, NULL,
2160                           "set restrict mode");
2161     cmd_AddParm(ts, "-server", CMD_SINGLE, 0, "machine name");
2162     cmd_AddParm(ts, "-mode", CMD_SINGLE, 0, "mode to set");
2163     add_std_args(ts);
2164 #endif
2165
2166     code = cmd_Dispatch(argc, argv);
2167     rx_Finalize();
2168     exit(code);
2169 }