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