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