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