]> git.sesse.net Git - rdpsrv/blob - Xserver/programs/Xserver/os/utils.c
d2d042292676c48dc234d8c53a04e8ea85bd4f67
[rdpsrv] / Xserver / programs / Xserver / os / utils.c
1 /* $TOG: utils.c /main/128 1997/06/01 13:50:39 sekhar $ */
2 /*
3
4 Copyright (c) 1987  X Consortium
5
6 Permission is hereby granted, free of charge, to any person obtaining
7 a copy of this software and associated documentation files (the
8 "Software"), to deal in the Software without restriction, including
9 without limitation the rights to use, copy, modify, merge, publish,
10 distribute, sublicense, and/or sell copies of the Software, and to
11 permit persons to whom the Software is furnished to do so, subject to
12 the following conditions:
13
14 The above copyright notice and this permission notice shall be included
15 in all copies or substantial portions of the Software.
16
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR
21 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 OTHER DEALINGS IN THE SOFTWARE.
24
25 Except as contained in this notice, the name of the X Consortium shall
26 not be used in advertising or otherwise to promote the sale, use or
27 other dealings in this Software without prior written authorization
28 from the X Consortium.
29
30
31 Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,
32 Copyright 1994 Quarterdeck Office Systems.
33
34                         All Rights Reserved
35
36 Permission to use, copy, modify, and distribute this software and its
37 documentation for any purpose and without fee is hereby granted,
38 provided that the above copyright notice appear in all copies and that
39 both that copyright notice and this permission notice appear in
40 supporting documentation, and that the names of Digital and
41 Quarterdeck not be used in advertising or publicity pertaining to
42 distribution of the software without specific, written prior
43 permission.
44
45 DIGITAL AND QUARTERDECK DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
46 SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
47 FITNESS, IN NO EVENT SHALL DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT
48 OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
49 OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
50 OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
51 OR PERFORMANCE OF THIS SOFTWARE.
52
53 */
54 /* $XFree86: xc/programs/Xserver/os/utils.c,v 3.27.2.6 1998/02/20 15:13:58 robin Exp $ */
55
56 #ifdef WIN32
57 #include <X11/Xwinsock.h>
58 #endif
59 #include "Xos.h"
60 #include <stdio.h>
61 #include "misc.h"
62 #include "X.h"
63 #include "input.h"
64 #include "opaque.h"
65 #ifdef X_POSIX_C_SOURCE
66 #define _POSIX_C_SOURCE X_POSIX_C_SOURCE
67 #include <signal.h>
68 #undef _POSIX_C_SOURCE
69 #else
70 #if defined(X_NOT_POSIX) || defined(_POSIX_SOURCE)
71 #include <signal.h>
72 #else
73 #define _POSIX_SOURCE
74 #include <signal.h>
75 #undef _POSIX_SOURCE
76 #endif
77 #endif
78 #if !defined(SYSV) && !defined(AMOEBA) && !defined(_MINIX) && !defined(WIN32) && !defined(Lynx) || defined(hpux) || defined(AIXV4)
79 #include <sys/resource.h>
80 #endif
81 #include <time.h>
82 #include <sys/stat.h>
83 #include <ctype.h>    /* for isspace */
84 #if NeedVarargsPrototypes
85 #include <stdarg.h>
86 #endif
87
88 #ifdef AMOEBA
89 #include "osdep.h"
90 #include <amoeba.h>
91 #include <module/mutex.h>
92
93 static mutex print_lock;
94 #endif
95
96 #if defined(__STDC__) || defined(AMOEBA)
97 /* DHD: SVR4.0 has a prototype for abs() in stdlib.h */
98 /* DHD: might be better to move this include higher up? */
99 #ifdef abs
100 #undef abs
101 #endif
102 #ifndef NOSTDHDRS
103 #include <stdlib.h>     /* for malloc() */
104 #endif
105 #endif
106
107 extern char *display;
108
109 extern CARD32 defaultScreenSaverTime;   /* for parsing command line */
110 extern CARD32 defaultScreenSaverInterval;
111 extern int defaultScreenSaverBlanking;
112 extern int defaultBackingStore;
113 extern Bool disableBackingStore;
114 extern Bool disableSaveUnders;
115 extern Bool PartialNetwork;
116 #ifndef NOLOGOHACK
117 extern int logoScreenSaver;
118 #endif
119 #ifdef RLIMIT_DATA
120 extern int limitDataSpace;
121 #endif
122 #ifdef RLIMIT_STACK
123 extern int limitStackSpace;
124 #endif
125 #ifdef RLIMIT_NOFILE
126 extern int limitNoFile;
127 #endif
128 extern int defaultColorVisualClass;
129 extern Bool permitOldBugs;
130 extern int monitorResolution;
131 extern Bool defeatAccessControl;
132 #ifdef SERVER_LOCK
133 static Bool nolock = FALSE;
134 #endif
135
136 extern char* protNoListen;
137
138 Bool CoreDump;
139 Bool noTestExtensions;
140
141 int auditTrailLevel = 1;
142
143 void ddxUseMsg();
144 #if NeedVarargsPrototypes
145 void VErrorF(char*, va_list);
146 #endif
147
148 #ifdef DEBUG
149 #ifndef SPECIAL_MALLOC
150 #define MEMBUG
151 #endif
152 #endif
153
154 #ifdef MEMBUG
155 #define MEM_FAIL_SCALE 100000
156 long Memory_fail = 0;
157 #ifdef linux
158 #include <stdlib.h>  /* for random() */
159 #endif
160 #endif
161
162 #ifdef sgi
163 int userdefinedfontpath = 0;
164 #endif /* sgi */
165
166 Bool Must_have_memory = FALSE;
167
168 char *dev_tty_from_init = NULL;         /* since we need to parse it anyway */
169
170 OsSigHandlerPtr
171 OsSignal(sig, handler)
172     int sig;
173     OsSigHandlerPtr handler;
174 {
175 #ifdef X_NOT_POSIX
176     return signal(sig, handler);
177 #else
178     struct sigaction act, oact;
179
180     sigemptyset(&act.sa_mask);
181     if (handler != SIG_IGN)
182         sigaddset(&act.sa_mask, sig);
183     act.sa_flags = 0;
184     act.sa_handler = handler;
185     sigaction(sig, &act, &oact);
186     return oact.sa_handler;
187 #endif
188 }
189
190 #include <errno.h>
191 extern int errno;
192
193 #ifdef SERVER_LOCK
194 /*
195  * Explicit support for a server lock file like the ones used for UUCP.
196  * For architectures with virtual terminals that can run more than one
197  * server at a time.  This keeps the servers from stomping on each other
198  * if the user forgets to give them different display numbers.
199  */
200 #ifndef __EMX__
201 #define LOCK_DIR "/tmp"
202 #define LOCK_TMP_PREFIX "/.tX"
203 #define LOCK_PREFIX "/.X"
204 #define LOCK_SUFFIX "-lock"
205 #else
206 #define LOCK_TMP_PREFIX "/xf86$"
207 #define LOCK_PREFIX "/xf86_"
208 #define LOCK_SUFFIX ".lck"
209 #endif
210
211 #ifdef _MINIX
212 #include <limits.h>     /* For PATH_MAX */
213 #endif
214
215 #ifdef __EMX__
216 #define link rename
217 #endif
218
219 #ifndef PATH_MAX
220 #ifndef Lynx
221 #include <sys/param.h>
222 #else
223 #include <param.h>
224 #endif
225 #ifndef PATH_MAX
226 #ifdef MAXPATHLEN
227 #define PATH_MAX MAXPATHLEN
228 #else
229 #define PATH_MAX 1024
230 #endif
231 #endif
232 #endif
233
234 static Bool StillLocking = FALSE;
235 static char LockFile[PATH_MAX];
236
237 /*
238  * LockServer --
239  *      Check if the server lock file exists.  If so, check if the PID
240  *      contained inside is valid.  If so, then die.  Otherwise, create
241  *      the lock file containing the PID.
242  */
243 void
244 LockServer()
245 {
246 #ifndef AMOEBA
247   char tmp[PATH_MAX], pid_str[12];
248   int lfd, i, haslock, l_pid, t;
249   char *tmppath = NULL;
250   int len;
251
252   if (nolock) return;
253   /*
254    * Path names
255    */
256 #ifndef __EMX__
257   tmppath = LOCK_DIR;
258 #else
259   /* OS/2 uses TMP directory, must also prepare for 8.3 names */
260   tmppath = getenv("TMP");
261   if (!tmppath)
262     FatalError("No TMP dir found\n");
263 #endif
264
265   len = strlen(LOCK_PREFIX) > strlen(LOCK_TMP_PREFIX) ? strlen(LOCK_PREFIX) :
266                                                 strlen(LOCK_TMP_PREFIX);
267   len += strlen(tmppath) + strlen(display) + strlen(LOCK_SUFFIX) + 1;
268   if (len > sizeof(LockFile))
269     FatalError("Display name `%s' is too long\n");
270   (void)sprintf(tmp, "%s" LOCK_TMP_PREFIX "%s" LOCK_SUFFIX, tmppath, display);
271   (void)sprintf(LockFile, "%s" LOCK_PREFIX "%s" LOCK_SUFFIX, tmppath, display);
272
273   /*
274    * Create a temporary file containing our PID.  Attempt three times
275    * to create the file.
276    */
277   StillLocking = TRUE;
278   i = 0;
279   do {
280     i++;
281     lfd = open(tmp, O_CREAT | O_EXCL | O_WRONLY, 0644);
282     if (lfd < 0)
283        sleep(2);
284     else
285        break;
286   } while (i < 3);
287   if (lfd < 0) {
288     unlink(tmp);
289     i = 0;
290     do {
291       i++;
292       lfd = open(tmp, O_CREAT | O_EXCL | O_WRONLY, 0644);
293       if (lfd < 0)
294          sleep(2);
295       else
296          break;
297     } while (i < 3);
298   }
299   if (lfd < 0)
300     FatalError("Could not create lock file in %s\n", tmp);
301   (void) sprintf(pid_str, "%10d\n", getpid());
302   (void) write(lfd, pid_str, 11);
303 #ifndef __EMX__
304 #ifndef USE_CHMOD
305   (void) fchmod(lfd, 0444);
306 #else
307   (void) chmod(tmp, 0444);
308 #endif
309 #endif
310   (void) close(lfd);
311
312   /*
313    * OK.  Now the tmp file exists.  Try three times to move it in place
314    * for the lock.
315    */
316   i = 0;
317   haslock = 0;
318   while ((!haslock) && (i++ < 3)) {
319     haslock = (link(tmp,LockFile) == 0);
320     if (haslock) {
321       /*
322        * We're done.
323        */
324       break;
325     }
326     else {
327       /*
328        * Read the pid from the existing file
329        */
330       lfd = open(LockFile, O_RDONLY);
331       if (lfd < 0) {
332         unlink(tmp);
333         FatalError("Can't read lock file %s\n", LockFile);
334       }
335       pid_str[0] = '\0';
336       if (read(lfd, pid_str, 11) != 11) {
337         /*
338          * Bogus lock file.
339          */
340         unlink(LockFile);
341         close(lfd);
342         continue;
343       }
344       pid_str[11] = '\0';
345       sscanf(pid_str, "%d", &l_pid);
346       close(lfd);
347
348       /*
349        * Now try to kill the PID to see if it exists.
350        */
351       errno = 0;
352       t = kill(l_pid, 0);
353       if ((t< 0) && (errno == ESRCH)) {
354         /*
355          * Stale lock file.
356          */
357         unlink(LockFile);
358         continue;
359       }
360       else if (((t < 0) && (errno == EPERM)) || (t == 0)) {
361         /*
362          * Process is still active.
363          */
364         unlink(tmp);
365         FatalError("Server is already active for display %s\n%s %s\n%s\n",
366                    display, "\tIf this server is no longer running, remove",
367                    LockFile, "\tand start again.");
368       }
369     }
370   }
371   unlink(tmp);
372   if (!haslock)
373     FatalError("Could not create server lock file: %s\n", LockFile);
374   StillLocking = FALSE;
375 #endif /* !AMOEBA */
376 }
377
378 /*
379  * UnlockServer --
380  *      Remove the server lock file.
381  */
382 void
383 UnlockServer()
384 {
385 #ifndef AMOEBA
386   if (nolock) return;
387
388   if (!StillLocking){
389
390 #ifdef __EMX__
391   (void) chmod(LockFile,S_IREAD|S_IWRITE);
392 #endif /* __EMX__ */
393   (void) unlink(LockFile);
394   }
395 #endif
396
397 }
398 #endif /* SERVER_LOCK */
399
400 /* Force connections to close on SIGHUP from init */
401
402 /*ARGSUSED*/
403 SIGVAL
404 AutoResetServer (sig)
405     int sig;
406 {
407     dispatchException |= DE_RESET;
408     isItTimeToYield = TRUE;
409 #ifdef GPROF
410     chdir ("/tmp");
411     exit (0);
412 #endif
413 #if defined(SYSV) && defined(X_NOT_POSIX)
414     OsSignal (SIGHUP, AutoResetServer);
415 #endif
416 #ifdef AMOEBA
417     WakeUpMainThread();
418 #endif
419 }
420
421 /* Force connections to close and then exit on SIGTERM, SIGINT */
422
423 /*ARGSUSED*/
424 SIGVAL
425 GiveUp(sig)
426     int sig;
427 {
428     dispatchException |= DE_TERMINATE;
429     isItTimeToYield = TRUE;
430 #if defined(SYSV) && defined(X_NOT_POSIX)
431     if (sig)
432         OsSignal(sig, SIG_IGN);
433 #endif
434 #ifdef AMOEBA
435     WakeUpMainThread();
436 #endif
437 }
438
439 #if __GNUC__
440 static void AbortServer() __attribute__((noreturn));
441 #endif
442
443 static void
444 AbortServer()
445 {
446     extern void AbortDDX();
447
448     OsCleanup();
449     AbortDDX();
450     fflush(stderr);
451 #ifdef AMOEBA
452     IOPCleanUp();
453 #endif
454     if (CoreDump)
455         abort();
456     exit (1);
457 }
458
459 void
460 Error(str)
461     char *str;
462 {
463 #ifdef AMOEBA
464     mu_lock(&print_lock);
465 #endif
466     perror(str);
467 #ifdef AMOEBA
468     mu_unlock(&print_lock);
469 #endif
470 }
471
472 #ifndef DDXTIME
473 CARD32
474 GetTimeInMillis()
475 {
476 #ifndef AMOEBA
477     struct timeval  tp;
478
479     X_GETTIMEOFDAY(&tp);
480     return(tp.tv_sec * 1000) + (tp.tv_usec / 1000);
481 #else
482     return sys_milli();
483 #endif
484 }
485 #endif
486
487 AdjustWaitForDelay (waitTime, newdelay)
488     pointer         waitTime;
489     unsigned long   newdelay;
490 {
491     static struct timeval   delay_val;
492     struct timeval          **wt = (struct timeval **) waitTime;
493     unsigned long           olddelay;
494
495     if (*wt == NULL)
496     {
497         delay_val.tv_sec = newdelay / 1000;
498         delay_val.tv_usec = 1000 * (newdelay % 1000);
499         *wt = &delay_val;
500     }
501     else
502     {
503         olddelay = (*wt)->tv_sec * 1000 + (*wt)->tv_usec / 1000;
504         if (newdelay < olddelay)
505         {
506             (*wt)->tv_sec = newdelay / 1000;
507             (*wt)->tv_usec = 1000 * (newdelay % 1000);
508         }
509     }
510 }
511
512 void UseMsg()
513 {
514 #if !defined(AIXrt) && !defined(AIX386)
515 #ifndef AMOEBA
516     ErrorF("use: X [:<display>] [option]\n");
517 #else
518     ErrorF("use: X [[<host>]:<display>] [option]\n");
519 #endif
520     ErrorF("-a #                   mouse acceleration (pixels)\n");
521     ErrorF("-ac                    disable access control restrictions\n");
522 #ifdef MEMBUG
523     ErrorF("-alloc int             chance alloc should fail\n");
524 #endif
525     ErrorF("-audit int             set audit trail level\n");   
526     ErrorF("-auth file             select authorization file\n");       
527     ErrorF("bc                     enable bug compatibility\n");
528     ErrorF("-bs                    disable any backing store support\n");
529     ErrorF("-c                     turns off key-click\n");
530     ErrorF("c #                    key-click volume (0-100)\n");
531     ErrorF("-cc int                default color visual class\n");
532     ErrorF("-co file               color database file\n");
533 #if 0
534     ErrorF("-config file           read options from file\n");
535 #endif
536     ErrorF("-core                  generate core dump on fatal error\n");
537     ErrorF("-dpi int               screen resolution in dots per inch\n");
538 #ifdef DPMSExtension
539     ErrorF("dpms                   enables VESA DPMS monitor control\n");
540     ErrorF("-dpms                  disables VESA DPMS monitor control\n");
541 #endif
542     ErrorF("-deferglyphs [none|all|16] defer loading of [no|all|16-bit] glyphs\n");
543     ErrorF("-f #                   bell base (0-100)\n");
544     ErrorF("-fc string             cursor font\n");
545     ErrorF("-fn string             default font name\n");
546     ErrorF("-fp string             default font path\n");
547     ErrorF("-help                  prints message with these options\n");
548     ErrorF("-I                     ignore all remaining arguments\n");
549 #ifdef RLIMIT_DATA
550     ErrorF("-ld int                limit data space to N Kb\n");
551 #endif
552 #ifdef RLIMIT_NOFILE
553     ErrorF("-lf int                limit number of open files to N\n");
554 #endif
555 #ifdef RLIMIT_STACK
556     ErrorF("-ls int                limit stack space to N Kb\n");
557 #endif
558 #ifdef SERVER_LOCK
559     ErrorF("-nolock                disable the locking mechanism\n");
560 #endif
561 #ifndef NOLOGOHACK
562     ErrorF("-logo                  enable logo in screen saver\n");
563     ErrorF("nologo                 disable logo in screen saver\n");
564 #endif
565     ErrorF("-nolisten string       don't listen on protocol\n");
566     ErrorF("-p #                   screen-saver pattern duration (minutes)\n");
567     ErrorF("-pn                    accept failure to listen on all ports\n");
568     ErrorF("-nopn                  reject failure to listen on all ports\n");
569     ErrorF("-r                     turns off auto-repeat\n");
570     ErrorF("r                      turns on auto-repeat \n");
571     ErrorF("-s #                   screen-saver timeout (minutes)\n");
572 #ifdef XCSECURITY
573     ErrorF("-sp file               security policy file\n");
574 #endif
575     ErrorF("-su                    disable any save under support\n");
576     ErrorF("-t #                   mouse threshold (pixels)\n");
577     ErrorF("-terminate             terminate at server reset\n");
578     ErrorF("-to #                  connection time out\n");
579     ErrorF("-tst                   disable testing extensions\n");
580     ErrorF("ttyxx                  server started from init on /dev/ttyxx\n");
581     ErrorF("v                      video blanking for screen-saver\n");
582     ErrorF("-v                     screen-saver without video blanking\n");
583     ErrorF("-wm                    WhenMapped default backing-store\n");
584     ErrorF("-x string              loads named extension at init time \n");
585 #ifdef AMOEBA
586     ErrorF("-tcp capability        specify TCP/IP server capability\n");
587 #endif
588 #ifdef XDMCP
589     XdmcpUseMsg();
590 #endif
591 #endif /* !AIXrt && ! AIX386 */
592 #ifdef XKB
593     XkbUseMsg();
594 #endif
595     ddxUseMsg();
596 }
597
598 /*
599  * This function parses the command line. Handles device-independent fields
600  * and allows ddx to handle additional fields.  It is not allowed to modify
601  * argc or any of the strings pointed to by argv.
602  */
603 void
604 ProcessCommandLine ( argc, argv )
605 int     argc;
606 char    *argv[];
607
608 {
609     int i, skip;
610
611 #ifdef AMOEBA
612     mu_init(&print_lock);
613 #endif
614
615     defaultKeyboardControl.autoRepeat = TRUE;
616
617 #ifdef PART_NET
618         PartialNetwork = TRUE;
619 #endif
620
621     for ( i = 1; i < argc; i++ )
622     {
623         /* call ddx first, so it can peek/override if it wants */
624         if(skip = ddxProcessArgument(argc, argv, i))
625         {
626             i += (skip - 1);
627         }
628         else if(argv[i][0] ==  ':')  
629         {
630             /* initialize display */
631             display = argv[i];
632             display++;
633         }
634 #ifdef AMOEBA
635         else if (strchr(argv[i], ':') != NULL) {
636             char *p;
637
638             XServerHostName = argv[i];
639             if ((p = strchr(argv[i], ':')) != NULL) {
640                 *p++ = '\0';
641                 display = p;
642             }
643         } else if (strcmp( argv[i], "-tcp") == 0) {
644             if (++i < argc)
645                 XTcpServerName = argv[i];
646             else
647                 UseMsg();
648         }
649 #endif /* AMOEBA */
650         else if ( strcmp( argv[i], "-a") == 0)
651         {
652             if(++i < argc)
653                 defaultPointerControl.num = atoi(argv[i]);
654             else
655                 UseMsg();
656         }
657         else if ( strcmp( argv[i], "-ac") == 0)
658         {
659             defeatAccessControl = TRUE;
660         }
661 #ifdef MEMBUG
662         else if ( strcmp( argv[i], "-alloc") == 0)
663         {
664             if(++i < argc)
665                 Memory_fail = atoi(argv[i]);
666             else
667                 UseMsg();
668         }
669 #endif
670         else if ( strcmp( argv[i], "-audit") == 0)
671         {
672             if(++i < argc)
673                 auditTrailLevel = atoi(argv[i]);
674             else
675                 UseMsg();
676         }
677         else if ( strcmp( argv[i], "-auth") == 0)
678         {
679             if(++i < argc)
680                 InitAuthorization (argv[i]);
681             else
682                 UseMsg();
683         }
684         else if ( strcmp( argv[i], "bc") == 0)
685             permitOldBugs = TRUE;
686         else if ( strcmp( argv[i], "-bs") == 0)
687             disableBackingStore = TRUE;
688         else if ( strcmp( argv[i], "c") == 0)
689         {
690             if(++i < argc)
691                 defaultKeyboardControl.click = atoi(argv[i]);
692             else
693                 UseMsg();
694         }
695         else if ( strcmp( argv[i], "-c") == 0)
696         {
697             defaultKeyboardControl.click = 0;
698         }
699         else if ( strcmp( argv[i], "-cc") == 0)
700         {
701             if(++i < argc)
702                 defaultColorVisualClass = atoi(argv[i]);
703             else
704                 UseMsg();
705         }
706         else if ( strcmp( argv[i], "-co") == 0)
707         {
708             if(++i < argc)
709                 rgbPath = argv[i];
710             else
711                 UseMsg();
712         }
713         else if ( strcmp( argv[i], "-core") == 0)
714             CoreDump = TRUE;
715         else if ( strcmp( argv[i], "-dpi") == 0)
716         {
717             if(++i < argc)
718                 monitorResolution = atoi(argv[i]);
719             else
720                 UseMsg();
721         }
722 #ifdef DPMSExtension
723         else if ( strcmp( argv[i], "dpms") == 0)
724             DPMSEnabledSwitch = TRUE;
725         else if ( strcmp( argv[i], "-dpms") == 0)
726             DPMSDisabledSwitch = TRUE;
727 #endif
728         else if ( strcmp( argv[i], "-deferglyphs") == 0)
729         {
730             if(++i >= argc || !ParseGlyphCachingMode(argv[i]))
731                 UseMsg();
732         }
733         else if ( strcmp( argv[i], "-f") == 0)
734         {
735             if(++i < argc)
736                 defaultKeyboardControl.bell = atoi(argv[i]);
737             else
738                 UseMsg();
739         }
740         else if ( strcmp( argv[i], "-fc") == 0)
741         {
742             if(++i < argc)
743                 defaultCursorFont = argv[i];
744             else
745                 UseMsg();
746         }
747         else if ( strcmp( argv[i], "-fn") == 0)
748         {
749             if(++i < argc)
750                 defaultTextFont = argv[i];
751             else
752                 UseMsg();
753         }
754         else if ( strcmp( argv[i], "-fp") == 0)
755         {
756             if(++i < argc)
757             {
758 #ifdef sgi
759                 userdefinedfontpath = 1;
760 #endif /* sgi */
761                 defaultFontPath = argv[i];
762             }
763             else
764                 UseMsg();
765         }
766         else if ( strcmp( argv[i], "-help") == 0)
767         {
768             UseMsg();
769             exit(0);
770         }
771 #ifdef XKB
772         else if ( (skip=XkbProcessArguments(argc,argv,i))!=0 ) {
773             if (skip>0)
774                  i+= skip-1;
775             else UseMsg();
776         }
777 #endif
778 #ifdef RLIMIT_DATA
779         else if ( strcmp( argv[i], "-ld") == 0)
780         {
781             if(++i < argc)
782             {
783                 limitDataSpace = atoi(argv[i]);
784                 if (limitDataSpace > 0)
785                     limitDataSpace *= 1024;
786             }
787             else
788                 UseMsg();
789         }
790 #endif
791 #ifdef RLIMIT_NOFILE
792         else if ( strcmp( argv[i], "-lf") == 0)
793         {
794             if(++i < argc)
795                 limitNoFile = atoi(argv[i]);
796             else
797                 UseMsg();
798         }
799 #endif
800 #ifdef RLIMIT_STACK
801         else if ( strcmp( argv[i], "-ls") == 0)
802         {
803             if(++i < argc)
804             {
805                 limitStackSpace = atoi(argv[i]);
806                 if (limitStackSpace > 0)
807                     limitStackSpace *= 1024;
808             }
809             else
810                 UseMsg();
811         }
812 #endif
813 #ifdef SERVER_LOCK
814         else if ( strcmp ( argv[i], "-nolock") == 0)
815         {
816             nolock = TRUE;
817         }
818 #endif
819 #ifndef NOLOGOHACK
820         else if ( strcmp( argv[i], "-logo") == 0)
821         {
822             logoScreenSaver = 1;
823         }
824         else if ( strcmp( argv[i], "nologo") == 0)
825         {
826             logoScreenSaver = 0;
827         }
828 #endif
829         else if ( strcmp( argv[i], "-nolisten") == 0)
830         {
831             if(++i < argc)
832                 protNoListen = argv[i];
833             else
834                 UseMsg();
835         }
836         else if ( strcmp( argv[i], "-p") == 0)
837         {
838             if(++i < argc)
839                 defaultScreenSaverInterval = ((CARD32)atoi(argv[i])) *
840                                              MILLI_PER_MIN;
841             else
842                 UseMsg();
843         }
844         else if ( strcmp( argv[i], "-pn") == 0)
845             PartialNetwork = TRUE;
846         else if ( strcmp( argv[i], "-nopn") == 0)
847             PartialNetwork = FALSE;
848         else if ( strcmp( argv[i], "r") == 0)
849             defaultKeyboardControl.autoRepeat = TRUE;
850         else if ( strcmp( argv[i], "-r") == 0)
851             defaultKeyboardControl.autoRepeat = FALSE;
852         else if ( strcmp( argv[i], "-s") == 0)
853         {
854             if(++i < argc)
855                 defaultScreenSaverTime = ((CARD32)atoi(argv[i])) *
856                                          MILLI_PER_MIN;
857             else
858                 UseMsg();
859         }
860         else if ( strcmp( argv[i], "-su") == 0)
861             disableSaveUnders = TRUE;
862         else if ( strcmp( argv[i], "-t") == 0)
863         {
864             if(++i < argc)
865                 defaultPointerControl.threshold = atoi(argv[i]);
866             else
867                 UseMsg();
868         }
869         else if ( strcmp( argv[i], "-terminate") == 0)
870         {
871             extern Bool terminateAtReset;
872             
873             terminateAtReset = TRUE;
874         }
875         else if ( strcmp( argv[i], "-to") == 0)
876         {
877             if(++i < argc)
878                 TimeOutValue = ((CARD32)atoi(argv[i])) * MILLI_PER_SECOND;
879             else
880                 UseMsg();
881         }
882         else if ( strcmp( argv[i], "-tst") == 0)
883         {
884             noTestExtensions = TRUE;
885         }
886         else if ( strcmp( argv[i], "v") == 0)
887             defaultScreenSaverBlanking = PreferBlanking;
888         else if ( strcmp( argv[i], "-v") == 0)
889             defaultScreenSaverBlanking = DontPreferBlanking;
890         else if ( strcmp( argv[i], "-wm") == 0)
891             defaultBackingStore = WhenMapped;
892         else if ( strcmp( argv[i], "-x") == 0)
893         {
894             if(++i >= argc)
895                 UseMsg();
896             /* For U**x, which doesn't support dynamic loading, there's nothing
897              * to do when we see a -x.  Either the extension is linked in or
898              * it isn't */
899         }
900         else if ( strcmp( argv[i], "-I") == 0)
901         {
902             /* ignore all remaining arguments */
903             break;
904         }
905         else if (strncmp (argv[i], "tty", 3) == 0)
906         {
907             /* just in case any body is interested */
908             dev_tty_from_init = argv[i];
909         }
910 #ifdef XDMCP
911         else if ((skip = XdmcpOptions(argc, argv, i)) != i)
912         {
913             i = skip - 1;
914         }
915 #endif
916 #ifdef XPRINT
917         else if ((skip = XprintOptions(argc, argv, i)) != i)
918         {
919             i = skip - 1;
920         }
921 #endif
922 #ifdef XCSECURITY
923         else if ((skip = XSecurityOptions(argc, argv, i)) != i)
924         {
925             i = skip - 1;
926         }
927 #endif
928         else
929         {
930             ErrorF("Unrecognized option: %s\n", argv[i]);
931             UseMsg();
932             exit (1);
933         }
934     }
935 }
936
937 #if 0
938 static void
939 InsertFileIntoCommandLine(resargc, resargv, prefix_argc, prefix_argv,
940                           filename, suffix_argc, suffix_argv)
941     int *resargc;
942     char ***resargv;
943     int prefix_argc;
944     char **prefix_argv;
945     char *filename;
946     int suffix_argc;
947     char **suffix_argv;
948 {
949     struct stat     st;
950     FILE           *f;
951     char           *p;
952     char           *q;
953     int             insert_argc;
954     char           *buf;
955     int             len;
956     int             i;
957
958     f = fopen(filename, "r");
959     if (!f)
960         FatalError("Can't open option file %s\n", filename);
961
962     fstat(fileno(f), &st);
963
964     buf = (char *) xalloc((unsigned) st.st_size + 1);
965     if (!buf)
966         FatalError("Out of Memory\n");
967
968     len = fread(buf, 1, (unsigned) st.st_size, f);
969
970     fclose(f);
971
972     if (len < 0)
973         FatalError("Error reading option file %s\n", filename);
974
975     buf[len] = '\0';
976
977     p = buf;
978     q = buf;
979     insert_argc = 0;
980
981     while (*p)
982     {
983         while (isspace(*p))
984             p++;
985         if (!*p)
986             break;
987         if (*p == '#')
988         {
989             while (*p && *p != '\n')
990                 p++;
991         } else
992         {
993             while (*p && !isspace(*p))
994                 *q++ = *p++;
995             /* Since p and q might still be pointing at the same place, we       */
996             /* need to step p over the whitespace now before we add the null.    */
997             if (*p)
998                 p++;
999             *q++ = '\0';
1000             insert_argc++;
1001         }
1002     }
1003
1004     buf = (char *) xrealloc(buf, q - buf);
1005     if (!buf)
1006         FatalError("Out of memory reallocing option buf\n");
1007
1008     *resargc = prefix_argc + insert_argc + suffix_argc;
1009     *resargv = (char **) xalloc((*resargc + 1) * sizeof(char *));
1010
1011     memcpy(*resargv, prefix_argv, prefix_argc * sizeof(char *));
1012
1013     p = buf;
1014     for (i = 0; i < insert_argc; i++)
1015     {
1016         (*resargv)[prefix_argc + i] = p;
1017         p += strlen(p) + 1;
1018     }
1019
1020     memcpy(*resargv + prefix_argc + insert_argc,
1021            suffix_argv, suffix_argc * sizeof(char *));
1022
1023     (*resargv)[*resargc] = NULL;
1024 } /* end InsertFileIntoCommandLine */
1025
1026 void
1027 ExpandCommandLine(pargc, pargv)
1028     int *pargc;
1029     char ***pargv;
1030 {
1031     int i;
1032
1033     for (i = 1; i < *pargc; i++)
1034     {
1035         if ( (0 == strcmp((*pargv)[i], "-config")) && (i < (*pargc - 1)) )
1036         {
1037             InsertFileIntoCommandLine(pargc, pargv,
1038                                           i, *pargv,
1039                                           (*pargv)[i+1], /* filename */
1040                                           *pargc - i - 2, *pargv + i + 2);
1041             i--;
1042         }
1043     }
1044 } /* end ExpandCommandLine */
1045 #endif
1046
1047 #if defined(TCPCONN) || defined(STREAMSCONN)
1048 #ifndef WIN32
1049 #include <netdb.h>
1050 #endif
1051 #endif
1052
1053 /* Implement a simple-minded font authorization scheme.  The authorization
1054    name is "hp-hostname-1", the contents are simply the host name. */
1055 int
1056 set_font_authorizations(authorizations, authlen, client)
1057 char **authorizations;
1058 int *authlen;
1059 pointer client;
1060 {
1061 #define AUTHORIZATION_NAME "hp-hostname-1"
1062 #if defined(TCPCONN) || defined(STREAMSCONN)
1063     static char result[1024];
1064     static char *p = NULL;
1065
1066     if (p == NULL)
1067     {
1068         char hname[1024], *hnameptr;
1069         struct hostent *host;
1070         int len;
1071
1072         gethostname(hname, 1024);
1073         host = gethostbyname(hname);
1074         if (host == NULL)
1075             hnameptr = hname;
1076         else
1077             hnameptr = host->h_name;
1078
1079         p = result;
1080         *p++ = sizeof(AUTHORIZATION_NAME) >> 8;
1081         *p++ = sizeof(AUTHORIZATION_NAME) & 0xff;
1082         *p++ = (len = strlen(hnameptr) + 1) >> 8;
1083         *p++ = (len & 0xff);
1084
1085         memmove(p, AUTHORIZATION_NAME, sizeof(AUTHORIZATION_NAME));
1086         p += sizeof(AUTHORIZATION_NAME);
1087         memmove(p, hnameptr, len);
1088         p += len;
1089     }
1090     *authlen = p - result;
1091     *authorizations = result;
1092     return 1;
1093 #else /* TCPCONN */
1094     return 0;
1095 #endif /* TCPCONN */
1096 }
1097
1098 /* XALLOC -- X's internal memory allocator.  Why does it return unsigned
1099  * long * instead of the more common char *?  Well, if you read K&R you'll
1100  * see they say that alloc must return a pointer "suitable for conversion"
1101  * to whatever type you really want.  In a full-blown generic allocator
1102  * there's no way to solve the alignment problems without potentially
1103  * wasting lots of space.  But we have a more limited problem. We know
1104  * we're only ever returning pointers to structures which will have to
1105  * be long word aligned.  So we are making a stronger guarantee.  It might
1106  * have made sense to make Xalloc return char * to conform with people's
1107  * expectations of malloc, but this makes lint happier.
1108  */
1109
1110 #ifndef INTERNAL_MALLOC
1111
1112 unsigned long * 
1113 Xalloc (amount)
1114     unsigned long amount;
1115 {
1116 #if !defined(__STDC__) && !defined(AMOEBA)
1117     char                *malloc();
1118 #endif
1119     register pointer  ptr;
1120         
1121     if ((long)amount <= 0) {
1122         return (unsigned long *)NULL;
1123     }
1124     /* aligned extra on long word boundary */
1125     amount = (amount + (sizeof(long) - 1)) & ~(sizeof(long) - 1);
1126 #ifdef MEMBUG
1127     if (!Must_have_memory && Memory_fail &&
1128         ((random() % MEM_FAIL_SCALE) < Memory_fail))
1129         return (unsigned long *)NULL;
1130 #endif
1131     if (ptr = (pointer)malloc(amount)) {
1132         return (unsigned long *)ptr;
1133     }
1134     if (Must_have_memory)
1135         FatalError("Out of memory");
1136     return (unsigned long *)NULL;
1137 }
1138
1139 /*****************
1140  * XNFalloc 
1141  * "no failure" realloc, alternate interface to Xalloc w/o Must_have_memory
1142  *****************/
1143
1144 unsigned long *
1145 XNFalloc (amount)
1146     unsigned long amount;
1147 {
1148 #if !defined(__STDC__) && !defined(AMOEBA)
1149     char             *malloc();
1150 #endif
1151     register pointer ptr;
1152
1153     if ((long)amount <= 0)
1154     {
1155         return (unsigned long *)NULL;
1156     }
1157     /* aligned extra on long word boundary */
1158     amount = (amount + (sizeof(long) - 1)) & ~(sizeof(long) - 1);
1159     ptr = (pointer)malloc(amount);
1160     if (!ptr)
1161     {
1162         FatalError("Out of memory");
1163     }
1164     return ((unsigned long *)ptr);
1165 }
1166
1167 /*****************
1168  * Xcalloc
1169  *****************/
1170
1171 unsigned long *
1172 Xcalloc (amount)
1173     unsigned long   amount;
1174 {
1175     unsigned long   *ret;
1176
1177     ret = Xalloc (amount);
1178     if (ret)
1179         bzero ((char *) ret, (int) amount);
1180     return ret;
1181 }
1182
1183 /*****************
1184  * Xrealloc
1185  *****************/
1186
1187 unsigned long *
1188 Xrealloc (ptr, amount)
1189     register pointer ptr;
1190     unsigned long amount;
1191 {
1192 #if !defined(__STDC__) && !defined(AMOEBA)
1193     char *malloc();
1194     char *realloc();
1195 #endif
1196
1197 #ifdef MEMBUG
1198     if (!Must_have_memory && Memory_fail &&
1199         ((random() % MEM_FAIL_SCALE) < Memory_fail))
1200         return (unsigned long *)NULL;
1201 #endif
1202     if ((long)amount <= 0)
1203     {
1204         if (ptr && !amount)
1205             free(ptr);
1206         return (unsigned long *)NULL;
1207     }
1208     amount = (amount + (sizeof(long) - 1)) & ~(sizeof(long) - 1);
1209     if (ptr)
1210         ptr = (pointer)realloc((char *)ptr, amount);
1211     else
1212         ptr = (pointer)malloc(amount);
1213     if (ptr)
1214         return (unsigned long *)ptr;
1215     if (Must_have_memory)
1216         FatalError("Out of memory");
1217     return (unsigned long *)NULL;
1218 }
1219                     
1220 /*****************
1221  * XNFrealloc 
1222  * "no failure" realloc, alternate interface to Xrealloc w/o Must_have_memory
1223  *****************/
1224
1225 unsigned long *
1226 XNFrealloc (ptr, amount)
1227     register pointer ptr;
1228     unsigned long amount;
1229 {
1230     if (( ptr = (pointer)Xrealloc( ptr, amount ) ) == NULL)
1231     {
1232         FatalError( "Out of memory" );
1233     }
1234     return ((unsigned long *)ptr);
1235 }
1236
1237 /*****************
1238  *  Xfree
1239  *    calls free 
1240  *****************/    
1241
1242 void
1243 Xfree(ptr)
1244     register pointer ptr;
1245 {
1246     if (ptr)
1247         free((char *)ptr); 
1248 }
1249
1250 void
1251 OsInitAllocator ()
1252 {
1253 #ifdef MEMBUG
1254     static int  been_here;
1255
1256     /* Check the memory system after each generation */
1257     if (been_here)
1258         CheckMemory ();
1259     else
1260         been_here = 1;
1261 #endif
1262 }
1263 #endif
1264
1265 void
1266 AuditPrefix(f)
1267     char *f;
1268 {
1269 #ifdef X_NOT_STDC_ENV
1270     long tm;
1271 #else
1272     time_t tm;
1273 #endif
1274     char *autime, *s;
1275     if (*f != ' ')
1276     {
1277         time(&tm);
1278         autime = ctime(&tm);
1279         if (s = strchr(autime, '\n'))
1280             *s = '\0';
1281         if (s = strrchr(argvGlobal[0], '/'))
1282             s++;
1283         else
1284             s = argvGlobal[0];
1285         ErrorF("AUDIT: %s: %d %s: ", autime, getpid(), s);
1286     }
1287 }
1288
1289 /*VARARGS1*/
1290 void
1291 AuditF(
1292 #if NeedVarargsPrototypes
1293     char * f, ...)
1294 #else
1295     f, s0, s1, s2, s3, s4, s5, s6, s7, s8, s9) /* limit of ten args */
1296     char *f;
1297     char *s0, *s1, *s2, *s3, *s4, *s5, *s6, *s7, *s8, *s9;
1298 #endif
1299 {
1300 #if NeedVarargsPrototypes
1301     va_list args;
1302 #endif
1303
1304     AuditPrefix(f);
1305
1306 #if NeedVarargsPrototypes
1307     va_start(args, f);
1308     VErrorF(f, args);
1309     va_end(args);
1310 #else
1311     ErrorF(f, s0, s1, s2, s3, s4, s5, s6, s7, s8, s9);
1312 #endif
1313 }
1314
1315 /*VARARGS1*/
1316 void
1317 FatalError(
1318 #if NeedVarargsPrototypes
1319     char *f, ...)
1320 #else
1321 f, s0, s1, s2, s3, s4, s5, s6, s7, s8, s9) /* limit of ten args */
1322     char *f;
1323     char *s0, *s1, *s2, *s3, *s4, *s5, *s6, *s7, *s8, *s9;
1324 #endif
1325 {
1326 #if NeedVarargsPrototypes
1327     va_list args;
1328 #endif
1329     ErrorF("\nFatal server error:\n");
1330 #if NeedVarargsPrototypes
1331     va_start(args, f);
1332     VErrorF(f, args);
1333     va_end(args);
1334 #else
1335     ErrorF(f, s0, s1, s2, s3, s4, s5, s6, s7, s8, s9);
1336 #endif
1337     ErrorF("\n");
1338 #ifdef DDXOSFATALERROR
1339     OsVendorFatalError();
1340 #endif
1341     AbortServer();
1342     /*NOTREACHED*/
1343 }
1344
1345 #if NeedVarargsPrototypes
1346 void
1347 VErrorF(f, args)
1348     char *f;
1349     va_list args;
1350 {
1351     vfprintf(stderr, f, args);
1352 }
1353 #endif
1354
1355 /*VARARGS1*/
1356 void
1357 ErrorF(
1358 #if NeedVarargsPrototypes
1359     char * f, ...)
1360 #else
1361  f, s0, s1, s2, s3, s4, s5, s6, s7, s8, s9) /* limit of ten args */
1362     char *f;
1363     char *s0, *s1, *s2, *s3, *s4, *s5, *s6, *s7, *s8, *s9;
1364 #endif
1365 {
1366 #if NeedVarargsPrototypes
1367     va_list args;
1368     va_start(args, f);
1369     VErrorF(f, args);
1370     va_end(args);
1371 #else
1372 #ifdef AMOEBA
1373     mu_lock(&print_lock);
1374 #endif
1375     fprintf( stderr, f, s0, s1, s2, s3, s4, s5, s6, s7, s8, s9);
1376 #ifdef AMOEBA
1377     mu_unlock(&print_lock);
1378 #endif
1379 #endif
1380 }
1381
1382 #if !defined(WIN32) && !defined(__EMX__)
1383 /*
1384  * "safer" versions of system(3), popen(3) and pclose(3) which give up
1385  * all privs before running a command.
1386  *
1387  * This is based on the code in FreeBSD 2.2 libc.
1388  */
1389
1390 int
1391 System(command)
1392     char *command;
1393 {
1394     int pid, p;
1395     void (*csig)();
1396     int status;
1397
1398     if (!command)
1399         return(1);
1400
1401 #ifdef SIGCHLD
1402     csig = signal(SIGCHLD, SIG_DFL);
1403 #endif
1404
1405     ErrorF("System: `%s'\n", command);
1406
1407     switch (pid = fork()) {
1408     case -1:    /* error */
1409         p = -1;
1410     case 0:     /* child */
1411         setgid(getgid());
1412         setuid(getuid());
1413         execl("/bin/sh", "sh", "-c", command, (char *)NULL);
1414         _exit(127);
1415     default:    /* parent */
1416         do {
1417             p = waitpid(pid, &status, 0);
1418         } while (p == -1 && errno == EINTR);
1419         
1420     }
1421
1422 #ifdef SIGCHLD
1423     signal(SIGCHLD, csig);
1424 #endif
1425
1426     return p == -1 ? -1 : status;
1427 }
1428
1429 static struct pid {
1430     struct pid *next;
1431     FILE *fp;
1432     int pid;
1433 } *pidlist;
1434
1435 pointer
1436 Popen(command, type)
1437     char *command;
1438     char *type;
1439 {
1440     struct pid *cur;
1441     FILE *iop;
1442     int pdes[2], pid;
1443     void (*csig)();
1444
1445     if (command == NULL || type == NULL)
1446         return NULL;
1447
1448     if ((*type != 'r' && *type != 'w') || type[1])
1449         return NULL;
1450
1451     if ((cur = (struct pid *)xalloc(sizeof(struct pid))) == NULL)
1452         return NULL;
1453
1454     if (pipe(pdes) < 0) {
1455         xfree(cur);
1456         return NULL;
1457     }
1458
1459     switch (pid = fork()) {
1460     case -1:    /* error */
1461         close(pdes[0]);
1462         close(pdes[1]);
1463         xfree(cur);
1464         return NULL;
1465     case 0:     /* child */
1466         setgid(getgid());
1467         setuid(getuid());
1468         if (*type == 'r') {
1469             if (pdes[1] != 1) {
1470                 /* stdout */
1471                 dup2(pdes[1], 1);
1472                 close(pdes[1]);
1473             }
1474             close(pdes[0]);
1475         } else {
1476             if (pdes[0] != 0) {
1477                 /* stdin */
1478                 dup2(pdes[0], 0);
1479                 close(pdes[0]);
1480             }
1481             close(pdes[1]);
1482         }
1483         execl("/bin/sh", "sh", "-c", command, (char *)NULL);
1484         _exit(127);
1485     }
1486
1487     /* parent */
1488     if (*type == 'r') {
1489         iop = fdopen(pdes[0], type);
1490         close(pdes[1]);
1491     } else {
1492         iop = fdopen(pdes[1], type);
1493         close(pdes[0]);
1494     }
1495
1496     cur->fp = iop;
1497     cur->pid = pid;
1498     cur->next = pidlist;
1499     pidlist = cur;
1500
1501 #if 0
1502     ErrorF("Popen: `%s', fp = %p\n", command, iop);
1503 #endif
1504
1505     return iop;
1506 }
1507
1508 int
1509 Pclose(iop)
1510     pointer iop;
1511 {
1512     struct pid *cur, *last;
1513     int omask;
1514     int pstat;
1515     int pid;
1516
1517 #if 0
1518     ErrorF("Pclose: fp = %p\n", iop);
1519 #endif
1520
1521     fclose(iop);
1522
1523     for (last = NULL, cur = pidlist; cur; last = cur, cur = cur->next)
1524         if (cur->fp = iop)
1525             break;
1526     if (cur == NULL)
1527         return -1;
1528
1529     do {
1530         pid = waitpid(cur->pid, &pstat, 0);
1531     } while (pid == -1 && errno == EINTR);
1532
1533     if (last == NULL)
1534         pidlist = cur->next;
1535     else
1536         last->next = cur->next;
1537     xfree(cur);
1538
1539     return pid == -1 ? -1 : pstat;
1540 }
1541 #endif /* !WIN32 && !__EMX__ */