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