3 Copyright 1987, 1998 The Open Group
5 Permission to use, copy, modify, distribute, and sell this software and its
6 documentation for any purpose is hereby granted without fee, provided that
7 the above copyright notice appear in all copies and that both that
8 copyright notice and this permission notice appear in supporting
11 The above copyright notice and this permission notice shall be included
12 in all copies or substantial portions of the Software.
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 OTHER DEALINGS IN THE SOFTWARE.
22 Except as contained in this notice, the name of The Open Group shall
23 not be used in advertising or otherwise to promote the sale, use or
24 other dealings in this Software without prior written authorization
28 Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,
29 Copyright 1994 Quarterdeck Office Systems.
33 Permission to use, copy, modify, and distribute this software and its
34 documentation for any purpose and without fee is hereby granted,
35 provided that the above copyright notice appear in all copies and that
36 both that copyright notice and this permission notice appear in
37 supporting documentation, and that the names of Digital and
38 Quarterdeck not be used in advertising or publicity pertaining to
39 distribution of the software without specific, written prior
42 DIGITAL AND QUARTERDECK DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
43 SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
44 FITNESS, IN NO EVENT SHALL DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT
45 OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
46 OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
47 OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
48 OR PERFORMANCE OF THIS SOFTWARE.
52 #ifdef HAVE_DIX_CONFIG_H
53 #include <dix-config.h>
61 #if defined(WIN32) && !defined(__CYGWIN__)
62 #include <X11/Xwinsock.h>
67 #if !defined(WIN32) || !defined(__MINGW32__)
69 #include <sys/resource.h>
76 #include <X11/Xtrans/Xtrans.h>
80 #include "extension.h"
81 #ifdef X_POSIX_C_SOURCE
82 #define _POSIX_C_SOURCE X_POSIX_C_SOURCE
84 #undef _POSIX_C_SOURCE
86 #if defined(X_NOT_POSIX) || defined(_POSIX_SOURCE)
97 #if !defined(SYSV) && !defined(WIN32) && !defined(Lynx) && !defined(QNX4)
98 #include <sys/resource.h>
100 #include <sys/stat.h>
101 #include <ctype.h> /* for isspace */
105 #include <sys/resource.h>
109 #include <stdlib.h> /* for malloc() */
111 #if defined(TCPCONN) || defined(STREAMSCONN)
119 #ifdef SMART_SCHEDULE
120 #include "dixstruct.h"
127 #include "securitysrv.h"
138 _X_EXPORT Bool noTestExtensions
;
140 _X_EXPORT Bool noBigReqExtension
= FALSE
;
143 _X_EXPORT Bool noCompositeExtension
= FALSE
;
147 _X_EXPORT Bool noDamageExtension
= FALSE
;
150 _X_EXPORT Bool noDbeExtension
= FALSE
;
153 _X_EXPORT Bool noDPMSExtension
= FALSE
;
156 _X_EXPORT Bool noEVIExtension
= FALSE
;
159 _X_EXPORT Bool noFontCacheExtension
= FALSE
;
162 _X_EXPORT Bool noGlxExtension
= FALSE
;
165 _X_EXPORT Bool noScreenSaverExtension
= FALSE
;
168 _X_EXPORT Bool noMITShmExtension
= FALSE
;
171 _X_EXPORT Bool noMITMiscExtension
= FALSE
;
174 _X_EXPORT Bool noMultibufferExtension
= FALSE
;
177 _X_EXPORT Bool noRRExtension
= FALSE
;
180 _X_EXPORT Bool noRenderExtension
= FALSE
;
183 _X_EXPORT Bool noShapeExtension
= FALSE
;
186 _X_EXPORT Bool noSecurityExtension
= FALSE
;
189 _X_EXPORT Bool noSyncExtension
= FALSE
;
192 _X_EXPORT Bool noXcupExtension
= FALSE
;
195 _X_EXPORT Bool noResExtension
= FALSE
;
198 _X_EXPORT Bool noXagExtension
= FALSE
;
201 _X_EXPORT Bool noXCMiscExtension
= FALSE
;
204 /* Xevie is disabled by default for now until the
205 * interface is stable */
206 _X_EXPORT Bool noXevieExtension
= TRUE
;
209 _X_EXPORT Bool noXFree86BigfontExtension
= FALSE
;
212 _X_EXPORT Bool noXFree86DGAExtension
= FALSE
;
215 _X_EXPORT Bool noXFree86DRIExtension
= FALSE
;
218 _X_EXPORT Bool noXFree86MiscExtension
= FALSE
;
221 _X_EXPORT Bool noXFree86VidModeExtension
= FALSE
;
224 _X_EXPORT Bool noXFixesExtension
= FALSE
;
226 /* |noXkbExtension| is defined in xc/programs/Xserver/xkb/xkbInit.c */
228 /* Xinerama is disabled by default unless enabled via +xinerama */
229 _X_EXPORT Bool noPanoramiXExtension
= TRUE
;
232 _X_EXPORT Bool noXInputExtension
= FALSE
;
235 _X_EXPORT Bool noXIdleExtension
= FALSE
;
238 _X_EXPORT Bool noXvExtension
= FALSE
;
241 #define X_INCLUDE_NETDB_H
242 #include <X11/Xos_r.h>
249 Bool PanoramiXExtensionDisabledHack
= FALSE
;
252 int auditTrailLevel
= 1;
254 _X_EXPORT Bool Must_have_memory
= FALSE
;
258 extern int SelectWaitTime
;
261 #if defined(SVR4) || defined(__linux__) || defined(CSRG_BASED)
262 #define HAS_SAVED_IDS_AND_SETEUID
266 #define MEM_FAIL_SCALE 100000
267 long Memory_fail
= 0;
268 #include <stdlib.h> /* for random() */
271 static char *dev_tty_from_init
= NULL
; /* since we need to parse it anyway */
274 OsSignal(sig
, handler
)
276 OsSigHandlerPtr handler
;
279 return signal(sig
, handler
);
281 struct sigaction act
, oact
;
283 sigemptyset(&act
.sa_mask
);
284 if (handler
!= SIG_IGN
)
285 sigaddset(&act
.sa_mask
, sig
);
287 act
.sa_handler
= handler
;
288 sigaction(sig
, &act
, &oact
);
289 return oact
.sa_handler
;
295 * Explicit support for a server lock file like the ones used for UUCP.
296 * For architectures with virtual terminals that can run more than one
297 * server at a time. This keeps the servers from stomping on each other
298 * if the user forgets to give them different display numbers.
300 #define LOCK_DIR "/tmp"
301 #define LOCK_TMP_PREFIX "/.tX"
302 #define LOCK_PREFIX "/.X"
303 #define LOCK_SUFFIX "-lock"
307 #include <sys/param.h>
312 #include <sys/param.h>
318 #define PATH_MAX MAXPATHLEN
320 #define PATH_MAX 1024
325 static Bool StillLocking
= FALSE
;
326 static char LockFile
[PATH_MAX
];
327 static Bool nolock
= FALSE
;
331 * Check if the server lock file exists. If so, check if the PID
332 * contained inside is valid. If so, then die. Otherwise, create
333 * the lock file containing the PID.
338 char tmp
[PATH_MAX
], pid_str
[12];
339 int lfd
, i
, haslock
, l_pid
, t
;
340 char *tmppath
= NULL
;
350 sprintf(port
, "%d", atoi(display
));
351 len
= strlen(LOCK_PREFIX
) > strlen(LOCK_TMP_PREFIX
) ? strlen(LOCK_PREFIX
) :
352 strlen(LOCK_TMP_PREFIX
);
353 len
+= strlen(tmppath
) + strlen(port
) + strlen(LOCK_SUFFIX
) + 1;
354 if (len
> sizeof(LockFile
))
355 FatalError("Display name `%s' is too long\n", port
);
356 (void)sprintf(tmp
, "%s" LOCK_TMP_PREFIX
"%s" LOCK_SUFFIX
, tmppath
, port
);
357 (void)sprintf(LockFile
, "%s" LOCK_PREFIX
"%s" LOCK_SUFFIX
, tmppath
, port
);
360 * Create a temporary file containing our PID. Attempt three times
361 * to create the file.
367 lfd
= open(tmp
, O_CREAT
| O_EXCL
| O_WRONLY
, 0644);
378 lfd
= open(tmp
, O_CREAT
| O_EXCL
| O_WRONLY
, 0644);
386 FatalError("Could not create lock file in %s\n", tmp
);
387 (void) sprintf(pid_str
, "%10ld\n", (long)getpid());
388 (void) write(lfd
, pid_str
, 11);
390 (void) fchmod(lfd
, 0444);
392 (void) chmod(tmp
, 0444);
397 * OK. Now the tmp file exists. Try three times to move it in place
402 while ((!haslock
) && (i
++ < 3)) {
403 haslock
= (link(tmp
,LockFile
) == 0);
412 * Read the pid from the existing file
414 lfd
= open(LockFile
, O_RDONLY
);
417 FatalError("Can't read lock file %s\n", LockFile
);
420 if (read(lfd
, pid_str
, 11) != 11) {
429 sscanf(pid_str
, "%d", &l_pid
);
433 * Now try to kill the PID to see if it exists.
437 if ((t
< 0) && (errno
== ESRCH
)) {
444 else if (((t
< 0) && (errno
== EPERM
)) || (t
== 0)) {
446 * Process is still active.
449 FatalError("Server is already active for display %s\n%s %s\n%s\n",
450 port
, "\tIf this server is no longer running, remove",
451 LockFile
, "\tand start again.");
457 FatalError("Could not create server lock file: %s\n", LockFile
);
458 StillLocking
= FALSE
;
463 * Remove the server lock file.
472 (void) unlink(LockFile
);
475 #endif /* SERVER_LOCK */
477 /* Force connections to close on SIGHUP from init */
481 AutoResetServer (int sig
)
483 int olderrno
= errno
;
485 dispatchException
|= DE_RESET
;
486 isItTimeToYield
= TRUE
;
491 #if defined(SYSV) && defined(X_NOT_POSIX)
492 OsSignal (SIGHUP
, AutoResetServer
);
497 /* Force connections to close and then exit on SIGTERM, SIGINT */
503 int olderrno
= errno
;
505 dispatchException
|= DE_TERMINATE
;
506 isItTimeToYield
= TRUE
;
507 #if defined(SYSV) && defined(X_NOT_POSIX)
509 OsSignal(sig
, SIG_IGN
);
514 #if defined WIN32 && defined __MINGW32__
516 GetTimeInMillis (void)
518 return GetTickCount ();
522 GetTimeInMillis(void)
526 #ifdef MONOTONIC_CLOCK
528 if (clock_gettime(CLOCK_MONOTONIC
, &tp
) == 0)
529 return (tp
.tv_sec
* 1000) + (tp
.tv_nsec
/ 1000000L);
533 return(tv
.tv_sec
* 1000) + (tv
.tv_usec
/ 1000);
538 AdjustWaitForDelay (pointer waitTime
, unsigned long newdelay
)
540 static struct timeval delay_val
;
541 struct timeval
**wt
= (struct timeval
**) waitTime
;
542 unsigned long olddelay
;
546 delay_val
.tv_sec
= newdelay
/ 1000;
547 delay_val
.tv_usec
= 1000 * (newdelay
% 1000);
552 olddelay
= (*wt
)->tv_sec
* 1000 + (*wt
)->tv_usec
/ 1000;
553 if (newdelay
< olddelay
)
555 (*wt
)->tv_sec
= newdelay
/ 1000;
556 (*wt
)->tv_usec
= 1000 * (newdelay
% 1000);
563 #if !defined(AIXrt) && !defined(AIX386)
564 ErrorF("use: X [:<display>] [option]\n");
565 ErrorF("-a # mouse acceleration (pixels)\n");
566 ErrorF("-ac disable access control restrictions\n");
568 ErrorF("-alloc int chance alloc should fail\n");
570 ErrorF("-audit int set audit trail level\n");
571 ErrorF("-auth file select authorization file\n");
572 ErrorF("-br create root window with black background\n");
573 ErrorF("+bs enable any backing store support\n");
574 ErrorF("-bs disable any backing store support\n");
575 ErrorF("-c turns off key-click\n");
576 ErrorF("c # key-click volume (0-100)\n");
577 ErrorF("-cc int default color visual class\n");
578 ErrorF("-co file color database file\n");
579 #ifdef COMMANDLINE_CHALLENGED_OPERATING_SYSTEMS
580 ErrorF("-config file read options from file\n");
582 ErrorF("-core generate core dump on fatal error\n");
583 ErrorF("-dpi int screen resolution in dots per inch\n");
585 ErrorF("dpms enables VESA DPMS monitor control\n");
586 ErrorF("-dpms disables VESA DPMS monitor control\n");
588 ErrorF("-deferglyphs [none|all|16] defer loading of [no|all|16-bit] glyphs\n");
589 ErrorF("-f # bell base (0-100)\n");
590 ErrorF("-fc string cursor font\n");
591 ErrorF("-fn string default font name\n");
592 ErrorF("-fp string default font path\n");
593 ErrorF("-help prints message with these options\n");
594 ErrorF("-I ignore all remaining arguments\n");
596 ErrorF("-ld int limit data space to N Kb\n");
599 ErrorF("-lf int limit number of open files to N\n");
602 ErrorF("-ls int limit stack space to N Kb\n");
605 ErrorF("-nolock disable the locking mechanism\n");
608 ErrorF("-logo enable logo in screen saver\n");
609 ErrorF("nologo disable logo in screen saver\n");
611 ErrorF("-nolisten string don't listen on protocol\n");
612 ErrorF("-noreset don't reset after last client exists\n");
613 ErrorF("-reset reset after last client exists\n");
614 ErrorF("-p # screen-saver pattern duration (minutes)\n");
615 ErrorF("-pn accept failure to listen on all ports\n");
616 ErrorF("-nopn reject failure to listen on all ports\n");
617 ErrorF("-r turns off auto-repeat\n");
618 ErrorF("r turns on auto-repeat \n");
620 ErrorF("-render [default|mono|gray|color] set render color alloc policy\n");
622 ErrorF("-s # screen-saver timeout (minutes)\n");
624 ErrorF("-sp file security policy file\n");
629 ErrorF("-su disable any save under support\n");
630 ErrorF("-t # mouse threshold (pixels)\n");
631 ErrorF("-terminate terminate at server reset\n");
632 ErrorF("-to # connection time out\n");
633 ErrorF("-tst disable testing extensions\n");
634 ErrorF("ttyxx server started from init on /dev/ttyxx\n");
635 ErrorF("v video blanking for screen-saver\n");
636 ErrorF("-v screen-saver without video blanking\n");
637 ErrorF("-wm WhenMapped default backing-store\n");
638 ErrorF("-wr create root window with white background\n");
639 ErrorF("-x string loads named extension at init time \n");
640 ErrorF("-maxbigreqsize set maximal bigrequest size \n");
642 ErrorF("+xinerama Enable XINERAMA extension\n");
643 ErrorF("-xinerama Disable XINERAMA extension\n");
645 #ifdef SMART_SCHEDULE
646 ErrorF("-dumbSched Disable smart scheduling, enable old behavior\n");
647 ErrorF("-schedInterval int Set scheduler interval in msec\n");
649 ErrorF("+extension name Enable extension\n");
650 ErrorF("-extension name Disable extension\n");
654 #endif /* !AIXrt && ! AIX386 */
661 /* This function performs a rudimentary sanity check
662 * on the display name passed in on the command-line,
663 * since this string is used to generate filenames.
664 * It is especially important that the display name
665 * not contain a "/" and not start with a "-".
669 VerifyDisplayName(const char *d
)
671 if ( d
== (char *)0 ) return( 0 ); /* null */
672 if ( *d
== '\0' ) return( 0 ); /* empty */
673 if ( *d
== '-' ) return( 0 ); /* could be confused for an option */
674 if ( *d
== '.' ) return( 0 ); /* must not equal "." or ".." */
675 if ( strchr(d
, '/') != (char *)0 ) return( 0 ); /* very important!!! */
680 * This function is responsible for doing initalisation of any global
681 * variables at an very early point of server startup (even before
682 * |ProcessCommandLine()|.
684 void InitGlobals(void)
691 * This function parses the command line. Handles device-independent fields
692 * and allows ddx to handle additional fields. It is not allowed to modify
693 * argc or any of the strings pointed to by argv.
696 ProcessCommandLine(int argc
, char *argv
[])
700 defaultKeyboardControl
.autoRepeat
= TRUE
;
703 PartialNetwork
= FALSE
;
705 PartialNetwork
= TRUE
;
708 for ( i
= 1; i
< argc
; i
++ )
710 /* call ddx first, so it can peek/override if it wants */
711 if((skip
= ddxProcessArgument(argc
, argv
, i
)))
715 else if(argv
[i
][0] == ':')
717 /* initialize display */
720 if( ! VerifyDisplayName( display
) ) {
721 ErrorF("Bad display name: %s\n", display
);
723 FatalError("Bad display name, exiting: %s\n", display
);
726 else if ( strcmp( argv
[i
], "-a") == 0)
729 defaultPointerControl
.num
= atoi(argv
[i
]);
733 else if ( strcmp( argv
[i
], "-ac") == 0)
735 defeatAccessControl
= TRUE
;
738 else if ( strcmp( argv
[i
], "-alloc") == 0)
741 Memory_fail
= atoi(argv
[i
]);
746 else if ( strcmp( argv
[i
], "-audit") == 0)
749 auditTrailLevel
= atoi(argv
[i
]);
753 else if ( strcmp( argv
[i
], "-auth") == 0)
756 InitAuthorization (argv
[i
]);
760 else if ( strcmp( argv
[i
], "-br") == 0)
762 else if ( strcmp( argv
[i
], "+bs") == 0)
763 enableBackingStore
= TRUE
;
764 else if ( strcmp( argv
[i
], "-bs") == 0)
765 disableBackingStore
= TRUE
;
766 else if ( strcmp( argv
[i
], "c") == 0)
769 defaultKeyboardControl
.click
= atoi(argv
[i
]);
773 else if ( strcmp( argv
[i
], "-c") == 0)
775 defaultKeyboardControl
.click
= 0;
777 else if ( strcmp( argv
[i
], "-cc") == 0)
780 defaultColorVisualClass
= atoi(argv
[i
]);
784 else if ( strcmp( argv
[i
], "-co") == 0)
791 else if ( strcmp( argv
[i
], "-core") == 0)
794 #if !defined(WIN32) || !defined(__MINGW32__)
795 struct rlimit core_limit
;
796 getrlimit (RLIMIT_CORE
, &core_limit
);
797 core_limit
.rlim_cur
= core_limit
.rlim_max
;
798 setrlimit (RLIMIT_CORE
, &core_limit
);
801 else if ( strcmp( argv
[i
], "-dpi") == 0)
804 monitorResolution
= atoi(argv
[i
]);
809 else if ( strcmp( argv
[i
], "dpms") == 0)
810 DPMSEnabledSwitch
= TRUE
;
811 else if ( strcmp( argv
[i
], "-dpms") == 0)
812 DPMSDisabledSwitch
= TRUE
;
814 else if ( strcmp( argv
[i
], "-deferglyphs") == 0)
816 if(++i
>= argc
|| !ParseGlyphCachingMode(argv
[i
]))
819 else if ( strcmp( argv
[i
], "-f") == 0)
822 defaultKeyboardControl
.bell
= atoi(argv
[i
]);
826 else if ( strcmp( argv
[i
], "-fc") == 0)
829 defaultCursorFont
= argv
[i
];
833 else if ( strcmp( argv
[i
], "-fn") == 0)
836 defaultTextFont
= argv
[i
];
840 else if ( strcmp( argv
[i
], "-fp") == 0)
844 defaultFontPath
= argv
[i
];
849 else if ( strcmp( argv
[i
], "-help") == 0)
855 else if ( (skip
=XkbProcessArguments(argc
,argv
,i
))!=0 ) {
862 else if ( strcmp( argv
[i
], "-ld") == 0)
866 limitDataSpace
= atoi(argv
[i
]);
867 if (limitDataSpace
> 0)
868 limitDataSpace
*= 1024;
875 else if ( strcmp( argv
[i
], "-lf") == 0)
878 limitNoFile
= atoi(argv
[i
]);
884 else if ( strcmp( argv
[i
], "-ls") == 0)
888 limitStackSpace
= atoi(argv
[i
]);
889 if (limitStackSpace
> 0)
890 limitStackSpace
*= 1024;
897 else if ( strcmp ( argv
[i
], "-nolock") == 0)
899 #if !defined(WIN32) && !defined(__CYGWIN__)
901 ErrorF("Warning: the -nolock option can only be used by root\n");
908 else if ( strcmp( argv
[i
], "-logo") == 0)
912 else if ( strcmp( argv
[i
], "nologo") == 0)
917 else if ( strcmp( argv
[i
], "-nolisten") == 0)
920 if (_XSERVTransNoListen(argv
[i
]))
921 FatalError ("Failed to disable listen for %s transport",
926 else if ( strcmp( argv
[i
], "-noreset") == 0)
928 dispatchExceptionAtReset
= 0;
930 else if ( strcmp( argv
[i
], "-reset") == 0)
932 dispatchExceptionAtReset
= DE_RESET
;
934 else if ( strcmp( argv
[i
], "-p") == 0)
937 defaultScreenSaverInterval
= ((CARD32
)atoi(argv
[i
])) *
942 else if ( strcmp( argv
[i
], "-pn") == 0)
943 PartialNetwork
= TRUE
;
944 else if ( strcmp( argv
[i
], "-nopn") == 0)
945 PartialNetwork
= FALSE
;
946 else if ( strcmp( argv
[i
], "r") == 0)
947 defaultKeyboardControl
.autoRepeat
= TRUE
;
948 else if ( strcmp( argv
[i
], "-r") == 0)
949 defaultKeyboardControl
.autoRepeat
= FALSE
;
950 else if ( strcmp( argv
[i
], "-s") == 0)
953 defaultScreenSaverTime
= ((CARD32
)atoi(argv
[i
])) *
958 else if ( strcmp( argv
[i
], "-su") == 0)
959 disableSaveUnders
= TRUE
;
960 else if ( strcmp( argv
[i
], "-t") == 0)
963 defaultPointerControl
.threshold
= atoi(argv
[i
]);
967 else if ( strcmp( argv
[i
], "-terminate") == 0)
969 dispatchExceptionAtReset
= DE_TERMINATE
;
971 else if ( strcmp( argv
[i
], "-to") == 0)
974 TimeOutValue
= ((CARD32
)atoi(argv
[i
])) * MILLI_PER_SECOND
;
978 else if ( strcmp( argv
[i
], "-tst") == 0)
980 noTestExtensions
= TRUE
;
982 else if ( strcmp( argv
[i
], "v") == 0)
983 defaultScreenSaverBlanking
= PreferBlanking
;
984 else if ( strcmp( argv
[i
], "-v") == 0)
985 defaultScreenSaverBlanking
= DontPreferBlanking
;
986 else if ( strcmp( argv
[i
], "-wm") == 0)
987 defaultBackingStore
= WhenMapped
;
988 else if ( strcmp( argv
[i
], "-wr") == 0)
990 else if ( strcmp( argv
[i
], "-maxbigreqsize") == 0) {
992 long reqSizeArg
= atol(argv
[i
]);
994 /* Request size > 128MB does not make much sense... */
995 if( reqSizeArg
> 0L && reqSizeArg
< 128L ) {
996 maxBigRequestSize
= (reqSizeArg
* 1048576L) - 1L;
1009 else if ( strcmp( argv
[i
], "+xinerama") == 0){
1010 noPanoramiXExtension
= FALSE
;
1012 else if ( strcmp( argv
[i
], "-xinerama") == 0){
1013 noPanoramiXExtension
= TRUE
;
1015 else if ( strcmp( argv
[i
], "-disablexineramaextension") == 0){
1016 PanoramiXExtensionDisabledHack
= TRUE
;
1019 else if ( strcmp( argv
[i
], "-x") == 0)
1023 /* For U**x, which doesn't support dynamic loading, there's nothing
1024 * to do when we see a -x. Either the extension is linked in or
1027 else if ( strcmp( argv
[i
], "-I") == 0)
1029 /* ignore all remaining arguments */
1032 else if (strncmp (argv
[i
], "tty", 3) == 0)
1034 /* just in case any body is interested */
1035 dev_tty_from_init
= argv
[i
];
1038 else if ((skip
= XdmcpOptions(argc
, argv
, i
)) != i
)
1044 else if ((skip
= PrinterOptions(argc
, argv
, i
)) != i
)
1050 else if ((skip
= XSecurityOptions(argc
, argv
, i
)) != i
)
1056 else if ( strcmp( argv
[i
], "-timeout") == 0)
1059 SelectWaitTime
= atoi(argv
[i
]);
1063 else if ( strcmp( argv
[i
], "-sync") == 0)
1068 #ifdef SMART_SCHEDULE
1069 else if ( strcmp( argv
[i
], "-dumbSched") == 0)
1071 SmartScheduleDisable
= TRUE
;
1073 else if ( strcmp( argv
[i
], "-schedInterval") == 0)
1077 SmartScheduleInterval
= atoi(argv
[i
]);
1078 SmartScheduleSlice
= SmartScheduleInterval
;
1083 else if ( strcmp( argv
[i
], "-schedMax") == 0)
1087 SmartScheduleMaxSlice
= atoi(argv
[i
]);
1094 else if ( strcmp( argv
[i
], "-render" ) == 0)
1098 int policy
= PictureParseCmapPolicy (argv
[i
]);
1100 if (policy
!= PictureCmapPolicyInvalid
)
1101 PictureCmapPolicy
= policy
;
1109 else if ( strcmp( argv
[i
], "+extension") == 0)
1113 if (!EnableDisableExtension(argv
[i
], TRUE
))
1114 EnableDisableExtensionError(argv
[i
], TRUE
);
1119 else if ( strcmp( argv
[i
], "-extension") == 0)
1123 if (!EnableDisableExtension(argv
[i
], FALSE
))
1124 EnableDisableExtensionError(argv
[i
], FALSE
);
1131 ErrorF("Unrecognized option: %s\n", argv
[i
]);
1133 FatalError("Unrecognized option: %s\n", argv
[i
]);
1138 #ifdef COMMANDLINE_CHALLENGED_OPERATING_SYSTEMS
1140 InsertFileIntoCommandLine(
1141 int *resargc
, char ***resargv
,
1142 int prefix_argc
, char **prefix_argv
,
1144 int suffix_argc
, char **suffix_argv
)
1155 f
= fopen(filename
, "r");
1157 FatalError("Can't open option file %s\n", filename
);
1159 fstat(fileno(f
), &st
);
1161 buf
= (char *) xalloc((unsigned) st
.st_size
+ 1);
1163 FatalError("Out of Memory\n");
1165 len
= fread(buf
, 1, (unsigned) st
.st_size
, f
);
1170 FatalError("Error reading option file %s\n", filename
);
1186 while (*p
&& *p
!= '\n')
1190 while (*p
&& !isspace(*p
))
1192 /* Since p and q might still be pointing at the same place, we */
1193 /* need to step p over the whitespace now before we add the null. */
1201 buf
= (char *) xrealloc(buf
, q
- buf
);
1203 FatalError("Out of memory reallocing option buf\n");
1205 *resargc
= prefix_argc
+ insert_argc
+ suffix_argc
;
1206 *resargv
= (char **) xalloc((*resargc
+ 1) * sizeof(char *));
1208 FatalError("Out of Memory\n");
1210 memcpy(*resargv
, prefix_argv
, prefix_argc
* sizeof(char *));
1213 for (i
= 0; i
< insert_argc
; i
++)
1215 (*resargv
)[prefix_argc
+ i
] = p
;
1219 memcpy(*resargv
+ prefix_argc
+ insert_argc
,
1220 suffix_argv
, suffix_argc
* sizeof(char *));
1222 (*resargv
)[*resargc
] = NULL
;
1223 } /* end InsertFileIntoCommandLine */
1227 ExpandCommandLine(int *pargc
, char ***pargv
)
1231 #if !defined(WIN32) && !defined(__CYGWIN__)
1232 if (getuid() != geteuid())
1236 for (i
= 1; i
< *pargc
; i
++)
1238 if ( (0 == strcmp((*pargv
)[i
], "-config")) && (i
< (*pargc
- 1)) )
1240 InsertFileIntoCommandLine(pargc
, pargv
,
1242 (*pargv
)[i
+1], /* filename */
1243 *pargc
- i
- 2, *pargv
+ i
+ 2);
1247 } /* end ExpandCommandLine */
1250 /* Implement a simple-minded font authorization scheme. The authorization
1251 name is "hp-hostname-1", the contents are simply the host name. */
1253 set_font_authorizations(char **authorizations
, int *authlen
, pointer client
)
1255 #define AUTHORIZATION_NAME "hp-hostname-1"
1256 #if defined(TCPCONN) || defined(STREAMSCONN)
1257 static char *result
= NULL
;
1258 static char *p
= NULL
;
1262 char hname
[1024], *hnameptr
;
1264 #if defined(IPv6) && defined(AF_INET6)
1265 struct addrinfo hints
, *ai
= NULL
;
1267 struct hostent
*host
;
1268 #ifdef XTHREADS_NEEDS_BYNAMEPARAMS
1269 _Xgethostbynameparams hparams
;
1273 gethostname(hname
, 1024);
1274 #if defined(IPv6) && defined(AF_INET6)
1275 bzero(&hints
, sizeof(hints
));
1276 hints
.ai_flags
= AI_CANONNAME
;
1277 if (getaddrinfo(hname
, NULL
, &hints
, &ai
) == 0) {
1278 hnameptr
= ai
->ai_canonname
;
1283 host
= _XGethostbyname(hname
, hparams
);
1287 hnameptr
= host
->h_name
;
1290 len
= strlen(hnameptr
) + 1;
1291 result
= xalloc(len
+ sizeof(AUTHORIZATION_NAME
) + 4);
1294 *p
++ = sizeof(AUTHORIZATION_NAME
) >> 8;
1295 *p
++ = sizeof(AUTHORIZATION_NAME
) & 0xff;
1297 *p
++ = (len
& 0xff);
1299 memmove(p
, AUTHORIZATION_NAME
, sizeof(AUTHORIZATION_NAME
));
1300 p
+= sizeof(AUTHORIZATION_NAME
);
1301 memmove(p
, hnameptr
, len
);
1303 #if defined(IPv6) && defined(AF_INET6)
1309 *authlen
= p
- result
;
1310 *authorizations
= result
;
1314 #endif /* TCPCONN */
1317 /* XALLOC -- X's internal memory allocator. Why does it return unsigned
1318 * long * instead of the more common char *? Well, if you read K&R you'll
1319 * see they say that alloc must return a pointer "suitable for conversion"
1320 * to whatever type you really want. In a full-blown generic allocator
1321 * there's no way to solve the alignment problems without potentially
1322 * wasting lots of space. But we have a more limited problem. We know
1323 * we're only ever returning pointers to structures which will have to
1324 * be long word aligned. So we are making a stronger guarantee. It might
1325 * have made sense to make Xalloc return char * to conform with people's
1326 * expectations of malloc, but this makes lint happier.
1329 #ifndef INTERNAL_MALLOC
1332 Xalloc(unsigned long amount
)
1334 register pointer ptr
;
1336 if ((long)amount
<= 0) {
1337 return (unsigned long *)NULL
;
1339 /* aligned extra on long word boundary */
1340 amount
= (amount
+ (sizeof(long) - 1)) & ~(sizeof(long) - 1);
1342 if (!Must_have_memory
&& Memory_fail
&&
1343 ((random() % MEM_FAIL_SCALE
) < Memory_fail
))
1344 return (unsigned long *)NULL
;
1346 if ((ptr
= (pointer
)malloc(amount
))) {
1347 return (unsigned long *)ptr
;
1349 if (Must_have_memory
)
1350 FatalError("Out of memory");
1351 return (unsigned long *)NULL
;
1356 * "no failure" realloc, alternate interface to Xalloc w/o Must_have_memory
1360 XNFalloc(unsigned long amount
)
1362 register pointer ptr
;
1364 if ((long)amount
<= 0)
1366 return (unsigned long *)NULL
;
1368 /* aligned extra on long word boundary */
1369 amount
= (amount
+ (sizeof(long) - 1)) & ~(sizeof(long) - 1);
1370 ptr
= (pointer
)malloc(amount
);
1373 FatalError("Out of memory");
1375 return ((unsigned long *)ptr
);
1383 Xcalloc(unsigned long amount
)
1387 ret
= Xalloc (amount
);
1389 bzero ((char *) ret
, (int) amount
);
1398 XNFcalloc(unsigned long amount
)
1402 ret
= Xalloc (amount
);
1404 bzero ((char *) ret
, (int) amount
);
1405 else if ((long)amount
> 0)
1406 FatalError("Out of memory");
1415 Xrealloc(pointer ptr
, unsigned long amount
)
1418 if (!Must_have_memory
&& Memory_fail
&&
1419 ((random() % MEM_FAIL_SCALE
) < Memory_fail
))
1420 return (unsigned long *)NULL
;
1422 if ((long)amount
<= 0)
1426 return (unsigned long *)NULL
;
1428 amount
= (amount
+ (sizeof(long) - 1)) & ~(sizeof(long) - 1);
1430 ptr
= (pointer
)realloc((char *)ptr
, amount
);
1432 ptr
= (pointer
)malloc(amount
);
1434 return (unsigned long *)ptr
;
1435 if (Must_have_memory
)
1436 FatalError("Out of memory");
1437 return (unsigned long *)NULL
;
1442 * "no failure" realloc, alternate interface to Xrealloc w/o Must_have_memory
1446 XNFrealloc(pointer ptr
, unsigned long amount
)
1448 if (( ptr
= (pointer
)Xrealloc( ptr
, amount
) ) == NULL
)
1450 if ((long)amount
> 0)
1451 FatalError( "Out of memory" );
1453 return ((unsigned long *)ptr
);
1469 OsInitAllocator (void)
1472 static int been_here
;
1474 /* Check the memory system after each generation */
1481 #endif /* !INTERNAL_MALLOC */
1485 Xstrdup(const char *s
)
1492 sd
= (char *)Xalloc(strlen(s
) + 1);
1500 XNFstrdup(const char *s
)
1507 sd
= (char *)XNFalloc(strlen(s
) + 1);
1512 #ifdef SMART_SCHEDULE
1514 unsigned long SmartScheduleIdleCount
;
1515 Bool SmartScheduleIdle
;
1516 Bool SmartScheduleTimerStopped
;
1519 #define SMART_SCHEDULE_POSSIBLE
1522 #ifdef SMART_SCHEDULE_POSSIBLE
1523 #define SMART_SCHEDULE_SIGNAL SIGALRM
1524 #define SMART_SCHEDULE_TIMER ITIMER_REAL
1528 SmartScheduleStopTimer (void)
1530 #ifdef SMART_SCHEDULE_POSSIBLE
1531 struct itimerval timer
;
1533 timer
.it_interval
.tv_sec
= 0;
1534 timer
.it_interval
.tv_usec
= 0;
1535 timer
.it_value
.tv_sec
= 0;
1536 timer
.it_value
.tv_usec
= 0;
1537 (void) setitimer (ITIMER_REAL
, &timer
, 0);
1538 SmartScheduleTimerStopped
= TRUE
;
1543 SmartScheduleStartTimer (void)
1545 #ifdef SMART_SCHEDULE_POSSIBLE
1546 struct itimerval timer
;
1548 SmartScheduleTimerStopped
= FALSE
;
1549 timer
.it_interval
.tv_sec
= 0;
1550 timer
.it_interval
.tv_usec
= SmartScheduleInterval
* 1000;
1551 timer
.it_value
.tv_sec
= 0;
1552 timer
.it_value
.tv_usec
= SmartScheduleInterval
* 1000;
1553 return setitimer (ITIMER_REAL
, &timer
, 0) >= 0;
1558 #ifdef SMART_SCHEDULE_POSSIBLE
1560 SmartScheduleTimer (int sig
)
1562 int olderrno
= errno
;
1564 SmartScheduleTime
+= SmartScheduleInterval
;
1565 if (SmartScheduleIdle
)
1567 SmartScheduleStopTimer ();
1574 SmartScheduleInit (void)
1576 #ifdef SMART_SCHEDULE_POSSIBLE
1577 struct sigaction act
;
1579 if (SmartScheduleDisable
)
1582 bzero ((char *) &act
, sizeof(struct sigaction
));
1584 /* Set up the timer signal function */
1585 act
.sa_handler
= SmartScheduleTimer
;
1586 sigemptyset (&act
.sa_mask
);
1587 sigaddset (&act
.sa_mask
, SMART_SCHEDULE_SIGNAL
);
1588 if (sigaction (SMART_SCHEDULE_SIGNAL
, &act
, 0) < 0)
1590 perror ("sigaction for smart scheduler");
1593 /* Set up the virtual timer */
1594 if (!SmartScheduleStartTimer ())
1596 perror ("scheduling timer");
1599 /* stop the timer and wait for WaitForSomething to start it */
1600 SmartScheduleStopTimer ();
1609 static sigset_t PreviousSignalMask
;
1610 static int BlockedSignalCount
;
1614 OsBlockSignals (void)
1617 if (BlockedSignalCount
++ == 0)
1623 sigaddset (&set
, SIGALRM
);
1626 sigaddset (&set
, SIGVTALRM
);
1629 sigaddset (&set
, SIGWINCH
);
1632 sigaddset (&set
, SIGIO
);
1635 sigaddset (&set
, SIGTSTP
);
1638 sigaddset (&set
, SIGTTIN
);
1641 sigaddset (&set
, SIGTTOU
);
1644 sigaddset (&set
, SIGCHLD
);
1646 sigprocmask (SIG_BLOCK
, &set
, &PreviousSignalMask
);
1652 OsReleaseSignals (void)
1655 if (--BlockedSignalCount
== 0)
1657 sigprocmask (SIG_SETMASK
, &PreviousSignalMask
, 0);
1664 * "safer" versions of system(3), popen(3) and pclose(3) which give up
1665 * all privs before running a command.
1667 * This is based on the code in FreeBSD 2.2 libc.
1669 * XXX It'd be good to redirect stderr so that it ends up in the log file
1670 * as well. As it is now, xkbcomp messages don't end up in the log file.
1674 System(char *command
)
1686 csig
= signal(SIGCHLD
, SIG_DFL
);
1690 ErrorF("System: `%s'\n", command
);
1693 switch (pid
= fork()) {
1694 case -1: /* error */
1697 if (setgid(getgid()) == -1)
1699 if (setuid(getuid()) == -1)
1701 execl("/bin/sh", "sh", "-c", command
, (char *)NULL
);
1703 default: /* parent */
1705 p
= waitpid(pid
, &status
, 0);
1706 } while (p
== -1 && errno
== EINTR
);
1711 signal(SIGCHLD
, csig
);
1714 return p
== -1 ? -1 : status
;
1724 Popen(char *command
, char *type
)
1730 if (command
== NULL
|| type
== NULL
)
1733 if ((*type
!= 'r' && *type
!= 'w') || type
[1])
1736 if ((cur
= (struct pid
*)xalloc(sizeof(struct pid
))) == NULL
)
1739 if (pipe(pdes
) < 0) {
1744 switch (pid
= fork()) {
1745 case -1: /* error */
1751 if (setgid(getgid()) == -1)
1753 if (setuid(getuid()) == -1)
1770 execl("/bin/sh", "sh", "-c", command
, (char *)NULL
);
1774 /* Avoid EINTR during stdio calls */
1779 iop
= fdopen(pdes
[0], type
);
1782 iop
= fdopen(pdes
[1], type
);
1788 cur
->next
= pidlist
;
1792 ErrorF("Popen: `%s', fp = %p\n", command
, iop
);
1798 /* fopen that drops privileges */
1800 Fopen(char *file
, char *type
)
1803 #ifndef HAS_SAVED_IDS_AND_SETEUID
1807 if (file
== NULL
|| type
== NULL
)
1810 if ((*type
!= 'r' && *type
!= 'w') || type
[1])
1813 if ((cur
= (struct pid
*)xalloc(sizeof(struct pid
))) == NULL
)
1816 if (pipe(pdes
) < 0) {
1821 switch (pid
= fork()) {
1822 case -1: /* error */
1828 if (setgid(getgid()) == -1)
1830 if (setuid(getuid()) == -1)
1847 execl("/bin/cat", "cat", file
, (char *)NULL
);
1851 /* Avoid EINTR during stdio calls */
1856 iop
= fdopen(pdes
[0], type
);
1859 iop
= fdopen(pdes
[1], type
);
1865 cur
->next
= pidlist
;
1869 ErrorF("Fopen(%s), fp = %p\n", file
, iop
);
1879 if (seteuid(ruid
) == -1) {
1882 iop
= fopen(file
, type
);
1884 if (seteuid(euid
) == -1) {
1889 #endif /* HAS_SAVED_IDS_AND_SETEUID */
1895 struct pid
*cur
, *last
;
1900 ErrorF("Pclose: fp = %p\n", iop
);
1905 for (last
= NULL
, cur
= pidlist
; cur
; last
= cur
, cur
= cur
->next
)
1912 pid
= waitpid(cur
->pid
, &pstat
, 0);
1913 } while (pid
== -1 && errno
== EINTR
);
1916 pidlist
= cur
->next
;
1918 last
->next
= cur
->next
;
1921 /* allow EINTR again */
1922 OsReleaseSignals ();
1924 return pid
== -1 ? -1 : pstat
;
1930 #ifdef HAS_SAVED_IDS_AND_SETEUID
1941 * CheckUserParameters: check for long command line arguments and long
1942 * environment variables. By default, these checks are only done when
1943 * the server's euid != ruid. In 3.3.x, these checks were done in an
1944 * external wrapper utility.
1947 /* Consider LD* variables insecure? */
1948 #ifndef REMOVE_ENV_LD
1949 #define REMOVE_ENV_LD 1
1952 /* Remove long environment variables? */
1953 #ifndef REMOVE_LONG_ENV
1954 #define REMOVE_LONG_ENV 1
1958 * Disallow stdout or stderr as pipes? It's possible to block the X server
1959 * when piping stdout+stderr to a pipe.
1961 * Don't enable this because it looks like it's going to cause problems.
1963 #ifndef NO_OUTPUT_PIPES
1964 #define NO_OUTPUT_PIPES 0
1968 /* Check args and env only if running setuid (euid == 0 && euid != uid) ? */
1971 #define CHECK_EUID 1
1973 #define CHECK_EUID 0
1978 * Maybe the locale can be faked to make isprint(3) report that everything
1979 * is printable? Avoid it by default.
1982 #define USE_ISPRINT 0
1985 #define MAX_ARG_LENGTH 128
1986 #define MAX_ENV_LENGTH 256
1987 #define MAX_ENV_PATH_LENGTH 2048 /* Limit for *PATH and TERMCAP */
1991 #define checkPrintable(c) isprint(c)
1993 #define checkPrintable(c) (((c) & 0x7f) >= 0x20 && ((c) & 0x7f) != 0x7f)
2006 #if defined(VENDORSUPPORT)
2007 #define BUGADDRESS VENDORSUPPORT
2008 #elif defined(BUILDERADDR)
2009 #define BUGADDRESS BUILDERADDR
2011 #define BUGADDRESS "xorg@freedesktop.org"
2015 "\nIf the arguments used are valid, and have been rejected incorrectly\n" \
2016 "please send details of the arguments and why they are valid to\n" \
2017 "%s. In the meantime, you can start the Xserver as\n" \
2018 "the \"super user\" (root).\n"
2021 "\nIf the environment is valid, and have been rejected incorrectly\n" \
2022 "please send details of the environment and why it is valid to\n" \
2023 "%s. In the meantime, you can start the Xserver as\n" \
2024 "the \"super user\" (root).\n"
2027 CheckUserParameters(int argc
, char **argv
, char **envp
)
2029 enum BadCode bad
= NotBad
;
2032 #if defined(__QNX__) && !defined(__QNXNTO__)
2037 if (geteuid() == 0 && getuid() != geteuid())
2040 /* Check each argv[] */
2041 for (i
= 1; i
< argc
; i
++) {
2042 if (strcmp(argv
[i
], "-fp") == 0)
2044 i
++; /* continue with next argument. skip the length check */
2049 if (strlen(argv
[i
]) > MAX_ARG_LENGTH
) {
2056 if (checkPrintable(*a
) == 0) {
2057 bad
= UnprintableArg
;
2066 /* Check each envp[] */
2067 for (i
= 0; envp
[i
]; i
++) {
2069 /* Check for bad environment variables and values */
2071 while (envp
[i
] && (strncmp(envp
[i
], "LD", 2) == 0)) {
2073 ErrorF("CheckUserParameters: removing %s from the "
2074 "environment\n", strtok(envp
[i
], "="));
2076 for (j
= i
; envp
[j
]; j
++) {
2077 envp
[j
] = envp
[j
+1];
2081 if (envp
[i
] && (strlen(envp
[i
]) > MAX_ENV_LENGTH
)) {
2084 ErrorF("CheckUserParameters: removing %s from the "
2085 "environment\n", strtok(envp
[i
], "="));
2087 for (j
= i
; envp
[j
]; j
++) {
2088 envp
[j
] = envp
[j
+1];
2095 eq
= strchr(envp
[i
], '=');
2099 e
= malloc(len
+ 1);
2101 bad
= InternalError
;
2104 strncpy(e
, envp
[i
], len
);
2107 (strcmp(e
+ len
- 4, "PATH") == 0 ||
2108 strcmp(e
, "TERMCAP") == 0)) {
2109 if (strlen(envp
[i
]) > MAX_ENV_PATH_LENGTH
) {
2127 if (fstat(fileno(stdout
), &buf
) == 0 && S_ISFIFO(buf
.st_mode
))
2129 if (fstat(fileno(stderr
), &buf
) == 0 && S_ISFIFO(buf
.st_mode
))
2138 ErrorF("Command line argument number %d is unsafe\n", i
);
2139 ErrorF(ARGMSG
, BUGADDRESS
);
2142 ErrorF("Command line argument number %d is too long\n", i
);
2143 ErrorF(ARGMSG
, BUGADDRESS
);
2145 case UnprintableArg
:
2146 ErrorF("Command line argument number %d contains unprintable"
2147 " characters\n", i
);
2148 ErrorF(ARGMSG
, BUGADDRESS
);
2151 ErrorF("Environment variable `%s' is too long\n", e
);
2152 ErrorF(ENVMSG
, BUGADDRESS
);
2155 ErrorF("Stdout and/or stderr is a pipe\n");
2158 ErrorF("Internal Error\n");
2161 ErrorF("Unknown error\n");
2162 ErrorF(ARGMSG
, BUGADDRESS
);
2163 ErrorF(ENVMSG
, BUGADDRESS
);
2166 FatalError("X server aborted because of unsafe environment\n");
2170 * CheckUserAuthorization: check if the user is allowed to start the
2171 * X server. This usually means some sort of PAM checking, and it is
2172 * usually only done for setuid servers (uid != euid).
2176 #include <security/pam_appl.h>
2177 #include <security/pam_misc.h>
2179 #endif /* USE_PAM */
2182 CheckUserAuthorization(void)
2185 static struct pam_conv conv
= {
2190 pam_handle_t
*pamh
= NULL
;
2194 if (getuid() != geteuid()) {
2195 pw
= getpwuid(getuid());
2197 FatalError("getpwuid() failed for uid %d\n", getuid());
2199 retval
= pam_start("xserver", pw
->pw_name
, &conv
, &pamh
);
2200 if (retval
!= PAM_SUCCESS
)
2201 FatalError("pam_start() failed.\n"
2202 "\tMissing or mangled PAM config file or module?\n");
2204 retval
= pam_authenticate(pamh
, 0);
2205 if (retval
!= PAM_SUCCESS
) {
2206 pam_end(pamh
, retval
);
2207 FatalError("PAM authentication failed, cannot start X server.\n"
2208 "\tPerhaps you do not have console ownership?\n");
2211 retval
= pam_acct_mgmt(pamh
, 0);
2212 if (retval
!= PAM_SUCCESS
) {
2213 pam_end(pamh
, retval
);
2214 FatalError("PAM authentication failed, cannot start X server.\n"
2215 "\tPerhaps you do not have console ownership?\n");
2218 /* this is not a session, so do not do session management */
2219 pam_end(pamh
, PAM_SUCCESS
);
2228 lockit (int fd
, short what
)
2237 (void)fcntl (fd
, F_SETLKW
, &lck
);
2240 /* SCO OpenServer 5 lacks pread/pwrite. Emulate them. */
2242 pread (int fd
, void *buf
, size_t nbytes
, off_t offset
)
2247 lockit (fd
, F_RDLCK
);
2248 saved
= lseek (fd
, 0, SEEK_CUR
);
2249 lseek (fd
, offset
, SEEK_SET
);
2250 ret
= read (fd
, buf
, nbytes
);
2251 lseek (fd
, saved
, SEEK_SET
);
2252 lockit (fd
, F_UNLCK
);
2258 pwrite (int fd
, const void *buf
, size_t nbytes
, off_t offset
)
2263 lockit (fd
, F_WRLCK
);
2264 saved
= lseek (fd
, 0, SEEK_CUR
);
2265 lseek (fd
, offset
, SEEK_SET
);
2266 ret
= write (fd
, buf
, nbytes
);
2267 lseek (fd
, saved
, SEEK_SET
);
2268 lockit (fd
, F_UNLCK
);
2272 #endif /* __SCO__ */