rxgen-prototypes-fixes-20020310
[openafs.git] / src / bozo / bosoprocs.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("$Header$");
14
15 #include <afs/stds.h>
16 #include <sys/types.h>
17 #ifdef AFS_NT40_ENV
18 #include <io.h>
19 #include <fcntl.h>
20 #include <sys/utime.h>
21 #else
22 #include <sys/file.h>
23 #include <netinet/in.h>
24 #endif /* AFS_NT40_ENV */
25 #include <rx/xdr.h>
26 #include <rx/rx.h>
27 #include <rx/rxkad.h>
28 #include <errno.h>
29 #include <afs/cellconfig.h>
30 #include <afs/keys.h>
31 #include <sys/stat.h>
32 #include <des.h>
33 #include <dirent.h>
34 #include <stdio.h>
35 #include <afs/afsutil.h>
36 #include <afs/fileutil.h>
37 #include <afs/ktime.h>
38 #include <afs/audit.h>
39
40 #include "bnode.h"
41 #include "bosint.h"
42
43
44 extern struct ktime bozo_nextRestartKT, bozo_nextDayKT;
45
46 extern struct afsconf_dir *bozo_confdir;
47 extern struct rx_securityClass *bozo_rxsc[2];
48 extern int bozo_newKTs;
49 extern int DoLogging;
50 #ifdef BOS_RESTRICTED_MODE
51 extern int bozo_isrestricted;
52 #endif
53
54 afs_int32 SBOZO_GetRestartTime(acall, atype, aktime)
55     struct rx_call *acall;
56     afs_int32 atype;
57     struct bozo_netKTime *aktime;
58 {
59     register afs_int32 code;
60
61     code = 0;           /* assume success */
62     switch (atype) {
63       case 1:
64         memcpy(aktime, &bozo_nextRestartKT, sizeof(struct ktime));
65         break;
66
67       case 2:
68         memcpy(aktime, &bozo_nextDayKT, sizeof(struct ktime));
69         break;
70
71       default:
72         code = BZDOM;
73         break;
74     }
75
76     return code;
77 }
78
79 afs_int32 SBOZO_SetRestartTime(acall, atype, aktime)
80     struct rx_call *acall;
81     afs_int32 atype;
82     struct bozo_netKTime *aktime;
83 {
84     register afs_int32 code;
85     char caller[MAXKTCNAMELEN];
86
87     /* check for proper permissions */
88     if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
89       code = BZACCESS;
90       goto fail;
91     }
92     if (DoLogging) bozo_Log("%s is executing SetRestartTime\n", caller);
93
94     code = 0;           /* assume success */
95     switch (atype) {
96       case 1:
97         memcpy(&bozo_nextRestartKT, aktime, sizeof(struct ktime));
98         break;
99
100       case 2:
101         memcpy(&bozo_nextDayKT, aktime, sizeof(struct ktime));
102         break;
103
104       default:
105         code = BZDOM;
106         break;
107     }
108
109     if (code == 0) {
110         /* try to update the bozo init file */
111         code = WriteBozoFile(0);
112         bozo_newKTs = 1;
113     }
114
115 fail:
116     osi_auditU (acall, BOS_SetRestartEvent, code, AUD_END);
117     return code;
118 }
119
120 afs_int32 SBOZO_Exec(acall, acmd)
121 struct rx_call *acall;
122 char *acmd; {
123
124     char caller[MAXKTCNAMELEN];
125     int code;
126
127     if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
128       code = BZACCESS;
129       goto fail;
130     }
131 #ifdef BOS_RESTRICTED_MODE
132     if (bozo_isrestricted) {
133       code = BZACCESS;
134       goto fail;
135     }
136 #endif
137     if (DoLogging) bozo_Log("%s is executing the shell command '%s'\n", caller, acmd);
138
139     /* should copy output to acall, but don't yet cause its hard */
140     /*  hard... NOT!  Nnow _at least_ return the exit status */
141     code = system(acmd);
142     osi_auditU (acall, BOS_ExecEvent, code, AUD_STR, acmd, AUD_END);
143
144 fail:
145     return code;
146 }
147
148 afs_int32 SBOZO_GetDates(acall, aname, atime, abakTime, aoldTime)
149 struct rx_call *acall;
150 char *aname;
151 afs_int32 *atime, *abakTime, *aoldTime; {
152     struct stat tstat;
153     char *strp;
154     char tbuffer[AFSDIR_PATH_MAX];
155
156     *atime = *abakTime = *aoldTime = 0;
157
158     /* construct local path from canonical (wire-format) path */
159     if (ConstructLocalBinPath(aname, &strp)) {
160         return 0;
161     }
162     strcpy(tbuffer, strp);
163     free(strp);
164
165     strp = tbuffer + strlen(tbuffer);
166
167     if (!stat(tbuffer, &tstat)) {
168         *atime = tstat.st_mtime;
169     }
170
171     strcpy(strp, ".BAK");
172     if (!stat(tbuffer, &tstat)) {
173         *abakTime = tstat.st_mtime;
174     }
175
176     strcpy(strp, ".OLD");
177     if (!stat(tbuffer, &tstat)) {
178         *aoldTime = tstat.st_mtime;
179     }
180     return 0;
181 }
182
183 afs_int32 SBOZO_UnInstall(acall, aname)
184 struct rx_call *acall;
185 register char *aname; {
186     char *filepath;
187     char fpOld[AFSDIR_PATH_MAX], fpBak[AFSDIR_PATH_MAX];
188     afs_int32 code;
189     char caller[MAXKTCNAMELEN];
190     struct stat tstat;
191
192     if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
193         code = BZACCESS;
194         osi_auditU (acall, BOS_UnInstallEvent, code, AUD_STR, aname, AUD_END);
195         return code;
196     }
197 #ifdef BOS_RESTRICTED_MODE
198     if (bozo_isrestricted) {
199         code = BZACCESS;
200         osi_auditU (acall, BOS_UnInstallEvent, code, AUD_STR, aname, AUD_END);
201         return code;
202     }
203 #endif
204
205     /* construct local path from canonical (wire-format) path */
206     if (ConstructLocalBinPath(aname, &filepath)) {
207         return BZNOENT;
208     }
209
210     if (DoLogging) bozo_Log("%s is executing UnInstall '%s'\n", caller, filepath);
211
212     strcpy(fpBak, filepath);
213     strcat(fpBak, ".BAK");
214     strcpy(fpOld, filepath);
215     strcat(fpOld, ".OLD");
216
217     code = renamefile(fpBak, filepath);
218     if (code) {
219         /* can't find .BAK, try .OLD */
220         code = renamefile(fpOld, filepath);
221         if (code && errno == ENOENT)  /* If doesn't exist don't fail */
222             code = 0;
223     } else {
224         /* now rename .OLD to .BAK */
225         if (stat(fpOld, &tstat) == 0)
226             code = renamefile(fpOld, fpBak);
227     }
228     if (code)
229         code = errno;
230
231     osi_auditU (acall, BOS_UnInstallEvent, code, AUD_STR, filepath, AUD_END);
232     free(filepath);
233
234     return code;
235 }
236
237 #define BOZO_OLDTIME        (7*24*3600)     /* 7 days old */
238 static void SaveOldFiles(char *aname)
239 {
240     register afs_int32 code;
241     char bbuffer[AFSDIR_PATH_MAX], obuffer[AFSDIR_PATH_MAX];
242     struct stat tstat;
243     register afs_int32 now;
244     afs_int32 oldTime, bakTime;
245     
246     strcpy(bbuffer, aname);
247     strcat(bbuffer, ".BAK");
248     strcpy(obuffer, aname);
249     strcat(obuffer, ".OLD");
250     now = FT_ApproxTime();
251
252     code = stat(aname, &tstat);
253     if (code < 0) return;       /* can't stat file */
254     
255     code = stat(obuffer, &tstat);    /* discover old file's time */
256     if (code) oldTime = 0;
257     else oldTime = tstat.st_mtime;
258
259     code = stat(bbuffer, &tstat);    /* discover back file's time */
260     if (code) bakTime = 0;
261     else bakTime = tstat.st_mtime;
262
263     if (bakTime && (oldTime == 0 || bakTime < now - BOZO_OLDTIME)) {
264         /* no .OLD file, or .BAK is at least a week old */
265         code = renamefile(bbuffer, obuffer);
266     }
267     
268     /* finally rename to .BAK extension */
269     renamefile(aname, bbuffer);
270 }
271
272 afs_int32 SBOZO_Install(acall, aname, asize, mode, amtime)
273 struct rx_call *acall;
274 char *aname;
275 afs_int32 asize;
276 afs_int32 amtime;
277 afs_int32 mode; {
278     afs_int32 code;
279     int fd;
280     afs_int32 len;
281     afs_int32 total;
282 #ifdef AFS_NT40_ENV
283     struct _utimbuf utbuf;
284 #else
285     struct timeval tvb[2];
286 #endif
287     char filepath[AFSDIR_PATH_MAX], tbuffer[AFSDIR_PATH_MAX], *fpp;
288     char caller[MAXKTCNAMELEN];
289
290     if (!afsconf_SuperUser(bozo_confdir, acall, caller)) return BZACCESS;
291 #ifdef BOS_RESTRICTED_MODE
292     if (bozo_isrestricted) return BZACCESS;
293 #endif
294
295     /* construct local path from canonical (wire-format) path */
296     if (ConstructLocalBinPath(aname, &fpp)) {
297         return BZNOENT;
298     }
299     strcpy(filepath, fpp);
300     free(fpp);
301
302     if (DoLogging) bozo_Log("%s is executing Install '%s'\n", caller, filepath);
303
304     /* open file */
305     fpp = filepath + strlen(filepath);
306     strcpy(fpp, ".NEW");  /* append ".NEW" to end of filepath */
307     fd = open(filepath, O_CREAT | O_RDWR | O_TRUNC, 0777);
308     if (fd < 0) return errno;
309     total = 0;
310     while(1) {
311         len = rx_Read(acall, tbuffer, sizeof(tbuffer));
312         if (len < 0) {
313             close(fd);
314             unlink(filepath);
315             return 102;
316         }
317         if (len == 0) break;    /* no more input */
318         code = write(fd, tbuffer, len);
319         if (code != len) {
320             close(fd);
321             unlink(filepath);
322             return 100;
323         }
324         total += len;   /* track total written for safety check at end */
325     }
326     close(fd);
327     if (asize != total) {
328         unlink(filepath);
329         return 101; /* wrong size */
330     }
331
332     /* save old files */
333     *fpp = '\0';  /* remove ".NEW" from end of filepath */
334     SaveOldFiles(filepath);    /* don't care if it works, still install */
335
336     /* all done, rename to final name */
337     strcpy(tbuffer, filepath);
338     strcat(tbuffer, ".NEW");
339     code = (renamefile(tbuffer, filepath) ? errno : 0);
340
341     /* label file with same time for our sanity */
342 #ifdef AFS_NT40_ENV
343     utbuf.actime = utbuf.modtime = amtime;
344     _utime(filepath, &utbuf);
345 #else
346     tvb[0].tv_sec = tvb[1].tv_sec = amtime;
347     tvb[0].tv_usec = tvb[1].tv_usec = 0;
348     utimes(filepath, tvb);
349 #endif /* AFS_NT40_ENV */
350
351     if (mode)
352         chmod(filepath, mode);
353
354     if (code < 0) {
355       osi_auditU (acall, BOS_InstallEvent, code, AUD_STR, filepath, AUD_END);
356       return errno;
357     }
358     else return 0;
359 }
360
361 afs_int32 SBOZO_SetCellName(acall, aname)
362 struct rx_call *acall;
363 char *aname; {
364     struct afsconf_cell tcell;
365     register afs_int32 code;
366     char caller[MAXKTCNAMELEN];
367     char clones[MAXHOSTSPERCELL];
368     
369     if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
370       code = BZACCESS;
371       goto fail;
372     }
373     if (DoLogging) bozo_Log("%s is executing SetCellName '%s'\n", caller, aname);
374
375     code = afsconf_GetExtendedCellInfo(bozo_confdir, (char *) 0, (char *) 0, &tcell, &clones);
376     if (code) 
377       goto fail;
378
379     /* Check that tcell has enough space for the new cellname. */
380     if (strlen(aname) > sizeof tcell.name - 1) {
381         bozo_Log("ERROR: SetCellName: cell name '%s' exceeds %ld bytes (cell name not changed)\n",
382                  aname, (long)(sizeof tcell.name - 1));
383         code = BZDOM;
384         goto fail;
385     }
386
387     strcpy(tcell.name, aname);
388     code = afsconf_SetExtendedCellInfo(bozo_confdir, AFSDIR_SERVER_ETC_DIRPATH, &tcell, &clones);
389
390   fail:
391     osi_auditU (acall, BOS_SetCellEvent, code, AUD_STR, aname, AUD_END);
392     return code;
393 }
394
395 afs_int32 SBOZO_GetCellName(acall, aname)
396 struct rx_call *acall;
397 char **aname; {
398     register afs_int32 code;
399     char tname[MAXCELLCHARS];
400     
401     code = afsconf_GetLocalCell(bozo_confdir, tname, sizeof(tname));
402     if (code) {
403       /* must set output parameters even if aborting */
404       *aname = (char *) malloc(1);
405       **aname = 0;
406     }
407     else { 
408       *aname = (char *) malloc(strlen(tname)+1);
409       strcpy(*aname, tname);
410     }
411
412     return code;
413 }
414
415 afs_int32 SBOZO_GetCellHost(acall, awhich, aname)
416 struct rx_call *acall;
417 afs_uint32 awhich;
418 char **aname; {
419     register afs_int32 code;
420     struct afsconf_cell tcell;
421     register char *tp;
422     char clones[MAXHOSTSPERCELL];
423
424     code = afsconf_GetExtendedCellInfo(bozo_confdir, (char *) 0, (char *) 0, &tcell, &clones);
425     if (code) goto fail;
426
427     if (awhich >= tcell.numServers) {
428         code = BZDOM;
429         goto fail;
430     }
431     
432     tp = tcell.hostName[awhich];
433     *aname = (char *) malloc(strlen(tp)+3);
434     if (clones[awhich]) {
435         strcpy(*aname, "[");
436         strcat(*aname, tp);
437         strcat(*aname, "]");
438     } else
439         strcpy(*aname, tp);
440     goto done;
441     
442 fail:
443     *aname = (char *) malloc(1);        /* return fake string */
444     **aname = 0;
445
446 done:
447     return code;
448 }
449
450 afs_int32 SBOZO_DeleteCellHost(acall, aname)
451 struct rx_call *acall;
452 char *aname; {
453     register afs_int32 code;
454     struct afsconf_cell tcell;
455     afs_int32 which;
456     register int i;
457     char caller[MAXKTCNAMELEN];
458     char clones[MAXHOSTSPERCELL];
459
460     if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
461       code = BZACCESS;
462       goto fail;
463     }
464     if (DoLogging) 
465       bozo_Log("%s is executing DeleteCellHost '%s'\n", caller, aname);
466
467     code = afsconf_GetExtendedCellInfo(bozo_confdir, (char *) 0, (char *) 0, &tcell, &clones);
468     if (code) 
469       goto fail;
470
471     which = -1;
472     for(i=0;i<tcell.numServers;i++) {
473         if (strcmp(tcell.hostName[i], aname) == 0) {
474             which = i;
475             break;
476         }
477     }
478
479     if (which < 0) {
480       code = BZNOENT;
481       goto fail;
482     }
483
484     memset(&tcell.hostAddr[which], 0, sizeof(struct sockaddr_in));
485     memset(tcell.hostName[which], 0, MAXHOSTCHARS);
486     code = afsconf_SetExtendedCellInfo(bozo_confdir, AFSDIR_SERVER_ETC_DIRPATH, &tcell, &clones);
487
488   fail:
489     osi_auditU( acall, BOS_DeleteHostEvent, code, AUD_STR, aname, AUD_END);
490     return code;
491 }
492
493 afs_int32 SBOZO_AddCellHost(acall, aname)
494 struct rx_call *acall;
495 char *aname; {
496     register afs_int32 code;
497     struct afsconf_cell tcell;
498     afs_int32 which;
499     register int i;
500     char caller[MAXKTCNAMELEN];
501     char clones[MAXHOSTSPERCELL];
502     char *n;
503     char isClone = 0;
504
505     if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
506       code = BZACCESS;
507       goto fail;
508     }
509     if (DoLogging) 
510       bozo_Log("%s is executing AddCellHost '%s'\n", caller, aname);
511
512     code = afsconf_GetExtendedCellInfo(bozo_confdir, (char *) 0, (char *) 0, &tcell, &clones);
513     if (code) 
514       goto fail;
515
516     n = aname;
517     if (*n == '[') {
518         *(n + strlen(n) -1) = 0;
519         ++n;
520         isClone = 1;
521     }
522
523     which = -1;
524     for(i=0;i<tcell.numServers;i++) {
525         if (strcmp(tcell.hostName[i], n) == 0) {
526             which = i;
527             break;
528         }
529     }
530     if (which < 0) {
531         which = tcell.numServers;
532         tcell.numServers++;
533
534         /*
535          * Check that tcell has enough space for an additional host.
536          *
537          * We assume that tcell.hostAddr[] and tcell.hostName[] have the
538          * same number of entries.
539          */
540         if (tcell.numServers > sizeof tcell.hostAddr/sizeof tcell.hostAddr[0]) {
541             bozo_Log("ERROR: AddCellHost: attempt to add more than %ld database servers (database server '%s' not added)\n",
542                      (long)(sizeof tcell.hostAddr/sizeof tcell.hostAddr[0]), aname);
543             code = BZDOM;
544             goto fail;
545         }
546
547         /* Check that tcell has enough space for the new hostname. */
548         if (strlen(aname) > sizeof tcell.hostName[0] - 1) {
549             bozo_Log("ERROR: AddCellHost: host name '%s' exceeds %ld bytes (not added)\n",
550                      aname, (long)(sizeof tcell.hostName[0] - 1));
551             code = BZDOM;
552             goto fail;
553         }
554     }
555
556     memset(&tcell.hostAddr[which], 0, sizeof(struct sockaddr_in));
557     strcpy(tcell.hostName[which], n);
558     clones[which] = isClone;
559     code = afsconf_SetExtendedCellInfo(bozo_confdir, AFSDIR_SERVER_ETC_DIRPATH, &tcell, &clones);
560
561   fail:
562     osi_auditU(acall, BOS_AddHostEvent, code, AUD_STR, aname, AUD_END);
563     return code;
564 }
565
566 afs_int32 SBOZO_ListKeys(acall, an, akvno, akey, akeyinfo)
567 struct rx_call *acall;
568 afs_int32 an;
569 afs_int32 *akvno;
570 struct bozo_keyInfo *akeyinfo;
571 struct bozo_key *akey;
572 {
573     struct afsconf_keys tkeys;
574     register afs_int32 code;
575     struct stat tstat;
576     int noauth;
577     char caller[MAXKTCNAMELEN];
578     rxkad_level enc_level = rxkad_clear;
579
580     if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
581       code = BZACCESS;
582       goto fail;
583     }
584     if (DoLogging) bozo_Log("%s is executing ListKeys\n", caller);
585
586     code = afsconf_GetKeys(bozo_confdir, &tkeys);
587     if (code) 
588       goto fail;
589
590     if (tkeys.nkeys <= an) {
591       code = BZDOM;
592       goto fail;
593     }
594     *akvno = tkeys.key[an].kvno;
595     memset(akeyinfo, 0, sizeof(struct bozo_keyInfo));
596
597     noauth = afsconf_GetNoAuthFlag(bozo_confdir);
598     rxkad_GetServerInfo(acall->conn, &enc_level, 0, 0, 0, 0, 0);
599     /* 
600      * only return actual keys in noauth or if this is an encrypted connection
601      */
602
603     if ((noauth) || (enc_level == rxkad_crypt)) {
604         memcpy(akey, tkeys.key[an].key, 8);
605     }
606     else memset(akey, 0, 8);
607
608     code = stat(AFSDIR_SERVER_KEY_FILEPATH, &tstat);
609     if (code == 0) {
610         akeyinfo->mod_sec = tstat.st_mtime;
611     }
612     ka_KeyCheckSum (tkeys.key[an].key, &akeyinfo->keyCheckSum);
613     /* only errors is bad key parity */
614
615 fail:
616     if (noauth)
617       osi_auditU(acall, BOS_UnAuthListKeysEvent, code, AUD_END);
618     osi_auditU(acall, BOS_ListKeysEvent, code, AUD_END);
619     return code;
620 }
621
622 afs_int32 SBOZO_AddKey(acall, an, akey)
623 struct rx_call *acall;
624 afs_int32 an;
625 struct bozo_key *akey; {
626     register afs_int32 code;
627     char caller[MAXKTCNAMELEN];
628     rxkad_level enc_level = rxkad_clear;
629     int noauth;
630
631     if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
632       code = BZACCESS;
633       goto fail;
634     }
635     noauth = afsconf_GetNoAuthFlag(bozo_confdir);
636     rxkad_GetServerInfo(acall->conn, &enc_level, 0, 0, 0, 0, 0);
637     if ((!noauth) && (enc_level != rxkad_crypt)) {
638       code = BZENCREQ;
639       goto fail;
640     }
641     if (DoLogging) bozo_Log("%s is executing AddKey\n", caller);
642
643     code = afsconf_AddKey(bozo_confdir, an, akey, 0);
644     if (code == AFSCONF_KEYINUSE)       
645         code = BZKEYINUSE;      /* Unique code for afs rpc calls */
646 fail:
647     osi_auditU(acall, BOS_AddKeyEvent, code, AUD_END);
648     return code;
649 }
650
651 afs_int32 SBOZO_SetNoAuthFlag(acall, aflag)
652 register struct rx_call *acall;
653 afs_int32 aflag; {
654     register afs_int32 code  = 0;
655     char caller[MAXKTCNAMELEN];
656
657     if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
658       code = BZACCESS;
659       goto fail;
660     }
661     if (DoLogging) bozo_Log("%s is executing Set No Authentication\n", caller);
662
663     afsconf_SetNoAuthFlag(bozo_confdir, aflag);
664
665 fail:
666     osi_auditU(acall, BOS_SetNoAuthEvent, code, AUD_LONG, aflag, AUD_END);
667     return code;
668 }
669
670 afs_int32 SBOZO_DeleteKey(acall, an)
671 struct rx_call *acall;
672 afs_int32 an; {
673     register afs_int32 code;
674     char caller[MAXKTCNAMELEN];
675
676     if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
677       code = BZACCESS;
678       goto fail;
679     }
680     if (DoLogging) bozo_Log("%s is executing DeleteKey\n", caller);
681
682     code = afsconf_DeleteKey(bozo_confdir, an);
683
684 fail:
685     osi_auditU(acall, BOS_DeleteKeyEvent, code, AUD_END);
686     return code;
687 }
688
689
690 afs_int32 SBOZO_ListSUsers(acall, an, aname)
691 struct rx_call *acall;
692 afs_int32 an;
693 register char **aname; {
694     register afs_int32 code;
695     register char *tp;
696
697     tp = *aname = (char *) malloc(256);
698     *tp = 0;    /* in case getnthuser doesn't null-terminate the string */
699     code = afsconf_GetNthUser(bozo_confdir, an, tp, 256);
700
701 fail:
702     osi_auditU(acall, BOS_ListSUserEvent, code, AUD_END);
703     return code;
704 }
705
706 afs_int32 SBOZO_AddSUser(acall, aname)
707 struct rx_call *acall;
708 char *aname; {
709     register afs_int32 code;
710     char caller[MAXKTCNAMELEN];
711
712     if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
713       code = BZACCESS;
714       goto fail;
715     }
716     if (DoLogging) 
717       bozo_Log("%s is executing Add SuperUser '%s'\n", caller, aname);
718
719     code = afsconf_AddUser(bozo_confdir, aname);
720
721 fail:
722     osi_auditU(acall, BOS_AddSUserEvent, code, AUD_END);
723     return code;
724 }
725
726 afs_int32 SBOZO_DeleteSUser(acall, aname)
727 struct rx_call *acall;
728 char *aname; {
729     register afs_int32 code;
730     char caller[MAXKTCNAMELEN];
731
732     if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
733       code = BZACCESS;
734       goto fail;
735     }
736
737     if (DoLogging) 
738       bozo_Log("%s is executing Delete SuperUser '%s'\n", caller, aname);
739
740     code = afsconf_DeleteUser(bozo_confdir, aname);
741
742 fail:
743     osi_auditU(acall, BOS_DeleteSUserEvent, code, AUD_END);
744     return code;
745 }
746
747 afs_int32 SBOZO_CreateBnode(acall, atype, ainstance, ap1, ap2, ap3, ap4, ap5, notifier)
748 struct rx_call *acall;
749 char *atype;
750 char *ainstance;
751 char *ap1, *ap2, *ap3, *ap4, *ap5;
752 char *notifier; {
753     struct bnode *tb;
754     afs_int32 code;
755     char caller[MAXKTCNAMELEN];
756
757     if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
758       code = BZACCESS;
759       goto fail;
760     }
761 #ifdef BOS_RESTRICTED_MODE
762     if (bozo_isrestricted) {
763          if (strcmp(atype, "cron") || strcmp(ainstance, "salvage-tmp") ||
764              strcmp(ap2, "now") ||
765              strncmp(ap1, AFSDIR_CANONICAL_SERVER_SALVAGER_FILEPATH, 
766                      strlen(AFSDIR_CANONICAL_SERVER_SALVAGER_FILEPATH))) {
767               code = BZACCESS;
768               goto fail;
769          }
770     }
771 #endif
772
773     code = bnode_Create(atype, ainstance, &tb, ap1, ap2, ap3, ap4, ap5, notifier,BSTAT_NORMAL);
774     if (!code)
775       bnode_SetStat(tb, BSTAT_NORMAL);
776
777   fail:
778     osi_auditU(acall, BOS_CreateBnodeEvent, code, AUD_END);
779     return code;
780 }
781
782 afs_int32 SBOZO_WaitAll(acall)
783 register struct rx_call *acall; {
784     register afs_int32 code;
785     char caller[MAXKTCNAMELEN];
786
787     if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
788       code = BZACCESS;
789       goto fail;
790     }
791
792     if (DoLogging) bozo_Log("%s is executing Wait for All\n", caller);
793
794     code = bnode_WaitAll();
795
796 fail:
797     osi_auditU(acall, BOS_WaitAllEvent, code, AUD_END);
798     return code;
799 }
800
801 afs_int32 SBOZO_DeleteBnode(acall, ainstance)
802 struct rx_call *acall;
803 char *ainstance; {
804     register afs_int32 code;
805     char caller[MAXKTCNAMELEN];
806
807     if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
808       code = BZACCESS;
809       goto fail;
810     }
811 #ifdef BOS_RESTRICTED_MODE
812     if (bozo_isrestricted) {
813       code = BZACCESS;
814       goto fail;
815     }
816 #endif
817     if (DoLogging) bozo_Log("%s is executing DeleteBnode '%s'\n", caller, ainstance);
818
819     code = bnode_DeleteName(ainstance);
820
821 fail:
822     osi_auditU(acall, BOS_DeleteBnodeEvent, code, AUD_STR, ainstance, AUD_END);
823     return code;
824 }
825
826 static swproc(abnode, arock)
827 register struct bnode *abnode;
828 char *arock; {
829     if (abnode->goal == BSTAT_NORMAL) return 0; /* this one's not shutting down */
830     /* otherwise, we are shutting down */
831     bnode_Hold(abnode);
832     bnode_WaitStatus(abnode, BSTAT_SHUTDOWN);
833     bnode_Release(abnode);
834     return 0;   /* don't stop apply function early, no matter what */
835 }
836
837 static stproc(abnode, arock)
838 struct bnode *abnode;
839 char *arock; {
840     if (abnode->fileGoal == BSTAT_SHUTDOWN) return 0;   /* don't do these guys */
841
842     bnode_Hold(abnode);
843     bnode_SetStat(abnode, BSTAT_NORMAL);
844     bnode_Release(abnode);
845     return 0;
846 }
847
848 static sdproc(abnode, arock)
849 struct bnode *abnode;
850 char *arock; {
851     bnode_Hold(abnode);
852     bnode_SetStat(abnode, BSTAT_SHUTDOWN);
853     bnode_Release(abnode);
854     return 0;
855 }
856
857 /* shutdown and leave down */
858 afs_int32 SBOZO_ShutdownAll(acall)
859 struct rx_call *acall; {
860     /* iterate over all bnodes, setting the status to temporarily disabled */
861     register afs_int32 code;
862     char caller[MAXKTCNAMELEN];
863     
864     /* check for authorization */
865     if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
866       code = BZACCESS;
867       goto fail;
868     }
869     if (DoLogging) bozo_Log("%s is executing ShutdownAll\n", caller);
870
871     code = bnode_ApplyInstance(sdproc, (char *) 0);
872
873   fail:
874     osi_auditU (acall, BOS_ShutdownAllEvent, code, AUD_END);
875     return code;
876 }
877
878 /* shutdown and restart */
879 afs_int32 SBOZO_RestartAll(acall)
880 struct rx_call *acall; {
881     register afs_int32 code;
882     char caller[MAXKTCNAMELEN];
883     
884     if (!afsconf_SuperUser(bozo_confdir, acall, caller)) { 
885       code = BZACCESS; 
886       goto fail; 
887     }
888     if (DoLogging) bozo_Log("%s is executing RestartAll\n", caller);
889
890     /* start shutdown of all processes */
891     code = bnode_ApplyInstance(sdproc, (char *) 0);
892     if (code) goto fail;
893
894     /* wait for all done */
895     code = bnode_ApplyInstance(swproc, (char *) 0);
896     if (code) goto fail;
897
898     /* start them up again */
899     code = bnode_ApplyInstance(stproc, (char *) 0);
900
901   fail:
902     osi_auditU (acall, BOS_RestartAllEvent, code, AUD_END);
903     return code;
904 }
905
906 afs_int32 SBOZO_ReBozo(acall)
907 register struct rx_call *acall; {
908     register afs_int32 code;
909     char caller[MAXKTCNAMELEN];
910
911     /* acall is null if called internally to restart bosserver */
912     if (acall && !afsconf_SuperUser(bozo_confdir, acall, caller)) { 
913       code = BZACCESS;
914       goto fail;
915     }
916     if (DoLogging) bozo_Log("%s is executing ReBozo\n", caller);
917
918     /* start shutdown of all processes */
919     code = bnode_ApplyInstance(sdproc, (char *) 0);
920     if (code) goto fail;
921
922     /* wait for all done */
923     code = bnode_ApplyInstance(swproc, (char *) 0);
924     if (code) goto fail;
925
926     if (acall) osi_auditU (acall, BOS_RebozoEvent, code, AUD_END);
927     else       osi_audit (BOS_RebozoIntEvent, code, AUD_END);
928
929     if (acall) rx_EndCall(acall, 0);   /* try to get it done */
930     rx_Finalize();
931     bozo_ReBozo();  /* this reexecs us, and doesn't return, of course */
932
933 fail:
934     /* Differentiate between external and internal ReBozo; prevents AFS_Aud_NoCall event */
935     if (acall) osi_auditU (acall, BOS_RebozoEvent, code, AUD_END);
936     else       osi_audit (BOS_RebozoIntEvent, code, AUD_END);
937     return code;   /* should only get here in unusual circumstances */
938 }
939
940 /* make sure all are running */
941 afs_int32 SBOZO_StartupAll(acall)
942 struct rx_call *acall; {
943     register afs_int32 code;
944     char caller[MAXKTCNAMELEN];
945
946     if (!afsconf_SuperUser(bozo_confdir, acall, caller)) { 
947       code = BZACCESS; 
948       goto fail; 
949     }
950     if (DoLogging) bozo_Log("%s is executing StartupAll\n", caller);
951     code = bnode_ApplyInstance(stproc, (char *) 0);
952
953 fail:
954     osi_auditU (acall, BOS_StartupAllEvent, code, AUD_END);
955     return code;
956 }
957
958 afs_int32 SBOZO_Restart(acall, ainstance)
959 struct rx_call *acall;
960 register char *ainstance; {
961     register struct bnode *tb;
962     register afs_int32 code;
963     char caller[MAXKTCNAMELEN];
964     
965     if (!afsconf_SuperUser(bozo_confdir, acall, caller)) { 
966       code = BZACCESS; 
967       goto fail;
968     }
969     if (DoLogging) bozo_Log("%s is executing Restart '%s'\n", caller, ainstance);
970
971     tb = bnode_FindInstance(ainstance);
972     if (!tb) {
973       code = BZNOENT;
974       goto fail;
975     }
976     
977     /* setup return code */
978     code = 0;
979
980     bnode_Hold(tb);
981     bnode_SetStat(tb, BSTAT_SHUTDOWN);
982     code = bnode_WaitStatus(tb, BSTAT_SHUTDOWN);    /* this can fail */
983     bnode_SetStat(tb, BSTAT_NORMAL);
984     bnode_Release(tb);
985
986 fail:
987     osi_auditU (acall, BOS_RestartEvent, code, AUD_STR, ainstance, AUD_END);
988     return code;
989 }
990
991 /* set temp status */
992 afs_int32 SBOZO_SetTStatus(acall, ainstance, astatus)
993 struct rx_call *acall;
994 char *ainstance;
995 afs_int32 astatus; {
996     register struct bnode *tb;
997     register afs_int32 code;
998     char caller[MAXKTCNAMELEN];
999
1000     if (!afsconf_SuperUser(bozo_confdir, acall, caller)) { 
1001       code = BZACCESS; 
1002       goto fail;
1003     }
1004     if (DoLogging) bozo_Log("%s is executing SetTempStatus '%s'\n", caller, ainstance);
1005
1006     tb = bnode_FindInstance(ainstance);
1007     if (!tb) {
1008       code = BZNOENT;
1009       goto fail;
1010     }
1011     bnode_Hold(tb);
1012     code = bnode_SetStat(tb, astatus);
1013     bnode_Release(tb);
1014
1015 fail:
1016     osi_auditU (acall, BOS_SetTempStatusEvent, code, AUD_STR, ainstance, AUD_END);
1017     return code;
1018 }
1019
1020 afs_int32 SBOZO_SetStatus(acall, ainstance, astatus)
1021 struct rx_call *acall;
1022 char *ainstance;
1023 afs_int32 astatus; {
1024     register struct bnode *tb;
1025     register afs_int32 code;
1026     char caller[MAXKTCNAMELEN];
1027
1028     if (!afsconf_SuperUser(bozo_confdir, acall, caller)) { 
1029       code = BZACCESS; 
1030       goto fail; 
1031     }
1032     if (DoLogging) bozo_Log("%s is executing SetStatus '%s' (status = %d)\n", caller, ainstance, astatus);
1033
1034     tb = bnode_FindInstance(ainstance);
1035     if (!tb) {
1036       code = BZNOENT;
1037       goto fail;
1038     }
1039     bnode_Hold(tb);
1040     bnode_SetFileGoal(tb, astatus);
1041     code = bnode_SetStat(tb, astatus);
1042     bnode_Release(tb);
1043
1044 fail:
1045     osi_auditU (acall, BOS_SetStatusEvent, code, AUD_STR, ainstance, AUD_END);
1046     return code;
1047 }
1048
1049 afs_int32 SBOZO_GetStatus(acall, ainstance, astat, astatDescr)
1050 struct rx_call *acall;
1051 char *ainstance;
1052 afs_int32 *astat;
1053 char **astatDescr; {
1054     register struct bnode *tb;
1055     register afs_int32 code;
1056
1057     tb = bnode_FindInstance(ainstance);
1058     if (!tb) {
1059         code = BZNOENT;
1060         goto fail;
1061     }
1062     
1063     bnode_Hold(tb);
1064     code = bnode_GetStat(tb, astat);
1065     if (code) {
1066         bnode_Release(tb);
1067         goto fail;
1068     }
1069     
1070     *astatDescr = (char *) malloc(BOZO_BSSIZE);
1071     code = bnode_GetString(tb, *astatDescr, BOZO_BSSIZE);
1072     bnode_Release(tb);
1073     if (code) (*astatDescr)[0] = 0;     /* null string means no further info */
1074     return 0;
1075
1076 fail:
1077     *astatDescr = (char *) malloc(1);
1078     **astatDescr = 0;
1079     return code;
1080 }
1081
1082 struct eidata {
1083     char *iname;
1084     int counter;
1085 };
1086
1087 static eifunc(abnode, arock)
1088 struct bnode *abnode;
1089 struct eidata *arock; {
1090     if (arock->counter-- == 0) {
1091         /* done */
1092         strcpy(arock->iname, abnode->name);
1093         return 1;
1094     }
1095     else {
1096         /* not there yet */
1097         return 0;
1098     }
1099 }
1100
1101 static ZapFile(adir, aname)
1102 register char *adir;
1103 register char *aname; {
1104     char tbuffer[256];
1105     strcpy(tbuffer, adir);
1106     strcat(tbuffer, "/");
1107     strcat(tbuffer, aname);
1108     return unlink(tbuffer);
1109 }
1110
1111 afs_int32 SBOZO_Prune(acall, aflags)
1112 struct rx_call *acall;
1113 afs_int32 aflags; {
1114     register afs_int32 code;
1115     DIR *dirp;
1116     register struct dirent *tde;
1117     register int i;
1118     char caller[MAXKTCNAMELEN];
1119
1120     if (!afsconf_SuperUser(bozo_confdir, acall, caller)) { 
1121       code = BZACCESS;
1122       goto fail; 
1123     }
1124 #ifdef BOS_RESTRICTED_MODE
1125     if (bozo_isrestricted) {
1126          code = BZACCESS;
1127          goto fail; 
1128     }
1129 #endif
1130     if (DoLogging) bozo_Log("%s is executing Prune (flags=%d)\n", caller, aflags);
1131
1132     /* first scan AFS binary directory */
1133     dirp = opendir(AFSDIR_SERVER_BIN_DIRPATH);
1134     if (dirp) {
1135         for(tde=readdir(dirp);tde;tde=readdir(dirp)) {
1136             i = strlen(tde->d_name);
1137             if (aflags & BOZO_PRUNEOLD) {
1138                 if(i >= 4 && strncmp(tde->d_name+i-4, ".OLD", 4)==0)
1139                     ZapFile(AFSDIR_SERVER_BIN_DIRPATH, tde->d_name);
1140             }
1141             if (aflags & BOZO_PRUNEBAK) {
1142                 if(i >= 4 && strncmp(tde->d_name+i-4, ".BAK", 4)==0)
1143                     ZapFile(AFSDIR_SERVER_BIN_DIRPATH, tde->d_name);
1144             }
1145         }
1146         closedir(dirp);
1147     }
1148
1149     /* then scan AFS log directory */
1150     dirp = opendir(AFSDIR_SERVER_LOGS_DIRPATH);
1151     if (dirp) {
1152         for(tde=readdir(dirp);tde;tde=readdir(dirp)) {
1153             if (aflags & BOZO_PRUNECORE) {
1154                 if(strncmp(tde->d_name, AFSDIR_CORE_FILE, 4)==0)
1155                     ZapFile(AFSDIR_SERVER_LOGS_DIRPATH, tde->d_name);
1156             }
1157         }
1158         closedir(dirp);
1159     }
1160     code = 0;
1161
1162   fail:
1163     osi_auditU ( acall, BOS_PruneLogs, code, AUD_END);
1164     return code;
1165 }
1166
1167 afs_int32 SBOZO_EnumerateInstance(acall, anum, ainstance)
1168 struct rx_call *acall;
1169 afs_int32 anum;
1170 char **ainstance; {
1171     struct eidata tdata;
1172
1173     *ainstance = (char *) malloc(BOZO_BSSIZE);
1174     **ainstance = 0;
1175     tdata.counter = anum;
1176     tdata.iname = *ainstance;
1177     bnode_ApplyInstance(eifunc, &tdata);
1178     if (tdata.counter >= 0) return BZDOM;       /* anum > # of actual instances */
1179     else return 0;
1180 }
1181
1182 struct bozo_bosEntryStats bozo_bosEntryStats[] = {
1183     {NULL, 1,1, 0755, 02}, /* AFSDIR_SERVER_AFS_DIRPATH    */
1184     {NULL, 1,1, 0755, 02}, /* AFSDIR_SERVER_ETC_DIRPATH    */
1185     {NULL, 1,1, 0755, 02}, /* AFSDIR_SERVER_BIN_DIRPATH    */
1186     {NULL, 1,1, 0755, 02}, /* AFSDIR_SERVER_LOGS_DIRPATH   */
1187     {NULL, 1,0, 0700, 07}, /* AFSDIR_SERVER_BACKUP_DIRPATH */
1188     {NULL, 1,1, 0700, 07}, /* AFSDIR_SERVER_DB_DIRPATH     */
1189     {NULL, 1,1, 0700, 07}, /* AFSDIR_SERVER_LOCAL_DIRPATH  */
1190     {NULL, 0,1, 0600, 07}, /* AFSDIR_SERVER_KEY_FILEPATH   */
1191     {NULL, 0,1, 0600, 03}};/* AFSDIR_SERVER_ULIST_FILEPATH */
1192 int bozo_nbosEntryStats =
1193     sizeof(bozo_bosEntryStats) / sizeof(bozo_bosEntryStats[0]);
1194
1195 /* This function performs initialization of the bozo_bosEntrystats[]
1196  * array. This array contains the list of dirs that the bosserver 
1197  * is interested in along with their recommended permissions
1198  * NOTE: This initialization is a bit ugly. This was caused because
1199  * the path names require procedural as opposed to static initialization.
1200  * The other fields in the struct are however, statically initialized.
1201  */
1202 int initBosEntryStats()
1203 {
1204   bozo_bosEntryStats[0].path = AFSDIR_SERVER_AFS_DIRPATH;
1205   bozo_bosEntryStats[1].path = AFSDIR_SERVER_ETC_DIRPATH;
1206   bozo_bosEntryStats[2].path = AFSDIR_SERVER_BIN_DIRPATH;
1207   bozo_bosEntryStats[3].path = AFSDIR_SERVER_LOGS_DIRPATH;
1208   bozo_bosEntryStats[4].path = AFSDIR_SERVER_BACKUP_DIRPATH;
1209   bozo_bosEntryStats[5].path = AFSDIR_SERVER_DB_DIRPATH;
1210   bozo_bosEntryStats[6].path = AFSDIR_SERVER_LOCAL_DIRPATH;
1211   bozo_bosEntryStats[7].path = AFSDIR_SERVER_KEY_FILEPATH;
1212   bozo_bosEntryStats[8].path = AFSDIR_SERVER_ULIST_FILEPATH;
1213
1214   return 0;
1215 }
1216 /* StatEachEntry - If it's not there, it is okay.  If anything else goes wrong
1217  * complain.  Otherwise check permissions: shouldn't allow write or (usually)
1218  * read. */
1219
1220 static int StatEachEntry (stats)
1221   IN struct bozo_bosEntryStats *stats;
1222 {
1223     struct stat info;
1224     if (stat (stats->path, &info)) {
1225         if (errno == ENOENT) return 1;  /* no such entry: just ignore it */
1226         return 0;                       /* something else went wrong */
1227     } else {
1228         int rights;
1229         if (((info.st_mode & S_IFDIR) != 0) != stats->dir)
1230             return 0;                   /* not expected type */
1231         if (stats->rootOwner && (info.st_uid != 0))
1232             return 0;                   /* not owned by root */
1233         rights = (info.st_mode & 0000777);
1234         if ((rights & stats->reqPerm) != stats->reqPerm)
1235             return 0;                   /* required permissions not present */
1236         if ((rights & stats->proPerm) != 0)
1237             return 0;                   /* prohibited permissions present */
1238     }
1239     return 1;
1240 }
1241
1242 /* DirAccessOK - checks the mode bits on the AFS dir and decendents and
1243  * returns 0 if some are not OK and 1 otherwise.  For efficiency, it doesn't do
1244  * this check more often than every 5 seconds. */
1245
1246 int DirAccessOK ()
1247 {
1248 #ifdef AFS_NT40_ENV
1249     /* underlying filesystem may not support directory protection */
1250     return 1;
1251 #else
1252     static afs_uint32 lastTime = 0;
1253     afs_uint32 now = FT_ApproxTime();
1254     static int lastResult = -1;
1255     int result;
1256     int i;
1257
1258     if ((now-lastTime) < 5) return lastResult;
1259     lastTime = now;
1260
1261     result = 1;
1262     for (i=0; i<bozo_nbosEntryStats; i++) {
1263         struct bozo_bosEntryStats *e = &bozo_bosEntryStats[i];
1264         if (!StatEachEntry (e)) {
1265             result = 0;
1266             break;
1267         }
1268     }
1269
1270     if (result != lastResult) {         /* log changes */
1271         bozo_Log ("Server directory access is %sokay\n",
1272                   (result ? "" : "not "));
1273     }
1274     lastResult = result;
1275     return lastResult;
1276 #endif /* AFS_NT40_ENV */
1277 }
1278
1279 int GetRequiredDirPerm (path)
1280   IN char *path;
1281 {
1282     int i;
1283     for (i=0; i<bozo_nbosEntryStats; i++)
1284         if (strcmp (path, bozo_bosEntryStats[i].path) == 0)
1285             return bozo_bosEntryStats[i].reqPerm;
1286     return -1;
1287 }
1288
1289 afs_int32 SBOZO_GetInstanceInfo(acall, ainstance, atype, astatus)
1290   IN struct rx_call *acall;
1291   IN char *ainstance;
1292   OUT char **atype;
1293   OUT struct bozo_status *astatus;
1294 {
1295     register struct bnode *tb;
1296     
1297     tb = bnode_FindInstance(ainstance);
1298     *atype = (char *) malloc(BOZO_BSSIZE);
1299     **atype = 0;
1300     if (!tb) return BZNOENT;
1301     if (tb->type)
1302         strcpy(*atype, tb->type->name);
1303     else
1304         (*atype)[0] = 0;    /* null string */
1305     memset(astatus, 0, sizeof(struct bozo_status));     /* good defaults */
1306     astatus->goal = tb->goal;
1307     astatus->fileGoal = tb->fileGoal;
1308     astatus->procStartTime = tb->procStartTime;
1309     astatus->procStarts = tb->procStarts;
1310     astatus->lastAnyExit = tb->lastAnyExit;
1311     astatus->lastErrorExit = tb->lastErrorExit;
1312     astatus->errorCode = tb->errorCode;
1313     astatus->errorSignal = tb->errorSignal;
1314     if (tb->flags & BNODE_ERRORSTOP)
1315         astatus->flags |= BOZO_ERRORSTOP;
1316     if (bnode_HasCore(tb))
1317         astatus->flags |= BOZO_HASCORE;
1318     if (!DirAccessOK())
1319         astatus->flags |= BOZO_BADDIRACCESS;
1320     return 0;
1321 }
1322
1323 afs_int32 SBOZO_GetInstanceParm(acall, ainstance, anum, aparm)
1324 struct rx_call *acall;
1325 char *ainstance;
1326 afs_int32 anum;
1327 char **aparm; {
1328     register struct bnode *tb;
1329     register char *tp;
1330     register afs_int32 code;
1331     
1332     tp = (char *) malloc(BOZO_BSSIZE);
1333     *aparm = tp;
1334     *tp = 0;        /* null-terminate string in error case */
1335     tb = bnode_FindInstance(ainstance);
1336     if (!tb) return BZNOENT;
1337     bnode_Hold(tb);
1338     if (anum == 999) {
1339         if (tb->notifier) {
1340             memcpy(tp, tb->notifier, strlen(tb->notifier)+1);
1341             code = 0;
1342         } else
1343             code = BZNOENT;     /* XXXXX */
1344     } else
1345         code = bnode_GetParm(tb, anum, tp, BOZO_BSSIZE);
1346     bnode_Release(tb);
1347
1348     /* Not Currently Audited */
1349     return code;
1350 }
1351
1352 afs_int32 SBOZO_GetLog(acall, aname)
1353 register struct rx_call *acall;
1354 char *aname; {
1355     register afs_int32 code;
1356     FILE *tfile;
1357     int tc;
1358     char *logpath;
1359     char buffer;
1360     char caller[MAXKTCNAMELEN];
1361
1362     /* Check access since 'aname' could specify a file outside of the
1363      * AFS log directory (which is bosserver's working directory).
1364      */
1365     if (!afsconf_SuperUser(bozo_confdir, acall, caller)) { 
1366       code = BZACCESS; 
1367       goto fail; 
1368     }
1369 #ifdef BOS_RESTRICTED_MODE
1370     if (bozo_isrestricted && strchr(aname, '/') && 
1371         strcmp(aname, AFSDIR_CANONICAL_SERVER_SLVGLOG_FILEPATH)) { 
1372       code = BZACCESS; 
1373       goto fail; 
1374     }
1375 #endif
1376
1377     /* construct local path from canonical (wire-format) path */
1378     if (ConstructLocalLogPath(aname, &logpath)) {
1379         return BZNOENT;
1380     }
1381     if (DoLogging) bozo_Log("%s is executing GetLog '%s'\n", caller, logpath);
1382     tfile = fopen(logpath, "r");
1383     free(logpath);
1384
1385     if (!tfile) {
1386         return BZNOENT;
1387     }
1388
1389     while (1) {
1390         tc = getc(tfile);
1391         if (tc == 0) continue;  /* our termination condition on other end */
1392         if (tc == EOF) break;
1393         buffer = tc;
1394         if (rx_Write(acall, &buffer, 1) != 1) {
1395             fclose(tfile);
1396             code = BZNET;
1397             goto fail;
1398         }
1399     }
1400
1401     /* all done, cleanup and return */
1402     fclose(tfile);
1403
1404     /* write out the end delimeter */
1405     buffer = 0;
1406     if (rx_Write(acall, &buffer, 1) != 1) return BZNET;
1407     code = 0;
1408
1409   fail:
1410     osi_auditU( acall, BOS_GetLogsEvent, code, AUD_END);
1411     return code;
1412 }
1413
1414 afs_int32 SBOZO_GetInstanceStrings(acall, abnodeName, as1, as2, as3, as4)
1415 struct rx_call *acall;
1416 char *abnodeName;
1417 char **as1, **as2, **as3, **as4; {
1418     register struct bnode *tb;
1419
1420     *as2 = (char *) malloc(1);
1421     **as2 = 0;
1422     *as3 = (char *) malloc(1);
1423     **as3 = 0;
1424     *as4 = (char *) malloc(1);
1425     **as4 = 0;
1426     tb = bnode_FindInstance(abnodeName);
1427     if (!tb) goto fail;
1428
1429     /* now, return the appropriate error string, if any */
1430     if (tb->lastErrorName) {
1431         *as1 = (char *) malloc(strlen(tb->lastErrorName)+1);
1432         strcpy(*as1, tb->lastErrorName);
1433     }
1434     else {
1435         *as1 = (char *) malloc(1);
1436         **as1 = 0;
1437     }
1438     return 0;
1439
1440   fail:
1441     *as1 = (char *) malloc(1);
1442     **as1 = 0;
1443     return BZNOENT;
1444 }
1445
1446 #ifdef BOS_RESTRICTED_MODE
1447 afs_int32 SBOZO_GetRestrictedMode(acall, arestmode) 
1448 struct rx_call *acall;
1449 afs_int32 *arestmode; 
1450 {
1451      *arestmode=bozo_isrestricted;
1452      return 0;
1453 }
1454
1455 afs_int32 SBOZO_SetRestrictedMode(acall, arestmode) 
1456 struct rx_call *acall;
1457 afs_int32 arestmode; 
1458 {
1459      afs_int32 code;
1460      char caller[MAXKTCNAMELEN];
1461      
1462      if (!afsconf_SuperUser(bozo_confdir, acall, caller)) { 
1463           return BZACCESS; 
1464      }     
1465      if (bozo_isrestricted) {
1466           return BZACCESS; 
1467      }     
1468      if (arestmode !=0 && arestmode !=1) {
1469           return BZDOM;
1470      }
1471      bozo_isrestricted=arestmode;
1472      code = WriteBozoFile(0);
1473  fail:
1474      return code;
1475 }
1476 #else
1477 afs_int32 SBOZO_GetRestrictedMode(acall, arestmode) 
1478 struct rx_call *acall;
1479 afs_int32 *arestmode; 
1480 {
1481      return RXGEN_OPCODE;
1482 }
1483
1484 afs_int32 SBOZO_SetRestrictedMode(acall, arestmode) 
1485 struct rx_call *acall;
1486 afs_int32 arestmode; 
1487 {
1488      return RXGEN_OPCODE;
1489 }
1490 #endif
1491
1492 void bozo_ShutdownAndExit(int asignal)
1493 {
1494     int code;
1495
1496     bozo_Log("Shutdown of BOS server and processes in response to signal %d\n",
1497              asignal);
1498
1499     /* start shutdown of all processes */
1500     if ((code = bnode_ApplyInstance(sdproc, (char *) 0)) == 0) {
1501         /* wait for shutdown to complete */
1502         code = bnode_ApplyInstance(swproc, (char *) 0);
1503     }
1504
1505     if (code) {
1506         bozo_Log("Shutdown incomplete (code = %d); manual cleanup required\n",
1507                  code);
1508     }
1509
1510     rx_Finalize();
1511     exit(code);
1512 }