threaded-logging-20050619
[openafs.git] / src / viced / viced.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 /*  viced.c     - File Server main loop                                  */
11 /*                                                                       */
12 /*  Date: 5/1/85                                                         */
13 /*                                                                       */
14 /*  Function    - This routine has the initialization code for           */
15 /*                FileServer II                                          */
16 /*                                                                       */
17 /* ********************************************************************** */
18
19 #include <afsconfig.h>
20 #include <afs/param.h>
21
22 RCSID
23     ("$Header$");
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <errno.h>
28 #include <sys/types.h>
29 #include <afs/procmgmt.h>       /* signal(), kill(), wait(), etc. */
30 #include <sys/stat.h>
31 #ifdef AFS_NT40_ENV
32 #include <fcntl.h>
33 #include <io.h>
34 #include <windows.h>
35 #include <WINNT/afsevent.h>
36 #else
37 #include <sys/file.h>
38 #include <netinet/in.h>
39 #include <netdb.h>
40 #include <unistd.h>             /* sysconf() */
41
42 #ifdef HAVE_STRING_H
43 #include <string.h>
44 #else
45 #ifdef HAVE_STRINGS_H
46 #include <strings.h>
47 #endif
48 #endif
49
50 #ifndef ITIMER_REAL
51 #include <sys/time.h>
52 #endif /* ITIMER_REAL */
53 #include <sys/resource.h>
54 #endif /* AFS_NT40_ENV */
55 #include <afs/stds.h>
56 #undef SHARED
57 #include <rx/xdr.h>
58 #include <afs/nfs.h>
59 #ifdef AFS_PTHREAD_ENV
60 #include <assert.h>
61 #else /* AFS_PTHREAD_ENV */
62 #include <afs/assert.h>
63 #endif /* AFS_PTHREAD_ENV */
64 #include <lwp.h>
65 #include <lock.h>
66 #include <afs/ptclient.h>
67 #include <afs/afsint.h>
68 #include <afs/vldbint.h>
69 #include <afs/errors.h>
70 #include <afs/ihandle.h>
71 #include <afs/vnode.h>
72 #include <afs/volume.h>
73 #include <afs/auth.h>
74 #include <afs/cellconfig.h>
75 #include <afs/acl.h>
76 #include <afs/prs_fs.h>
77 #include <rx/rx.h>
78 #include <rx/rxkad.h>
79 #include <afs/keys.h>
80 #include <afs/afs_args.h>
81 #include <afs/vlserver.h>
82 #include <afs/afsutil.h>
83 #include <afs/fileutil.h>
84 #ifndef AFS_NT40_ENV
85 #include <afs/netutils.h>
86 #endif
87 #include "viced.h"
88 #include "host.h"
89 #ifdef AFS_PTHREAD_ENV
90 #include "softsig.h"
91 #endif
92 #if defined(AFS_SGI_ENV)
93 #include "sys/schedctl.h"
94 #include "sys/lock.h"
95 #endif
96 #include <rx/rx_globals.h>
97
98 #ifdef O_LARGEFILE
99 #define afs_stat        stat64
100 #define afs_fstat       fstat64
101 #define afs_open        open64
102 #define afs_fopen       fopen64
103 #else /* !O_LARGEFILE */
104 #define afs_stat        stat
105 #define afs_fstat       fstat
106 #define afs_open        open
107 #define afs_fopen       fopen
108 #endif /* !O_LARGEFILE */
109
110 extern int BreakVolumeCallBacks(), InitCallBack();
111 extern int BreakVolumeCallBacks(), InitCallBack(), BreakLaterCallBacks();
112 extern int BreakVolumeCallBacksLater();
113 extern int LogLevel, etext;
114 extern afs_int32 BlocksSpare, PctSpare;
115
116 void ShutDown(void);
117 static void ClearXStatValues(), NewParms(), PrintCounters();
118 static void ResetCheckDescriptors(void), ResetCheckSignal(void);
119 static void CheckSignal(void);
120 extern int GetKeysFromToken();
121 extern int RXAFS_ExecuteRequest();
122 extern int RXSTATS_ExecuteRequest();
123 afs_int32 Do_VLRegisterRPC();
124
125 int eventlog = 0, rxlog = 0;
126 FILE *debugFile;
127 FILE *console = NULL;
128
129 #ifdef AFS_PTHREAD_ENV
130 pthread_mutex_t fsync_glock_mutex;
131 pthread_cond_t fsync_cond;
132 #else
133 char fsync_wait[1];
134 #endif /* AFS_PTHREAD_ENV */
135
136 #ifdef AFS_NT40_ENV
137 #define AFS_QUIETFS_ENV 1
138 #define NT_OPEN_MAX    1024     /* This is an arbitrary no. we came up with for 
139                                  * now. We hope this will be replaced by a more
140                                  * intelligent estimate later. */
141 #endif
142
143 int SystemId;                   /* ViceID of "Administrators" */
144 int SystemAnyUser;              /* Viceid of "System:AnyUser" */
145 prlist SystemAnyUserCPS;        /* CPS for "system:AnyUser */
146 int AnonymousID = 0;            /* ViceId of "Anonymous" */
147 prlist AnonCPS;                 /* CPS for "Anonymous" */
148
149 struct afsconf_dir *confDir;    /* Configuration dir object */
150
151 int restartMode = RESTART_ORDINARY;
152
153 int Testing = 0;                /* for ListViceInodes */
154
155 /*
156  * Home for the performance statistics.
157  */
158 struct afs_PerfStats afs_perfstats;
159
160 extern int LogLevel;
161 extern int Statistics;
162
163 int busyonrst = 1;
164 int timeout = 30;
165 int SawSpare;
166 int SawPctSpare;
167 int debuglevel = 0;
168 int printBanner = 0;
169 int rxJumbograms = 1;           /* default is to send and receive jumbograms. */
170 afs_int32 implicitAdminRights = PRSFS_LOOKUP;   /* The ADMINISTER right is 
171                                                  * already implied */
172 afs_int32 readonlyServer = 0;
173
174 int stack = 24;
175 int stackSize = 24000;
176 int fiveminutes = 300;          /* 5 minutes.  Change this for debugging only */
177 int CurrentConnections = 0;
178 int hostaclRefresh = 7200;      /* refresh host clients' acls every 2 hrs */
179 #if defined(AFS_SGI_ENV)
180 int SawLock;
181 #endif
182 time_t StartTime;
183
184 int rxpackets = 150;            /* 100 */
185 int nSmallVns = 400;            /* 200 */
186 int large = 400;                /* 200 */
187 int volcache = 400;             /* 400 */
188 int numberofcbs = 60000;        /* 60000 */
189 int lwps = 9;                   /* 6 */
190 int buffs = 90;                 /* 70 */
191 int novbc = 0;                  /* Enable Volume Break calls */
192 int busy_threshold = 600;
193 int abort_threshold = 10;
194 int udpBufSize = 0;             /* UDP buffer size for receive */
195 int sendBufSize = 16384;        /* send buffer size */
196
197 struct timeval tp;
198
199 /*
200  * FileServer's name and IP address, both network byte order and
201  * host byte order.
202  */
203 #define ADDRSPERSITE 16         /* Same global is in rx/rx_user.c */
204
205 char FS_HostName[128] = "localhost";
206 afs_uint32 FS_HostAddr_NBO;
207 afs_uint32 FS_HostAddr_HBO;
208 afs_uint32 FS_HostAddrs[ADDRSPERSITE], FS_HostAddr_cnt = 0, FS_registered = 0;
209 /* All addresses in FS_HostAddrs are in NBO */
210 afsUUID FS_HostUUID;
211
212 static void FlagMsg();
213
214 /*
215  * Home for the performance statistics.
216  */
217
218 /* DEBUG HACK */
219 static void
220 CheckDescriptors()
221 {
222 #ifndef AFS_NT40_ENV
223     struct afs_stat status;
224     register int tsize = getdtablesize();
225     register int i;
226     for (i = 0; i < tsize; i++) {
227         if (afs_fstat(i, &status) != -1) {
228             printf("%d: dev %x, inode %u, length %u, type/mode %x\n", i,
229                    status.st_dev, status.st_ino, status.st_size,
230                    status.st_mode);
231         }
232     }
233     fflush(stdout);
234     ResetCheckDescriptors();
235 #endif
236 }                               /*CheckDescriptors */
237
238
239 #ifdef AFS_PTHREAD_ENV
240 void
241 CheckSignal_Signal(x)
242 {
243     CheckSignal();
244 }
245
246 void
247 ShutDown_Signal(x)
248 {
249     ShutDown();
250 }
251
252 void
253 CheckDescriptors_Signal(x)
254 {
255     CheckDescriptors();
256 }
257 #else /* AFS_PTHREAD_ENV */
258 void
259 CheckSignal_Signal(x)
260 {
261     IOMGR_SoftSig(CheckSignal, 0);
262 }
263
264 void
265 ShutDown_Signal(x)
266 {
267     IOMGR_SoftSig(ShutDown, 0);
268 }
269
270 void
271 CheckDescriptors_Signal(x)
272 {
273     IOMGR_SoftSig(CheckDescriptors, 0);
274 }
275 #endif /* AFS_PTHREAD_ENV */
276
277 /* check whether caller is authorized to manage RX statistics */
278 int
279 fs_rxstat_userok(struct rx_call *call)
280 {
281     return afsconf_SuperUser(confDir, call, NULL);
282 }
283
284 static void
285 ResetCheckSignal(void)
286 {
287     int signo;
288
289 #if defined(AFS_HPUX_ENV)
290     signo = SIGPOLL;
291 #else
292 #if defined(AFS_NT40_ENV)
293     signo = SIGUSR2;
294 #else
295     signo = SIGXCPU;
296 #endif
297 #endif
298
299 #if defined(AFS_PTHREAD_ENV) && !defined(AFS_NT40_ENV)
300     softsig_signal(signo, CheckSignal_Signal);
301 #else
302     signal(signo, CheckSignal_Signal);
303 #endif
304 }
305
306 static void
307 ResetCheckDescriptors(void)
308 {
309 #ifndef AFS_NT40_ENV
310 #if defined(AFS_PTHREAD_ENV)
311     softsig_signal(SIGTERM, CheckDescriptors_Signal);
312 #else
313     (void)signal(SIGTERM, CheckDescriptors_Signal);
314 #endif
315 #endif
316 }
317
318 #if defined(AFS_PTHREAD_ENV)
319 char *
320 threadName(void)
321 {
322     char threadid[16];
323     if (LogLevel > 999) {
324         afs_snprintf(threadid, 16, "%d", pthread_getspecific(rx_thread_id_key));
325         return threadid;
326     } else 
327         return NULL;
328 }
329 #endif
330
331 /* proc called by rxkad module to get a key */
332 static int
333 get_key(char *arock, register afs_int32 akvno, char *akey)
334 {
335     /* find the key */
336     static struct afsconf_key tkey;
337     register afs_int32 code;
338
339     if (!confDir) {
340         ViceLog(0, ("conf dir not open\n"));
341         return 1;
342     }
343     code = afsconf_GetKey(confDir, akvno, tkey.key);
344     if (code)
345         return code;
346     memcpy(akey, tkey.key, sizeof(tkey.key));
347     return 0;
348
349 }                               /*get_key */
350
351 #ifndef AFS_NT40_ENV
352 int
353 viced_syscall(afs_uint32 a3, afs_uint32 a4, void *a5)
354 {
355     afs_uint32 rcode;
356     void (*old) ();
357
358 #ifndef AFS_LINUX20_ENV
359     old = (void (*)())signal(SIGSYS, SIG_IGN);
360 #endif
361     rcode = syscall(AFS_SYSCALL, 28 /* AFSCALL_CALL */ , a3, a4, a5);
362 #ifndef AFS_LINUX20_ENV
363     signal(SIGSYS, old);
364 #endif
365
366     return rcode;
367 }
368 #endif
369
370 #if !defined(AFS_NT40_ENV)
371 #include "AFS_component_version_number.c"
372 #endif /* !AFS_NT40_ENV */
373
374 #define MAXADMINNAME 64
375 char adminName[MAXADMINNAME];
376
377 static void
378 CheckAdminName()
379 {
380     int fd = 0;
381     struct afs_stat status;
382
383     if ((afs_stat("/AdminName", &status)) ||    /* if file does not exist */
384         (status.st_size <= 0) ||        /* or it is too short */
385         (status.st_size >= (MAXADMINNAME)) ||   /* or it is too long */
386         !(fd = afs_open("/AdminName", O_RDONLY, 0))) {  /* or the open fails */
387         strcpy(adminName, "System:Administrators");     /* use the default name */
388     } else {
389         (void)read(fd, adminName, status.st_size);      /* use name from the file */
390     }
391     if (fd)
392         close(fd);              /* close fd if it was opened */
393
394 }                               /*CheckAdminName */
395
396
397 static void
398 setThreadId(char *s)
399 {
400 #if defined(AFS_PTHREAD_ENV) && !defined(AFS_NT40_ENV)
401     /* set our 'thread-id' so that the host hold table works */
402     MUTEX_ENTER(&rx_stats_mutex);       /* protects rxi_pthread_hinum */
403     ++rxi_pthread_hinum;
404     pthread_setspecific(rx_thread_id_key, (void *)rxi_pthread_hinum);
405     MUTEX_EXIT(&rx_stats_mutex);
406     ViceLog(0,
407             ("Set thread id %d for '%s'\n",
408              pthread_getspecific(rx_thread_id_key), s));
409 #endif
410 }
411
412 /* This LWP does things roughly every 5 minutes */
413 static void
414 FiveMinuteCheckLWP()
415 {
416     static int msg = 0;
417     char tbuffer[32];
418
419     ViceLog(1, ("Starting five minute check process\n"));
420     setThreadId("FiveMinuteCheckLWP");
421     while (1) {
422 #ifdef AFS_PTHREAD_ENV
423         sleep(fiveminutes);
424 #else /* AFS_PTHREAD_ENV */
425         IOMGR_Sleep(fiveminutes);
426 #endif /* AFS_PTHREAD_ENV */
427
428         /* close the log so it can be removed */
429         ReOpenLog(AFSDIR_SERVER_FILELOG_FILEPATH);      /* don't trunc, just append */
430         ViceLog(2, ("Cleaning up timed out callbacks\n"));
431         if (CleanupTimedOutCallBacks())
432             ViceLog(5, ("Timed out callbacks deleted\n"));
433         ViceLog(2, ("Set disk usage statistics\n"));
434         VSetDiskUsage();
435         if (FS_registered == 1)
436             Do_VLRegisterRPC();
437         /* Force wakeup in case we missed something; pthreads does timedwait */
438 #ifndef AFS_PTHREAD_ENV
439         LWP_NoYieldSignal(fsync_wait);
440 #endif
441         if (printBanner && (++msg & 1)) {       /* Every 10 minutes */
442             time_t now = FT_ApproxTime();
443             if (console != NULL) {
444 #ifndef AFS_QUIETFS_ENV
445                 fprintf(console, "File server is running at %s\r",
446                         afs_ctime(&now, tbuffer, sizeof(tbuffer)));
447 #endif /* AFS_QUIETFS_ENV */
448                 ViceLog(2,
449                         ("File server is running at %s\n",
450                          afs_ctime(&now, tbuffer, sizeof(tbuffer))));
451             }
452         }
453     }
454 }                               /*FiveMinuteCheckLWP */
455
456
457 /* This LWP does host checks every 5 minutes:  it should not be used for
458  * other 5 minute activities because it may be delayed by timeouts when
459  * it probes the workstations
460  */
461 static void
462 HostCheckLWP()
463 {
464     ViceLog(1, ("Starting Host check process\n"));
465     setThreadId("HostCheckLWP");
466     while (1) {
467 #ifdef AFS_PTHREAD_ENV
468         sleep(fiveminutes);
469 #else /* AFS_PTHREAD_ENV */
470         IOMGR_Sleep(fiveminutes);
471 #endif /* AFS_PTHREAD_ENV */
472         ViceLog(2, ("Checking for dead venii & clients\n"));
473         h_CheckHosts();
474     }
475 }                               /*HostCheckLWP */
476
477 /* This LWP does fsync checks every 5 minutes:  it should not be used for
478  * other 5 minute activities because it may be delayed by timeouts when
479  * it probes the workstations
480  */
481 static
482 FsyncCheckLWP()
483 {
484     afs_int32 code;
485 #ifdef AFS_PTHREAD_ENV
486     struct timespec fsync_next;
487 #endif
488     ViceLog(1, ("Starting fsync check process\n"));
489
490     setThreadId("FsyncCheckLWP");
491
492 #ifdef AFS_PTHREAD_ENV
493     assert(pthread_cond_init(&fsync_cond, NULL) == 0);
494     assert(pthread_mutex_init(&fsync_glock_mutex, NULL) == 0);
495 #endif
496
497     while (1) {
498         FSYNC_LOCK;
499 #ifdef AFS_PTHREAD_ENV
500         /* rounding is fine */
501         fsync_next.tv_nsec = 0;
502         fsync_next.tv_sec = time(0) + fiveminutes;
503
504         code =
505             pthread_cond_timedwait(&fsync_cond, &fsync_glock_mutex,
506                                    &fsync_next);
507         if (code != 0 && code != ETIMEDOUT)
508             ViceLog(0, ("pthread_cond_timedwait returned %d\n", code));
509 #else /* AFS_PTHREAD_ENV */
510         if ((code = LWP_WaitProcess(fsync_wait)) != LWP_SUCCESS)
511             ViceLog(0, ("LWP_WaitProcess returned %d\n", code));
512 #endif /* AFS_PTHREAD_ENV */
513         FSYNC_UNLOCK;
514         ViceLog(2, ("Checking for fsync events\n"));
515         do {
516             code = BreakLaterCallBacks();
517         } while (code != 0);
518     }
519 }
520
521 /*------------------------------------------------------------------------
522  * PRIVATE ClearXStatValues
523  *
524  * Description:
525  *      Initialize all of the values collected via the xstat
526  *      interface.
527  *
528  * Arguments:
529  *      None.
530  *
531  * Returns:
532  *      Nothing.
533  *
534  * Environment:
535  *      Must be called during File Server initialization.
536  *
537  * Side Effects:
538  *      As advertised.
539  *------------------------------------------------------------------------*/
540
541 static void
542 ClearXStatValues()
543 {                               /*ClearXStatValues */
544
545     struct fs_stats_opTimingData *opTimeP;      /*Ptr to timing struct */
546     struct fs_stats_xferData *opXferP;  /*Ptr to xfer struct */
547     int i;                      /*Loop counter */
548
549     /*
550      * Zero all xstat-related structures.
551      */
552     memset((char *)(&afs_perfstats), 0, sizeof(struct afs_PerfStats));
553 #if FS_STATS_DETAILED
554     memset((char *)(&afs_FullPerfStats), 0,
555            sizeof(struct fs_stats_FullPerfStats));
556
557     /*
558      * That's not enough.  We have to set reasonable minima for
559      * time and xfer values in the detailed stats.
560      */
561     opTimeP = &(afs_FullPerfStats.det.rpcOpTimes[0]);
562     for (i = 0; i < FS_STATS_NUM_RPC_OPS; i++, opTimeP++)
563         opTimeP->minTime.tv_sec = 999999;
564
565     opXferP = &(afs_FullPerfStats.det.xferOpTimes[0]);
566     for (i = 0; i < FS_STATS_NUM_XFER_OPS; i++, opXferP++) {
567         opXferP->minTime.tv_sec = 999999;
568         opXferP->minBytes = 999999999;
569     }
570
571     /*
572      * There's more.  We have to set our unique system identifier, as
573      * declared in param.h.  If such a thing is not defined, we bitch
574      * and declare ourselves to be an unknown system type.
575      */
576 #ifdef SYS_NAME_ID
577     afs_perfstats.sysname_ID = SYS_NAME_ID;
578 #else
579 #ifndef AFS_NT40_ENV
580     ViceLog(0, ("Sys name ID constant not defined in param.h!!\n"));
581     ViceLog(0, ("[Choosing ``undefined'' sys name ID.\n"));
582 #endif
583     afs_perfstats.sysname_ID = SYS_NAME_ID_UNDEFINED;
584 #endif /* SYS_NAME_ID */
585 #endif
586
587 }                               /*ClearXStatValues */
588
589
590 static void
591 PrintCounters()
592 {
593     int dirbuff, dircall, dirio;
594     struct timeval tpl;
595     int workstations, activeworkstations, delworkstations;
596     int processSize = 0;
597     char tbuffer[32];
598
599     TM_GetTimeOfDay(&tpl, 0);
600     Statistics = 1;
601     ViceLog(0,
602             ("Vice was last started at %s\n",
603              afs_ctime(&StartTime, tbuffer, sizeof(tbuffer))));
604
605     VPrintCacheStats();
606     VPrintDiskStats();
607     DStat(&dirbuff, &dircall, &dirio);
608     ViceLog(0,
609             ("With %d directory buffers; %d reads resulted in %d read I/Os\n",
610              dirbuff, dircall, dirio));
611     rx_PrintStats(stderr);
612     h_PrintStats();
613     PrintCallBackStats();
614 #ifdef AFS_NT40_ENV
615     processSize = -1;           /* TODO: */
616 #else
617     processSize = (int)((long)sbrk(0) >> 10);
618 #endif
619     ViceLog(0,
620             ("There are %d connections, process size %d\n",
621              CurrentConnections, processSize));
622     h_GetWorkStats(&workstations, &activeworkstations, &delworkstations,
623                    tpl.tv_sec - 15 * 60);
624     ViceLog(0,
625             ("There are %d workstations, %d are active (req in < 15 mins), %d marked \"down\"\n",
626              workstations, activeworkstations, delworkstations));
627     Statistics = 0;
628
629 }                               /*PrintCounters */
630
631
632
633 static void
634 CheckSignal()
635 {
636     if (FS_registered > 0) {
637         /*
638          * We have proper ip addresses; tell the vlserver what we got; the following
639          * routine will do the proper reporting for us
640          */
641         Do_VLRegisterRPC();
642     }
643     h_DumpHosts();
644     h_PrintClients();
645     DumpCallBackState();
646     PrintCounters();
647     ResetCheckSignal();
648
649 }                               /*CheckSignal */
650
651 void
652 ShutDownAndCore(int dopanic)
653 {
654     time_t now = time(0);
655     char tbuffer[32];
656
657     ViceLog(0,
658             ("Shutting down file server at %s",
659              afs_ctime(&now, tbuffer, sizeof(tbuffer))));
660     if (dopanic)
661         ViceLog(0, ("ABNORMAL SHUTDOWN, see core file.\n"));
662 #ifndef AFS_QUIETFS_ENV
663     if (console != NULL) {
664         fprintf(console, "File server restart/shutdown received at %s\r",
665                 afs_ctime(&now, tbuffer, sizeof(tbuffer)));
666     }
667 #endif
668     DFlush();
669     if (!dopanic)
670         PrintCounters();
671
672     /* do not allows new reqests to be served from now on, all new requests
673      * are returned with an error code of RX_RESTARTING ( transient failure ) */
674     rx_SetRxTranquil();         /* dhruba */
675     VShutdown();
676
677     if (debugFile) {
678         rx_PrintStats(debugFile);
679         fflush(debugFile);
680     }
681     if (console != NULL) {
682         now = time(0);
683         if (dopanic) {
684 #ifndef AFS_QUIETFS_ENV
685             fprintf(console, "File server has terminated abnormally at %s\r",
686                     afs_ctime(&now, tbuffer, sizeof(tbuffer)));
687 #endif
688             ViceLog(0,
689                     ("File server has terminated abnormally at %s\n",
690                      afs_ctime(&now, tbuffer, sizeof(tbuffer))));
691         } else {
692 #ifndef AFS_QUIETFS_ENV
693             fprintf(console, "File server has terminated normally at %s\r",
694                     afs_ctime(&now, tbuffer, sizeof(tbuffer)));
695 #endif
696             ViceLog(0,
697                     ("File server has terminated normally at %s\n",
698                      afs_ctime(&now, tbuffer, sizeof(tbuffer))));
699         }
700     }
701
702     exit(0);
703
704 }                               /*ShutDown */
705
706 void
707 ShutDown(void)
708 {                               /* backward compatibility */
709     ShutDownAndCore(DONTPANIC);
710 }
711
712
713 static void
714 FlagMsg()
715 {
716     char buffer[1024];
717
718     /* default supports help flag */
719
720     strcpy(buffer, "Usage: fileserver ");
721     strcat(buffer, "[-d <debug level>] ");
722     strcat(buffer, "[-p <number of processes>] ");
723     strcat(buffer, "[-spare <number of spare blocks>] ");
724     strcat(buffer, "[-pctspare <percentage spare>] ");
725     strcat(buffer, "[-b <buffers>] ");
726     strcat(buffer, "[-l <large vnodes>] ");
727     strcat(buffer, "[-s <small vnodes>] ");
728     strcat(buffer, "[-vc <volume cachesize>] ");
729     strcat(buffer, "[-w <call back wait interval>] ");
730     strcat(buffer, "[-cb <number of call backs>] ");
731     strcat(buffer, "[-banner (print banner every 10 minutes)] ");
732     strcat(buffer, "[-novbc (whole volume cbs disabled)] ");
733     strcat(buffer, "[-implicit <admin mode bits: rlidwka>] ");
734     strcat(buffer, "[-readonly (read-only file server)] ");
735     strcat(buffer,
736            "[-hr <number of hours between refreshing the host cps>] ");
737     strcat(buffer, "[-busyat <redirect clients when queue > n>] ");
738     strcat(buffer, "[-nobusy <no VBUSY before a volume is attached>] ");
739     strcat(buffer, "[-rxpck <number of rx extra packets>] ");
740     strcat(buffer, "[-rxdbg (enable rx debugging)] ");
741     strcat(buffer, "[-rxdbge (enable rxevent debugging)] ");
742 #if AFS_PTHREAD_ENV
743     strcat(buffer, "[-vattachpar <number of volume attach threads>] ");
744 #endif
745 #ifdef  AFS_AIX32_ENV
746     strcat(buffer, "[-m <min percentage spare in partition>] ");
747 #endif
748 #if defined(AFS_SGI_ENV)
749     strcat(buffer, "[-lock (keep fileserver from swapping)] ");
750 #endif
751     strcat(buffer, "[-L (large server conf)] ");
752     strcat(buffer, "[-S (small server conf)] ");
753     strcat(buffer, "[-k <stack size>] ");
754     strcat(buffer, "[-realm <Kerberos realm name>] ");
755     strcat(buffer, "[-udpsize <size of socket buffer in bytes>] ");
756     strcat(buffer, "[-sendsize <size of send buffer in bytes>] ");
757 /*   strcat(buffer, "[-enable_peer_stats] "); */
758 /*   strcat(buffer, "[-enable_process_stats] "); */
759     strcat(buffer, "[-help]\n");
760 /*
761     ViceLog(0, ("%s", buffer));
762 */
763
764     printf("%s", buffer);
765     fflush(stdout);
766
767 }                               /*FlagMsg */
768
769
770 static afs_int32
771 ParseRights(char *arights)
772 {
773     afs_int32 mode = 0;
774     int i, len;
775     char tc;
776
777     if (!arights || !strcmp(arights, "")) {
778         printf("Missing list of mode bits on -implicit option\n");
779         return -1;
780     }
781     if (!strcmp(arights, "none"))
782         mode = 0;
783     else if (!strcmp(arights, "read"))
784         mode = PRSFS_READ | PRSFS_LOOKUP;
785     else if (!strcmp(arights, "write"))
786         mode =
787             PRSFS_READ | PRSFS_LOOKUP | PRSFS_INSERT | PRSFS_DELETE |
788             PRSFS_WRITE | PRSFS_LOCK;
789     else if (!strcmp(arights, "all"))
790         mode =
791             PRSFS_READ | PRSFS_LOOKUP | PRSFS_INSERT | PRSFS_DELETE |
792             PRSFS_WRITE | PRSFS_LOCK | PRSFS_ADMINISTER;
793     else {
794         len = strlen(arights);
795         for (i = 0; i < len; i++) {
796             tc = *arights++;
797             if (tc == 'r')
798                 mode |= PRSFS_READ;
799             else if (tc == 'l')
800                 mode |= PRSFS_LOOKUP;
801             else if (tc == 'i')
802                 mode |= PRSFS_INSERT;
803             else if (tc == 'd')
804                 mode |= PRSFS_DELETE;
805             else if (tc == 'w')
806                 mode |= PRSFS_WRITE;
807             else if (tc == 'k')
808                 mode |= PRSFS_LOCK;
809             else if (tc == 'a')
810                 mode |= PRSFS_ADMINISTER;
811             else if (tc == 'A')
812                 mode |= PRSFS_USR0;
813             else if (tc == 'B')
814                 mode |= PRSFS_USR1;
815             else if (tc == 'C')
816                 mode |= PRSFS_USR2;
817             else if (tc == 'D')
818                 mode |= PRSFS_USR3;
819             else if (tc == 'E')
820                 mode |= PRSFS_USR4;
821             else if (tc == 'F')
822                 mode |= PRSFS_USR5;
823             else if (tc == 'G')
824                 mode |= PRSFS_USR6;
825             else if (tc == 'H')
826                 mode |= PRSFS_USR7;
827             else {
828                 printf("Illegal -implicit rights character '%c'.\n", tc);
829                 return -1;
830             }
831         }
832     }
833     return mode;
834 }
835
836 /*
837  * Limit MAX_FILESERVER_THREAD by the system limit on the number of
838  * pthreads (sysconf(_SC_THREAD_THREADS_MAX)), if applicable and
839  * available.
840  *
841  * AIX:         sysconf() limit is real
842  * HP-UX:       sysconf() limit is real
843  * IRIX:        sysconf() limit is apparently NOT real -- too small
844  * DUX:         sysconf() limit is apparently NOT real -- too big
845  * Linux:       sysconf() limit is apparently NOT real -- too big
846  * Solaris:     no sysconf() limit
847  */
848 static int
849 max_fileserver_thread(void)
850 {
851 #if defined(AFS_PTHREAD_ENV)
852 #if defined(AFS_AIX_ENV) || defined(AFS_HPUX_ENV)
853     long ans;
854
855     ans = sysconf(_SC_THREAD_THREADS_MAX);
856     if (0 < ans && ans < MAX_FILESERVER_THREAD)
857         return (int)ans;
858 #endif
859 #endif /* defined(AFS_PTHREAD_ENV) */
860     return MAX_FILESERVER_THREAD;
861 }
862
863 static int
864 ParseArgs(int argc, char *argv[])
865 {
866     int SawL = 0, SawS = 0, SawVC = 0;
867     int Sawrxpck = 0, Sawsmall = 0, Sawlarge = 0, Sawcbs = 0, Sawlwps =
868         0, Sawbufs = 0;
869     int Sawbusy = 0;
870     int i;
871     int bufSize = 0;            /* temp variable to read in udp socket buf size */
872
873     for (i = 1; i < argc; i++) {
874         if (!strcmp(argv[i], "-d")) {
875             if ((i + 1) >= argc) {
876                 fprintf(stderr, "missing argument for -d\n"); 
877                 return -1; 
878             }
879             debuglevel = atoi(argv[++i]);
880             LogLevel = debuglevel;
881         } else if (!strcmp(argv[i], "-banner")) {
882             printBanner = 1;
883         } else if (!strcmp(argv[i], "-implicit")) {
884             if ((i + 1) >= argc) {
885                 fprintf(stderr, "missing argument for -implicit\n"); 
886                 return -1; 
887             }
888             implicitAdminRights = ParseRights(argv[++i]);
889             if (implicitAdminRights < 0)
890                 return implicitAdminRights;
891         } else if (!strcmp(argv[i], "-readonly")) {
892             readonlyServer = 1;
893         } else if (!strcmp(argv[i], "-L")) {
894             SawL = 1;
895         } else if (!strcmp(argv[i], "-S")) {
896             SawS = 1;
897         } else if (!strcmp(argv[i], "-p")) {
898             int lwps_max =
899                 max_fileserver_thread() - FILESERVER_HELPER_THREADS;
900             Sawlwps = 1;
901             if ((i + 1) >= argc) {
902                 fprintf(stderr, "missing argument for -p\n"); 
903                 return -1; 
904             }
905             lwps = atoi(argv[++i]);
906             if (lwps > lwps_max)
907                 lwps = lwps_max;
908             else if (lwps < 6)
909                 lwps = 6;
910         } else if (!strcmp(argv[i], "-b")) {
911             Sawbufs = 1;
912             if ((i + 1) >= argc) {
913                 fprintf(stderr, "missing argument for -b\n"); 
914                 return -1; 
915             }
916             buffs = atoi(argv[++i]);
917         } else if (!strcmp(argv[i], "-l")) {
918             Sawlarge = 1;
919             if ((i + 1) >= argc) {
920                 fprintf(stderr, "missing argument for -l\n"); 
921                 return -1; 
922             }
923             large = atoi(argv[++i]);
924         } else if (!strcmp(argv[i], "-vc")) {
925             SawVC = 1;
926             if ((i + 1) >= argc) {
927                 fprintf(stderr, "missing argument for -vc\n"); 
928                 return -1; 
929             }
930             volcache = atoi(argv[++i]);
931         } else if (!strcmp(argv[i], "-novbc")) {
932             novbc = 1;
933         } else if (!strcmp(argv[i], "-rxpck")) {
934             Sawrxpck = 1;
935             if ((i + 1) >= argc) {
936                 fprintf(stderr, "missing argument for -rxpck\n"); 
937                 return -1; 
938             }
939             rxpackets = atoi(argv[++i]);
940 #ifdef AFS_PTHREAD_ENV
941         } else if (!strcmp(argv[i], "-vattachpar")) {
942             if ((i + 1) >= argc) {
943                 fprintf(stderr, "missing argument for -vattachpar\n"); 
944                 return -1; 
945             }
946             vol_attach_threads = atoi(argv[++i]);
947 #endif /* AFS_PTHREAD_ENV */
948         } else if (!strcmp(argv[i], "-s")) {
949             Sawsmall = 1;
950             if ((i + 1) >= argc) {
951                 fprintf(stderr, "missing argument for -s\n"); 
952                 return -1; 
953             }
954             nSmallVns = atoi(argv[++i]);
955         } else if (!strcmp(argv[i], "-abortthreshold")) {
956             if ((i + 1) >= argc) {
957                 fprintf(stderr, "missing argument for -abortthreshold\n"); 
958                 return -1; 
959             }
960             abort_threshold = atoi(argv[++i]);
961         } else if (!strcmp(argv[i], "-k")) {
962             if ((i + 1) >= argc) {
963                 fprintf(stderr, "missing argument for -k\n"); 
964                 return -1; 
965             }
966             stack = atoi(argv[++i]);
967         }
968 #if defined(AFS_SGI_ENV)
969         else if (!strcmp(argv[i], "-lock")) {
970             SawLock = 1;
971         }
972 #endif
973         else if (!strcmp(argv[i], "-spare")) {
974             if ((i + 1) >= argc) {
975                 fprintf(stderr, "missing argument for -spare\n"); 
976                 return -1; 
977             }
978             BlocksSpare = atoi(argv[++i]);
979             SawSpare = 1;
980         } else if (!strcmp(argv[i], "-pctspare")) {
981             if ((i + 1) >= argc) {
982                 fprintf(stderr, "missing argument for -pctspare\n"); 
983                 return -1; 
984             }
985             PctSpare = atoi(argv[++i]);
986             BlocksSpare = 0;    /* has non-zero default */
987             SawPctSpare = 1;
988         } else if (!strcmp(argv[i], "-w")) {
989             if ((i + 1) >= argc) {
990                 fprintf(stderr, "missing argument for -w\n"); 
991                 return -1; 
992             }
993             fiveminutes = atoi(argv[++i]);
994         } else if (!strcmp(argv[i], "-hr")) {
995             int hr;
996             if ((i + 1) >= argc) {
997                 fprintf(stderr, "missing argument for -hr\n"); 
998                 return -1; 
999             }
1000             hr = atoi(argv[++i]);
1001             if ((hr < 1) || (hr > 36)) {
1002                 printf
1003                     ("host acl refresh interval of %d hours is invalid; hours must be between 1 and 36\n\n",
1004                      hr);
1005                 return -1;
1006             }
1007             hostaclRefresh = hr * 60 * 60;
1008         } else if (!strcmp(argv[i], "-rxdbg"))
1009             rxlog = 1;
1010         else if (!strcmp(argv[i], "-rxdbge"))
1011             eventlog = 1;
1012         else if (!strcmp(argv[i], "-cb")) {
1013             Sawcbs = 1;
1014             if ((i + 1) >= argc) {
1015                 fprintf(stderr, "missing argument for -cb\n"); 
1016                 return -1; 
1017             }
1018             numberofcbs = atoi(argv[++i]);
1019             if ((numberofcbs < 10000) || (numberofcbs > 2147483647)) {
1020                 printf
1021                     ("number of cbs %d invalid; must be between 10000 and 2147483647\n",
1022                      numberofcbs);
1023                 return -1;
1024             }
1025         } else if (!strcmp(argv[i], "-busyat")) {
1026             Sawbusy = 1;
1027             if ((i + 1) >= argc) {
1028                 fprintf(stderr, "missing argument for -busyat\n"); 
1029                 return -1; 
1030             }
1031             busy_threshold = atoi(argv[++i]);
1032             if (busy_threshold < 10) {
1033                 printf
1034                     ("Busy threshold %d is too low, will compute default.\n",
1035                      busy_threshold);
1036                 Sawbusy = 0;
1037             }
1038         } else if (!strcmp(argv[i], "-nobusy"))
1039             busyonrst = 0;
1040 #ifdef  AFS_AIX32_ENV
1041         else if (!strcmp(argv[i], "-m")) {
1042             extern int aixlow_water;
1043             if ((i + 1) >= argc) {
1044                 fprintf(stderr, "missing argument for -m\n"); 
1045                 return -1; 
1046             }
1047             aixlow_water = atoi(argv[++i]);
1048             if ((aixlow_water < 0) || (aixlow_water > 30)) {
1049                 printf("space reserved %d% invalid; must be between 0-30%\n",
1050                        aixlow_water);
1051                 return -1;
1052             }
1053         }
1054 #endif
1055         else if (!strcmp(argv[i], "-nojumbo")) {
1056             rxJumbograms = 0;
1057         } else if (!strcmp(argv[i], "-realm")) {
1058             extern char local_realm[AFS_REALM_SZ];
1059             if ((i + 1) >= argc) {
1060                 fprintf(stderr, "missing argument for -realm\n"); 
1061                 return -1; 
1062             }
1063             if (strlen(argv[++i]) >= AFS_REALM_SZ) {
1064                 printf
1065                     ("-realm argument must contain fewer than %d characters.\n",
1066                      AFS_REALM_SZ);
1067                 return -1;
1068             }
1069             strncpy(local_realm, argv[i], AFS_REALM_SZ);
1070         } else if (!strcmp(argv[i], "-udpsize")) {
1071             if ((i + 1) >= argc) {
1072                 printf("You have to specify -udpsize <integer value>\n");
1073                 return -1;
1074             }
1075             bufSize = atoi(argv[++i]);
1076             if (bufSize < rx_GetMinUdpBufSize())
1077                 printf
1078                     ("Warning:udpsize %d is less than minimum %d; ignoring\n",
1079                      bufSize, rx_GetMinUdpBufSize());
1080             else
1081                 udpBufSize = bufSize;
1082         } else if (!strcmp(argv[i], "-sendsize")) {
1083             if ((i + 1) >= argc) {
1084                 printf("You have to specify -sendsize <integer value>\n");
1085                 return -1;
1086             }
1087             bufSize = atoi(argv[++i]);
1088             if (bufSize < 16384)
1089                 printf
1090                     ("Warning:sendsize %d is less than minimum %d; ignoring\n",
1091                      bufSize, 16384);
1092             else
1093                 sendBufSize = bufSize;
1094         } else if (!strcmp(argv[i], "-enable_peer_stats")) {
1095             rx_enablePeerRPCStats();
1096         } else if (!strcmp(argv[i], "-enable_process_stats")) {
1097             rx_enableProcessRPCStats();
1098         }
1099 #ifndef AFS_NT40_ENV
1100         else if (strcmp(argv[i], "-syslog") == 0) {
1101             /* set syslog logging flag */
1102             serverLogSyslog = 1;
1103         } else if (strncmp(argv[i], "-syslog=", 8) == 0) {
1104             serverLogSyslog = 1;
1105             serverLogSyslogFacility = atoi(argv[i] + 8);
1106         }
1107 #endif
1108         else if (strcmp(argv[i], "-mrafslogs") == 0) {
1109             /* set syslog logging flag */
1110             mrafsStyleLogs = 1;
1111         } 
1112         else {
1113             return (-1);
1114         }
1115     }
1116     if (SawS && SawL) {
1117         printf("Only one of -L, or -S must be specified\n");
1118         return -1;
1119     }
1120     if (SawS) {
1121         if (!Sawrxpck)
1122             rxpackets = 100;
1123         if (!Sawsmall)
1124             nSmallVns = 200;
1125         if (!Sawlarge)
1126             large = 200;
1127         if (!Sawcbs)
1128             numberofcbs = 20000;
1129         if (!Sawlwps)
1130             lwps = 6;
1131         if (!Sawbufs)
1132             buffs = 70;
1133         if (!SawVC)
1134             volcache = 200;
1135     }
1136     if (SawL) {
1137         if (!Sawrxpck)
1138             rxpackets = 200;
1139         if (!Sawsmall)
1140             nSmallVns = 600;
1141         if (!Sawlarge)
1142             large = 600;
1143         if (!Sawcbs)
1144             numberofcbs = 64000;
1145         if (!Sawlwps)
1146             lwps = 12;
1147         if (!Sawbufs)
1148             buffs = 120;
1149         if (!SawVC)
1150             volcache = 600;
1151     }
1152     if (!Sawbusy)
1153         busy_threshold = 3 * rxpackets / 2;
1154
1155     return (0);
1156
1157 }                               /*ParseArgs */
1158
1159
1160 #define MAXPARMS 15
1161
1162 static void
1163 NewParms(int initializing)
1164 {
1165     static struct afs_stat sbuf;
1166     register int i, fd;
1167     char *parms;
1168     char *argv[MAXPARMS];
1169     register int argc;
1170
1171     if (!(afs_stat("/vice/file/parms", &sbuf))) {
1172         parms = (char *)malloc(sbuf.st_size);
1173         if (!parms)
1174             return;
1175         fd = afs_open("parms", O_RDONLY, 0666);
1176         if (fd <= 0) {
1177             ViceLog(0, ("Open for parms failed with errno = %d\n", errno));
1178             return;
1179         }
1180
1181         i = read(fd, parms, sbuf.st_size);
1182         close(fd);
1183         if (i != sbuf.st_size) {
1184             if (i < 0) {
1185                 ViceLog(0, ("Read on parms failed with errno = %d\n", errno));
1186             } else {
1187                 ViceLog(0,
1188                         ("Read on parms failed; expected %d bytes but read %d\n",
1189                          sbuf.st_size, i));
1190             }
1191             free(parms);
1192             return;
1193         }
1194
1195         for (i = 0; i < MAXPARMS; argv[i++] = 0);
1196
1197         for (argc = i = 0; i < sbuf.st_size; i++) {
1198             if ((*(parms + i) != ' ') && (*(parms + i) != '\n')) {
1199                 if (argv[argc] == 0)
1200                     argv[argc] = (parms + i);
1201             } else {
1202                 *(parms + i) = '\0';
1203                 if (argv[argc] != 0) {
1204                     if (++argc == MAXPARMS)
1205                         break;
1206                 }
1207                 while ((*(parms + i + 1) == ' ')
1208                        || (*(parms + i + 1) == '\n'))
1209                     i++;
1210             }
1211         }
1212         if (ParseArgs(argc, argv) == 0) {
1213             ViceLog(0, ("Change parameters to:"));
1214         } else {
1215             ViceLog(0, ("Invalid parameter in:"));
1216         }
1217         for (i = 0; i < argc; i++) {
1218             ViceLog(0, (" %s", argv[i]));
1219         }
1220         ViceLog(0, ("\n"));
1221         free(parms);
1222     } else if (!initializing)
1223         ViceLog(0,
1224                 ("Received request to change parms but no parms file exists\n"));
1225
1226 }                               /*NewParms */
1227
1228
1229 /* Miscellaneous routines */
1230 void
1231 Die(char *msg)
1232 {
1233     ViceLog(0, ("%s\n", msg));
1234     assert(0);
1235
1236 }                               /*Die */
1237
1238
1239 afs_int32
1240 InitPR()
1241 {
1242     register code;
1243
1244     /*
1245      * If this fails, it's because something major is wrong, and is not
1246      * likely to be time dependent.
1247      */
1248     code = pr_Initialize(2, AFSDIR_SERVER_ETC_DIRPATH, 0);
1249     if (code != 0) {
1250         ViceLog(0,
1251                 ("Couldn't initialize protection library; code=%d.\n", code));
1252         return code;
1253     }
1254     SystemId = SYSADMINID;
1255     SystemAnyUser = ANYUSERID;
1256     SystemAnyUserCPS.prlist_len = 0;
1257     SystemAnyUserCPS.prlist_val = NULL;
1258     AnonCPS.prlist_len = 0;
1259     AnonCPS.prlist_val = NULL;
1260     while (1) {
1261         code = pr_GetCPS(SystemAnyUser, &SystemAnyUserCPS);
1262         if (code != 0) {
1263             ViceLog(0,
1264                     ("Couldn't get CPS for AnyUser, will try again in 30 seconds; code=%d.\n",
1265                      code));
1266             goto sleep;
1267         }
1268         code = pr_GetCPS(ANONYMOUSID, &AnonCPS);
1269         if (code != 0) {
1270             ViceLog(0,
1271                     ("Couldn't get Anonymous CPS, exiting; code=%d.\n",
1272                      code));
1273             return -1;
1274         }
1275         AnonymousID = ANONYMOUSID;
1276         return 0;
1277       sleep:
1278 #ifdef AFS_PTHREAD_ENV
1279         sleep(30);
1280 #else /* AFS_PTHREAD_ENV */
1281         IOMGR_Sleep(30);
1282 #endif /* AFS_PTHREAD_ENV */
1283     }
1284 }                               /*InitPR */
1285
1286 struct rx_connection *serverconns[MAXSERVERS];
1287 struct ubik_client *cstruct;
1288
1289 afs_int32
1290 vl_Initialize(char *confDir)
1291 {
1292     afs_int32 code, scIndex = 0, i;
1293     struct afsconf_dir *tdir;
1294     struct rx_securityClass *sc;
1295     struct afsconf_cell info;
1296
1297     tdir = afsconf_Open(confDir);
1298     if (!tdir) {
1299         ViceLog(0,
1300                 ("Could not open configuration directory (%s).\n", confDir));
1301         exit(1);
1302     }
1303     code = afsconf_ClientAuth(tdir, &sc, &scIndex);
1304     if (code) {
1305         ViceLog(0, ("Could not get security object for localAuth\n"));
1306         exit(1);
1307     }
1308     code = afsconf_GetCellInfo(tdir, NULL, AFSCONF_VLDBSERVICE, &info);
1309     if (info.numServers > MAXSERVERS) {
1310         ViceLog(0,
1311                 ("vl_Initialize: info.numServers=%d (> MAXSERVERS=%d)\n",
1312                  info.numServers, MAXSERVERS));
1313         exit(1);
1314     }
1315     for (i = 0; i < info.numServers; i++)
1316         serverconns[i] =
1317             rx_NewConnection(info.hostAddr[i].sin_addr.s_addr,
1318                              info.hostAddr[i].sin_port, USER_SERVICE_ID, sc,
1319                              scIndex);
1320     code = ubik_ClientInit(serverconns, &cstruct);
1321     if (code) {
1322         ViceLog(0, ("vl_Initialize: ubik client init failed.\n"));
1323         return code;
1324     }
1325     return 0;
1326 }
1327
1328 #define SYSIDMAGIC      0x88aabbcc
1329 #define SYSIDVERSION    1
1330
1331 afs_int32
1332 ReadSysIdFile()
1333 {
1334     afs_int32 fd, nentries, i;
1335     struct versionStamp vsn;
1336     struct afs_stat status;
1337     afsUUID uuid;
1338
1339     if ((afs_stat(AFSDIR_SERVER_SYSID_FILEPATH, &status))
1340         || (status.st_size <= 0)) {
1341         ViceLog(0, ("%s: doesn't exist\n", AFSDIR_SERVER_SYSID_FILEPATH));
1342         return ENOENT;
1343     }
1344     if (!(fd = afs_open(AFSDIR_SERVER_SYSID_FILEPATH, O_RDONLY, 0))) {
1345         ViceLog(0,
1346                 ("%s: can't open (%d)\n", AFSDIR_SERVER_SYSID_FILEPATH,
1347                  errno));
1348         return EIO;
1349     }
1350     if ((i = read(fd, (char *)&vsn, sizeof(vsn))) != sizeof(vsn)) {
1351         ViceLog(0,
1352                 ("%s: Read failed (%d)\n", AFSDIR_SERVER_SYSID_FILEPATH,
1353                  errno));
1354         return EIO;
1355     }
1356     if (vsn.magic != SYSIDMAGIC) {
1357         ViceLog(0,
1358                 ("%s: wrong magic %x (we support %x)\n",
1359                  AFSDIR_SERVER_SYSID_FILEPATH, vsn.magic, SYSIDMAGIC));
1360         return EIO;
1361     }
1362     if (vsn.version != SYSIDVERSION) {
1363         ViceLog(0,
1364                 ("%s: wrong version %d (we support %d)\n",
1365                  AFSDIR_SERVER_SYSID_FILEPATH, vsn.version, SYSIDVERSION));
1366         return EIO;
1367     }
1368     if ((i =
1369          read(fd, (char *)&uuid,
1370               sizeof(struct afsUUID))) != sizeof(struct afsUUID)) {
1371         ViceLog(0,
1372                 ("%s: read of uuid failed (%d)\n",
1373                  AFSDIR_SERVER_SYSID_FILEPATH, errno));
1374         return EIO;
1375     }
1376     afs_ntohuuid(&uuid);
1377     FS_HostUUID = uuid;
1378     if ((i =
1379          read(fd, (char *)&nentries,
1380               sizeof(afs_int32))) != sizeof(afs_int32)) {
1381         ViceLog(0,
1382                 ("%s: Read of entries failed (%d)\n",
1383                  AFSDIR_SERVER_SYSID_FILEPATH, errno));
1384         return EIO;
1385     }
1386     if (nentries <= 0 || nentries > ADDRSPERSITE) {
1387         ViceLog(0,
1388                 ("%s: invalid num of interfaces: %d\n",
1389                  AFSDIR_SERVER_SYSID_FILEPATH, nentries));
1390         return EIO;
1391     }
1392     FS_HostAddr_cnt = nentries;
1393     for (i = 0; i < nentries; i++) {
1394         if (read(fd, (char *)&FS_HostAddrs[i], sizeof(afs_int32)) !=
1395             sizeof(afs_int32)) {
1396             ViceLog(0,
1397                     ("%s: Read of addresses failed (%d)\n",
1398                      AFSDIR_SERVER_SYSID_FILEPATH, errno));
1399             FS_HostAddr_cnt = 0;        /* reset it */
1400             return EIO;
1401         }
1402     }
1403     close(fd);
1404     return 0;
1405 }
1406
1407 afs_int32
1408 WriteSysIdFile()
1409 {
1410     afs_int32 fd, i;
1411     struct versionStamp vsn;
1412     struct afs_stat status;
1413     afsUUID uuid;
1414
1415     if (!afs_stat(AFSDIR_SERVER_SYSID_FILEPATH, &status)) {
1416         /*
1417          * File exists; keep the old one around
1418          */
1419         renamefile(AFSDIR_SERVER_SYSID_FILEPATH,
1420                    AFSDIR_SERVER_OLDSYSID_FILEPATH);
1421     }
1422     fd = afs_open(AFSDIR_SERVER_SYSID_FILEPATH, O_WRONLY | O_TRUNC | O_CREAT,
1423                   0666);
1424     if (fd < 1) {
1425         ViceLog(0,
1426                 ("%s: can't create (%d)\n", AFSDIR_SERVER_SYSID_FILEPATH,
1427                  errno));
1428         return EIO;
1429     }
1430     vsn.magic = SYSIDMAGIC;
1431     vsn.version = 1;
1432     if ((i = write(fd, (char *)&vsn, sizeof(vsn))) != sizeof(vsn)) {
1433         ViceLog(0,
1434                 ("%s: write failed (%d)\n", AFSDIR_SERVER_SYSID_FILEPATH,
1435                  errno));
1436         return EIO;
1437     }
1438     uuid = FS_HostUUID;
1439     afs_htonuuid(&uuid);
1440     if ((i =
1441          write(fd, (char *)&uuid,
1442                sizeof(struct afsUUID))) != sizeof(struct afsUUID)) {
1443         ViceLog(0,
1444                 ("%s: write of uuid failed (%d)\n",
1445                  AFSDIR_SERVER_SYSID_FILEPATH, errno));
1446         return EIO;
1447     }
1448     if ((i =
1449          write(fd, (char *)&FS_HostAddr_cnt,
1450                sizeof(afs_int32))) != sizeof(afs_int32)) {
1451         ViceLog(0,
1452                 ("%s: write of # of entries failed (%d)\n",
1453                  AFSDIR_SERVER_SYSID_FILEPATH, errno));
1454         return EIO;
1455     }
1456     for (i = 0; i < FS_HostAddr_cnt; i++) {
1457         if (write(fd, (char *)&FS_HostAddrs[i], sizeof(afs_int32)) !=
1458             sizeof(afs_int32)) {
1459             ViceLog(0,
1460                     ("%s: write of addresses failed (%d)\n",
1461                      AFSDIR_SERVER_SYSID_FILEPATH, errno));
1462             return EIO;
1463         }
1464     }
1465     close(fd);
1466     return 0;
1467 }
1468
1469 /*
1470  * defect 10966 
1471  * This routine sets up the buffers for the VL_RegisterAddrs RPC. All addresses
1472  * in FS_HostAddrs[] are in NBO, while the RPC treats them as a "blob" of data
1473  * and so we need to convert each of them into HBO which is what the extra 
1474  * array called FS_HostAddrs_HBO is used here.
1475  */
1476 afs_int32
1477 Do_VLRegisterRPC()
1478 {
1479     register int code;
1480     bulkaddrs addrs;
1481     extern int VL_RegisterAddrs();
1482     afs_uint32 FS_HostAddrs_HBO[ADDRSPERSITE];
1483     int i = 0;
1484
1485     for (i = 0; i < FS_HostAddr_cnt; i++)
1486         FS_HostAddrs_HBO[i] = ntohl(FS_HostAddrs[i]);
1487     addrs.bulkaddrs_len = FS_HostAddr_cnt;
1488     addrs.bulkaddrs_val = (afs_uint32 *) FS_HostAddrs_HBO;
1489     code = ubik_Call(VL_RegisterAddrs, cstruct, 0, &FS_HostUUID, 0, &addrs);
1490     if (code) {
1491         if (code == VL_MULTIPADDR) {
1492             ViceLog(0,
1493                     ("VL_RegisterAddrs rpc failed; The IP address exists on a different server; repair it\n"));
1494             ViceLog(0,
1495                     ("VL_RegisterAddrs rpc failed; See VLLog for details\n"));
1496             return code;
1497         } else if (code == RXGEN_OPCODE) {
1498             ViceLog(0,
1499                     ("vlserver doesn't support VL_RegisterAddrs rpc; ignored\n"));
1500             FS_registered = 2;  /* So we don't have to retry in the gc daemon */
1501         } else {
1502             ViceLog(0,
1503                     ("VL_RegisterAddrs rpc failed; will retry periodically (code=%d, err=%d)\n",
1504                      code, errno));
1505         }
1506     } else {
1507         FS_registered = 2;      /* So we don't have to retry in the gc daemon */
1508         WriteSysIdFile();
1509     }
1510
1511     return 0;
1512 }
1513
1514 afs_int32
1515 InitVL()
1516 {
1517     afs_int32 code;
1518     extern int rxi_numNetAddrs;
1519     extern afs_uint32 rxi_NetAddrs[];
1520
1521     /*
1522      * If this fails, it's because something major is wrong, and is not
1523      * likely to be time dependent.
1524      */
1525     code = vl_Initialize(AFSDIR_SERVER_ETC_DIRPATH);
1526     if (code != 0) {
1527         ViceLog(0,
1528                 ("Couldn't initialize protection library; code=%d.\n", code));
1529         return code;
1530     }
1531
1532     /* Read or create the sysid file and register the fileserver's
1533      * IP addresses with the vlserver.
1534      */
1535     code = ReadSysIdFile();
1536     if (code) {
1537         /* Need to create the file */
1538         ViceLog(0, ("Creating new SysID file\n"));
1539         if ((code = afs_uuid_create(&FS_HostUUID))) {
1540             ViceLog(0, ("Failed to create new uuid: %d\n", code));
1541             exit(1);
1542         }
1543     }
1544     /* A good sysid file exists; inform the vlserver. If any conflicts,
1545      * we always use the latest interface available as the real truth.
1546      */
1547 #ifndef AFS_NT40_ENV
1548     if (AFSDIR_SERVER_NETRESTRICT_FILEPATH || AFSDIR_SERVER_NETINFO_FILEPATH) {
1549         /*
1550          * Find addresses we are supposed to register as per the netrestrict 
1551          * and netinfo files (/usr/afs/local/NetInfo and 
1552          * /usr/afs/local/NetRestict)
1553          */
1554         char reason[1024];
1555         afs_int32 code = parseNetFiles(FS_HostAddrs, NULL, NULL,
1556                                        ADDRSPERSITE, reason,
1557                                        AFSDIR_SERVER_NETINFO_FILEPATH,
1558                                        AFSDIR_SERVER_NETRESTRICT_FILEPATH);
1559         if (code < 0) {
1560             ViceLog(0, ("Can't register any valid addresses: %s\n", reason));
1561             exit(1);
1562         }
1563         FS_HostAddr_cnt = (afs_uint32) code;
1564     } else
1565 #endif
1566     {
1567         FS_HostAddr_cnt = rx_getAllAddr(FS_HostAddrs, ADDRSPERSITE);
1568     }
1569
1570     FS_registered = 1;
1571     code = Do_VLRegisterRPC();
1572     return code;
1573 }
1574
1575 int
1576 main(int argc, char *argv[])
1577 {
1578     afs_int32 code;
1579     char tbuffer[32];
1580     struct rx_securityClass *sc[4];
1581     struct rx_service *tservice;
1582 #ifdef AFS_PTHREAD_ENV
1583     pthread_t serverPid;
1584     pthread_attr_t tattr;
1585 #else /* AFS_PTHREAD_ENV */
1586     PROCESS parentPid, serverPid;
1587 #endif /* AFS_PTHREAD_ENV */
1588     struct hostent *he;
1589     int minVnodesRequired;      /* min size of vnode cache */
1590 #ifndef AFS_NT40_ENV
1591     struct rlimit rlim;         /* max number of open file descriptors */
1592 #endif
1593     int curLimit;
1594     time_t t;
1595
1596 #ifdef  AFS_AIX32_ENV
1597     struct sigaction nsa;
1598
1599     sigemptyset(&nsa.sa_mask);
1600     nsa.sa_handler = SIG_DFL;
1601     nsa.sa_flags = SA_FULLDUMP;
1602     sigaction(SIGABRT, &nsa, NULL);
1603     sigaction(SIGSEGV, &nsa, NULL);
1604 #endif
1605
1606     /* Initialize dirpaths */
1607     if (!(initAFSDirPath() & AFSDIR_SERVER_PATHS_OK)) {
1608 #ifdef AFS_NT40_ENV
1609         ReportErrorEventAlt(AFSEVT_SVR_NO_INSTALL_DIR, 0, argv[0], 0);
1610 #endif
1611         fprintf(stderr, "%s: Unable to obtain AFS server directory.\n",
1612                 argv[0]);
1613         exit(2);
1614     }
1615 #ifndef AFS_QUIETFS_ENV
1616     console = afs_fopen("/dev/console", "w");
1617 #endif
1618
1619     if (ParseArgs(argc, argv)) {
1620         FlagMsg();
1621         exit(-1);
1622     }
1623 #ifdef AFS_PTHREAD_ENV
1624     assert(pthread_mutex_init(&fileproc_glock_mutex, NULL) == 0);
1625 #endif /* AFS_PTHREAD_ENV */
1626
1627 #ifdef AFS_SGI_VNODE_GLUE
1628     if (afs_init_kernel_config(-1) < 0) {
1629         printf
1630             ("Can't determine NUMA configuration, not starting fileserver.\n");
1631         exit(1);
1632     }
1633 #endif
1634     confDir = afsconf_Open(AFSDIR_SERVER_ETC_DIRPATH);
1635     if (!confDir) {
1636         fprintf(stderr, "Unable to open config directory %s\n",
1637                 AFSDIR_SERVER_ETC_DIRPATH);
1638         exit(-1);
1639     }
1640
1641     NewParms(1);
1642
1643     /* Open FileLog on stdout, stderr, fd 1 and fd2 (for perror), sigh. */
1644 #ifndef AFS_NT40_ENV
1645     serverLogSyslogTag = "fileserver";
1646 #endif
1647     OpenLog(AFSDIR_SERVER_FILELOG_FILEPATH);
1648     SetupLogSignals();
1649
1650     if (SawSpare && SawPctSpare) {
1651         ViceLog(0, ("Both -spare and -pctspare specified, exiting.\n"));
1652         exit(-1);
1653     }
1654 #ifdef AFS_SGI_XFS_IOPS_ENV
1655     ViceLog(0, ("XFS/EFS File server starting\n"));
1656 #else
1657     ViceLog(0, ("File server starting\n"));
1658 #endif
1659
1660 #if defined(AFS_PTHREAD_ENV) && !defined(AFS_NT40_ENV)
1661     /* initialize the pthread soft signal handler thread */
1662     softsig_init();
1663 #endif
1664
1665     /* install signal handlers for controlling the fileserver process */
1666     ResetCheckSignal();         /* set CheckSignal_Signal() sig handler */
1667     ResetCheckDescriptors();    /* set CheckDescriptors_Signal() sig handler */
1668
1669 #if defined(AFS_SGI_ENV)
1670     /* give this guy a non-degrading priority so help busy servers */
1671     schedctl(NDPRI, 0, NDPNORMMAX);
1672     if (SawLock)
1673         plock(PROCLOCK);
1674 #else
1675 #ifndef AFS_NT40_ENV
1676     nice(-5);                   /* TODO: */
1677 #endif
1678 #endif
1679     assert(DInit(buffs) == 0);
1680
1681 #ifdef AFS_NT40_ENV
1682     if (afs_winsockInit() < 0) {
1683         ReportErrorEventAlt(AFSEVT_SVR_WINSOCK_INIT_FAILED, 0, argv[0], 0);
1684         ViceLog(0, ("File server failed to intialize winsock.\n"));
1685         exit(1);
1686     }
1687 #endif
1688     CheckAdminName();
1689
1690     /* if we support more than 16 threads, then we better have the ability 
1691      ** to keep open a large number of files simultaneously 
1692      */
1693 #if     defined(AFS_AIX_ENV) && !defined(AFS_AIX42_ENV)
1694     curLimit = OPEN_MAX;        /* for pre AIX 4.2 systems */
1695 #elif defined(AFS_NT40_ENV)
1696     curLimit = NT_OPEN_MAX;     /* open file descriptor limit on NT */
1697 #else
1698
1699     curLimit = 0;               /* the number of open file descriptors */
1700     code = getrlimit(RLIMIT_NOFILE, &rlim);
1701     if (code == 0) {
1702         curLimit = rlim.rlim_cur;
1703         rlim.rlim_cur = rlim.rlim_max;
1704         code = setrlimit(RLIMIT_NOFILE, &rlim);
1705         if (code == 0)
1706             curLimit = rlim.rlim_max;
1707     }
1708     if (code != 0)
1709         ViceLog(0, ("Failed to increase open file limit, using default\n"));
1710
1711 #endif /* defined(AFS_AIX_ENV) && !defined(AFS_AIX42_ENV) */
1712
1713     curLimit -= 32;             /* leave a slack of 32 file descriptors */
1714     if (lwps > curLimit) {
1715         if (curLimit > 0)
1716             lwps = curLimit;
1717         else if (lwps > 16)
1718             lwps = 16;          /* default to a maximum of 16 threads */
1719         ViceLog(0,
1720                 ("The system supports a max of %d open files and we are starting %d threads\n",
1721                  curLimit, lwps));
1722     }
1723 #ifndef AFS_PTHREAD_ENV
1724     assert(LWP_InitializeProcessSupport(LWP_MAX_PRIORITY - 2, &parentPid) ==
1725            LWP_SUCCESS);
1726 #endif /* !AFS_PTHREAD_ENV */
1727
1728     /* Initialize volume support */
1729     if (!novbc) {
1730         V_BreakVolumeCallbacks = BreakVolumeCallBacksLater;
1731     }
1732
1733 #ifdef AFS_PTHREAD_ENV
1734     SetLogThreadNameProgram( threadName );
1735 #endif
1736
1737     /* initialize libacl routines */
1738     acl_Initialize(ACL_VERSION);
1739
1740     /* initialize RX support */
1741 #ifndef AFS_NT40_ENV
1742     rxi_syscallp = viced_syscall;
1743 #endif
1744     rx_extraPackets = rxpackets;
1745     rx_extraQuota = 4;          /* for outgoing prserver calls from R threads */
1746     rx_SetBusyThreshold(busy_threshold, VBUSY);
1747     rx_SetCallAbortThreshold(abort_threshold);
1748     rx_SetConnAbortThreshold(abort_threshold);
1749     stackSize = lwps * 4000;
1750     if (stackSize < 32000)
1751         stackSize = 32000;
1752     else if (stackSize > 44000)
1753         stackSize = 44000;
1754 #if    defined(AFS_HPUX_ENV) || defined(AFS_SUN_ENV) || defined(AFS_SGI51_ENV)
1755     rx_SetStackSize(1, stackSize);
1756 #endif
1757     if (udpBufSize)
1758         rx_SetUdpBufSize(udpBufSize);   /* set the UDP buffer size for receive */
1759     if (rx_Init((int)htons(7000)) < 0) {
1760         ViceLog(0, ("Cannot initialize RX\n"));
1761         exit(1);
1762     }
1763     if (!rxJumbograms) {
1764         /* Don't send and don't allow 3.4 clients to send jumbograms. */
1765         rx_SetNoJumbo();
1766     }
1767     rx_GetIFInfo();
1768     rx_SetRxDeadTime(30);
1769     sc[0] = rxnull_NewServerSecurityObject();
1770     sc[1] = 0;                  /* rxvab_NewServerSecurityObject(key1, 0) */
1771     sc[2] = rxkad_NewServerSecurityObject(rxkad_clear, NULL, get_key, NULL);
1772     sc[3] = rxkad_NewServerSecurityObject(rxkad_crypt, NULL, get_key, NULL);
1773     tservice = rx_NewService( /* port */ 0, /* service id */ 1, /*service name */
1774                              "AFS",
1775                                                         /* security classes */ sc,
1776                                                         /* numb sec classes */
1777                              4, RXAFS_ExecuteRequest);
1778     if (!tservice) {
1779         ViceLog(0,
1780                 ("Failed to initialize RX, probably two servers running.\n"));
1781         exit(-1);
1782     }
1783     rx_SetDestroyConnProc(tservice, (void (*)())h_FreeConnection);
1784     rx_SetMinProcs(tservice, 3);
1785     rx_SetMaxProcs(tservice, lwps);
1786     rx_SetCheckReach(tservice, 1);
1787
1788     tservice =
1789         rx_NewService(0, RX_STATS_SERVICE_ID, "rpcstats", sc, 4,
1790                       RXSTATS_ExecuteRequest);
1791     if (!tservice) {
1792         ViceLog(0, ("Failed to initialize rpc stat service.\n"));
1793         exit(-1);
1794     }
1795     rx_SetMinProcs(tservice, 2);
1796     rx_SetMaxProcs(tservice, 4);
1797
1798     /*
1799      * Enable RX hot threads, which allows the listener thread to trade
1800      * places with an idle thread and moves the context switch from listener
1801      * to worker out of the critical path.
1802      */
1803     rx_EnableHotThread();
1804
1805     /* Some rx debugging */
1806     if (rxlog || eventlog) {
1807         debugFile = afs_fopen("rx_dbg", "w");
1808         if (rxlog)
1809             rx_debugFile = debugFile;
1810         if (eventlog)
1811             rxevent_debugFile = debugFile;
1812     }
1813
1814     init_sys_error_to_et();     /* Set up error table translation */
1815     h_InitHostPackage();        /* set up local cellname and realmname */
1816     InitCallBack(numberofcbs);
1817     ClearXStatValues();
1818
1819     code = InitVL();
1820     if (code) {
1821         ViceLog(0, ("Fatal error in library initialization, exiting!!\n"));
1822         exit(1);
1823     }
1824
1825     code = InitPR();
1826     if (code) {
1827         ViceLog(0, ("Fatal error in protection initialization, exiting!!\n"));
1828         exit(1);
1829     }
1830
1831     /* allow super users to manage RX statistics */
1832     rx_SetRxStatUserOk(fs_rxstat_userok);
1833
1834     rx_StartServer(0);          /* now start handling requests */
1835
1836     /* we ensure that there is enough space in the vnode buffer to satisfy
1837      ** requests from all concurrent threads. 
1838      ** the maximum number of vnodes used by a single thread at any one time
1839      ** is three ( "link" uses three vnodes simultaneously, one vLarge and
1840      ** two vSmall for linking files and two vLarge and one vSmall for linking
1841      ** files  ) : dhruba 
1842      */
1843     minVnodesRequired = 2 * lwps + 1;
1844     if (minVnodesRequired > nSmallVns) {
1845         nSmallVns = minVnodesRequired;
1846         ViceLog(0,
1847                 ("Overriding -s command line parameter with %d\n",
1848                  nSmallVns));
1849     }
1850     if (minVnodesRequired > large) {
1851         large = minVnodesRequired;
1852         ViceLog(0, ("Overriding -l command line parameter with %d\n", large));
1853     }
1854
1855     /* We now do this after getting the listener up and running, so that client
1856      * connections don't timeout (maybe) if a file server is restarted, since it
1857      * will be available "real soon now".  Worry about whether we can satisfy the 
1858      * calls in the volume package itself.
1859      */
1860     if (VInitVolumePackage(fileServer, large, nSmallVns, 0, volcache)) {
1861         ViceLog(0,
1862                 ("Shutting down: errors encountered initializing volume package\n"));
1863         VShutdown();
1864         exit(1);
1865     }
1866
1867     /*
1868      * We are done calling fopen/fdopen. It is safe to use a large
1869      * of the file descriptor cache.
1870      */
1871     ih_UseLargeCache();
1872
1873 #ifdef AFS_PTHREAD_ENV
1874     ViceLog(5, ("Starting pthreads\n"));
1875     assert(pthread_attr_init(&tattr) == 0);
1876     assert(pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED) == 0);
1877
1878     assert(pthread_create
1879            (&serverPid, &tattr, (void *)FiveMinuteCheckLWP,
1880             &fiveminutes) == 0);
1881     assert(pthread_create
1882            (&serverPid, &tattr, (void *)HostCheckLWP, &fiveminutes) == 0);
1883     assert(pthread_create
1884            (&serverPid, &tattr, (void *)FsyncCheckLWP, &fiveminutes) == 0);
1885 #else /* AFS_PTHREAD_ENV */
1886     ViceLog(5, ("Starting LWP\n"));
1887     assert(LWP_CreateProcess
1888            (FiveMinuteCheckLWP, stack * 1024, LWP_MAX_PRIORITY - 2,
1889             (void *)&fiveminutes, "FiveMinuteChecks",
1890             &serverPid) == LWP_SUCCESS);
1891
1892     assert(LWP_CreateProcess
1893            (HostCheckLWP, stack * 1024, LWP_MAX_PRIORITY - 2,
1894             (void *)&fiveminutes, "HostCheck", &serverPid) == LWP_SUCCESS);
1895     assert(LWP_CreateProcess
1896            (FsyncCheckLWP, stack * 1024, LWP_MAX_PRIORITY - 2,
1897             (void *)&fiveminutes, "FsyncCheck", &serverPid) == LWP_SUCCESS);
1898 #endif /* AFS_PTHREAD_ENV */
1899
1900     TM_GetTimeOfDay(&tp, 0);
1901
1902 #ifndef AFS_QUIETFS_ENV
1903     if (console != NULL) { 
1904         time_t t = tp.tv_sec;
1905         fprintf(console, "File server has started at %s\r",
1906                 afs_ctime(&t, tbuffer, sizeof(tbuffer)));
1907     }
1908 #endif
1909
1910     /*
1911      * Figure out the FileServer's name and primary address.
1912      */
1913     ViceLog(0, ("Getting FileServer name...\n"));
1914     code = gethostname(FS_HostName, 64);
1915     if (code) {
1916         ViceLog(0, ("gethostname() failed\n"));
1917     }
1918     ViceLog(0, ("FileServer host name is '%s'\n", FS_HostName));
1919
1920     ViceLog(0, ("Getting FileServer address...\n"));
1921     he = gethostbyname(FS_HostName);
1922     if (!he) {
1923         ViceLog(0, ("Can't find address for FileServer '%s'\n", FS_HostName));
1924     } else {
1925         char hoststr[16];
1926         memcpy(&FS_HostAddr_NBO, he->h_addr, 4);
1927         (void)afs_inet_ntoa_r(FS_HostAddr_NBO, hoststr);
1928         FS_HostAddr_HBO = ntohl(FS_HostAddr_NBO);
1929         ViceLog(0,
1930                 ("FileServer %s has address %s (0x%x or 0x%x in host byte order)\n",
1931                  FS_HostName, hoststr, FS_HostAddr_NBO, FS_HostAddr_HBO));
1932     }
1933
1934     /* Install handler to catch the shutdown signal;
1935      * bosserver assumes SIGQUIT shutdown
1936      */
1937 #if defined(AFS_PTHREAD_ENV) && !defined(AFS_NT40_ENV)
1938     softsig_signal(SIGQUIT, ShutDown_Signal);
1939 #else
1940     (void)signal(SIGQUIT, ShutDown_Signal);
1941 #endif
1942
1943     t = tp.tv_sec;
1944     ViceLog(0,
1945             ("File Server started %s",
1946              afs_ctime(&t, tbuffer, sizeof(tbuffer))));
1947 #if FS_STATS_DETAILED
1948     afs_FullPerfStats.det.epoch.tv_sec = StartTime = tp.tv_sec;
1949 #endif
1950 #ifdef AFS_PTHREAD_ENV
1951     while (1) {
1952         sleep(1000);            /* long time */
1953     }
1954 #else /* AFS_PTHREAD_ENV */
1955     assert(LWP_WaitProcess(&parentPid) == LWP_SUCCESS);
1956 #endif /* AFS_PTHREAD_ENV */
1957 }