utils.c 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641
  1. /*
  2. Copyright 1987, 1998 The Open Group
  3. Permission to use, copy, modify, distribute, and sell this software and its
  4. documentation for any purpose is hereby granted without fee, provided that
  5. the above copyright notice appear in all copies and that both that
  6. copyright notice and this permission notice appear in supporting
  7. documentation.
  8. The above copyright notice and this permission notice shall be included
  9. in all copies or substantial portions of the Software.
  10. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  11. OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  12. MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  13. IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
  14. OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  15. ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  16. OTHER DEALINGS IN THE SOFTWARE.
  17. Except as contained in this notice, the name of The Open Group shall
  18. not be used in advertising or otherwise to promote the sale, use or
  19. other dealings in this Software without prior written authorization
  20. from The Open Group.
  21. Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,
  22. Copyright 1994 Quarterdeck Office Systems.
  23. All Rights Reserved
  24. Permission to use, copy, modify, and distribute this software and its
  25. documentation for any purpose and without fee is hereby granted,
  26. provided that the above copyright notice appear in all copies and that
  27. both that copyright notice and this permission notice appear in
  28. supporting documentation, and that the names of Digital and
  29. Quarterdeck not be used in advertising or publicity pertaining to
  30. distribution of the software without specific, written prior
  31. permission.
  32. DIGITAL AND QUARTERDECK DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
  33. SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
  34. FITNESS, IN NO EVENT SHALL DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT
  35. OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
  36. OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  37. OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
  38. OR PERFORMANCE OF THIS SOFTWARE.
  39. */
  40. #ifdef HAVE_DIX_CONFIG_H
  41. #include <dix-config.h>
  42. #endif
  43. #include <X11/Xos.h>
  44. #include <stdio.h>
  45. #include <time.h>
  46. #include "misc.h"
  47. #include <X11/X.h>
  48. #define XSERV_t
  49. #define TRANS_SERVER
  50. #define TRANS_REOPEN
  51. #include <X11/Xtrans/Xtrans.h>
  52. #include "input.h"
  53. #include "dixfont.h"
  54. #include "osdep.h"
  55. #include "extension.h"
  56. #ifdef X_POSIX_C_SOURCE
  57. #define _POSIX_C_SOURCE X_POSIX_C_SOURCE
  58. #include <signal.h>
  59. #undef _POSIX_C_SOURCE
  60. #else
  61. #if defined(X_NOT_POSIX) || defined(_POSIX_SOURCE)
  62. #include <signal.h>
  63. #else
  64. #define _POSIX_SOURCE
  65. #include <signal.h>
  66. #undef _POSIX_SOURCE
  67. #endif
  68. #endif
  69. #include <sys/wait.h>
  70. #include <sys/resource.h>
  71. #include <sys/stat.h>
  72. #include <ctype.h> /* for isspace */
  73. #include <stdarg.h>
  74. #include <stdlib.h> /* for malloc() */
  75. #if defined(TCPCONN)
  76. # include <netdb.h>
  77. #endif
  78. #include "opaque.h"
  79. #ifdef SMART_SCHEDULE
  80. #include "dixstruct.h"
  81. #endif
  82. #include "picture.h"
  83. _X_EXPORT Bool noTestExtensions;
  84. _X_EXPORT Bool noBigReqExtension = FALSE;
  85. _X_EXPORT Bool noDamageExtension = FALSE;
  86. #ifdef DBE
  87. _X_EXPORT Bool noDbeExtension = FALSE;
  88. #endif
  89. #ifdef DPMSExtension
  90. _X_EXPORT Bool noDPMSExtension = FALSE;
  91. #endif
  92. #ifdef SCREENSAVER
  93. _X_EXPORT Bool noScreenSaverExtension = FALSE;
  94. #endif
  95. _X_EXPORT Bool noMITShmExtension = FALSE;
  96. _X_EXPORT Bool noRRExtension = FALSE;
  97. _X_EXPORT Bool noRenderExtension = FALSE;
  98. _X_EXPORT Bool noShapeExtension = FALSE;
  99. _X_EXPORT Bool noSyncExtension = FALSE;
  100. #ifdef RES
  101. _X_EXPORT Bool noResExtension = FALSE;
  102. #endif
  103. _X_EXPORT Bool noXCMiscExtension = FALSE;
  104. #ifdef XF86BIGFONT
  105. _X_EXPORT Bool noXFree86BigfontExtension = FALSE;
  106. #endif
  107. _X_EXPORT Bool noXFixesExtension = FALSE;
  108. #define X_INCLUDE_NETDB_H
  109. #include <X11/Xos_r.h>
  110. #include <errno.h>
  111. Bool CoreDump;
  112. int auditTrailLevel = 0;
  113. _X_EXPORT Bool Must_have_memory = FALSE;
  114. #if defined(__linux__) || defined(CSRG_BASED)
  115. #define HAS_SAVED_IDS_AND_SETEUID
  116. #endif
  117. #ifdef MEMBUG
  118. #define MEM_FAIL_SCALE 100000
  119. long Memory_fail = 0;
  120. #include <stdlib.h> /* for random() */
  121. #endif
  122. char *dev_tty_from_init = NULL; /* since we need to parse it anyway */
  123. OsSigHandlerPtr
  124. OsSignal(sig, handler)
  125. int sig;
  126. OsSigHandlerPtr handler;
  127. {
  128. struct sigaction act, oact;
  129. sigemptyset(&act.sa_mask);
  130. if (handler != SIG_IGN)
  131. sigaddset(&act.sa_mask, sig);
  132. act.sa_flags = 0;
  133. act.sa_handler = handler;
  134. sigaction(sig, &act, &oact);
  135. return oact.sa_handler;
  136. }
  137. /*
  138. * Explicit support for a server lock file like the ones used for UUCP.
  139. * For architectures with virtual terminals that can run more than one
  140. * server at a time. This keeps the servers from stomping on each other
  141. * if the user forgets to give them different display numbers.
  142. */
  143. #define LOCK_DIR "/tmp"
  144. #define LOCK_TMP_PREFIX "/.tX"
  145. #define LOCK_PREFIX "/.X"
  146. #define LOCK_SUFFIX "-lock"
  147. #ifndef PATH_MAX
  148. #include <sys/param.h>
  149. #ifndef PATH_MAX
  150. #ifdef MAXPATHLEN
  151. #define PATH_MAX MAXPATHLEN
  152. #else
  153. #define PATH_MAX 1024
  154. #endif
  155. #endif
  156. #endif
  157. static Bool StillLocking = FALSE;
  158. static char LockFile[PATH_MAX];
  159. static Bool nolock = FALSE;
  160. /*
  161. * LockServer --
  162. * Check if the server lock file exists. If so, check if the PID
  163. * contained inside is valid. If so, then die. Otherwise, create
  164. * the lock file containing the PID.
  165. */
  166. void
  167. LockServer(void)
  168. {
  169. char tmp[PATH_MAX], pid_str[12];
  170. int lfd, i, haslock, l_pid, t;
  171. char *tmppath = NULL;
  172. int len;
  173. char port[20];
  174. if (nolock) return;
  175. /*
  176. * Path names
  177. */
  178. tmppath = LOCK_DIR;
  179. sprintf(port, "%d", atoi(display));
  180. len = strlen(LOCK_PREFIX) > strlen(LOCK_TMP_PREFIX) ? strlen(LOCK_PREFIX) :
  181. strlen(LOCK_TMP_PREFIX);
  182. len += strlen(tmppath) + strlen(port) + strlen(LOCK_SUFFIX) + 1;
  183. if (len > sizeof(LockFile))
  184. FatalError("Display name `%s' is too long\n", port);
  185. (void)sprintf(tmp, "%s" LOCK_TMP_PREFIX "%s" LOCK_SUFFIX, tmppath, port);
  186. (void)sprintf(LockFile, "%s" LOCK_PREFIX "%s" LOCK_SUFFIX, tmppath, port);
  187. /*
  188. * Create a temporary file containing our PID. Attempt three times
  189. * to create the file.
  190. */
  191. StillLocking = TRUE;
  192. i = 0;
  193. do {
  194. i++;
  195. lfd = open(tmp, O_CREAT | O_EXCL | O_WRONLY, 0644);
  196. if (lfd < 0)
  197. sleep(2);
  198. else
  199. break;
  200. } while (i < 3);
  201. if (lfd < 0) {
  202. unlink(tmp);
  203. i = 0;
  204. do {
  205. i++;
  206. lfd = open(tmp, O_CREAT | O_EXCL | O_WRONLY, 0644);
  207. if (lfd < 0)
  208. sleep(2);
  209. else
  210. break;
  211. } while (i < 3);
  212. }
  213. if (lfd < 0)
  214. FatalError("Could not create lock file in %s\n", tmp);
  215. (void) sprintf(pid_str, "%10ld\n", (long)getpid());
  216. (void) write(lfd, pid_str, 11);
  217. #ifndef USE_CHMOD
  218. (void) fchmod(lfd, 0444);
  219. #else
  220. (void) chmod(tmp, 0444);
  221. #endif
  222. (void) close(lfd);
  223. /*
  224. * OK. Now the tmp file exists. Try three times to move it in place
  225. * for the lock.
  226. */
  227. i = 0;
  228. haslock = 0;
  229. while ((!haslock) && (i++ < 3)) {
  230. haslock = (link(tmp,LockFile) == 0);
  231. if (haslock) {
  232. /*
  233. * We're done.
  234. */
  235. break;
  236. }
  237. else {
  238. /*
  239. * Read the pid from the existing file
  240. */
  241. lfd = open(LockFile, O_RDONLY);
  242. if (lfd < 0) {
  243. unlink(tmp);
  244. FatalError("Can't read lock file %s\n", LockFile);
  245. }
  246. pid_str[0] = '\0';
  247. if (read(lfd, pid_str, 11) != 11) {
  248. /*
  249. * Bogus lock file.
  250. */
  251. unlink(LockFile);
  252. close(lfd);
  253. continue;
  254. }
  255. pid_str[11] = '\0';
  256. sscanf(pid_str, "%d", &l_pid);
  257. close(lfd);
  258. /*
  259. * Now try to kill the PID to see if it exists.
  260. */
  261. errno = 0;
  262. t = kill(l_pid, 0);
  263. if ((t< 0) && (errno == ESRCH)) {
  264. /*
  265. * Stale lock file.
  266. */
  267. unlink(LockFile);
  268. continue;
  269. }
  270. else if (((t < 0) && (errno == EPERM)) || (t == 0)) {
  271. /*
  272. * Process is still active.
  273. */
  274. unlink(tmp);
  275. FatalError("Server is already active for display %s\n%s %s\n%s\n",
  276. port, "\tIf this server is no longer running, remove",
  277. LockFile, "\tand start again.");
  278. }
  279. }
  280. }
  281. unlink(tmp);
  282. if (!haslock)
  283. FatalError("Could not create server lock file: %s\n", LockFile);
  284. StillLocking = FALSE;
  285. }
  286. /*
  287. * UnlockServer --
  288. * Remove the server lock file.
  289. */
  290. void
  291. UnlockServer(void)
  292. {
  293. if (nolock) return;
  294. if (!StillLocking){
  295. (void) unlink(LockFile);
  296. }
  297. }
  298. /* Force connections to close on SIGHUP from init */
  299. /*ARGSUSED*/
  300. SIGVAL
  301. AutoResetServer (int sig)
  302. {
  303. int olderrno = errno;
  304. dispatchException |= DE_RESET;
  305. isItTimeToYield = TRUE;
  306. #ifdef GPROF
  307. chdir ("/tmp");
  308. exit (0);
  309. #endif
  310. errno = olderrno;
  311. }
  312. /* Force connections to close and then exit on SIGTERM, SIGINT */
  313. /*ARGSUSED*/
  314. _X_EXPORT SIGVAL
  315. GiveUp(int sig)
  316. {
  317. int olderrno = errno;
  318. dispatchException |= DE_TERMINATE;
  319. isItTimeToYield = TRUE;
  320. errno = olderrno;
  321. }
  322. _X_EXPORT CARD32
  323. GetTimeInMillis(void)
  324. {
  325. struct timeval tv;
  326. #ifdef MONOTONIC_CLOCK
  327. struct timespec tp;
  328. if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0)
  329. return (tp.tv_sec * 1000) + (tp.tv_nsec / 1000000L);
  330. #endif
  331. X_GETTIMEOFDAY(&tv);
  332. return(tv.tv_sec * 1000) + (tv.tv_usec / 1000);
  333. }
  334. _X_EXPORT void
  335. AdjustWaitForDelay (pointer waitTime, unsigned long newdelay)
  336. {
  337. static struct timeval delay_val;
  338. struct timeval **wt = (struct timeval **) waitTime;
  339. unsigned long olddelay;
  340. if (*wt == NULL)
  341. {
  342. delay_val.tv_sec = newdelay / 1000;
  343. delay_val.tv_usec = 1000 * (newdelay % 1000);
  344. *wt = &delay_val;
  345. }
  346. else
  347. {
  348. olddelay = (*wt)->tv_sec * 1000 + (*wt)->tv_usec / 1000;
  349. if (newdelay < olddelay)
  350. {
  351. (*wt)->tv_sec = newdelay / 1000;
  352. (*wt)->tv_usec = 1000 * (newdelay % 1000);
  353. }
  354. }
  355. }
  356. void UseMsg(void)
  357. {
  358. ErrorF("%s\n\n", PACKAGE_STRING);
  359. ErrorF("use: X [:<display>] [option]\n");
  360. ErrorF("-a # mouse acceleration (pixels)\n");
  361. ErrorF("-ac disable access control restrictions\n");
  362. #ifdef MEMBUG
  363. ErrorF("-alloc int chance alloc should fail\n");
  364. #endif
  365. ErrorF("-audit int set audit trail level\n");
  366. ErrorF("-auth file select authorization file\n");
  367. ErrorF("-br create root window with black background\n");
  368. ErrorF("-c turns off key-click\n");
  369. ErrorF("c # key-click volume (0-100)\n");
  370. ErrorF("-cc int default color visual class\n");
  371. ErrorF("-core generate core dump on fatal error\n");
  372. ErrorF("-dpi int screen resolution in dots per inch\n");
  373. #ifdef DPMSExtension
  374. ErrorF("dpms enables VESA DPMS monitor control\n");
  375. ErrorF("-dpms disables VESA DPMS monitor control\n");
  376. #endif
  377. ErrorF("-deferglyphs [none|all|16] defer loading of [no|all|16-bit] glyphs\n");
  378. ErrorF("-f # bell base (0-100)\n");
  379. ErrorF("-fc string cursor font\n");
  380. ErrorF("-fn string default font name\n");
  381. ErrorF("-fp string default font path\n");
  382. ErrorF("-help prints message with these options\n");
  383. ErrorF("-I ignore all remaining arguments\n");
  384. #ifdef RLIMIT_DATA
  385. ErrorF("-ld int limit data space to N Kb\n");
  386. #endif
  387. #ifdef RLIMIT_NOFILE
  388. ErrorF("-lf int limit number of open files to N\n");
  389. #endif
  390. #ifdef RLIMIT_STACK
  391. ErrorF("-ls int limit stack space to N Kb\n");
  392. #endif
  393. ErrorF("-nolock disable the locking mechanism\n");
  394. #ifndef NOLOGOHACK
  395. ErrorF("-logo enable logo in screen saver\n");
  396. ErrorF("nologo disable logo in screen saver\n");
  397. #endif
  398. ErrorF("-nolisten string don't listen on protocol\n");
  399. ErrorF("-noreset don't reset after last client exists\n");
  400. ErrorF("-reset reset after last client exists\n");
  401. ErrorF("-p # screen-saver pattern duration (minutes)\n");
  402. ErrorF("-pn accept failure to listen on all ports\n");
  403. ErrorF("-nopn reject failure to listen on all ports\n");
  404. ErrorF("-r turns off auto-repeat\n");
  405. ErrorF("r turns on auto-repeat \n");
  406. ErrorF("-render [default|mono|gray|color] set render color alloc policy\n");
  407. ErrorF("-s # screen-saver timeout (minutes)\n");
  408. ErrorF("-startbench shut down immediately\n");
  409. ErrorF("-t # mouse threshold (pixels)\n");
  410. ErrorF("-tcp listen for TCP (default is nolisten tcp)\n");
  411. ErrorF("-terminate terminate at server reset\n");
  412. ErrorF("-to # connection time out\n");
  413. ErrorF("-tst disable testing extensions\n");
  414. ErrorF("ttyxx server started from init on /dev/ttyxx\n");
  415. ErrorF("v video blanking for screen-saver\n");
  416. ErrorF("-v screen-saver without video blanking\n");
  417. ErrorF("-version show the server version\n");
  418. ErrorF("-wr create root window with white background\n");
  419. ErrorF("-x string loads named extension at init time \n");
  420. ErrorF("-maxbigreqsize set maximal bigrequest size \n");
  421. #ifdef SMART_SCHEDULE
  422. ErrorF("-dumbSched Disable smart scheduling, enable old behavior\n");
  423. ErrorF("-schedInterval int Set scheduler interval in msec\n");
  424. #endif
  425. ErrorF("+extension name Enable extension\n");
  426. ErrorF("-extension name Disable extension\n");
  427. #ifdef XDMCP
  428. XdmcpUseMsg();
  429. #endif
  430. ddxUseMsg();
  431. }
  432. /* This function performs a rudimentary sanity check
  433. * on the display name passed in on the command-line,
  434. * since this string is used to generate filenames.
  435. * It is especially important that the display name
  436. * not contain a "/" and not start with a "-".
  437. * --kvajk
  438. */
  439. static int
  440. VerifyDisplayName(const char *d)
  441. {
  442. if ( d == (char *)0 ) return( 0 ); /* null */
  443. if ( *d == '\0' ) return( 0 ); /* empty */
  444. if ( *d == '-' ) return( 0 ); /* could be confused for an option */
  445. if ( *d == '.' ) return( 0 ); /* must not equal "." or ".." */
  446. if ( strchr(d, '/') != (char *)0 ) return( 0 ); /* very important!!! */
  447. return( 1 );
  448. }
  449. /*
  450. * This function parses the command line. Handles device-independent fields
  451. * and allows ddx to handle additional fields. It is not allowed to modify
  452. * argc or any of the strings pointed to by argv.
  453. */
  454. void
  455. ProcessCommandLine(int argc, char *argv[])
  456. {
  457. int i, skip;
  458. int tcp = 0;
  459. defaultKeyboardControl.autoRepeat = TRUE;
  460. #ifdef NO_PART_NET
  461. PartialNetwork = FALSE;
  462. #else
  463. PartialNetwork = TRUE;
  464. #endif
  465. for ( i = 1; i < argc; i++ )
  466. {
  467. /* call ddx first, so it can peek/override if it wants */
  468. if((skip = ddxProcessArgument(argc, argv, i)))
  469. {
  470. i += (skip - 1);
  471. }
  472. else if(argv[i][0] == ':')
  473. {
  474. /* initialize display */
  475. display = argv[i];
  476. display++;
  477. if( ! VerifyDisplayName( display ) ) {
  478. ErrorF("Bad display name: %s\n", display);
  479. UseMsg();
  480. FatalError("Bad display name, exiting: %s\n", display);
  481. }
  482. }
  483. else if ( strcmp( argv[i], "-a") == 0)
  484. {
  485. if(++i < argc)
  486. defaultPointerControl.num = atoi(argv[i]);
  487. else
  488. UseMsg();
  489. }
  490. else if ( strcmp( argv[i], "-ac") == 0)
  491. {
  492. defeatAccessControl = TRUE;
  493. }
  494. #ifdef MEMBUG
  495. else if ( strcmp( argv[i], "-alloc") == 0)
  496. {
  497. if(++i < argc)
  498. Memory_fail = atoi(argv[i]);
  499. else
  500. UseMsg();
  501. }
  502. #endif
  503. else if ( strcmp( argv[i], "-audit") == 0)
  504. {
  505. if(++i < argc)
  506. auditTrailLevel = atoi(argv[i]);
  507. else
  508. UseMsg();
  509. }
  510. else if ( strcmp( argv[i], "-auth") == 0)
  511. {
  512. if(++i < argc)
  513. InitAuthorization (argv[i]);
  514. else
  515. UseMsg();
  516. }
  517. else if ( strcmp( argv[i], "-br") == 0)
  518. blackRoot = TRUE;
  519. else if ( strcmp( argv[i], "c") == 0)
  520. {
  521. if(++i < argc)
  522. defaultKeyboardControl.click = atoi(argv[i]);
  523. else
  524. UseMsg();
  525. }
  526. else if ( strcmp( argv[i], "-c") == 0)
  527. {
  528. defaultKeyboardControl.click = 0;
  529. }
  530. else if ( strcmp( argv[i], "-cc") == 0)
  531. {
  532. if(++i < argc)
  533. defaultColorVisualClass = atoi(argv[i]);
  534. else
  535. UseMsg();
  536. }
  537. else if ( strcmp( argv[i], "-core") == 0)
  538. CoreDump = TRUE;
  539. else if ( strcmp( argv[i], "-dpi") == 0)
  540. {
  541. if(++i < argc)
  542. monitorResolution = atoi(argv[i]);
  543. else
  544. UseMsg();
  545. }
  546. #ifdef DPMSExtension
  547. else if ( strcmp( argv[i], "dpms") == 0)
  548. DPMSEnabledSwitch = TRUE;
  549. else if ( strcmp( argv[i], "-dpms") == 0)
  550. DPMSDisabledSwitch = TRUE;
  551. #endif
  552. else if ( strcmp( argv[i], "-deferglyphs") == 0)
  553. {
  554. if(++i >= argc || !ParseGlyphCachingMode(argv[i]))
  555. UseMsg();
  556. }
  557. else if ( strcmp( argv[i], "-f") == 0)
  558. {
  559. if(++i < argc)
  560. defaultKeyboardControl.bell = atoi(argv[i]);
  561. else
  562. UseMsg();
  563. }
  564. else if ( strcmp( argv[i], "-fc") == 0)
  565. {
  566. if(++i < argc)
  567. defaultCursorFont = argv[i];
  568. else
  569. UseMsg();
  570. }
  571. else if ( strcmp( argv[i], "-fn") == 0)
  572. {
  573. if(++i < argc)
  574. defaultTextFont = argv[i];
  575. else
  576. UseMsg();
  577. }
  578. else if ( strcmp( argv[i], "-fp") == 0)
  579. {
  580. if(++i < argc)
  581. {
  582. defaultFontPath = argv[i];
  583. }
  584. else
  585. UseMsg();
  586. }
  587. else if ( strcmp( argv[i], "-help") == 0)
  588. {
  589. UseMsg();
  590. exit(0);
  591. }
  592. #ifdef RLIMIT_DATA
  593. else if ( strcmp( argv[i], "-ld") == 0)
  594. {
  595. if(++i < argc)
  596. {
  597. limitDataSpace = atoi(argv[i]);
  598. if (limitDataSpace > 0)
  599. limitDataSpace *= 1024;
  600. }
  601. else
  602. UseMsg();
  603. }
  604. #endif
  605. #ifdef RLIMIT_NOFILE
  606. else if ( strcmp( argv[i], "-lf") == 0)
  607. {
  608. if(++i < argc)
  609. limitNoFile = atoi(argv[i]);
  610. else
  611. UseMsg();
  612. }
  613. #endif
  614. #ifdef RLIMIT_STACK
  615. else if ( strcmp( argv[i], "-ls") == 0)
  616. {
  617. if(++i < argc)
  618. {
  619. limitStackSpace = atoi(argv[i]);
  620. if (limitStackSpace > 0)
  621. limitStackSpace *= 1024;
  622. }
  623. else
  624. UseMsg();
  625. }
  626. #endif
  627. else if ( strcmp ( argv[i], "-nolock") == 0)
  628. {
  629. if (getuid() != 0)
  630. ErrorF("Warning: the -nolock option can only be used by root\n");
  631. else
  632. nolock = TRUE;
  633. }
  634. #ifndef NOLOGOHACK
  635. else if ( strcmp( argv[i], "-logo") == 0)
  636. {
  637. logoScreenSaver = 1;
  638. }
  639. else if ( strcmp( argv[i], "nologo") == 0)
  640. {
  641. logoScreenSaver = 0;
  642. }
  643. #endif
  644. else if ( strcmp( argv[i], "-nolisten") == 0)
  645. {
  646. if(++i < argc) {
  647. if (_XSERVTransNoListen(argv[i]))
  648. FatalError ("Failed to disable listen for %s transport",
  649. argv[i]);
  650. } else
  651. UseMsg();
  652. }
  653. else if ( strcmp( argv[i], "-noreset") == 0)
  654. {
  655. dispatchExceptionAtReset = 0;
  656. }
  657. else if ( strcmp( argv[i], "-reset") == 0)
  658. {
  659. dispatchExceptionAtReset = DE_RESET;
  660. }
  661. else if ( strcmp( argv[i], "-p") == 0)
  662. {
  663. if(++i < argc)
  664. defaultScreenSaverInterval = ((CARD32)atoi(argv[i])) *
  665. MILLI_PER_MIN;
  666. else
  667. UseMsg();
  668. }
  669. else if ( strcmp( argv[i], "-pn") == 0)
  670. PartialNetwork = TRUE;
  671. else if ( strcmp( argv[i], "-nopn") == 0)
  672. PartialNetwork = FALSE;
  673. else if ( strcmp( argv[i], "r") == 0)
  674. defaultKeyboardControl.autoRepeat = TRUE;
  675. else if ( strcmp( argv[i], "-r") == 0)
  676. defaultKeyboardControl.autoRepeat = FALSE;
  677. else if ( strcmp( argv[i], "-startbench") == 0)
  678. {
  679. GiveUp(0);
  680. }
  681. else if ( strcmp( argv[i], "-s") == 0)
  682. {
  683. if(++i < argc)
  684. defaultScreenSaverTime = ((CARD32)atoi(argv[i])) *
  685. MILLI_PER_MIN;
  686. else
  687. UseMsg();
  688. }
  689. else if ( strcmp( argv[i], "-t") == 0)
  690. {
  691. if(++i < argc)
  692. defaultPointerControl.threshold = atoi(argv[i]);
  693. else
  694. UseMsg();
  695. }
  696. else if ( strcmp( argv[i], "-tcp") == 0)
  697. {
  698. tcp = 1;
  699. }
  700. else if ( strcmp( argv[i], "-terminate") == 0)
  701. {
  702. dispatchExceptionAtReset = DE_TERMINATE;
  703. }
  704. else if ( strcmp( argv[i], "-to") == 0)
  705. {
  706. if(++i < argc)
  707. TimeOutValue = ((CARD32)atoi(argv[i])) * MILLI_PER_SECOND;
  708. else
  709. UseMsg();
  710. }
  711. else if ( strcmp( argv[i], "-tst") == 0)
  712. {
  713. noTestExtensions = TRUE;
  714. }
  715. else if ( strcmp( argv[i], "v") == 0)
  716. defaultScreenSaverBlanking = PreferBlanking;
  717. else if ( strcmp( argv[i], "-v") == 0)
  718. defaultScreenSaverBlanking = DontPreferBlanking;
  719. else if ( strcmp( argv[i], "-wr") == 0)
  720. whiteRoot = TRUE;
  721. else if ( strcmp( argv[i], "-maxbigreqsize") == 0) {
  722. if(++i < argc) {
  723. long reqSizeArg = atol(argv[i]);
  724. /* Request size > 128MB does not make much sense... */
  725. if( reqSizeArg > 0L && reqSizeArg < 128L ) {
  726. maxBigRequestSize = (reqSizeArg * 1048576L) - 1L;
  727. }
  728. else
  729. {
  730. UseMsg();
  731. }
  732. }
  733. else
  734. {
  735. UseMsg();
  736. }
  737. }
  738. else if ( strcmp( argv[i], "-x") == 0)
  739. {
  740. if(++i >= argc)
  741. UseMsg();
  742. /* For U**x, which doesn't support dynamic loading, there's nothing
  743. * to do when we see a -x. Either the extension is linked in or
  744. * it isn't */
  745. }
  746. else if ( strcmp( argv[i], "-I") == 0)
  747. {
  748. /* ignore all remaining arguments */
  749. break;
  750. }
  751. else if (strncmp (argv[i], "tty", 3) == 0)
  752. {
  753. /* just in case any body is interested */
  754. dev_tty_from_init = argv[i];
  755. }
  756. #ifdef XDMCP
  757. else if ((skip = XdmcpOptions(argc, argv, i)) != i)
  758. {
  759. i = skip - 1;
  760. }
  761. #endif
  762. #ifdef SMART_SCHEDULE
  763. else if ( strcmp( argv[i], "-dumbSched") == 0)
  764. {
  765. SmartScheduleDisable = TRUE;
  766. }
  767. else if ( strcmp( argv[i], "-schedInterval") == 0)
  768. {
  769. if (++i < argc)
  770. {
  771. SmartScheduleInterval = atoi(argv[i]);
  772. SmartScheduleSlice = SmartScheduleInterval;
  773. }
  774. else
  775. UseMsg();
  776. }
  777. else if ( strcmp( argv[i], "-schedMax") == 0)
  778. {
  779. if (++i < argc)
  780. {
  781. SmartScheduleMaxSlice = atoi(argv[i]);
  782. }
  783. else
  784. UseMsg();
  785. }
  786. #endif
  787. else if ( strcmp( argv[i], "-render" ) == 0)
  788. {
  789. if (++i < argc)
  790. {
  791. int policy = PictureParseCmapPolicy (argv[i]);
  792. if (policy != PictureCmapPolicyInvalid)
  793. PictureCmapPolicy = policy;
  794. else
  795. UseMsg ();
  796. }
  797. else
  798. UseMsg ();
  799. }
  800. else if ( strcmp( argv[i], "+extension") == 0)
  801. {
  802. if (++i < argc)
  803. {
  804. if (!EnableDisableExtension(argv[i], TRUE))
  805. EnableDisableExtensionError(argv[i], TRUE);
  806. }
  807. else
  808. UseMsg();
  809. }
  810. else if ( strcmp( argv[i], "-extension") == 0)
  811. {
  812. if (++i < argc)
  813. {
  814. if (!EnableDisableExtension(argv[i], FALSE))
  815. EnableDisableExtensionError(argv[i], FALSE);
  816. }
  817. else
  818. UseMsg();
  819. }
  820. else
  821. {
  822. ErrorF("Unrecognized option: %s\n", argv[i]);
  823. UseMsg();
  824. FatalError("Unrecognized option: %s\n", argv[i]);
  825. }
  826. }
  827. if (!tcp)
  828. _XSERVTransNoListen("tcp");
  829. }
  830. /* Implement a simple-minded font authorization scheme. The authorization
  831. name is "hp-hostname-1", the contents are simply the host name. */
  832. int
  833. set_font_authorizations(char **authorizations, int *authlen, pointer client)
  834. {
  835. #define AUTHORIZATION_NAME "hp-hostname-1"
  836. #if defined(TCPCONN)
  837. static char *result = NULL;
  838. static char *p = NULL;
  839. if (p == NULL)
  840. {
  841. char hname[1024], *hnameptr;
  842. unsigned int len;
  843. #if defined(IPv6) && defined(AF_INET6)
  844. struct addrinfo hints, *ai = NULL;
  845. #else
  846. struct hostent *host;
  847. #ifdef XTHREADS_NEEDS_BYNAMEPARAMS
  848. _Xgethostbynameparams hparams;
  849. #endif
  850. #endif
  851. gethostname(hname, 1024);
  852. #if defined(IPv6) && defined(AF_INET6)
  853. bzero(&hints, sizeof(hints));
  854. hints.ai_flags = AI_CANONNAME;
  855. if (getaddrinfo(hname, NULL, &hints, &ai) == 0) {
  856. hnameptr = ai->ai_canonname;
  857. } else {
  858. hnameptr = hname;
  859. }
  860. #else
  861. host = _XGethostbyname(hname, hparams);
  862. if (host == NULL)
  863. hnameptr = hname;
  864. else
  865. hnameptr = host->h_name;
  866. #endif
  867. len = strlen(hnameptr) + 1;
  868. result = malloc(len + sizeof(AUTHORIZATION_NAME) + 4);
  869. p = result;
  870. *p++ = sizeof(AUTHORIZATION_NAME) >> 8;
  871. *p++ = sizeof(AUTHORIZATION_NAME) & 0xff;
  872. *p++ = (len) >> 8;
  873. *p++ = (len & 0xff);
  874. memmove(p, AUTHORIZATION_NAME, sizeof(AUTHORIZATION_NAME));
  875. p += sizeof(AUTHORIZATION_NAME);
  876. memmove(p, hnameptr, len);
  877. p += len;
  878. #if defined(IPv6) && defined(AF_INET6)
  879. if (ai) {
  880. freeaddrinfo(ai);
  881. }
  882. #endif
  883. }
  884. *authlen = p - result;
  885. *authorizations = result;
  886. return 1;
  887. #else /* TCPCONN */
  888. return 0;
  889. #endif /* TCPCONN */
  890. }
  891. void
  892. OsInitAllocator (void)
  893. {
  894. #ifdef MEMBUG
  895. static int been_here;
  896. /* Check the memory system after each generation */
  897. if (been_here)
  898. CheckMemory ();
  899. else
  900. been_here = 1;
  901. #endif
  902. }
  903. #ifdef SMART_SCHEDULE
  904. unsigned long SmartScheduleIdleCount;
  905. Bool SmartScheduleIdle;
  906. Bool SmartScheduleTimerStopped;
  907. #ifdef SIGVTALRM
  908. #define SMART_SCHEDULE_POSSIBLE
  909. #endif
  910. #ifdef SMART_SCHEDULE_POSSIBLE
  911. #define SMART_SCHEDULE_SIGNAL SIGALRM
  912. #define SMART_SCHEDULE_TIMER ITIMER_REAL
  913. #endif
  914. static void
  915. SmartScheduleStopTimer (void)
  916. {
  917. #ifdef SMART_SCHEDULE_POSSIBLE
  918. struct itimerval timer;
  919. timer.it_interval.tv_sec = 0;
  920. timer.it_interval.tv_usec = 0;
  921. timer.it_value.tv_sec = 0;
  922. timer.it_value.tv_usec = 0;
  923. (void) setitimer (ITIMER_REAL, &timer, 0);
  924. SmartScheduleTimerStopped = TRUE;
  925. #endif
  926. }
  927. Bool
  928. SmartScheduleStartTimer (void)
  929. {
  930. #ifdef SMART_SCHEDULE_POSSIBLE
  931. struct itimerval timer;
  932. SmartScheduleTimerStopped = FALSE;
  933. timer.it_interval.tv_sec = 0;
  934. timer.it_interval.tv_usec = SmartScheduleInterval * 1000;
  935. timer.it_value.tv_sec = 0;
  936. timer.it_value.tv_usec = SmartScheduleInterval * 1000;
  937. return setitimer (ITIMER_REAL, &timer, 0) >= 0;
  938. #endif
  939. return FALSE;
  940. }
  941. #ifdef SMART_SCHEDULE_POSSIBLE
  942. static void
  943. SmartScheduleTimer (int sig)
  944. {
  945. int olderrno = errno;
  946. SmartScheduleTime += SmartScheduleInterval;
  947. if (SmartScheduleIdle)
  948. {
  949. SmartScheduleStopTimer ();
  950. }
  951. errno = olderrno;
  952. }
  953. #endif
  954. Bool
  955. SmartScheduleInit (void)
  956. {
  957. #ifdef SMART_SCHEDULE_POSSIBLE
  958. struct sigaction act;
  959. if (SmartScheduleDisable)
  960. return TRUE;
  961. bzero ((char *) &act, sizeof(struct sigaction));
  962. /* Set up the timer signal function */
  963. act.sa_handler = SmartScheduleTimer;
  964. sigemptyset (&act.sa_mask);
  965. sigaddset (&act.sa_mask, SMART_SCHEDULE_SIGNAL);
  966. if (sigaction (SMART_SCHEDULE_SIGNAL, &act, 0) < 0)
  967. {
  968. perror ("sigaction for smart scheduler");
  969. return FALSE;
  970. }
  971. /* Set up the virtual timer */
  972. if (!SmartScheduleStartTimer ())
  973. {
  974. perror ("scheduling timer");
  975. return FALSE;
  976. }
  977. /* stop the timer and wait for WaitForSomething to start it */
  978. SmartScheduleStopTimer ();
  979. return TRUE;
  980. #else
  981. return FALSE;
  982. #endif
  983. }
  984. #endif
  985. #ifdef SIG_BLOCK
  986. static sigset_t PreviousSignalMask;
  987. static int BlockedSignalCount;
  988. #endif
  989. void
  990. OsBlockSignals (void)
  991. {
  992. #ifdef SIG_BLOCK
  993. if (BlockedSignalCount++ == 0)
  994. {
  995. sigset_t set;
  996. sigemptyset (&set);
  997. #ifdef SIGALRM
  998. sigaddset (&set, SIGALRM);
  999. #endif
  1000. #ifdef SIGVTALRM
  1001. sigaddset (&set, SIGVTALRM);
  1002. #endif
  1003. #ifdef SIGWINCH
  1004. sigaddset (&set, SIGWINCH);
  1005. #endif
  1006. #ifdef SIGIO
  1007. sigaddset (&set, SIGIO);
  1008. #endif
  1009. #ifdef SIGTSTP
  1010. sigaddset (&set, SIGTSTP);
  1011. #endif
  1012. #ifdef SIGTTIN
  1013. sigaddset (&set, SIGTTIN);
  1014. #endif
  1015. #ifdef SIGTTOU
  1016. sigaddset (&set, SIGTTOU);
  1017. #endif
  1018. #ifdef SIGCHLD
  1019. sigaddset (&set, SIGCHLD);
  1020. #endif
  1021. sigprocmask (SIG_BLOCK, &set, &PreviousSignalMask);
  1022. }
  1023. #endif
  1024. }
  1025. void
  1026. OsReleaseSignals (void)
  1027. {
  1028. #ifdef SIG_BLOCK
  1029. if (--BlockedSignalCount == 0)
  1030. {
  1031. sigprocmask (SIG_SETMASK, &PreviousSignalMask, 0);
  1032. }
  1033. #endif
  1034. }
  1035. /*
  1036. * "safer" versions of system(3), popen(3) and pclose(3) which give up
  1037. * all privs before running a command.
  1038. *
  1039. * This is based on the code in FreeBSD 2.2 libc.
  1040. *
  1041. * XXX It'd be good to redirect stderr so that it ends up in the log file
  1042. * as well. As it is now, xkbcomp messages don't end up in the log file.
  1043. */
  1044. int
  1045. System(char *command)
  1046. {
  1047. int pid, p;
  1048. #ifdef SIGCHLD
  1049. void (*csig)(int);
  1050. #endif
  1051. int status;
  1052. if (!command)
  1053. return(1);
  1054. #ifdef SIGCHLD
  1055. csig = signal(SIGCHLD, SIG_DFL);
  1056. #endif
  1057. #ifdef DEBUG
  1058. ErrorF("System: `%s'\n", command);
  1059. #endif
  1060. switch (pid = fork()) {
  1061. case -1: /* error */
  1062. return -1;
  1063. case 0: /* child */
  1064. if (setgid(getgid()) == -1)
  1065. _exit(127);
  1066. if (setuid(getuid()) == -1)
  1067. _exit(127);
  1068. execl("/bin/sh", "sh", "-c", command, (char *)NULL);
  1069. _exit(127);
  1070. default: /* parent */
  1071. do {
  1072. p = waitpid(pid, &status, 0);
  1073. } while (p == -1 && errno == EINTR);
  1074. }
  1075. #ifdef SIGCHLD
  1076. signal(SIGCHLD, csig);
  1077. #endif
  1078. return p == -1 ? -1 : status;
  1079. }
  1080. static struct pid {
  1081. struct pid *next;
  1082. FILE *fp;
  1083. int pid;
  1084. } *pidlist;
  1085. pointer
  1086. Popen(char *command, char *type)
  1087. {
  1088. struct pid *cur;
  1089. FILE *iop;
  1090. int pdes[2], pid;
  1091. if (command == NULL || type == NULL)
  1092. return NULL;
  1093. if ((*type != 'r' && *type != 'w') || type[1])
  1094. return NULL;
  1095. if ((cur = (struct pid *)malloc(sizeof(struct pid))) == NULL)
  1096. return NULL;
  1097. if (pipe(pdes) < 0) {
  1098. free(cur);
  1099. return NULL;
  1100. }
  1101. switch (pid = fork()) {
  1102. case -1: /* error */
  1103. close(pdes[0]);
  1104. close(pdes[1]);
  1105. free(cur);
  1106. return NULL;
  1107. case 0: /* child */
  1108. if (setgid(getgid()) == -1)
  1109. _exit(127);
  1110. if (setuid(getuid()) == -1)
  1111. _exit(127);
  1112. if (*type == 'r') {
  1113. if (pdes[1] != 1) {
  1114. /* stdout */
  1115. dup2(pdes[1], 1);
  1116. close(pdes[1]);
  1117. }
  1118. close(pdes[0]);
  1119. } else {
  1120. if (pdes[0] != 0) {
  1121. /* stdin */
  1122. dup2(pdes[0], 0);
  1123. close(pdes[0]);
  1124. }
  1125. close(pdes[1]);
  1126. }
  1127. execl("/bin/sh", "sh", "-c", command, (char *)NULL);
  1128. _exit(127);
  1129. }
  1130. /* Avoid EINTR during stdio calls */
  1131. OsBlockSignals ();
  1132. /* parent */
  1133. if (*type == 'r') {
  1134. iop = fdopen(pdes[0], type);
  1135. close(pdes[1]);
  1136. } else {
  1137. iop = fdopen(pdes[1], type);
  1138. close(pdes[0]);
  1139. }
  1140. cur->fp = iop;
  1141. cur->pid = pid;
  1142. cur->next = pidlist;
  1143. pidlist = cur;
  1144. #ifdef DEBUG
  1145. ErrorF("Popen: `%s', fp = %p\n", command, iop);
  1146. #endif
  1147. return iop;
  1148. }
  1149. /* fopen that drops privileges */
  1150. pointer
  1151. Fopen(char *file, char *type)
  1152. {
  1153. FILE *iop;
  1154. #ifndef HAS_SAVED_IDS_AND_SETEUID
  1155. struct pid *cur;
  1156. int pdes[2], pid;
  1157. if (file == NULL || type == NULL)
  1158. return NULL;
  1159. if ((*type != 'r' && *type != 'w') || type[1])
  1160. return NULL;
  1161. if ((cur = (struct pid *)malloc(sizeof(struct pid))) == NULL)
  1162. return NULL;
  1163. if (pipe(pdes) < 0) {
  1164. free(cur);
  1165. return NULL;
  1166. }
  1167. switch (pid = fork()) {
  1168. case -1: /* error */
  1169. close(pdes[0]);
  1170. close(pdes[1]);
  1171. free(cur);
  1172. return NULL;
  1173. case 0: /* child */
  1174. if (setgid(getgid()) == -1)
  1175. _exit(127);
  1176. if (setuid(getuid()) == -1)
  1177. _exit(127);
  1178. if (*type == 'r') {
  1179. if (pdes[1] != 1) {
  1180. /* stdout */
  1181. dup2(pdes[1], 1);
  1182. close(pdes[1]);
  1183. }
  1184. close(pdes[0]);
  1185. } else {
  1186. if (pdes[0] != 0) {
  1187. /* stdin */
  1188. dup2(pdes[0], 0);
  1189. close(pdes[0]);
  1190. }
  1191. close(pdes[1]);
  1192. }
  1193. execl("/bin/cat", "cat", file, (char *)NULL);
  1194. _exit(127);
  1195. }
  1196. /* Avoid EINTR during stdio calls */
  1197. OsBlockSignals ();
  1198. /* parent */
  1199. if (*type == 'r') {
  1200. iop = fdopen(pdes[0], type);
  1201. close(pdes[1]);
  1202. } else {
  1203. iop = fdopen(pdes[1], type);
  1204. close(pdes[0]);
  1205. }
  1206. cur->fp = iop;
  1207. cur->pid = pid;
  1208. cur->next = pidlist;
  1209. pidlist = cur;
  1210. #ifdef DEBUG
  1211. ErrorF("Popen: `%s', fp = %p\n", command, iop);
  1212. #endif
  1213. return iop;
  1214. #else
  1215. int ruid, euid;
  1216. ruid = getuid();
  1217. euid = geteuid();
  1218. if (seteuid(ruid) == -1) {
  1219. return NULL;
  1220. }
  1221. iop = fopen(file, type);
  1222. if (seteuid(euid) == -1) {
  1223. fclose(iop);
  1224. return NULL;
  1225. }
  1226. return iop;
  1227. #endif /* HAS_SAVED_IDS_AND_SETEUID */
  1228. }
  1229. int
  1230. Pclose(pointer iop)
  1231. {
  1232. struct pid *cur, *last;
  1233. int pstat;
  1234. int pid;
  1235. #ifdef DEBUG
  1236. ErrorF("Pclose: fp = %p\n", iop);
  1237. #endif
  1238. fclose(iop);
  1239. for (last = NULL, cur = pidlist; cur; last = cur, cur = cur->next)
  1240. if (cur->fp == iop)
  1241. break;
  1242. if (cur == NULL)
  1243. return -1;
  1244. do {
  1245. pid = waitpid(cur->pid, &pstat, 0);
  1246. } while (pid == -1 && errno == EINTR);
  1247. if (last == NULL)
  1248. pidlist = cur->next;
  1249. else
  1250. last->next = cur->next;
  1251. free(cur);
  1252. /* allow EINTR again */
  1253. OsReleaseSignals ();
  1254. return pid == -1 ? -1 : pstat;
  1255. }
  1256. int
  1257. Fclose(pointer iop)
  1258. {
  1259. #ifdef HAS_SAVED_IDS_AND_SETEUID
  1260. return fclose(iop);
  1261. #else
  1262. return Pclose(iop);
  1263. #endif
  1264. }
  1265. /*
  1266. * CheckUserParameters: check for long command line arguments and long
  1267. * environment variables. By default, these checks are only done when
  1268. * the server's euid != ruid. In 3.3.x, these checks were done in an
  1269. * external wrapper utility.
  1270. */
  1271. /* Consider LD* variables insecure? */
  1272. #ifndef REMOVE_ENV_LD
  1273. #define REMOVE_ENV_LD 1
  1274. #endif
  1275. /* Remove long environment variables? */
  1276. #ifndef REMOVE_LONG_ENV
  1277. #define REMOVE_LONG_ENV 1
  1278. #endif
  1279. /*
  1280. * Disallow stdout or stderr as pipes? It's possible to block the X server
  1281. * when piping stdout+stderr to a pipe.
  1282. *
  1283. * Don't enable this because it looks like it's going to cause problems.
  1284. */
  1285. #ifndef NO_OUTPUT_PIPES
  1286. #define NO_OUTPUT_PIPES 0
  1287. #endif
  1288. /* Check args and env only if running setuid (euid == 0 && euid != uid) ? */
  1289. #ifndef CHECK_EUID
  1290. #define CHECK_EUID 1
  1291. #endif
  1292. /*
  1293. * Maybe the locale can be faked to make isprint(3) report that everything
  1294. * is printable? Avoid it by default.
  1295. */
  1296. #ifndef USE_ISPRINT
  1297. #define USE_ISPRINT 0
  1298. #endif
  1299. #define MAX_ARG_LENGTH 128
  1300. #define MAX_ENV_LENGTH 256
  1301. #define MAX_ENV_PATH_LENGTH 2048 /* Limit for *PATH and TERMCAP */
  1302. #if USE_ISPRINT
  1303. #include <ctype.h>
  1304. #define checkPrintable(c) isprint(c)
  1305. #else
  1306. #define checkPrintable(c) (((c) & 0x7f) >= 0x20 && ((c) & 0x7f) != 0x7f)
  1307. #endif
  1308. enum BadCode {
  1309. NotBad = 0,
  1310. UnsafeArg,
  1311. ArgTooLong,
  1312. UnprintableArg,
  1313. EnvTooLong,
  1314. OutputIsPipe,
  1315. InternalError
  1316. };
  1317. #if defined(VENDORSUPPORT)
  1318. #define BUGADDRESS VENDORSUPPORT
  1319. #elif defined(BUILDERADDR)
  1320. #define BUGADDRESS BUILDERADDR
  1321. #else
  1322. #define BUGADDRESS "xorg@freedesktop.org"
  1323. #endif
  1324. #define ARGMSG \
  1325. "\nIf the arguments used are valid, and have been rejected incorrectly\n" \
  1326. "please send details of the arguments and why they are valid to\n" \
  1327. "%s. In the meantime, you can start the Xserver as\n" \
  1328. "the \"super user\" (root).\n"
  1329. #define ENVMSG \
  1330. "\nIf the environment is valid, and have been rejected incorrectly\n" \
  1331. "please send details of the environment and why it is valid to\n" \
  1332. "%s. In the meantime, you can start the Xserver as\n" \
  1333. "the \"super user\" (root).\n"
  1334. void
  1335. CheckUserParameters(int argc, char **argv, char **envp)
  1336. {
  1337. enum BadCode bad = NotBad;
  1338. int i = 0, j;
  1339. char *a, *e = NULL;
  1340. #if CHECK_EUID
  1341. if (geteuid() == 0 && getuid() != geteuid())
  1342. #endif
  1343. {
  1344. /* Check each argv[] */
  1345. for (i = 1; i < argc; i++) {
  1346. if (strcmp(argv[i], "-fp") == 0)
  1347. {
  1348. i++; /* continue with next argument. skip the length check */
  1349. if (i >= argc)
  1350. break;
  1351. } else
  1352. {
  1353. if (strlen(argv[i]) > MAX_ARG_LENGTH) {
  1354. bad = ArgTooLong;
  1355. break;
  1356. }
  1357. }
  1358. a = argv[i];
  1359. while (*a) {
  1360. if (checkPrintable(*a) == 0) {
  1361. bad = UnprintableArg;
  1362. break;
  1363. }
  1364. a++;
  1365. }
  1366. if (bad)
  1367. break;
  1368. }
  1369. if (!bad) {
  1370. /* Check each envp[] */
  1371. for (i = 0; envp[i]; i++) {
  1372. /* Check for bad environment variables and values */
  1373. #if REMOVE_ENV_LD
  1374. while (envp[i] && (strncmp(envp[i], "LD", 2) == 0)) {
  1375. #ifdef ENVDEBUG
  1376. ErrorF("CheckUserParameters: removing %s from the "
  1377. "environment\n", strtok(envp[i], "="));
  1378. #endif
  1379. for (j = i; envp[j]; j++) {
  1380. envp[j] = envp[j+1];
  1381. }
  1382. }
  1383. #endif
  1384. if (envp[i] && (strlen(envp[i]) > MAX_ENV_LENGTH)) {
  1385. #if REMOVE_LONG_ENV
  1386. #ifdef ENVDEBUG
  1387. ErrorF("CheckUserParameters: removing %s from the "
  1388. "environment\n", strtok(envp[i], "="));
  1389. #endif
  1390. for (j = i; envp[j]; j++) {
  1391. envp[j] = envp[j+1];
  1392. }
  1393. i--;
  1394. #else
  1395. char *eq;
  1396. int len;
  1397. eq = strchr(envp[i], '=');
  1398. if (!eq)
  1399. continue;
  1400. len = eq - envp[i];
  1401. e = malloc(len + 1);
  1402. if (!e) {
  1403. bad = InternalError;
  1404. break;
  1405. }
  1406. strncpy(e, envp[i], len);
  1407. e[len] = 0;
  1408. if (len >= 4 &&
  1409. (strcmp(e + len - 4, "PATH") == 0 ||
  1410. strcmp(e, "TERMCAP") == 0)) {
  1411. if (strlen(envp[i]) > MAX_ENV_PATH_LENGTH) {
  1412. bad = EnvTooLong;
  1413. break;
  1414. } else {
  1415. free(e);
  1416. }
  1417. } else {
  1418. bad = EnvTooLong;
  1419. break;
  1420. }
  1421. #endif
  1422. }
  1423. }
  1424. }
  1425. #if NO_OUTPUT_PIPES
  1426. if (!bad) {
  1427. struct stat buf;
  1428. if (fstat(fileno(stdout), &buf) == 0 && S_ISFIFO(buf.st_mode))
  1429. bad = OutputIsPipe;
  1430. if (fstat(fileno(stderr), &buf) == 0 && S_ISFIFO(buf.st_mode))
  1431. bad = OutputIsPipe;
  1432. }
  1433. #endif
  1434. }
  1435. switch (bad) {
  1436. case NotBad:
  1437. return;
  1438. case UnsafeArg:
  1439. ErrorF("Command line argument number %d is unsafe\n", i);
  1440. ErrorF(ARGMSG, BUGADDRESS);
  1441. break;
  1442. case ArgTooLong:
  1443. ErrorF("Command line argument number %d is too long\n", i);
  1444. ErrorF(ARGMSG, BUGADDRESS);
  1445. break;
  1446. case UnprintableArg:
  1447. ErrorF("Command line argument number %d contains unprintable"
  1448. " characters\n", i);
  1449. ErrorF(ARGMSG, BUGADDRESS);
  1450. break;
  1451. case EnvTooLong:
  1452. ErrorF("Environment variable `%s' is too long\n", e);
  1453. ErrorF(ENVMSG, BUGADDRESS);
  1454. break;
  1455. case OutputIsPipe:
  1456. ErrorF("Stdout and/or stderr is a pipe\n");
  1457. break;
  1458. case InternalError:
  1459. ErrorF("Internal Error\n");
  1460. break;
  1461. default:
  1462. ErrorF("Unknown error\n");
  1463. ErrorF(ARGMSG, BUGADDRESS);
  1464. ErrorF(ENVMSG, BUGADDRESS);
  1465. break;
  1466. }
  1467. FatalError("X server aborted because of unsafe environment\n");
  1468. }
  1469. /*
  1470. * CheckUserAuthorization: check if the user is allowed to start the
  1471. * X server. This usually means some sort of PAM checking, and it is
  1472. * usually only done for setuid servers (uid != euid).
  1473. */
  1474. void
  1475. CheckUserAuthorization(void)
  1476. {
  1477. }