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