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