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