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