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