pull-prototypes-to-head-20020821
[openafs.git] / src / libadmin / bos / afs_bosAdmin.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 <stdio.h>
16 #include <afs/stds.h>
17 #include "afs_bosAdmin.h"
18 #include "../adminutil/afs_AdminInternal.h"
19 #include <afs/afs_AdminErrors.h>
20 #include <afs/afs_utilAdmin.h>
21 #include <afs/bosint.h>
22 #include <afs/bnode.h>
23 #include <afs/ktime.h>
24 #include <afs/dirpath.h>
25 #include <fcntl.h>
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <stdlib.h>
29 #ifdef AFS_NT40_ENV
30 #include <io.h>
31 #else
32 #include <unistd.h>
33 #endif
34
35 #ifdef HAVE_STRING_H
36 #include <string.h>
37 #else
38 #ifdef HAVE_STRINGS_H
39 #include <strings.h>
40 #endif
41 #endif
42
43
44
45 /*
46  * Prototypes for functions that don't exist in any header files
47  */
48
49 extern int BOZO_AddCellHost();
50 extern int BOZO_AddKey();
51 extern int BOZO_AddSUser();
52 extern int BOZO_CreateBnode();
53 extern int BOZO_DeleteBnode();
54 extern int BOZO_DeleteCellHost();
55 extern int BOZO_DeleteKey();
56 extern int BOZO_DeleteSUser();
57 extern int BOZO_EnumerateInstance();
58 extern int BOZO_Exec();
59 extern int BOZO_GetCellHost();
60 extern int BOZO_GetCellName();
61 extern int BOZO_GetDates();
62 extern int BOZO_GetInstanceInfo();
63 extern int BOZO_GetInstanceParm();
64 extern int BOZO_GetInstanceParm();
65 extern int BOZO_GetRestartTime();
66 extern int BOZO_GetStatus();
67 extern int BOZO_ListSUsers();
68 extern int BOZO_ListKeys();
69 extern int BOZO_Prune();
70 extern int BOZO_ReBozo();
71 extern int BOZO_Restart();
72 extern int BOZO_RestartAll();
73 extern int BOZO_SetCellName();
74 extern int BOZO_SetNoAuthFlag();
75 extern int BOZO_SetRestartTime();
76 extern int BOZO_SetStatus(struct rx_connection *, char *, afs_int32);
77 extern int BOZO_SetTStatus(struct rx_connection *, char *, afs_int32);
78 extern int BOZO_ShutdownAll();
79 extern int BOZO_StartupAll();
80 extern int BOZO_UnInstall();
81 extern int BOZO_WaitAll();
82 extern int StartBOZO_GetLog();
83 extern int StartBOZO_Install();
84
85 typedef struct bos_server {
86     int begin_magic;
87     int is_valid;
88     struct rx_connection *server;
89     struct rx_connection *server_encrypt;
90     struct rx_connection *server_stats;
91     int end_magic;
92 } bos_server_t, *bos_server_p;
93
94 /*
95  * isValidServerHandle - validate a bos_server_p.
96  *
97  * PARAMETERS
98  *
99  * IN serverHandle - the handle to validate
100  *
101  * LOCKS
102  *
103  * No locks are obtained or released by this function
104  *
105  * RETURN CODES
106  *
107  * Returns != 0 upon successful completion.
108  */
109
110 int isValidServerHandle (
111   const bos_server_p serverHandle,
112   afs_status_p st)
113 {
114     int rc = 0;
115     afs_status_t tst = 0;
116
117     if (serverHandle == NULL) {
118         tst = ADMBOSSERVERHANDLENULL;
119         goto fail_IsValidServerHandle;
120     }
121
122     if ((serverHandle->begin_magic != BEGIN_MAGIC) ||
123         (serverHandle->end_magic != END_MAGIC)) {
124         tst = ADMBOSSERVERHANDLEBADMAGIC;
125         goto fail_IsValidServerHandle;
126     }
127
128     if (serverHandle->is_valid == 0) {
129         tst = ADMBOSSERVERHANDLEINVALID;
130         goto fail_IsValidServerHandle;
131     }
132
133     if (serverHandle->server == NULL) {
134         tst = ADMBOSSERVERHANDLENOSERVER;
135         goto fail_IsValidServerHandle;
136     }
137
138     if (serverHandle->server_encrypt == NULL) {
139         tst = ADMBOSSERVERHANDLENOSERVER;
140         goto fail_IsValidServerHandle;
141     }
142     rc = 1;
143
144 fail_IsValidServerHandle:
145  
146     if (st != NULL) {
147         *st = tst;
148     }
149     return rc;
150 }
151 /*
152  * IsValidCellHandle - verify that a cell handle can be used to make bos
153  * requests.
154  *
155  * PARAMETERS
156  *
157  * IN cellHandle - the cellHandle to be validated.
158  *
159  * LOCKS
160  *
161  * No locks are obtained or released by this function
162  *
163  * RETURN CODES
164  *
165  * Returns != 0 upon successful completion.
166  */
167  
168 static int IsValidCellHandle(
169   afs_cell_handle_p cellHandle,
170   afs_status_p st)
171 {
172     int rc = 0;
173     afs_status_t tst = 0;
174  
175     if (!CellHandleIsValid((void *) cellHandle, &tst)) {
176         goto fail_IsValidCellHandle;
177     }
178  
179     if (cellHandle->tokens == NULL) {
180         tst = ADMBOSCELLHANDLENOTOKENS;
181         goto fail_IsValidCellHandle;
182     }
183     rc = 1;
184  
185 fail_IsValidCellHandle:
186  
187     if (st != NULL) {
188         *st = tst;
189     }
190     return rc;
191 }
192  
193 /*
194  * bos_ServerOpen - open a bos server for work.
195  *
196  * PARAMETERS
197  *
198  * IN cellHandle - a previously opened cellHandle.
199  *
200  * IN serverName - the name of the machine that houses the bosserver of 
201  * interest.
202  *
203  * OUT serverHandleP - upon successful completion, this void pointer
204  * will point to a valid server handle for use in future operations.
205  *
206  * LOCKS
207  *
208  * No locks are obtained or released by this function
209  *
210  * RETURN CODES
211  *
212  * Returns != 0 upon successful completion.
213  */
214
215 int ADMINAPI bos_ServerOpen(
216   const void *cellHandle,
217   const char *serverName,
218   void **serverHandleP,
219   afs_status_p st)
220 {
221     int rc = 0;
222     afs_status_t tst = 0;
223     afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
224     bos_server_p bos_server = (bos_server_p) malloc(sizeof(bos_server_t));
225     int serverAddress;
226  
227     /*
228      * Validate parameters
229      */
230
231     if (!IsValidCellHandle(c_handle, &tst)) {
232         goto fail_bos_ServerOpen;
233     }
234
235     if ((serverName == NULL) || (*serverName == 0)) {
236         tst = ADMBOSSERVERNAMENULL;
237         goto fail_bos_ServerOpen;
238     }
239
240     if (serverHandleP == NULL) {
241         tst = ADMBOSSERVERHANDLEPNULL;
242         goto fail_bos_ServerOpen;
243     }
244
245     if (util_AdminServerAddressGetFromName(serverName, &serverAddress, &tst) == 0) {
246         goto fail_bos_ServerOpen;
247     }
248
249     if (bos_server == NULL) {
250         tst = ADMNOMEM;
251         goto fail_bos_ServerOpen;
252     }
253
254     bos_server->server = rx_GetCachedConnection(htonl(serverAddress),
255                                                 htons(AFSCONF_NANNYPORT), 1,
256                                                 c_handle->tokens->afs_sc[c_handle->tokens->sc_index], c_handle->tokens->sc_index);
257
258     bos_server->server_encrypt = rx_GetCachedConnection(htonl(serverAddress),
259                                                 htons(AFSCONF_NANNYPORT), 1,
260                                                 c_handle->tokens->afs_encrypt_sc[c_handle->tokens->sc_index], c_handle->tokens->sc_index);
261                                                 
262     bos_server->server_stats = rx_GetCachedConnection(htonl(serverAddress),
263                                                 htons(AFSCONF_NANNYPORT),
264                                                 RX_STATS_SERVICE_ID,
265                                                 c_handle->tokens->afs_sc[c_handle->tokens->sc_index], c_handle->tokens->sc_index);
266
267     if ((bos_server->server == NULL) || (bos_server->server_encrypt == NULL)) {
268         tst = ADMBOSSERVERNOCONNECTION;
269         goto fail_bos_ServerOpen;
270     }
271
272     bos_server->begin_magic = BEGIN_MAGIC;
273     bos_server->is_valid = 1;
274     bos_server->end_magic = END_MAGIC;
275
276     *serverHandleP = (void *) bos_server;
277     rc = 1;
278
279 fail_bos_ServerOpen:
280
281     if ((rc == 0) && (bos_server != NULL)) {
282         if (bos_server->server) {
283             rx_ReleaseCachedConnection(bos_server->server);
284         }
285         if (bos_server->server_encrypt) {
286             rx_ReleaseCachedConnection(bos_server->server_encrypt);
287         }
288         free(bos_server);
289     }
290
291     if (st != NULL) {
292         *st = tst;
293     }
294     return rc;
295 }
296
297 /*
298  * bos_ServerClose - close a bos server handle
299  *
300  * PARAMETERS
301  *
302  * IN serverHandle - a bos server handle previously returned by bos_ServerOpen
303  *
304  * LOCKS
305  *
306  * No locks are obtained or released by this function
307  *
308  * RETURN CODES
309  *
310  * Returns != 0 upon successful completion.
311  */
312
313 int ADMINAPI bos_ServerClose(
314   const void *serverHandle,
315   afs_status_p st)
316 {
317     int rc = 0;
318     afs_status_t tst = 0;
319     bos_server_p b_handle = (bos_server_p) serverHandle;
320  
321     if (isValidServerHandle(b_handle, &tst)) {
322         rx_ReleaseCachedConnection(b_handle->server);
323         b_handle->is_valid = 0;
324         free(b_handle);
325         rc = 1;
326     }
327
328     if (st != NULL) {
329         *st = tst;
330     }
331     return rc;
332 }
333
334 /*
335  * bos_ProcessCreate - create a new process to run at a bos server.
336  *
337  * PARAMETERS
338  *
339  * IN serverHandle - a previously opened serverHandle.
340  *
341  * IN processName - the name of the process to create.
342  *
343  * IN processType - the type of process to create.
344  *
345  * IN process - the path to the process binary at the bos server.
346  *
347  * IN cronTime - the time specification for cron processes.
348  *
349  * IN notifier - the path to the notifier binary at the bos server.
350  *
351  * LOCKS
352  *
353  * No locks are obtained or released by this function
354  *
355  * RETURN CODES
356  *
357  * Returns != 0 upon successful completion.
358  */
359
360 /*
361  * CAUTION - this list must match bos_ProcessType_t definition
362  */
363
364 static char *processTypes[] = {"simple", "fs", "cron", 0};
365
366 int ADMINAPI bos_ProcessCreate(
367   const void *serverHandle,
368   const char *processName, 
369   bos_ProcessType_t processType,
370   const char *process,
371   const char *cronTime,
372   const char *notifier, 
373   afs_status_p st)
374 {
375     int rc = 0;
376     afs_status_t tst = 0;
377     bos_server_p b_handle = (bos_server_p) serverHandle;
378  
379     if (!isValidServerHandle(b_handle, &tst)) {
380         goto fail_bos_ProcessCreate;
381     }
382
383     if (processType == BOS_PROCESS_FS) {
384         tst = ADMBOSPROCESSCREATEBADTYPE;
385         goto fail_bos_ProcessCreate;
386     }
387
388     if ((processName == NULL) || (*processName == 0)) {
389         tst = ADMBOSPROCESSNAMENULL;
390         goto fail_bos_ProcessCreate;
391     }
392
393     if ((process == NULL) || (*process == 0)) {
394         tst = ADMBOSPROCESSNULL;
395         goto fail_bos_ProcessCreate;
396     }
397
398     if ((processType == BOS_PROCESS_CRON) && (cronTime == NULL)) {
399         tst = ADMBOSCRONTIMENULL;
400         goto fail_bos_ProcessCreate;
401     }
402
403     if ((processType == BOS_PROCESS_SIMPLE) && (cronTime != NULL)) {
404         tst = ADMBOSCRONTIMENOTNULL;
405         goto fail_bos_ProcessCreate;
406     }
407
408     tst = BOZO_CreateBnode(b_handle->server, processTypes[processType],
409                            processName, process,
410                            (cronTime) ? cronTime : "", "", "", "", 
411                            (notifier) ? notifier : NONOTIFIER);
412     if (tst == 0) {
413         rc = 1;
414     }
415
416 fail_bos_ProcessCreate:
417
418     if (st != NULL) {
419         *st = tst;
420     }
421     return rc;
422 }
423
424 /*
425  * bos_FSProcessCreate - create the fs group of processes at the boserver.
426  *
427  * PARAMETERS
428  *
429  * IN serverHandle - a previously opened serverHandle.
430  *
431  * IN processName - the name of the process to create.
432  *
433  * IN fileserverPath - the path to the fileserver binary at the bos server.
434  *
435  * IN volserverPath - the path to the volserver binary at the bos server.
436  *
437  * IN salvagerPath - the path to the salvager binary at the bos server.
438  *
439  * IN notifier - the path to the notifier binary at the bos server.
440  *
441  * LOCKS
442  *
443  * No locks are obtained or released by this function
444  *
445  * RETURN CODES
446  *
447  * Returns != 0 upon successful completion.
448  */
449
450 int ADMINAPI bos_FSProcessCreate(
451   const void *serverHandle,
452   const char *processName, 
453   const char *fileserverPath,
454   const char *volserverPath,
455   const char *salvagerPath,
456   const char *notifier, 
457   afs_status_p st)
458 {
459     int rc = 0;
460     afs_status_t tst = 0;
461     bos_server_p b_handle = (bos_server_p) serverHandle;
462  
463     if (!isValidServerHandle(b_handle, &tst)) {
464         goto fail_bos_ProcessCreate;
465     }
466
467     if ((processName == NULL) || (*processName == 0)) {
468         tst = ADMBOSPROCESSNAMENULL;
469         goto fail_bos_ProcessCreate;
470     }
471
472     if ((fileserverPath == NULL) || (*fileserverPath == 0)) {
473         tst = ADMBOSFILESERVERPATHNULL;
474         goto fail_bos_ProcessCreate;
475     }
476
477     if ((volserverPath == NULL) || (*volserverPath == 0)) {
478         tst = ADMBOSVOLSERVERPATHNULL;
479         goto fail_bos_ProcessCreate;
480     }
481
482     if ((salvagerPath == NULL) || (*salvagerPath == 0)) {
483         tst = ADMBOSSALVAGERPATHNULL;
484         goto fail_bos_ProcessCreate;
485     }
486
487     tst = BOZO_CreateBnode(b_handle->server,
488                            processTypes[BOS_PROCESS_FS],
489                            processName,
490                            fileserverPath,
491                            volserverPath,
492                            salvagerPath,
493                            "",
494                            "", 
495                            (notifier) ? notifier : NONOTIFIER);
496     if (tst == 0) {
497         rc = 1;
498     }
499
500 fail_bos_ProcessCreate:
501
502     if (st != NULL) {
503         *st = tst;
504     }
505     return rc;
506 }
507
508 /*
509  * bos_ProcessDelete - delete an existing process at a bos server.
510  *
511  * PARAMETERS
512  *
513  * IN serverHandle - a previously opened serverHandle.
514  *
515  * IN processName - the name of the process to delete.
516  *
517  * LOCKS
518  *
519  * No locks are obtained or released by this function
520  *
521  * RETURN CODES
522  *
523  * Returns != 0 upon successful completion.
524  */
525
526 int ADMINAPI bos_ProcessDelete(
527   const void *serverHandle,
528   const char *processName, 
529   afs_status_p st)
530 {
531     int rc = 0;
532     afs_status_t tst = 0;
533     bos_server_p b_handle = (bos_server_p) serverHandle;
534  
535     if (!isValidServerHandle(b_handle, &tst)) {
536         goto fail_bos_ProcessDelete;
537     }
538
539     if ((processName == NULL) || (*processName == 0)) {
540         tst = ADMBOSPROCESSNAMENULL;
541         goto fail_bos_ProcessDelete;
542     }
543
544     tst = BOZO_DeleteBnode(b_handle->server, processName);
545
546     if (tst == 0) {
547         rc = 1;
548     }
549
550 fail_bos_ProcessDelete:
551
552     if (st != NULL) {
553         *st = tst;
554     }
555     return rc;
556 }
557
558 /*
559  * bos_ProcessExecutionStateGet - get the current execution state of a 
560  * process
561  *
562  * PARAMETERS
563  *
564  * IN serverHandle - a previously opened serverHandle.
565  *
566  * IN processName - the name of the process to retrieve.
567  *
568  * OUT processStatusP - upon successful completion the process execution state
569  *
570  * OUT auxiliaryProcessStatus - set to point to aux proc status if available.
571  * Pass a pointer to an char array at least BOS_MAX_NAME_LEN long.
572  *
573  * LOCKS
574  *
575  * No locks are obtained or released by this function
576  *
577  * RETURN CODES
578  *
579  * Returns != 0 upon successful completion.
580  */
581
582 int ADMINAPI bos_ProcessExecutionStateGet(
583   const void *serverHandle,
584   const char *processName, 
585   bos_ProcessExecutionState_p processStatusP,
586   char *auxiliaryProcessStatus,
587   afs_status_p st)
588 {
589     int rc = 0;
590     afs_status_t tst = 0;
591     bos_server_p b_handle = (bos_server_p) serverHandle;
592     afs_int32 state;
593  
594     if (!isValidServerHandle(b_handle, &tst)) {
595         goto fail_bos_ProcessExecutionStateGet;
596     }
597
598     if ((processName == NULL) || (*processName == 0)) {
599         tst = ADMBOSPROCESSNAMENULL;
600         goto fail_bos_ProcessExecutionStateGet;
601     }
602
603     if (processStatusP == NULL) {
604         tst = ADMBOSPROCESSSTATUSPNULL;
605         goto fail_bos_ProcessExecutionStateGet;
606     }
607
608     if (auxiliaryProcessStatus == NULL) {
609         tst = ADMBOSAUXILIARYPROCESSSTATUSNULL;
610         goto fail_bos_ProcessExecutionStateGet;
611     }
612
613     tst = BOZO_GetStatus(b_handle->server, processName, &state, &auxiliaryProcessStatus);
614
615     if (tst != 0) {
616         goto fail_bos_ProcessExecutionStateGet;
617     }
618
619     *processStatusP = (bos_ProcessExecutionState_t) state;
620     rc = 1;
621
622 fail_bos_ProcessExecutionStateGet:
623
624     if (st != NULL) {
625         *st = tst;
626     }
627     return rc;
628 }
629
630 /*
631  * SetExecutionState - set the execution state of a process
632  *
633  * PARAMETERS
634  *
635  * IN serverHandle - a previously opened serverHandle.
636  *
637  * IN processName - the name of the process to modify.
638  *
639  * IN processStatus - the new process state.
640  *
641  * IN func - the function to call to set the status.
642  *
643  * LOCKS
644  *
645  * No locks are obtained or released by this function
646  *
647  * RETURN CODES
648  *
649  * Returns != 0 upon successful completion.
650  */
651
652 static int SetExecutionState(
653   const void *serverHandle,
654   const char *processName, 
655   const bos_ProcessExecutionState_t processStatus,
656   int (*func)(struct rx_connection *, const char *, afs_int32),
657   afs_status_p st)
658 {
659     int rc = 0;
660     afs_status_t tst = 0;
661     bos_server_p b_handle = (bos_server_p) serverHandle;
662     afs_int32 state;
663  
664     if (!isValidServerHandle(b_handle, &tst)) {
665         goto fail_SetExecutionState;
666     }
667
668     if ((processName == NULL) || (*processName == 0)) {
669         tst = ADMBOSPROCESSNAMENULL;
670         goto fail_SetExecutionState;
671     }
672
673     if ((processStatus != BOS_PROCESS_STOPPED) &&
674         (processStatus != BOS_PROCESS_RUNNING)) {
675         tst = ADMBOSPROCESSSTATUSSET;
676         goto fail_SetExecutionState;
677     }
678
679     state = (afs_int32) processStatus;
680
681     tst = func(b_handle->server, processName, state);
682
683     if (tst == 0) {
684         rc = 1;
685     }
686
687 fail_SetExecutionState:
688
689     if (st != NULL) {
690         *st = tst;
691     }
692     return rc;
693 }
694
695 /*
696  * bos_ProcessExecutionStateSet - set the execution state of a process
697  *
698  * PARAMETERS
699  *
700  * IN serverHandle - a previously opened serverHandle.
701  *
702  * IN processName - the name of the process to modify.
703  *
704  * IN processStatus - the new process state.
705  *
706  * LOCKS
707  *
708  * No locks are obtained or released by this function
709  *
710  * RETURN CODES
711  *
712  * Returns != 0 upon successful completion.
713  */
714
715 int ADMINAPI bos_ProcessExecutionStateSet(
716   const void *serverHandle,
717   const char *processName, 
718   bos_ProcessExecutionState_t processStatus,
719   afs_status_p st)
720 {
721     return SetExecutionState(serverHandle, processName, processStatus,
722                              BOZO_SetStatus, st);
723 }
724
725 /*
726  * bos_ProcessExecutionStateSetTemporary - set the execution state of a process
727  * temporarily
728  *
729  * PARAMETERS
730  *
731  * IN serverHandle - a previously opened serverHandle.
732  *
733  * IN processName - the name of the process to modify.
734  *
735  * IN processStatus - the new process state.
736  *
737  * LOCKS
738  *
739  * No locks are obtained or released by this function
740  *
741  * RETURN CODES
742  *
743  * Returns != 0 upon successful completion.
744  */
745
746 int ADMINAPI bos_ProcessExecutionStateSetTemporary(
747   const void *serverHandle,
748   const char *processName, 
749   bos_ProcessExecutionState_t processStatus,
750   afs_status_p st)
751 {
752     return SetExecutionState(serverHandle, processName, processStatus,
753                              BOZO_SetTStatus, st);
754 }
755
756 /*
757  * The iterator functions and data for the process name retrieval functions
758  */
759
760 typedef struct process_name_get {
761   int next;
762   struct rx_connection *server;
763   char process[CACHED_ITEMS][BOS_MAX_NAME_LEN];
764 } process_name_get_t, *process_name_get_p;
765
766 static int GetProcessNameRPC(
767   void *rpc_specific,
768   int slot,
769   int *last_item,
770   int *last_item_contains_data,
771   afs_status_p st)
772 {
773     int rc = 0;
774     afs_status_t tst = 0;
775     process_name_get_p proc = (process_name_get_p) rpc_specific;
776     char *ptr = (char *) &proc->process[slot];
777
778     tst = BOZO_EnumerateInstance(proc->server, proc->next++, &ptr);
779
780     if (tst == 0) {
781         rc = 1;
782     } else if (tst == BZDOM) {
783         tst = 0;
784         rc = 1;
785         *last_item = 1;
786         *last_item_contains_data = 0;
787     }
788
789     if (st != NULL) {
790         *st = tst;
791     }
792     return rc;
793 }
794
795 static int GetProcessNameFromCache(
796   void *rpc_specific,
797   int slot,
798   void *dest,
799   afs_status_p st)
800 {
801     int rc = 0;
802     afs_status_t tst = 0;
803     process_name_get_p proc = (process_name_get_p) rpc_specific;
804
805     strcpy((char *) dest, (char *) &proc->process[slot]);
806     rc = 1;
807
808     if (st != NULL) {
809         *st = tst;
810     }
811     return rc;
812 }
813   
814 /*
815  * bos_ProcessNameGetBegin - begin iterating over the list of processes
816  * at a particular bos server.
817  *
818  * PARAMETERS
819  *
820  * IN serverHandle - a previously opened serverHandle.
821  *
822  * OUT iter - an iterator that can be passed to bos_ProcessNameGetNext
823  * to retrieve the process names.
824  *
825  * LOCKS
826  *
827  * No locks are obtained or released by this function
828  *
829  * RETURN CODES
830  *
831  * Returns != 0 upon successful completion.
832  *
833  */
834
835 int ADMINAPI bos_ProcessNameGetBegin(
836   const void *serverHandle,
837   void **iterationIdP,
838   afs_status_p st)
839 {
840     int rc = 0;
841     afs_status_t tst = 0;
842     bos_server_p b_handle = (bos_server_p) serverHandle;
843     afs_admin_iterator_p iter = (afs_admin_iterator_p) malloc(sizeof(afs_admin_iterator_t));
844     process_name_get_p proc = (process_name_get_p) malloc(sizeof(process_name_get_t));
845  
846     if (!isValidServerHandle(b_handle, &tst)) {
847         goto fail_bos_ProcessNameGetBegin;
848     }
849
850     if (iterationIdP == NULL) {
851         tst = ADMITERATIONIDPNULL;
852         goto fail_bos_ProcessNameGetBegin;
853     }
854
855     if ((iter == NULL) || (proc == NULL)) {
856         tst = ADMNOMEM;
857         goto fail_bos_ProcessNameGetBegin;
858     }
859
860     proc->next = 0;
861     proc->server = b_handle->server;
862
863     if (IteratorInit(iter, (void *) proc, GetProcessNameRPC, GetProcessNameFromCache, NULL, NULL, &tst)) {
864         *iterationIdP = (void *) iter;
865     } else {
866         goto fail_bos_ProcessNameGetBegin;
867     }
868     rc = 1;
869
870 fail_bos_ProcessNameGetBegin:
871
872     if (rc == 0) {
873         if (iter != NULL) {
874             free(iter);
875         }
876         if (proc != NULL) {
877             free(proc);
878         }
879     }
880
881     if (st != NULL) {
882         *st = tst;
883     }
884     return rc;
885 }
886   
887 /*
888  * bos_ProcessNameGetNext - retrieve the next process name from the bos server.
889  *
890  * PARAMETERS
891  *
892  * IN iterationId - an iterator previously returned by bos_ProcessNameGetBegin
893  *
894  * OUT processName - upon successful completion contains the next process name
895  * retrieved from the server.
896  *
897  * LOCKS
898  *
899  * No locks are obtained or released by this function
900  *
901  * RETURN CODES
902  *
903  * Returns != 0 upon successful completion.
904  *
905  */
906
907 int ADMINAPI bos_ProcessNameGetNext(
908   const void *iterationId,
909   char *processName,
910   afs_status_p st)
911 {
912     int rc = 0;
913     afs_status_t tst = 0;
914     afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
915  
916     if (processName == NULL) {
917         tst = ADMBOSPROCESSNAMENULL;
918         goto fail_bos_ProcessNameGetNext;
919     }
920
921     if (iterationId == NULL) {
922         tst = ADMITERATIONIDPNULL;
923         goto fail_bos_ProcessNameGetNext;
924     }
925
926     rc = IteratorNext(iter, (void *) processName, &tst);
927
928 fail_bos_ProcessNameGetNext:
929
930     if (st != NULL) {
931         *st = tst;
932     }
933     return rc;
934 }
935
936 /*
937  * bos_ProcessNameGetDone - finish using a process name iterator.
938  *
939  * PARAMETERS
940  *
941  * IN iterationId - an iterator previously returned by bos_ProcessNameGetBegin
942  *
943  * LOCKS
944  *
945  * No locks are obtained or released by this function
946  *
947  * RETURN CODES
948  *
949  * Returns != 0 upon successful completion.
950  *
951  */
952
953 int ADMINAPI bos_ProcessNameGetDone(
954   const void *iterationId,
955   afs_status_p st)
956 {
957     int rc = 0;
958     afs_status_t tst = 0;
959     afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
960  
961     if (iterationId == NULL) {
962         tst = ADMITERATIONIDPNULL;
963         goto fail_bos_ProcessNameGetDone;
964     }
965
966     rc = IteratorDone(iter, &tst);
967
968 fail_bos_ProcessNameGetDone:
969
970     if (st != NULL) {
971         *st = tst;
972     }
973     return rc;
974 }
975
976 /*
977  * bos_ProcessInfoGet - get information about a single process
978  *
979  * PARAMETERS
980  *
981  * IN serverHandle - a previously opened serverHandle.
982  *
983  * IN processName - the process of interest.
984  *
985  * OUT processTypeP - upon successful completion contains the process type
986  *
987  * OUT processInfoP - upon successful completion contains the process info
988  *
989  * LOCKS
990  *
991  * No locks are obtained or released by this function
992  *
993  * RETURN CODES
994  *
995  * Returns != 0 upon successful completion.
996  *
997  */
998
999 int ADMINAPI bos_ProcessInfoGet(
1000   const void *serverHandle,
1001   const char *processName,
1002   bos_ProcessType_p processTypeP, 
1003   bos_ProcessInfo_p processInfoP,
1004   afs_status_p st)
1005 {
1006     int rc = 0;
1007     afs_status_t tst = 0;
1008     bos_server_p b_handle = (bos_server_p) serverHandle;
1009     char type[BOS_MAX_NAME_LEN];
1010     char *ptr = type;
1011     struct bozo_status status;
1012     int i;
1013  
1014     if (!isValidServerHandle(b_handle, &tst)) {
1015         goto fail_bos_ProcessInfoGet;
1016     }
1017
1018     if ((processName == NULL) || (*processName == 0)) {
1019         tst = ADMBOSPROCESSNAMENULL;
1020         goto fail_bos_ProcessInfoGet;
1021     }
1022
1023     if (processTypeP == NULL) {
1024         tst = ADMBOSPROCESSTYPEPNULL;
1025         goto fail_bos_ProcessInfoGet;
1026     }
1027
1028     if (processInfoP == NULL) {
1029         tst = ADMBOSPROCESSINFOPNULL;
1030         goto fail_bos_ProcessInfoGet;
1031     }
1032
1033     tst = BOZO_GetInstanceInfo(b_handle->server, processName, &ptr, &status);
1034
1035     if (tst != 0) {
1036         goto fail_bos_ProcessInfoGet;
1037     }
1038
1039
1040     for(i=0;(processTypes[i] != NULL); i++) {
1041         if (!strcmp(processTypes[i], type)) {
1042             *processTypeP = (bos_ProcessType_t) i;
1043             break;
1044         }
1045     }
1046
1047     if (processTypes[i] == NULL) {
1048         tst = ADMBOSINVALIDPROCESSTYPE;
1049         goto fail_bos_ProcessInfoGet;
1050     }
1051
1052     processInfoP->processGoal = (bos_ProcessExecutionState_t) status.goal;
1053     processInfoP->processStartTime = status.procStartTime;
1054     processInfoP->numberProcessStarts = status.procStarts;
1055     processInfoP->processExitTime = status.lastAnyExit;
1056     processInfoP->processExitErrorTime = status.lastErrorExit;
1057     processInfoP->processErrorCode = status.errorCode;
1058     processInfoP->processErrorSignal = status.errorSignal;
1059     processInfoP->state = BOS_PROCESS_OK;
1060
1061     if (status.flags & BOZO_ERRORSTOP) {
1062         processInfoP->state |= BOS_PROCESS_TOO_MANY_ERRORS;
1063     }
1064     if (status.flags & BOZO_HASCORE) {
1065         processInfoP->state |= BOS_PROCESS_CORE_DUMPED;
1066     }
1067     if (status.flags & BOZO_BADDIRACCESS) {
1068         processInfoP->state |= BOS_PROCESS_BAD_FILE_ACCESS;
1069     }
1070     rc = 1;
1071
1072 fail_bos_ProcessInfoGet:
1073
1074     if (st != NULL) {
1075         *st = tst;
1076     }
1077     return rc;
1078 }
1079
1080 /*
1081  * The iterator functions and data for the parameter retrieval functions
1082  */
1083
1084 typedef struct param_get {
1085   int next;
1086   struct rx_connection *server;
1087   char processName[BOS_MAX_NAME_LEN];
1088   char param[CACHED_ITEMS][BOS_MAX_NAME_LEN];
1089 } param_get_t, *param_get_p;
1090
1091 static int GetParameterRPC(
1092   void *rpc_specific,
1093   int slot,
1094   int *last_item,
1095   int *last_item_contains_data,
1096   afs_status_p st)
1097 {
1098     int rc = 0;
1099     afs_status_t tst = 0;
1100     param_get_p param = (param_get_p) rpc_specific;
1101     char *ptr = (char *) &param->param[slot];
1102
1103     tst = BOZO_GetInstanceParm(param->server, param->processName,
1104                                param->next++, &ptr);
1105
1106     if (tst == 0) {
1107         rc = 1;
1108     } else if (tst == BZDOM) {
1109         tst = 0;
1110         rc = 1;
1111         *last_item = 1;
1112         *last_item_contains_data = 0;
1113     }
1114
1115     if (st != NULL) {
1116         *st = tst;
1117     }
1118     return rc;
1119 }
1120
1121 static int GetParameterFromCache(
1122   void *rpc_specific,
1123   int slot,
1124   void *dest,
1125   afs_status_p st)
1126 {
1127     int rc = 0;
1128     afs_status_t tst = 0;
1129     param_get_p param = (param_get_p) rpc_specific;
1130
1131     strcpy((char *) dest, (char *) &param->param[slot]);
1132     rc = 1;
1133
1134     if (st != NULL) {
1135         *st = tst;
1136     }
1137     return rc;
1138 }
1139   
1140 /*
1141  * bos_ProcessParameterGetBegin - begin iterating over the parameters
1142  * of a particular process.
1143  *
1144  * PARAMETERS
1145  *
1146  * IN serverHandle - a previously opened serverHandle.
1147  *
1148  * IN processName - the process whose parameters are returned.
1149  *
1150  * OUT iter - an iterator that can be passed to bos_ProcessParameterGetNext
1151  * to retrieve the parameters.
1152  *
1153  * LOCKS
1154  *
1155  * No locks are obtained or released by this function
1156  *
1157  * RETURN CODES
1158  *
1159  * Returns != 0 upon successful completion.
1160  *
1161  */
1162
1163 int ADMINAPI bos_ProcessParameterGetBegin(
1164   const void *serverHandle,
1165   const char *processName,
1166   void **iterationIdP,
1167   afs_status_p st)
1168 {
1169     int rc = 0;
1170     afs_status_t tst = 0;
1171     bos_server_p b_handle = (bos_server_p) serverHandle;
1172     afs_admin_iterator_p iter = (afs_admin_iterator_p) malloc(sizeof(afs_admin_iterator_t));
1173     param_get_p param = (param_get_p) malloc(sizeof(param_get_t));
1174  
1175     if (!isValidServerHandle(b_handle, &tst)) {
1176         goto fail_bos_ProcessParameterGetBegin;
1177     }
1178
1179     if ((processName == NULL) || (*processName == 0)) {
1180         tst = ADMBOSPROCESSNAMENULL;
1181         goto fail_bos_ProcessParameterGetBegin;
1182     }
1183
1184     if (iterationIdP == NULL) {
1185         tst = ADMITERATIONIDPNULL;
1186         goto fail_bos_ProcessParameterGetBegin;
1187     }
1188
1189     if ((iter == NULL) || (param == NULL)) {
1190         tst = ADMNOMEM;
1191         goto fail_bos_ProcessParameterGetBegin;
1192     }
1193
1194     param->next = 0;
1195     param->server = b_handle->server;
1196     strcpy(param->processName, processName);
1197
1198     if (IteratorInit(iter, (void *) param, GetParameterRPC,
1199                      GetParameterFromCache, NULL, NULL, &tst)) {
1200         *iterationIdP = (void *) iter;
1201     } else {
1202         goto fail_bos_ProcessParameterGetBegin;
1203     }
1204     rc = 1;
1205
1206 fail_bos_ProcessParameterGetBegin:
1207
1208     if (rc == 0) {
1209         if (iter != NULL) {
1210             free(iter);
1211         }
1212         if (param != NULL) {
1213             free(param);
1214         }
1215     }
1216
1217     if (st != NULL) {
1218         *st = tst;
1219     }
1220     return rc;
1221 }
1222
1223 /*
1224  * bos_ProcessParameterGetNext - retrieve the next parameter 
1225  * from the bos server.
1226  *
1227  * PARAMETERS
1228  *
1229  * IN iterationId - an iterator previously returned by 
1230  * bos_ProcessParameterGetBegin
1231  *
1232  * OUT parameter - upon successful completion contains the next parameter
1233  * retrieved from the server.
1234  *
1235  * LOCKS
1236  *
1237  * No locks are obtained or released by this function
1238  *
1239  * RETURN CODES
1240  *
1241  * Returns != 0 upon successful completion.
1242  *
1243  */
1244   
1245 int ADMINAPI bos_ProcessParameterGetNext(
1246   const void *iterationId,
1247   char *parameter,
1248   afs_status_p st)
1249 {
1250     int rc = 0;
1251     afs_status_t tst = 0;
1252     afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
1253  
1254     if (iterationId == NULL) {
1255         tst = ADMITERATIONIDPNULL;
1256         goto fail_bos_ProcessParameterGetNext;
1257     }
1258  
1259     if (parameter == NULL) {
1260         tst = ADMBOSPARAMETERNULL;
1261         goto fail_bos_ProcessParameterGetNext;
1262     }
1263
1264     rc = IteratorNext(iter, (void *) parameter, &tst);
1265
1266 fail_bos_ProcessParameterGetNext:
1267
1268     if (st != NULL) {
1269         *st = tst;
1270     }
1271     return rc;
1272 }
1273
1274 /*
1275  * bos_ProcessParameterGetDone - finish using a process name iterator.
1276  *
1277  * PARAMETERS
1278  *
1279  * IN iterationId - an iterator previously returned by
1280  * bos_ProcessParameterGetBegin
1281  *
1282  * LOCKS
1283  *
1284  * No locks are obtained or released by this function
1285  *
1286  * RETURN CODES
1287  *
1288  * Returns != 0 upon successful completion.
1289  *
1290  */
1291
1292 int ADMINAPI bos_ProcessParameterGetDone(
1293   const void *iterationId,
1294   afs_status_p st)
1295 {
1296     int rc = 0;
1297     afs_status_t tst = 0;
1298     afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
1299  
1300     if (iterationId == NULL) {
1301         tst = ADMITERATIONIDPNULL;
1302         goto fail_bos_ProcessParameterGetDone;
1303     }
1304
1305     rc = IteratorDone(iter, &tst);
1306
1307 fail_bos_ProcessParameterGetDone:
1308
1309     if (st != NULL) {
1310         *st = tst;
1311     }
1312     return rc;
1313 }
1314
1315 /*
1316  * bos_ProcessNotifierGet - retrieve the notifier associated with a
1317  * process.
1318  *
1319  * PARAMETERS
1320  *
1321  * IN serverHandle - a previously opened serverHandle.
1322  *
1323  * IN processName - the process whose notifier we are retrieving.
1324  *
1325  * OUT notifier - upon successful completion contains the notifier.
1326  *
1327  * LOCKS
1328  *
1329  * No locks are obtained or released by this function
1330  *
1331  * RETURN CODES
1332  *
1333  * Returns != 0 upon successful completion.
1334  *
1335  */
1336
1337 int ADMINAPI bos_ProcessNotifierGet(
1338   const void *serverHandle,
1339   const char *processName,
1340   char *notifier, 
1341   afs_status_p st)
1342 {
1343     int rc = 0;
1344     afs_status_t tst = 0;
1345     bos_server_p b_handle = (bos_server_p) serverHandle;
1346  
1347     if (!isValidServerHandle(b_handle, &tst)) {
1348         goto fail_bos_ProcessNotifierGet;
1349     }
1350
1351     if ((processName == NULL) || (*processName == 0)) {
1352         tst = ADMBOSPROCESSNAMENULL;
1353         goto fail_bos_ProcessNotifierGet;
1354     }
1355  
1356     if (notifier == NULL) {
1357         tst = ADMBOSNOTIFIERNULL;
1358         goto fail_bos_ProcessNotifierGet;
1359     }
1360
1361     tst = BOZO_GetInstanceParm(b_handle->server, processName, 999, &notifier);
1362
1363     if (tst == 0) {
1364         rc = 1;
1365     }
1366
1367 fail_bos_ProcessNotifierGet:
1368
1369     if (st != NULL) {
1370         *st = tst;
1371     }
1372     return rc;
1373 }
1374
1375 /*
1376  * bos_ProcessRestart - restart a particular process.
1377  *
1378  * PARAMETERS
1379  *
1380  * IN serverHandle - a previously opened serverHandle.
1381  *
1382  * IN processName - the process to restart
1383  *
1384  * LOCKS
1385  *
1386  * No locks are obtained or released by this function
1387  *
1388  * RETURN CODES
1389  *
1390  * Returns != 0 upon successful completion.
1391  *
1392  */
1393
1394 int ADMINAPI bos_ProcessRestart(
1395   const void *serverHandle,
1396   const char *processName,
1397   afs_status_p st)
1398 {
1399     int rc = 0;
1400     afs_status_t tst = 0;
1401     bos_server_p b_handle = (bos_server_p) serverHandle;
1402  
1403     if (!isValidServerHandle(b_handle, &tst)) {
1404         goto fail_bos_ProcessRestart;
1405     }
1406
1407     if ((processName == NULL) || (*processName == 0)) {
1408         tst = ADMBOSPROCESSNAMENULL;
1409         goto fail_bos_ProcessRestart;
1410     }
1411
1412     tst = BOZO_Restart(b_handle->server, processName);
1413
1414     if (tst == 0) {
1415         rc = 1;
1416     }
1417
1418 fail_bos_ProcessRestart:
1419
1420     if (st != NULL) {
1421         *st = tst;
1422     }
1423     return rc;
1424 }
1425
1426 /*
1427  * bos_ProcessAllStop - stop all running processes at a server.
1428  *
1429  * PARAMETERS
1430  *
1431  * IN serverHandle - a previously opened serverHandle.
1432  *
1433  * LOCKS
1434  *
1435  * No locks are obtained or released by this function
1436  *
1437  * RETURN CODES
1438  *
1439  * Returns != 0 upon successful completion.
1440  *
1441  */
1442
1443 int ADMINAPI bos_ProcessAllStop(
1444   const void *serverHandle,
1445   afs_status_p st)
1446 {
1447     int rc = 0;
1448     afs_status_t tst = 0;
1449     bos_server_p b_handle = (bos_server_p) serverHandle;
1450  
1451     if (!isValidServerHandle(b_handle, &tst)) {
1452         goto fail_bos_ProcessAllStop;
1453     }
1454  
1455     tst = BOZO_ShutdownAll(b_handle->server);
1456
1457     if (tst == 0) {
1458         rc = 1;
1459     }
1460
1461 fail_bos_ProcessAllStop:
1462
1463     if (st != NULL) {
1464         *st = tst;
1465     }
1466     return rc;
1467 }
1468
1469 /*
1470  * bos_ProcessAllStart - start all processes that should be running at a
1471  * server.
1472  *
1473  * PARAMETERS
1474  *
1475  * IN serverHandle - a previously opened serverHandle.
1476  *
1477  * LOCKS
1478  *
1479  * No locks are obtained or released by this function
1480  *
1481  * RETURN CODES
1482  *
1483  * Returns != 0 upon successful completion.
1484  *
1485  */
1486
1487 int ADMINAPI bos_ProcessAllStart(
1488   const void *serverHandle,
1489   afs_status_p st)
1490 {
1491     int rc = 0;
1492     afs_status_t tst = 0;
1493     bos_server_p b_handle = (bos_server_p) serverHandle;
1494  
1495     if (!isValidServerHandle(b_handle, &tst)) {
1496         goto fail_bos_ProcessAllStart;
1497     }
1498  
1499     tst = BOZO_StartupAll(b_handle->server);
1500
1501     if (tst == 0) {
1502         rc = 1;
1503     }
1504
1505 fail_bos_ProcessAllStart:
1506
1507     if (st != NULL) {
1508         *st = tst;
1509     }
1510     return rc;
1511 }
1512
1513 /*
1514  * bos_ProcessAllWaitStop - stop all processes, and block until they have
1515  * exited.
1516  *
1517  * PARAMETERS
1518  *
1519  * IN serverHandle - a previously opened serverHandle.
1520  *
1521  * LOCKS
1522  *
1523  * No locks are obtained or released by this function
1524  *
1525  * RETURN CODES
1526  *
1527  * Returns != 0 upon successful completion.
1528  *
1529  */
1530
1531 int ADMINAPI bos_ProcessAllWaitStop(
1532   const void *serverHandle,
1533   afs_status_p st)
1534 {
1535     int rc = 0;
1536     afs_status_t tst = 0;
1537     bos_server_p b_handle = (bos_server_p) serverHandle;
1538  
1539     if (!isValidServerHandle(b_handle, &tst)) {
1540         goto fail_bos_ProcessAllWaitStop;
1541     }
1542  
1543     if (!bos_ProcessAllStop(serverHandle, &tst)) {
1544         goto fail_bos_ProcessAllWaitStop;
1545     }
1546
1547     tst = BOZO_WaitAll(b_handle->server);
1548
1549     if (tst == 0) {
1550         rc = 1;
1551     }
1552
1553 fail_bos_ProcessAllWaitStop:
1554
1555     if (st != NULL) {
1556         *st = tst;
1557     }
1558     return rc;
1559 }
1560
1561 /*
1562  * bos_ProcessAllWaitTransition - block until all processes at the bosserver
1563  * have reached their desired state.
1564  *
1565  * PARAMETERS
1566  *
1567  * IN serverHandle - a previously opened serverHandle.
1568  *
1569  * LOCKS
1570  *
1571  * No locks are obtained or released by this function
1572  *
1573  * RETURN CODES
1574  *
1575  * Returns != 0 upon successful completion.
1576  *
1577  */
1578
1579 int ADMINAPI bos_ProcessAllWaitTransition(
1580   const void *serverHandle,
1581   afs_status_p st)
1582 {
1583     int rc = 0;
1584     afs_status_t tst = 0;
1585     bos_server_p b_handle = (bos_server_p) serverHandle;
1586  
1587     if (!isValidServerHandle(b_handle, &tst)) {
1588         goto fail_bos_ProcessAllWaitTransition;
1589     }
1590  
1591     tst = BOZO_WaitAll(b_handle->server);
1592
1593     if (tst == 0) {
1594         rc = 1;
1595     }
1596
1597 fail_bos_ProcessAllWaitTransition:
1598
1599     if (st != NULL) {
1600         *st = tst;
1601     }
1602     return rc;
1603 }
1604
1605 /*
1606  * bos_ProcessAllStopAndRestart - stop all the running processes, restart
1607  * them, and optionally restart the bosserver itself.
1608  * exited.
1609  *
1610  * PARAMETERS
1611  *
1612  * IN serverHandle - a previously opened serverHandle.
1613  *
1614  * IN restartBosServer - flag to indicate whether to restart bosserver.
1615  *
1616  * LOCKS
1617  *
1618  * No locks are obtained or released by this function
1619  *
1620  * RETURN CODES
1621  *
1622  * Returns != 0 upon successful completion.
1623  *
1624  */
1625
1626 int ADMINAPI bos_ProcessAllStopAndRestart(
1627   const void *serverHandle,
1628   bos_RestartBosServer_t restartBosServer,
1629   afs_status_p st)
1630 {
1631     int rc = 0;
1632     afs_status_t tst = 0;
1633     bos_server_p b_handle = (bos_server_p) serverHandle;
1634  
1635     if (!isValidServerHandle(b_handle, &tst)) {
1636         goto fail_bos_ProcessAllStopAndRestart;
1637     }
1638
1639     if (restartBosServer == BOS_RESTART_BOS_SERVER) {
1640         tst = BOZO_ReBozo(b_handle->server);
1641         if (tst != 0) {
1642             goto fail_bos_ProcessAllStopAndRestart;
1643         }
1644     }
1645
1646     tst = BOZO_RestartAll(b_handle->server);
1647     
1648     if (tst == 0) {
1649         rc = 1;
1650     }
1651
1652 fail_bos_ProcessAllStopAndRestart:
1653
1654     if (st != NULL) {
1655         *st = tst;
1656     }
1657     return rc;
1658 }
1659
1660 /*
1661  * bos_AdminCreate - create a new admin.
1662  *
1663  * PARAMETERS
1664  *
1665  * IN serverHandle - a previously opened serverHandle.
1666  *
1667  * IN adminName - the new admin name.
1668  *
1669  * LOCKS
1670  *
1671  * No locks are obtained or released by this function
1672  *
1673  * RETURN CODES
1674  *
1675  * Returns != 0 upon successful completion.
1676  *
1677  */
1678
1679 int ADMINAPI bos_AdminCreate(
1680   const void *serverHandle,
1681   const char *adminName,
1682   afs_status_p st)
1683 {
1684     int rc = 0;
1685     afs_status_t tst = 0;
1686     bos_server_p b_handle = (bos_server_p) serverHandle;
1687  
1688     if (!isValidServerHandle(b_handle, &tst)) {
1689         goto fail_bos_AdminCreate;
1690     }
1691
1692     if ((adminName == NULL) || (*adminName == 0)) {
1693         tst = ADMBOSADMINNAMENULL;
1694         goto fail_bos_AdminCreate;
1695     }
1696  
1697     tst = BOZO_AddSUser(b_handle->server, adminName);
1698     
1699     if (tst == 0) {
1700         rc = 1;
1701     }
1702
1703 fail_bos_AdminCreate:
1704
1705     if (st != NULL) {
1706         *st = tst;
1707     }
1708     return rc;
1709 }
1710
1711 /*
1712  * bos_AdminDelete - delete a new admin.
1713  *
1714  * PARAMETERS
1715  *
1716  * IN serverHandle - a previously opened serverHandle.
1717  *
1718  * IN adminName - the admin name.
1719  *
1720  * LOCKS
1721  *
1722  * No locks are obtained or released by this function
1723  *
1724  * RETURN CODES
1725  *
1726  * Returns != 0 upon successful completion.
1727  *
1728  */
1729
1730 int ADMINAPI bos_AdminDelete(
1731   const void *serverHandle,
1732   const char *adminName,
1733   afs_status_p st)
1734 {
1735     int rc = 0;
1736     afs_status_t tst = 0;
1737     bos_server_p b_handle = (bos_server_p) serverHandle;
1738  
1739     if (!isValidServerHandle(b_handle, &tst)) {
1740         goto fail_bos_AdminDelete;
1741     }
1742
1743     if ((adminName == NULL) || (*adminName == 0)) {
1744         tst = ADMBOSADMINNAMENULL;
1745         goto fail_bos_AdminDelete;
1746     }
1747  
1748     tst = BOZO_DeleteSUser(b_handle->server, adminName);
1749     
1750     if (tst == 0) {
1751         rc = 1;
1752     }
1753
1754 fail_bos_AdminDelete:
1755
1756     if (st != NULL) {
1757         *st = tst;
1758     }
1759     return rc;
1760 }
1761
1762 /*
1763  * The iterator functions and data for the admin retrieval functions
1764  */
1765
1766 typedef struct admin_get {
1767   int next;
1768   struct rx_connection *server;
1769   char admin[CACHED_ITEMS][BOS_MAX_NAME_LEN];
1770 } admin_get_t, *admin_get_p;
1771
1772 static int GetAdminRPC(
1773   void *rpc_specific,
1774   int slot,
1775   int *last_item,
1776   int *last_item_contains_data,
1777   afs_status_p st)
1778 {
1779     int rc = 0;
1780     afs_status_t tst = 0;
1781     admin_get_p admin = (admin_get_p) rpc_specific;
1782     char *ptr = (char *) &admin->admin[slot];
1783
1784     tst = BOZO_ListSUsers(admin->server, admin->next++, &ptr);
1785
1786     /*
1787      * There's no way to tell the difference between an rpc failure
1788      * and the end of the list, so we assume that any error means the
1789      * end of the list
1790      */
1791
1792     if (tst != 0) {
1793         tst = 0;
1794         *last_item = 1;
1795         *last_item_contains_data = 0;
1796     }
1797     rc = 1;
1798
1799     if (st != NULL) {
1800         *st = tst;
1801     }
1802     return rc;
1803 }
1804
1805 static int GetAdminFromCache(
1806   void *rpc_specific,
1807   int slot,
1808   void *dest,
1809   afs_status_p st)
1810 {
1811     int rc = 0;
1812     afs_status_t tst = 0;
1813     admin_get_p admin = (admin_get_p) rpc_specific;
1814
1815     strcpy((char *) dest, (char *) &admin->admin[slot]);
1816     rc = 1;
1817
1818     if (st != NULL) {
1819         *st = tst;
1820     }
1821     return rc;
1822 }
1823   
1824 /*
1825  * bos_AdminGetBegin - begin iterating over the administrators.
1826  *
1827  * PARAMETERS
1828  *
1829  * IN serverHandle - a previously opened serverHandle.
1830  *
1831  * OUT iter - an iterator that can be passed to bos_AdminGetBegin
1832  * to retrieve the administrators.
1833  *
1834  * LOCKS
1835  *
1836  * No locks are obtained or released by this function
1837  *
1838  * RETURN CODES
1839  *
1840  * Returns != 0 upon successful completion.
1841  *
1842  */
1843
1844 int ADMINAPI bos_AdminGetBegin(
1845   const void *serverHandle,
1846   void **iterationIdP,
1847   afs_status_p st)
1848 {
1849     int rc = 0;
1850     afs_status_t tst = 0;
1851     bos_server_p b_handle = (bos_server_p) serverHandle;
1852     afs_admin_iterator_p iter = (afs_admin_iterator_p) malloc(sizeof(afs_admin_iterator_t));
1853     admin_get_p admin = (admin_get_p) malloc(sizeof(admin_get_t));
1854  
1855     if (!isValidServerHandle(b_handle, &tst)) {
1856         goto fail_bos_AdminGetBegin;
1857     }
1858  
1859     if (iterationIdP == NULL) {
1860         tst = ADMITERATIONIDPNULL;
1861         goto fail_bos_AdminGetBegin;
1862     }
1863
1864     if ((iter == NULL) || (admin == NULL)) {
1865         tst = ADMNOMEM;
1866         goto fail_bos_AdminGetBegin;
1867     }
1868
1869     admin->next = 0;
1870     admin->server = b_handle->server;
1871
1872     if (IteratorInit(iter, (void *) admin, GetAdminRPC,
1873                      GetAdminFromCache, NULL, NULL, &tst)) {
1874         *iterationIdP = (void *) iter;
1875         rc = 1;
1876     }
1877
1878 fail_bos_AdminGetBegin:
1879
1880     if (rc == 0) {
1881         if (iter != NULL) {
1882             free(iter);
1883         }
1884         if (admin != NULL) {
1885             free(admin);
1886         }
1887     }
1888
1889     if (st != NULL) {
1890         *st = tst;
1891     }
1892     return rc;
1893 }
1894
1895 /*
1896  * bos_AdminGetNext - retrieve the next administrator 
1897  * from the bos server.
1898  *
1899  * PARAMETERS
1900  *
1901  * IN iterationId - an iterator previously returned by 
1902  * bos_AdminGetBegin
1903  *
1904  * OUT adminName - upon successful completion contains the next administrator
1905  * retrieved from the server.
1906  *
1907  * LOCKS
1908  *
1909  * No locks are obtained or released by this function
1910  *
1911  * RETURN CODES
1912  *
1913  * Returns != 0 upon successful completion.
1914  *
1915  */
1916   
1917 int ADMINAPI bos_AdminGetNext(
1918   const void *iterationId,
1919   char *adminName,
1920   afs_status_p st)
1921 {
1922     int rc = 0;
1923     afs_status_t tst = 0;
1924     afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
1925  
1926     if (iterationId == NULL) {
1927         tst = ADMITERATIONIDPNULL;
1928         goto fail_bos_AdminGetNext;
1929     }
1930
1931     if (adminName == NULL) {
1932         tst = ADMBOSADMINNAMENULL;
1933         goto fail_bos_AdminGetNext;
1934     }
1935
1936     rc = IteratorNext(iter, (void *) adminName, &tst);
1937
1938 fail_bos_AdminGetNext:
1939
1940     if (st != NULL) {
1941         *st = tst;
1942     }
1943     return rc;
1944 }
1945
1946 /*
1947  * bos_AdminGetDone - finish using a administrator iterator.
1948  *
1949  * PARAMETERS
1950  *
1951  * IN iterationId - an iterator previously returned by
1952  * bos_AdminGetBegin
1953  *
1954  * LOCKS
1955  *
1956  * No locks are obtained or released by this function
1957  *
1958  * RETURN CODES
1959  *
1960  * Returns != 0 upon successful completion.
1961  *
1962  */
1963
1964 int ADMINAPI bos_AdminGetDone(
1965   const void *iterationId,
1966   afs_status_p st)
1967 {
1968     int rc = 0;
1969     afs_status_t tst = 0;
1970     afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
1971  
1972     if (iterationId == NULL) {
1973         tst = ADMITERATIONIDPNULL;
1974         goto fail_bos_AdminGetDone;
1975     }
1976
1977     rc = IteratorDone(iter, &tst);
1978
1979 fail_bos_AdminGetDone:
1980
1981     if (st != NULL) {
1982         *st = tst;
1983     }
1984     return rc;
1985 }
1986
1987 /*
1988  * bos_KeyCreate - add a new key to the keyfile.
1989  *
1990  * PARAMETERS
1991  *
1992  * IN serverHandle - a previously opened serverHandle.
1993  *
1994  * IN keyVersionNumber - the key version number.
1995  *
1996  * IN key -  the new key.
1997  *
1998  * LOCKS
1999  *
2000  * No locks are obtained or released by this function
2001  *
2002  * RETURN CODES
2003  *
2004  * Returns != 0 upon successful completion.
2005  *
2006  */
2007
2008 int ADMINAPI bos_KeyCreate(
2009   const void *serverHandle,
2010   int keyVersionNumber,
2011   const kas_encryptionKey_p key,
2012   afs_status_p st)
2013 {
2014     int rc = 0;
2015     afs_status_t tst = 0;
2016     bos_server_p b_handle = (bos_server_p) serverHandle;
2017  
2018     if (!isValidServerHandle(b_handle, &tst)) {
2019         goto fail_bos_KeyCreate;
2020     }
2021
2022     if (key == NULL) {
2023         tst = ADMBOSKEYNULL;
2024         goto fail_bos_KeyCreate;
2025     }
2026  
2027     tst = BOZO_AddKey(b_handle->server_encrypt, keyVersionNumber, key);
2028
2029     if (tst == 0) {
2030         rc = 1;
2031     }
2032
2033 fail_bos_KeyCreate:
2034
2035     if (st != NULL) {
2036         *st = tst;
2037     }
2038     return rc;
2039 }
2040
2041 /*
2042  * bos_KeyDelete - delete an existing key from the keyfile.
2043  *
2044  * PARAMETERS
2045  *
2046  * IN serverHandle - a previously opened serverHandle.
2047  *
2048  * IN keyVersionNumber - the key version number.
2049  *
2050  * LOCKS
2051  *
2052  * No locks are obtained or released by this function
2053  *
2054  * RETURN CODES
2055  *
2056  * Returns != 0 upon successful completion.
2057  *
2058  */
2059
2060 int ADMINAPI bos_KeyDelete(
2061   const void *serverHandle,
2062   int keyVersionNumber,
2063   afs_status_p st)
2064 {
2065     int rc = 0;
2066     afs_status_t tst = 0;
2067     bos_server_p b_handle = (bos_server_p) serverHandle;
2068  
2069     if (!isValidServerHandle(b_handle, &tst)) {
2070         goto fail_bos_KeyDelete;
2071     }
2072  
2073     tst = BOZO_DeleteKey(b_handle->server, keyVersionNumber);
2074
2075     if (tst == 0) {
2076         rc = 1;
2077     }
2078
2079 fail_bos_KeyDelete:
2080
2081     if (st != NULL) {
2082         *st = tst;
2083     }
2084     return rc;
2085 }
2086
2087 /*
2088  * The iterator functions and data for the key retrieval functions
2089  */
2090
2091 typedef struct key_get {
2092   int next;
2093   struct rx_connection *server;
2094   bos_KeyInfo_t key[CACHED_ITEMS];
2095 } key_get_t, *key_get_p;
2096
2097 static int GetKeyRPC(
2098   void *rpc_specific,
2099   int slot,
2100   int *last_item,
2101   int *last_item_contains_data,
2102   afs_status_p st)
2103 {
2104     int rc = 0;
2105     afs_status_t tst = 0;
2106     key_get_p key = (key_get_p) rpc_specific;
2107     struct bozo_keyInfo keyInfo;
2108
2109     tst = BOZO_ListKeys(key->server, key->next++,
2110                         &key->key[slot].keyVersionNumber,
2111                         &key->key[slot].key, &keyInfo);
2112  
2113
2114     if (tst == 0) {
2115         key->key[slot].keyStatus.lastModificationDate = keyInfo.mod_sec;
2116         key->key[slot].keyStatus.lastModificationMicroSeconds = 
2117                                                               keyInfo.mod_usec;
2118         key->key[slot].keyStatus.checkSum = keyInfo.keyCheckSum;
2119         rc = 1;
2120     } else if (tst == BZDOM) {
2121         tst = 0;
2122         rc = 1;
2123         *last_item = 1;
2124         *last_item_contains_data = 0;
2125     }
2126
2127     if (st != NULL) {
2128         *st = tst;
2129     }
2130     return rc;
2131 }
2132
2133 static int GetKeyFromCache(
2134   void *rpc_specific,
2135   int slot,
2136   void *dest,
2137   afs_status_p st)
2138 {
2139     int rc = 0;
2140     afs_status_t tst = 0;
2141     key_get_p key = (key_get_p) rpc_specific;
2142
2143     memcpy(dest, &key->key[slot], sizeof(bos_KeyInfo_t));
2144     rc = 1;
2145
2146     if (st != NULL) {
2147         *st = tst;
2148     }
2149     return rc;
2150 }
2151   
2152 /*
2153  * bos_KeyGetBegin - begin iterating over the keys.
2154  *
2155  * PARAMETERS
2156  *
2157  * IN serverHandle - a previously opened serverHandle.
2158  *
2159  * OUT iter - an iterator that can be passed to bos_KeyGetNext
2160  * to retrieve the keys.
2161  *
2162  * LOCKS
2163  *
2164  * No locks are obtained or released by this function
2165  *
2166  * RETURN CODES
2167  *
2168  * Returns != 0 upon successful completion.
2169  *
2170  */
2171
2172 int ADMINAPI bos_KeyGetBegin(
2173   const void *serverHandle,
2174   void **iterationIdP,
2175   afs_status_p st)
2176 {
2177     int rc = 0;
2178     afs_status_t tst = 0;
2179     bos_server_p b_handle = (bos_server_p) serverHandle;
2180     afs_admin_iterator_p iter = (afs_admin_iterator_p) malloc(sizeof(afs_admin_iterator_t));
2181     key_get_p key = (key_get_p) malloc(sizeof(key_get_t));
2182  
2183     if (!isValidServerHandle(b_handle, &tst)) {
2184         goto fail_bos_KeyGetBegin;
2185     }
2186  
2187     if (iterationIdP == NULL) {
2188         tst = ADMITERATIONIDPNULL;
2189         goto fail_bos_KeyGetBegin;
2190     }
2191
2192     if ((iter == NULL) || (key == NULL)) {
2193         tst = ADMNOMEM;
2194         goto fail_bos_KeyGetBegin;
2195     }
2196
2197     key->next = 0;
2198     key->server = b_handle->server_encrypt;
2199
2200     if (IteratorInit(iter, (void *) key, GetKeyRPC,
2201                      GetKeyFromCache, NULL, NULL, &tst)) {
2202         *iterationIdP = (void *) iter;
2203         rc = 1;
2204     }
2205
2206 fail_bos_KeyGetBegin:
2207
2208     if (rc == 0) {
2209         if (iter != NULL) {
2210             free(iter);
2211         }
2212         if (key != NULL) {
2213             free(key);
2214         }
2215     }
2216
2217     if (st != NULL) {
2218         *st = tst;
2219     }
2220     return rc;
2221 }
2222
2223 /*
2224  * bos_KeyGetNext - retrieve the next key 
2225  * from the bos server.
2226  *
2227  * PARAMETERS
2228  *
2229  * IN iterationId - an iterator previously returned by 
2230  * bos_KeyGetBegin
2231  *
2232  * OUT keyP - upon successful completion contains the next key
2233  * retrieved from the server.
2234  *
2235  * LOCKS
2236  *
2237  * No locks are obtained or released by this function
2238  *
2239  * RETURN CODES
2240  *
2241  * Returns != 0 upon successful completion.
2242  *
2243  */
2244
2245 int ADMINAPI bos_KeyGetNext(
2246   const void *iterationId,
2247   bos_KeyInfo_p keyP,
2248   afs_status_p st)
2249 {
2250     int rc = 0;
2251     afs_status_t tst = 0;
2252     afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
2253  
2254     if (iterationId == NULL) {
2255         tst = ADMITERATIONIDPNULL;
2256         goto fail_bos_KeyGetNext;
2257     }
2258  
2259     if (keyP == NULL) {
2260         tst = ADMBOSKEYPNULL;
2261         goto fail_bos_KeyGetNext;
2262     }
2263
2264     rc = IteratorNext(iter, (void *) keyP, &tst);
2265
2266 fail_bos_KeyGetNext:
2267
2268     if (st != NULL) {
2269         *st = tst;
2270     }
2271     return rc;
2272 }
2273
2274 /*
2275  * bos_KeyGetDone - finish using a key iterator.
2276  *
2277  * PARAMETERS
2278  *
2279  * IN iterationId - an iterator previously returned by
2280  * bos_KeyGetBegin
2281  *
2282  * LOCKS
2283  *
2284  * No locks are obtained or released by this function
2285  *
2286  * RETURN CODES
2287  *
2288  * Returns != 0 upon successful completion.
2289  *
2290  */
2291
2292 int ADMINAPI bos_KeyGetDone(
2293   const void *iterationId,
2294   afs_status_p st)
2295 {
2296     int rc = 0;
2297     afs_status_t tst = 0;
2298     afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
2299  
2300     if (iterationId == NULL) {
2301         tst = ADMITERATIONIDPNULL;
2302         goto fail_bos_KeyGetDone;
2303     }
2304
2305     rc = IteratorDone(iter, &tst);
2306
2307 fail_bos_KeyGetDone:
2308
2309     if (st != NULL) {
2310         *st = tst;
2311     }
2312     return rc;
2313 }
2314
2315 /*
2316  * bos_CellSet - set the cell name at a bos server.
2317  *
2318  * PARAMETERS
2319  *
2320  * IN serverHandle - a previously opened serverHandle.
2321  *
2322  * IN cellName - the new cell name.
2323  *
2324  * LOCKS
2325  *
2326  * No locks are obtained or released by this function
2327  *
2328  * RETURN CODES
2329  *
2330  * Returns != 0 upon successful completion.
2331  */
2332
2333 int ADMINAPI bos_CellSet(
2334   const void *serverHandle,
2335   const char *cellName,
2336   afs_status_p st)
2337 {
2338     int rc = 0;
2339     afs_status_t tst = 0;
2340     bos_server_p b_handle = (bos_server_p) serverHandle;
2341  
2342     if (!isValidServerHandle(b_handle, &tst)) {
2343         goto fail_bos_CellSet;
2344     }
2345
2346     if ((cellName == NULL) || (*cellName == 0)) {
2347         tst = ADMCLIENTCELLNAMENULL;
2348         goto fail_bos_CellSet;
2349     }
2350  
2351     tst = BOZO_SetCellName(b_handle->server, cellName);
2352
2353     if (tst == 0) {
2354         rc = 1;
2355     }
2356
2357 fail_bos_CellSet:
2358
2359     if (st != NULL) {
2360         *st = tst;
2361     }
2362     return rc;
2363 }
2364
2365 /*
2366  * bos_CellGet - get the cell name at a bos server.
2367  *
2368  * PARAMETERS
2369  *
2370  * IN serverHandle - a previously opened serverHandle.
2371  *
2372  * OUT cellName - the cell name.
2373  *
2374  * LOCKS
2375  *
2376  * No locks are obtained or released by this function
2377  *
2378  * RETURN CODES
2379  *
2380  * Returns != 0 upon successful completion.
2381  */
2382
2383 int ADMINAPI bos_CellGet(
2384   const void *serverHandle,
2385   char *cellName,
2386   afs_status_p st)
2387 {
2388     int rc = 0;
2389     afs_status_t tst = 0;
2390     bos_server_p b_handle = (bos_server_p) serverHandle;
2391  
2392     if (!isValidServerHandle(b_handle, &tst)) {
2393         goto fail_bos_CellGet;
2394     }
2395
2396     if (cellName == NULL) {
2397         tst = ADMCLIENTCELLNAMENULL;
2398         goto fail_bos_CellGet;
2399     }
2400  
2401     tst = BOZO_GetCellName(b_handle->server, &cellName);
2402
2403     if (tst == 0) {
2404         rc = 1;
2405     }
2406  
2407 fail_bos_CellGet:
2408
2409     if (st != NULL) {
2410         *st = tst;
2411     }
2412     return rc;
2413 }
2414  
2415 /*
2416  * bos_HostCreate - add a new host to the cell.
2417  *
2418  * PARAMETERS
2419  *
2420  * IN serverHandle - a previously opened serverHandle.
2421  *
2422  * IN hostName - the new host.
2423  *
2424  * LOCKS
2425  *
2426  * No locks are obtained or released by this function
2427  *
2428  * RETURN CODES
2429  *
2430  * Returns != 0 upon successful completion.
2431  */
2432
2433 int ADMINAPI bos_HostCreate(
2434   const void *serverHandle,
2435   const char *hostName,
2436   afs_status_p st)
2437 {
2438     int rc = 0;
2439     afs_status_t tst = 0;
2440     bos_server_p b_handle = (bos_server_p) serverHandle;
2441  
2442     if (!isValidServerHandle(b_handle, &tst)) {
2443         goto fail_bos_HostCreate;
2444     }
2445
2446     if ((hostName == NULL) || (*hostName == 0)) {
2447         tst = ADMBOSHOSTNAMENULL;
2448         goto fail_bos_HostCreate;
2449     }
2450  
2451     tst = BOZO_AddCellHost(b_handle->server, hostName);
2452
2453     if (tst == 0) {
2454         rc = 1;
2455     }
2456  
2457 fail_bos_HostCreate:
2458
2459     if (st != NULL) {
2460         *st = tst;
2461     }
2462     return rc;
2463 }
2464  
2465 /*
2466  * bos_HostDelete - delete a host from the cell.
2467  *
2468  * PARAMETERS
2469  *
2470  * IN serverHandle - a previously opened serverHandle.
2471  *
2472  * IN hostName - the host.
2473  *
2474  * LOCKS
2475  *
2476  * No locks are obtained or released by this function
2477  *
2478  * RETURN CODES
2479  *
2480  * Returns != 0 upon successful completion.
2481  */
2482
2483 int ADMINAPI bos_HostDelete(
2484   const void *serverHandle,
2485   const char *hostName,
2486   afs_status_p st)
2487 {
2488     int rc = 0;
2489     afs_status_t tst = 0;
2490     bos_server_p b_handle = (bos_server_p) serverHandle;
2491  
2492     if (!isValidServerHandle(b_handle, &tst)) {
2493         goto fail_bos_HostDelete;
2494     }
2495  
2496     if ((hostName == NULL) || (*hostName == 0)) {
2497         tst = ADMBOSHOSTNAMENULL;
2498         goto fail_bos_HostDelete;
2499     }
2500  
2501     tst = BOZO_DeleteCellHost(b_handle->server, hostName);
2502
2503     if (tst == 0) {
2504         rc = 1;
2505     }
2506
2507 fail_bos_HostDelete:
2508
2509     if (st != NULL) {
2510         *st = tst;
2511     }
2512     return rc;
2513 }
2514
2515 /*
2516  * The iterator functions and data for the host retrieval functions
2517  */
2518
2519 typedef struct host_get {
2520   int next;
2521   struct rx_connection *server;
2522   char host[CACHED_ITEMS][BOS_MAX_NAME_LEN];
2523 } host_get_t, *host_get_p;
2524
2525 static int GetHostRPC(
2526   void *rpc_specific,
2527   int slot,
2528   int *last_item,
2529   int *last_item_contains_data,
2530   afs_status_p st)
2531 {
2532     int rc = 0;
2533     afs_status_t tst = 0;
2534     host_get_p host = (host_get_p) rpc_specific;
2535     char *ptr = (char *) &host->host[slot];
2536
2537     tst = BOZO_GetCellHost(host->server, host->next++, &ptr);
2538
2539     if (tst == 0) {
2540         rc = 1;
2541     } else if (tst == BZDOM) {
2542         tst = 0;
2543         rc = 1;
2544         *last_item = 1;
2545         *last_item_contains_data = 0;
2546     }
2547
2548     if (st != NULL) {
2549         *st = tst;
2550     }
2551     return rc;
2552 }
2553
2554 static int GetHostFromCache(
2555   void *rpc_specific,
2556   int slot,
2557   void *dest,
2558   afs_status_p st)
2559 {
2560     int rc = 0;
2561     afs_status_t tst = 0;
2562     host_get_p host = (host_get_p) rpc_specific;
2563
2564     strcpy((char *) dest, (char *) &host->host[slot]);
2565     rc = 1;
2566
2567     if (st != NULL) {
2568         *st = tst;
2569     }
2570     return rc;
2571 }
2572   
2573 /*
2574  * bos_HostGetBegin - begin iterating over the hosts in a cell
2575  * at a particular bos server.
2576  *
2577  * PARAMETERS
2578  *
2579  * IN serverHandle - a previously opened serverHandle.
2580  *
2581  * OUT iter - an iterator that can be passed to bos_HostGetNext
2582  * to retrieve the process names.
2583  *
2584  * LOCKS
2585  *
2586  * No locks are obtained or released by this function
2587  *
2588  * RETURN CODES
2589  *
2590  * Returns != 0 upon successful completion.
2591  *
2592  */
2593
2594 int ADMINAPI bos_HostGetBegin(
2595   const void *serverHandle,
2596   void **iterationIdP,
2597   afs_status_p st)
2598 {
2599     int rc = 0;
2600     afs_status_t tst = 0;
2601     bos_server_p b_handle = (bos_server_p) serverHandle;
2602     afs_admin_iterator_p iter = (afs_admin_iterator_p) malloc(sizeof(afs_admin_iterator_t));
2603     host_get_p host = (host_get_p) malloc(sizeof(host_get_t));
2604  
2605     if (!isValidServerHandle(b_handle, &tst)) {
2606         goto fail_bos_HostGetBegin;
2607     }
2608  
2609     if (iterationIdP == NULL) {
2610         tst = ADMITERATIONIDPNULL;
2611         goto fail_bos_HostGetBegin;
2612     }
2613
2614     if ((iter == NULL) || (host == NULL)) {
2615         tst = ADMNOMEM;
2616         goto fail_bos_HostGetBegin;
2617     }
2618
2619     host->next = 0;
2620     host->server = b_handle->server;
2621
2622     if (IteratorInit(iter, (void *) host, GetHostRPC,
2623                      GetHostFromCache, NULL, NULL, &tst)) {
2624         *iterationIdP = (void *) iter;
2625         rc = 1;
2626     }
2627
2628 fail_bos_HostGetBegin:
2629
2630     if (rc == 0) {
2631         if (iter != NULL) {
2632             free(iter);
2633         }
2634         if (host != NULL) {
2635             free(host);
2636         }
2637     }
2638
2639     if (st != NULL) {
2640         *st = tst;
2641     }
2642     return rc;
2643 }
2644
2645 /*
2646  * bos_HostGetNext - retrieve the next host 
2647  * from the bos server.
2648  *
2649  * PARAMETERS
2650  *
2651  * IN iterationId - an iterator previously returned by 
2652  * bos_HostGetBegin
2653  *
2654  * OUT hostName - upon successful completion contains the next host
2655  * retrieved from the server.
2656  *
2657  * LOCKS
2658  *
2659  * No locks are obtained or released by this function
2660  *
2661  * RETURN CODES
2662  *
2663  * Returns != 0 upon successful completion.
2664  *
2665  */
2666
2667 int ADMINAPI bos_HostGetNext(
2668   const void *iterationId,
2669   char *hostName,
2670   afs_status_p st)
2671 {
2672     int rc = 0;
2673     afs_status_t tst = 0;
2674     afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
2675  
2676     if (iterationId == NULL) {
2677         tst = ADMITERATIONIDPNULL;
2678         goto fail_bos_HostGetNext;
2679     }
2680  
2681     if (hostName == NULL) {
2682         tst = ADMBOSHOSTNAMENULL;
2683         goto fail_bos_HostGetNext;
2684     }
2685
2686     rc = IteratorNext(iter, (void *) hostName, &tst);
2687
2688 fail_bos_HostGetNext:
2689
2690     if (st != NULL) {
2691         *st = tst;
2692     }
2693     return rc;
2694 }
2695
2696 /*
2697  * bos_HostGetDone - finish using a host iterator.
2698  *
2699  * PARAMETERS
2700  *
2701  * IN iterationId - an iterator previously returned by
2702  * bos_HostGetBegin
2703  *
2704  * LOCKS
2705  *
2706  * No locks are obtained or released by this function
2707  *
2708  * RETURN CODES
2709  *
2710  * Returns != 0 upon successful completion.
2711  *
2712  */
2713
2714 int ADMINAPI bos_HostGetDone(
2715   const void *iterationId,
2716   afs_status_p st)
2717 {
2718     int rc = 0;
2719     afs_status_t tst = 0;
2720     afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
2721  
2722     if (iterationId == NULL) {
2723         tst = ADMITERATIONIDPNULL;
2724         goto fail_bos_HostGetDone;
2725     }
2726
2727     rc = IteratorDone(iter, &tst);
2728
2729 fail_bos_HostGetDone:
2730
2731     if (st != NULL) {
2732         *st = tst;
2733     }
2734     return rc;
2735 }
2736
2737 /*
2738  * bos_ExecutableCreate - create a new executable at the bos server.
2739  *
2740  * PARAMETERS
2741  *
2742  * IN serverHandle - a previously opened serverHandle.
2743  *
2744  * IN sourceFile - the executable to install at the bos server.
2745  *
2746  * IN destFile - the location where the executable will be installed.
2747  *
2748  * LOCKS
2749  *
2750  * No locks are obtained or released by this function
2751  *
2752  * RETURN CODES
2753  *
2754  * Returns != 0 upon successful completion.
2755  *
2756  */
2757
2758 int ADMINAPI bos_ExecutableCreate(
2759   const void *serverHandle,
2760   const char *sourceFile,
2761   const char *destFile,
2762   afs_status_p st)
2763 {
2764     int rc = 0;
2765     afs_status_t tst = 0;
2766     bos_server_p b_handle = (bos_server_p) serverHandle;
2767     int fd;
2768     struct stat estat;
2769     struct rx_call *tcall;
2770  
2771     /*
2772      * Validate arguments
2773      */
2774
2775     if (!isValidServerHandle(b_handle, &tst)) {
2776         goto fail_bos_ExecutableCreate;
2777     }
2778
2779     if ((sourceFile == NULL) || (*sourceFile == 0)) {
2780         tst = ADMBOSSOURCEFILENULL;
2781         goto fail_bos_ExecutableCreate;
2782     }
2783
2784     if ((destFile == NULL) || (*destFile == 0)) {
2785         tst = ADMBOSDESTFILENULL;
2786         goto fail_bos_ExecutableCreate;
2787     }
2788
2789     /*
2790      * Open the file locally and compute its size
2791      */
2792
2793     fd = open(sourceFile, O_RDONLY);
2794
2795     if (fd < 0) {
2796         tst = ADMBOSCANTOPENSOURCEFILE;
2797         goto fail_bos_ExecutableCreate;
2798     }
2799
2800     if (fstat(fd, &estat)) {
2801         tst = ADMBOSCANTSTATSOURCEFILE;
2802         goto fail_bos_ExecutableCreate;
2803     }
2804
2805     /*
2806      * Start a split rpc to the bos server.
2807      */
2808
2809     tcall = rx_NewCall(b_handle->server);
2810
2811     tst = StartBOZO_Install(tcall, destFile, estat.st_size,
2812                             (afs_int32) estat.st_mode, estat.st_mtime);
2813     
2814     if (tst) {
2815         rx_EndCall(tcall, tst);
2816         goto fail_bos_ExecutableCreate;
2817     }
2818
2819     /*
2820      * Copy the data to the server
2821      */
2822
2823     while(1) {
2824         char tbuffer[512];
2825         size_t len;
2826         len = read(fd, tbuffer, sizeof(tbuffer));
2827         if (len < 0) {
2828             tst = ADMBOSCANTREADSOURCEFILE;
2829             rx_EndCall(tcall, len);
2830             goto fail_bos_ExecutableCreate;
2831         }
2832         if (len == 0) {
2833             tst = 0;
2834             break;
2835         }
2836         tst = rx_Write(tcall, tbuffer, len);
2837         if (tst != len) {
2838             tst = ADMBOSSENDSOURCEFILE;
2839             rx_EndCall(tcall, tst);
2840             goto fail_bos_ExecutableCreate;
2841         }
2842     }
2843
2844     /*
2845      * Terminate the rpc to the server
2846      */
2847
2848     tst = rx_EndCall(tcall, tst);
2849
2850     if (tst == 0) {
2851         rc = 1;
2852     }
2853
2854 fail_bos_ExecutableCreate:
2855
2856     if (st != NULL) {
2857         *st = tst;
2858     }
2859     return rc;
2860 }
2861
2862 /*
2863  * bos_ExecutableRevert - revert an executable to a previous .BAK version.
2864  *
2865  * PARAMETERS
2866  *
2867  * IN serverHandle - a previously opened serverHandle.
2868  *
2869  * IN execFile - the executable to revert at the bos server.
2870  *
2871  * LOCKS
2872  *
2873  * No locks are obtained or released by this function
2874  *
2875  * RETURN CODES
2876  *
2877  * Returns != 0 upon successful completion.
2878  *
2879  */
2880
2881 int ADMINAPI bos_ExecutableRevert(
2882   const void *serverHandle,
2883   const char *execFile,
2884   afs_status_p st)
2885 {
2886     int rc = 0;
2887     afs_status_t tst = 0;
2888     bos_server_p b_handle = (bos_server_p) serverHandle;
2889  
2890     if (!isValidServerHandle(b_handle, &tst)) {
2891         goto fail_bos_ExecutableRevert;
2892     }
2893
2894     if ((execFile == NULL) || (*execFile == 0)) {
2895         tst = ADMBOSEXECFILENULL;
2896         goto fail_bos_ExecutableRevert;
2897     }
2898
2899     tst = BOZO_UnInstall(b_handle->server, execFile);
2900
2901     if (tst == 0) {
2902         rc = 1;
2903     }
2904
2905 fail_bos_ExecutableRevert:
2906
2907     if (st != NULL) {
2908         *st = tst;
2909     }
2910     return rc;
2911 }
2912
2913 /*
2914  * bos_ExecutableTimestampGet - get the last mod times for an executable,
2915  * the .BAK version of the executable, and the .OLD version of the
2916  * executable if they exist.
2917  *
2918  * PARAMETERS
2919  *
2920  * IN serverHandle - a previously opened serverHandle.
2921  *
2922  * IN execFile - the executable to revert at the bos server.
2923  *
2924  * LOCKS
2925  *
2926  * No locks are obtained or released by this function
2927  *
2928  * RETURN CODES
2929  *
2930  * Returns != 0 upon successful completion.
2931  *
2932  */
2933
2934 int ADMINAPI bos_ExecutableTimestampGet(
2935   const void *serverHandle,
2936   const char *execFile,
2937   unsigned long *newTime,
2938   unsigned long *oldTime,
2939   unsigned long *bakTime,
2940   afs_status_p st)
2941 {
2942     int rc = 0;
2943     afs_status_t tst = 0;
2944     bos_server_p b_handle = (bos_server_p) serverHandle;
2945  
2946     if (!isValidServerHandle(b_handle, &tst)) {
2947         goto fail_bos_ExecutableTimestampGet;
2948     }
2949  
2950     if ((execFile == NULL) || (*execFile == 0)) {
2951         tst = ADMBOSEXECFILENULL;
2952         goto fail_bos_ExecutableTimestampGet;
2953     }
2954
2955     if (newTime == NULL) {
2956         tst = ADMBOSNEWTIMENULL;
2957         goto fail_bos_ExecutableTimestampGet;
2958     }
2959
2960     if (oldTime == NULL) {
2961         tst = ADMBOSOLDTIMENULL;
2962         goto fail_bos_ExecutableTimestampGet;
2963     }
2964
2965     if (bakTime == NULL) {
2966         tst = ADMBOSBAKTIMENULL;
2967         goto fail_bos_ExecutableTimestampGet;
2968     }
2969  
2970     tst = BOZO_GetDates(b_handle->server, execFile, newTime, bakTime, oldTime);
2971
2972     if (tst == 0) {
2973         rc = 1;
2974     }
2975  
2976 fail_bos_ExecutableTimestampGet:
2977
2978     if (st != NULL) {
2979         *st = tst;
2980     }
2981     return rc;
2982 }
2983
2984 /*
2985  * bos_ExecutablePrune - prune the bak, old, and core files off a server
2986  * machine.
2987  *
2988  * PARAMETERS
2989  *
2990  * IN serverHandle - a previously opened serverHandle.
2991  *
2992  * IN oldFiles - prune .OLD files.
2993  *
2994  * IN bakFiles - prune .BAK files.
2995  *
2996  * IN coreFiles - prune core files.
2997  *
2998  * LOCKS
2999  *
3000  * No locks are obtained or released by this function
3001  *
3002  * RETURN CODES
3003  *
3004  * Returns != 0 upon successful completion.
3005  *
3006  */
3007
3008 int ADMINAPI bos_ExecutablePrune(
3009   const void *serverHandle,
3010   bos_Prune_t oldFiles,
3011   bos_Prune_t bakFiles,
3012   bos_Prune_t coreFiles,
3013   afs_status_p st)
3014 {
3015     int rc = 0;
3016     afs_status_t tst = 0;
3017     bos_server_p b_handle = (bos_server_p) serverHandle;
3018     afs_int32 flags = 0;
3019  
3020     if (!isValidServerHandle(b_handle, &tst)) {
3021         goto fail_bos_ExecutablePrune;
3022     }
3023
3024     if (oldFiles == BOS_PRUNE) {
3025         flags |= BOZO_PRUNEOLD;
3026     }
3027
3028     if (bakFiles == BOS_PRUNE) {
3029         flags |= BOZO_PRUNEBAK;
3030     }
3031
3032     if (coreFiles == BOS_PRUNE) {
3033         flags |= BOZO_PRUNECORE;
3034     }
3035
3036     tst = BOZO_Prune(b_handle->server, flags);
3037
3038     if (tst == 0) {
3039         rc = 1;
3040     }
3041  
3042 fail_bos_ExecutablePrune:
3043
3044     if (st != NULL) {
3045         *st = tst;
3046     }
3047     return rc;
3048 }
3049
3050 /*
3051  * bos_ExecutableRestartTimeSet - set the restart time of the bos server
3052  * machine.
3053  *
3054  * PARAMETERS
3055  *
3056  * IN serverHandle - a previously opened serverHandle.
3057  *
3058  * IN type - specifies either weekly restart or daily restart time.
3059  *
3060  * IN time - the time to begin restarts.
3061  *
3062  * LOCKS
3063  *
3064  * No locks are obtained or released by this function
3065  *
3066  * RETURN CODES
3067  *
3068  * Returns != 0 upon successful completion.
3069  *
3070  */
3071
3072 int ADMINAPI bos_ExecutableRestartTimeSet(
3073   const void *serverHandle,
3074   bos_Restart_t type,
3075   bos_RestartTime_t time,
3076   afs_status_p st)
3077 {
3078     int rc = 0;
3079     afs_status_t tst = 0;
3080     bos_server_p b_handle = (bos_server_p) serverHandle;
3081     afs_int32 restartType = 0;
3082     struct ktime restartTime;
3083  
3084     if (!isValidServerHandle(b_handle, &tst)) {
3085         goto fail_bos_ExecutableRestartTimeSet;
3086     }
3087  
3088     if (type == BOS_RESTART_WEEKLY) {
3089         restartType = 1;
3090     } else {
3091         restartType = 2;
3092     }
3093
3094     if ((time.mask & BOS_RESTART_TIME_HOUR) &&
3095         ((time.hour < 0) || (time.hour > 23))) {
3096         tst = ADMBOSHOURINVALID;
3097         goto fail_bos_ExecutableRestartTimeSet;
3098     }
3099
3100     if ((time.mask & BOS_RESTART_TIME_MINUTE) &&
3101         ((time.min < 0) || (time.min > 60))) {
3102         tst = ADMBOSMINUTEINVALID;
3103         goto fail_bos_ExecutableRestartTimeSet;
3104     }
3105
3106     if ((time.mask & BOS_RESTART_TIME_SECOND) &&
3107         ((time.sec < 0) || (time.sec > 60))) {
3108         tst = ADMBOSSECONDINVALID;
3109         goto fail_bos_ExecutableRestartTimeSet;
3110     }
3111
3112     if ((time.mask & BOS_RESTART_TIME_DAY) &&
3113         ((time.day < 0) || (time.day > 6))) {
3114         tst = ADMBOSDAYINVALID;
3115         goto fail_bos_ExecutableRestartTimeSet;
3116     }
3117
3118     restartTime.mask = time.mask;
3119     restartTime.hour = time.hour;
3120     restartTime.min = time.min;
3121     restartTime.sec = time.sec;
3122     restartTime.day = time.day;
3123
3124     tst = BOZO_SetRestartTime(b_handle->server, restartType, &restartTime);
3125
3126     if (tst == 0) {
3127         rc = 1;
3128     }
3129  
3130 fail_bos_ExecutableRestartTimeSet:
3131
3132     if (st != NULL) {
3133         *st = tst;
3134     }
3135     return rc;
3136 }
3137
3138 /*
3139  * bos_ExecutableRestartTimeGet - get the restart time of the bos server
3140  * machine.
3141  *
3142  * PARAMETERS
3143  *
3144  * IN serverHandle - a previously opened serverHandle.
3145  *
3146  * IN type - specifies either weekly restart or daily restart time.
3147  *
3148  * OUT timeP - the time to begin restarts.
3149  *
3150  * LOCKS
3151  *
3152  * No locks are obtained or released by this function
3153  *
3154  * RETURN CODES
3155  *
3156  * Returns != 0 upon successful completion.
3157  *
3158  */
3159
3160 int ADMINAPI bos_ExecutableRestartTimeGet(
3161   const void *serverHandle,
3162   bos_Restart_t type,
3163   bos_RestartTime_p timeP,
3164   afs_status_p st)
3165 {
3166     int rc = 0;
3167     afs_status_t tst = 0;
3168     bos_server_p b_handle = (bos_server_p) serverHandle;
3169     afs_int32 restartType = 0;
3170     struct ktime restartTime;
3171  
3172     if (!isValidServerHandle(b_handle, &tst)) {
3173         goto fail_bos_ExecutableRestartTimeGet;
3174     }
3175
3176     if (timeP == NULL) {
3177         tst = ADMBOSTIMEPNULL;
3178         goto fail_bos_ExecutableRestartTimeGet;
3179     }
3180  
3181     if (type == BOS_RESTART_WEEKLY) {
3182         restartType = 1;
3183     } else {
3184         restartType = 2;
3185     }
3186
3187     tst = BOZO_GetRestartTime(b_handle->server, restartType, &restartTime);
3188
3189     if (tst != 0) {
3190         goto fail_bos_ExecutableRestartTimeGet;
3191     }
3192
3193     timeP->mask = restartTime.mask;
3194     timeP->hour = restartTime.hour;
3195     timeP->min = restartTime.min;
3196     timeP->sec = restartTime.sec;
3197     timeP->day = restartTime.day;
3198     rc = 1;
3199  
3200 fail_bos_ExecutableRestartTimeGet:
3201
3202     if (st != NULL) {
3203         *st = tst;
3204     }
3205     return rc;
3206 }
3207
3208 /*
3209  * bos_LogGet - get a log file from the bos server machine.
3210  *
3211  * PARAMETERS
3212  *
3213  * IN serverHandle - a previously opened serverHandle.
3214  *
3215  * IN log - the log file to retrieve.
3216  *
3217  * IN/OUT logBufferSizeP - the length of the logData buffer on input,
3218  * and upon successful completion, the length of data stored in the buffer.
3219  *
3220  * OUT logData - the retrieved data upon successful completion.
3221  *
3222  * LOCKS
3223  *
3224  * No locks are obtained or released by this function
3225  *
3226  * RETURN CODES
3227  *
3228  * Returns != 0 upon successful completion.
3229  *
3230  */
3231
3232 int ADMINAPI bos_LogGet(
3233   const void *serverHandle,
3234   const char *log,
3235   unsigned long *logBufferSizeP,
3236   char *logData,
3237   afs_status_p st)
3238 {
3239     int rc = 0;
3240     afs_status_t tst = 0;
3241     bos_server_p b_handle = (bos_server_p) serverHandle;
3242     struct rx_call *tcall = NULL;
3243     afs_int32 error;
3244     char buffer;
3245     int have_call = 0;
3246     unsigned long bytes_read = 0;
3247  
3248     /*
3249      * Validate parameters
3250      */
3251
3252     if (!isValidServerHandle(b_handle, &tst)) {
3253         goto fail_bos_LogGet;
3254     }
3255
3256     if ((log == NULL) || (*log == 0)) {
3257         tst = ADMBOSLOGNULL;
3258         goto fail_bos_LogGet;
3259     }
3260
3261     if (logBufferSizeP == NULL) {
3262         tst = ADMBOSLOGBUFFERSIZEPNULL;
3263         goto fail_bos_LogGet;
3264     }
3265
3266     if (logData == NULL) {
3267         tst = ADMBOSLOGDATANULL;
3268         goto fail_bos_LogGet;
3269     }
3270
3271     /*
3272      * Begin to retrieve the data
3273      */
3274
3275     tcall = rx_NewCall(b_handle->server);
3276     have_call = 1;
3277     tst = StartBOZO_GetLog(tcall, log);
3278
3279     if (tst != 0) {
3280         goto fail_bos_LogGet;
3281     }
3282
3283     /*
3284      * Read the log file data
3285      */
3286
3287     while (1) {
3288         error = rx_Read(tcall, &buffer, 1);
3289         if (error != 1) {
3290             tst = ADMBOSLOGFILEERROR;
3291             goto fail_bos_LogGet;
3292         }
3293
3294         /*
3295          * check for the end of the log
3296          */
3297
3298         if (buffer == 0) {
3299             *logBufferSizeP = bytes_read;
3300             break;
3301         }
3302
3303         /*
3304          * We've successfully read another byte, copy it to logData
3305          * if there's room
3306          */
3307
3308         bytes_read++;
3309         if (bytes_read <= *logBufferSizeP) {
3310             *logData++ = buffer;
3311         } else {
3312            tst = ADMMOREDATA;
3313         }
3314     }
3315     if (tst == 0) {
3316         rc = 1;
3317     }
3318  
3319 fail_bos_LogGet:
3320
3321     if (have_call) {
3322         rx_EndCall(tcall, 0);
3323     }
3324
3325     if (st != NULL) {
3326         *st = tst;
3327     }
3328     return rc;
3329 }
3330
3331 /*
3332  * bos_AuthSet - set the authorization level required at the bos server.
3333  *
3334  * PARAMETERS
3335  *
3336  * IN serverHandle - a previously opened serverHandle.
3337  *
3338  * IN auth - specifies the new auth level.
3339  *
3340  * LOCKS
3341  *
3342  * No locks are obtained or released by this function
3343  *
3344  * RETURN CODES
3345  *
3346  * Returns != 0 upon successful completion.
3347  *
3348  */
3349
3350 int ADMINAPI bos_AuthSet(
3351   const void *serverHandle,
3352   bos_Auth_t auth,
3353   afs_status_p st)
3354 {
3355     int rc = 0;
3356     afs_status_t tst = 0;
3357     bos_server_p b_handle = (bos_server_p) serverHandle;
3358     afs_int32 level = 0;
3359  
3360     if (!isValidServerHandle(b_handle, &tst)) {
3361         goto fail_bos_AuthSet;
3362     }
3363
3364     if (auth == BOS_AUTH_REQUIRED) {
3365         level = 0;
3366     } else {
3367         level = 1;
3368     }
3369  
3370     tst = BOZO_SetNoAuthFlag(b_handle->server, level);
3371
3372     if (tst == 0) {
3373         rc = 1;
3374     }
3375
3376 fail_bos_AuthSet:
3377
3378     if (st != NULL) {
3379         *st = tst;
3380     }
3381     return rc;
3382 }
3383
3384 /*
3385  * bos_CommandExecute - execute a command at the bos server.
3386  *
3387  * PARAMETERS
3388  *
3389  * IN serverHandle - a previously opened serverHandle.
3390  *
3391  * IN command - the command to execute.
3392  *
3393  * LOCKS
3394  *
3395  * No locks are obtained or released by this function
3396  *
3397  * RETURN CODES
3398  *
3399  * Returns != 0 upon successful completion.
3400  *
3401  */
3402
3403 int ADMINAPI bos_CommandExecute(
3404   const void *serverHandle,
3405   const char *command,
3406   afs_status_p st)
3407 {
3408     int rc = 0;
3409     afs_status_t tst = 0;
3410     bos_server_p b_handle = (bos_server_p) serverHandle;
3411  
3412     if (!isValidServerHandle(b_handle, &tst)) {
3413         goto fail_bos_CommandExecute;
3414     }
3415
3416     if ((command == NULL) || (*command == 0)) {
3417         tst = ADMBOSCOMMANDNULL;
3418         goto fail_bos_CommandExecute;
3419     }
3420  
3421     tst = BOZO_Exec(b_handle->server, command);
3422
3423     if (tst == 0) {
3424         rc = 1;
3425     }
3426
3427 fail_bos_CommandExecute:
3428
3429     if (st != NULL) {
3430         *st = tst;
3431     }
3432     return rc;
3433 }
3434
3435 /*
3436  * bos_Salvage - perform a remote salvage operation.
3437  *
3438  * PARAMETERS
3439  *
3440  * IN cellHandle - a previously opened cellHandle.
3441  *
3442  * IN serverHandle - a previously opened serverHandle.
3443  *
3444  * IN partitionName - the partition to salvage.  Can be null.
3445  *
3446  * IN volumeName - the volume to salvage.  Can be null, if non-null,
3447  * partitionName cannot be null.
3448  *
3449  * IN numSalvagers - the number of salvage processes to run in parallel.
3450  *
3451  * IN tmpDir - directory to place temporary files.  Can be null.
3452  *
3453  * IN logFile - file where salvage log will be written.  Can be null.
3454  *
3455  * IN force - sets salvager -force flag.
3456  *
3457  * IN salvageDamagedVolumes - sets salvager -oktozap flag.
3458  *
3459  * IN writeInodes - sets salvager -inodes flag.
3460  *
3461  * IN writeRootInodes - sets salvager -rootinodes flag.
3462  *
3463  * IN forceDirectory - sets salvager -salvagedirs flag.
3464  *
3465  * IN forceBlockRead - sets salvager -blockread flag.
3466  *
3467  * LOCKS
3468  *
3469  * No locks are obtained or released by this function
3470  *
3471  * RETURN CODES
3472  *
3473  * Returns != 0 upon successful completion.
3474  *
3475  */
3476
3477 #define INITIAL_LOG_LEN 4096
3478
3479 int ADMINAPI bos_Salvage(
3480   const void *cellHandle,
3481   const void *serverHandle,
3482   const char *partitionName,
3483   const char *volumeName,
3484   int numSalvagers,
3485   const char *tmpDir,
3486   const char *logFile,
3487   vos_force_t force,
3488   bos_SalvageDamagedVolumes_t salvageDamagedVolumes,
3489   bos_WriteInodes_t writeInodes,
3490   bos_WriteRootInodes_t writeRootInodes,
3491   bos_ForceDirectory_t forceDirectory,
3492   bos_ForceBlockRead_t forceBlockRead,
3493   afs_status_p st)
3494 {
3495     int rc = 0;
3496     afs_status_t tst = 0;
3497     bos_server_p b_handle = (bos_server_p) serverHandle;
3498     afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
3499     int have_partition = 0;
3500     int have_volume = 0;
3501     unsigned int part = 0;
3502     int try_to_stop_fileserver = 0;
3503     bos_ProcessType_t procType;
3504     bos_ProcessInfo_t procInfo;
3505     FILE *log = NULL;
3506     char command[BOS_MAX_NAME_LEN];
3507     int command_len = 0;
3508     int poll_rc;
3509     char *logData = NULL;
3510     unsigned long logLen = INITIAL_LOG_LEN;
3511  
3512     /*
3513      * Validate arguments
3514      */
3515
3516     if (!IsValidCellHandle(c_handle, &tst)) {
3517         goto fail_bos_Salvage;
3518     }
3519
3520     if (!isValidServerHandle(b_handle, &tst)) {
3521         goto fail_bos_Salvage;
3522     }
3523
3524     if (c_handle->vos_valid == 0) {
3525         tst = ADMBOSCELLHANDLENOVOS;
3526         goto fail_bos_Salvage;
3527     }
3528
3529     if ((partitionName != NULL) && (*partitionName != 0)) {
3530         if (!vos_PartitionNameToId(partitionName, &part, &tst)) {
3531             goto fail_bos_Salvage;
3532         }
3533         have_partition = 1;
3534     }
3535
3536     if ((volumeName != NULL) && (*volumeName != 0)) {
3537         if (!have_partition) {
3538             tst = ADMBOSSALVAGEVOLUME;
3539             goto fail_bos_Salvage;
3540         }
3541         have_volume = 1;
3542     }
3543
3544     if ((logFile != NULL) && (*logFile != 0)) {
3545         log = fopen(logFile, "w");
3546         if (!log) {
3547             tst = ADMBOSSALVAGEBADLOG;
3548             goto fail_bos_Salvage;
3549         }
3550     }
3551
3552     /*
3553      * If we are salvaging more than a single volume, stop the fileserver
3554      */
3555
3556     if (!have_volume) {
3557         try_to_stop_fileserver = 1;
3558     }
3559
3560     /*
3561      * Only try to stop the fileserver if it is running
3562      */
3563
3564     if (try_to_stop_fileserver) {
3565         if (bos_ProcessInfoGet(serverHandle, "fs", &procType, &procInfo,
3566                                 &tst)) {
3567             if (procInfo.processGoal != BOS_PROCESS_RUNNING) {
3568                try_to_stop_fileserver = 0;
3569             }
3570         }
3571     }
3572
3573     /*
3574      * Make the call to stop the fileserver and wait for it to shutdown
3575      */
3576
3577     if (try_to_stop_fileserver) {
3578         if (!bos_ProcessExecutionStateSetTemporary(serverHandle, "fs",
3579                                                    BOS_PROCESS_STOPPED,
3580                                                    &tst)) {
3581             goto fail_bos_Salvage;
3582         }
3583         bos_ProcessAllWaitTransition(serverHandle, &tst);
3584     }
3585
3586     /*
3587      * Create the salvage command line arguments
3588      */
3589
3590     command_len = sprintf(command, "%s ",
3591                           AFSDIR_CANONICAL_SERVER_SALVAGER_FILEPATH);
3592     if (have_partition) {
3593         command_len += sprintf(&command[command_len], "-partition %s ",
3594                                partitionName);
3595     }
3596
3597     if (have_volume) {
3598         command_len += sprintf(&command[command_len], "-volumeid %s ",
3599                                volumeName);
3600     }
3601
3602     if (salvageDamagedVolumes == BOS_DONT_SALVAGE_DAMAGED_VOLUMES) {
3603         command_len += sprintf(&command[command_len], "-nowrite ");
3604     }
3605
3606     if (writeInodes == BOS_SALVAGE_WRITE_INODES) {
3607         command_len += sprintf(&command[command_len], "-inodes ");
3608     }
3609
3610     if (force == VOS_FORCE) {
3611         command_len += sprintf(&command[command_len], "-force ");
3612     }
3613
3614     if (writeRootInodes == BOS_SALVAGE_WRITE_ROOT_INODES) {
3615         command_len += sprintf(&command[command_len], "-rootinodes ");
3616     }
3617
3618     if (forceDirectory == BOS_SALVAGE_FORCE_DIRECTORIES) {
3619         command_len += sprintf(&command[command_len], "-salvagedirs ");
3620     }
3621
3622     if (forceBlockRead == BOS_SALVAGE_FORCE_BLOCK_READS) {
3623         command_len += sprintf(&command[command_len], "-blockreads ");
3624     }
3625
3626     command_len += sprintf(&command[command_len], "-parallel %d ", numSalvagers);
3627
3628     if ((tmpDir != NULL) && (*tmpDir != 0)) {
3629         command_len += sprintf(&command[command_len], "-tmpdir %s ", tmpDir);
3630     }
3631
3632     if (command_len > BOS_MAX_NAME_LEN) {
3633         tst = ADMBOSSALVAGEBADOPTIONS;
3634         goto fail_bos_Salvage;
3635     }
3636
3637     /*
3638      * Create the process at the bosserver and wait until it completes
3639      */
3640
3641     if (!bos_ProcessCreate(serverHandle, "salvage-tmp", BOS_PROCESS_CRON,
3642                            command, "now", 0, &tst)) {
3643         goto fail_bos_Salvage;
3644     }
3645
3646     while ((poll_rc = bos_ProcessInfoGet(serverHandle, "salvage-tmp", &procType,
3647                                         &procInfo, &tst))) {
3648         sleep(5);
3649     }
3650
3651     if (tst != BZNOENT) {
3652         goto fail_bos_Salvage;
3653     }
3654
3655     /*
3656      * Print out the salvage log if required by the user
3657      */
3658
3659     if (log != NULL) {
3660
3661         logData = (char *) malloc(INITIAL_LOG_LEN);
3662         if (!logData) {
3663             tst = ADMNOMEM;
3664             goto fail_bos_Salvage;
3665         }
3666
3667         while(!bos_LogGet(serverHandle,
3668                           AFSDIR_CANONICAL_SERVER_SLVGLOG_FILEPATH,
3669                           &logLen, logData, &tst)) {
3670             if (logLen > INITIAL_LOG_LEN) {
3671                 logData = (char *) realloc(logData, (logLen + (logLen / 10)));
3672                 if (logData == NULL) {
3673                     tst = ADMNOMEM;
3674                     goto fail_bos_Salvage;
3675                 }
3676             } else {
3677                 goto fail_bos_Salvage;
3678             }
3679         }
3680         fprintf(log, "SalvageLog:\n%s", logData);
3681     }
3682
3683     /*
3684      * Restart the fileserver if we had stopped it previously
3685      */
3686
3687     if (try_to_stop_fileserver) {
3688         try_to_stop_fileserver = 0;
3689         if (!bos_ProcessExecutionStateSetTemporary(serverHandle, "fs",
3690                                                    BOS_PROCESS_RUNNING,
3691                                                    &tst)) {
3692             goto fail_bos_Salvage;
3693         }
3694     }
3695     rc = 1;
3696
3697 fail_bos_Salvage:
3698
3699     if (log != NULL) {
3700         fclose(log);
3701     }
3702
3703     if (logData != NULL) {
3704         free(logData);
3705     }
3706
3707     if (try_to_stop_fileserver) {
3708         bos_ProcessExecutionStateSetTemporary(serverHandle, "fs",
3709                                               BOS_PROCESS_RUNNING, 0);
3710     }
3711
3712     if (st != NULL) {
3713         *st = tst;
3714     }
3715     return rc;
3716 }