2
0

dm.c 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875
  1. /*
  2. * CDE - Common Desktop Environment
  3. *
  4. * Copyright (c) 1993-2012, The Open Group. All rights reserved.
  5. *
  6. * These libraries and programs are free software; you can
  7. * redistribute them and/or modify them under the terms of the GNU
  8. * Lesser General Public License as published by the Free Software
  9. * Foundation; either version 2 of the License, or (at your option)
  10. * any later version.
  11. *
  12. * These libraries and programs are distributed in the hope that
  13. * they will be useful, but WITHOUT ANY WARRANTY; without even the
  14. * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  15. * PURPOSE. See the GNU Lesser General Public License for more
  16. * details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with these libraries and programs; if not, write
  20. * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
  21. * Floor, Boston, MA 02110-1301 USA
  22. */
  23. /* (c) Copyright 1997 The Open Group */
  24. /* *
  25. * (c) Copyright 1993, 1994 Hewlett-Packard Company *
  26. * (c) Copyright 1993, 1994 International Business Machines Corp. *
  27. * (c) Copyright 1993, 1994 Sun Microsystems, Inc. *
  28. * (c) Copyright 1993, 1994 Novell, Inc. *
  29. */
  30. /*
  31. * xdm - display manager daemon
  32. *
  33. * $TOG: dm.c /main/18 1999/01/19 17:44:08 mgreess $
  34. *
  35. * Copyright 1988 Massachusetts Institute of Technology
  36. *
  37. * Permission to use, copy, modify, and distribute this software and its
  38. * documentation for any purpose and without fee is hereby granted, provided
  39. * that the above copyright notice appear in all copies and that both that
  40. * copyright notice and this permission notice appear in supporting
  41. * documentation, and that the name of M.I.T. not be used in advertising or
  42. * publicity pertaining to distribution of the software without specific,
  43. * written prior permission. M.I.T. makes no representations about the
  44. * suitability of this software for any purpose. It is provided "as is"
  45. * without express or implied warranty.
  46. *
  47. * Author: Keith Packard, MIT X Consortium
  48. */
  49. /*
  50. * display manager
  51. */
  52. # include <sys/types.h>
  53. # include <sys/signal.h>
  54. # include <sys/stat.h>
  55. #if defined(__FreeBSD__) && OSMAJORVERSION > 8
  56. # include <utmpx.h>
  57. #else
  58. # include <utmp.h>
  59. #endif
  60. # include <time.h>
  61. # include <utime.h>
  62. # include <pwd.h>
  63. #if defined(__linux__) || defined(CSRG_BASED) || defined(sun)
  64. # include <stdarg.h>
  65. #else
  66. # include <varargs.h>
  67. #endif
  68. #if defined (SYSV) || defined (SVR4)
  69. #ifndef F_TLOCK
  70. # include <unistd.h>
  71. #endif
  72. #endif
  73. # include "dm.h"
  74. # include "vgmsg.h"
  75. #ifdef sun
  76. #include <sys/kbio.h>
  77. #include <sys/kbd.h>
  78. #endif
  79. #ifndef sigmask
  80. #define sigmask(m) (1 << (( m-1)))
  81. #endif
  82. /***************************************************************************
  83. *
  84. * Local procedure declarations
  85. *
  86. ***************************************************************************/
  87. static void CheckDisplayStatus( struct display *d) ;
  88. static void CheckRestartTime( void ) ;
  89. static void ChildNotify( int arg ) ;
  90. static void MarkDisplay( struct display *d) ;
  91. static void KillDisplay( struct display *d) ;
  92. static void MarkShutdownTime( void ) ;
  93. static void ProcessChildDeath( int pid, waitType status) ;
  94. static void RescanIfMod( void ) ;
  95. static void RescanNotify( int arg ) ;
  96. static void RescanServers( void ) ;
  97. static void RestartDisplay( struct display *d, int forceReserver) ;
  98. static int ScanServers( void ) ;
  99. static void SetAccessFileTime( void ) ;
  100. static void SetConfigFileTime( void ) ;
  101. static int StartGetty( struct display *d) ;
  102. static void StopAll( int arg ) ;
  103. static long StorePid( void ) ;
  104. static void TerminateProcess( int pid, int sig) ;
  105. static void UnlockPidFile( void ) ;
  106. static void dtMakeDefaultDir( void );
  107. static void dtmkdir(char *dir, mode_t dir_mode, int force);
  108. /***************************************************************************
  109. *
  110. * Global variables
  111. *
  112. ***************************************************************************/
  113. struct passwd puser; /* pseudo-user password entry */
  114. int Rescan;
  115. static long ServersModTime, ConfigModTime, AccessFileModTime;
  116. int wakeupTime = -1;
  117. char *progName;
  118. char DisplayName[32]="main";
  119. #ifdef OSFDEBUG
  120. int nofork_session = 0;
  121. #endif
  122. #ifndef NOXDMTITLE
  123. char *Title; /* Global argv[0] */
  124. int TitleLen;
  125. #endif
  126. static int parent_pid = -1; /* PID of parent dtlogin process */
  127. /***************************************************************************/
  128. int
  129. main( int argc, char **argv )
  130. {
  131. long oldpid;
  132. mode_t oldumask;
  133. struct passwd *p; /* pointer to passwd structure (pwd.h) */
  134. /*
  135. * make sure at least world write access is disabled...
  136. */
  137. if ( (oldumask = umask(022) & 002) == 002)
  138. (void) umask(oldumask);
  139. #ifndef NOXDMTITLE
  140. Title = argv[0];
  141. TitleLen = (argv[argc - 1] + strlen(argv[argc - 1])) - Title;
  142. #endif
  143. /*
  144. * save program name and path...
  145. */
  146. if ( (progName = malloc(strlen(argv[0]) + 1)) != NULL )
  147. strcpy(progName, argv[0]);
  148. /*
  149. * Step 1 - load configuration parameters
  150. */
  151. InitResources (argc, argv);
  152. SetConfigFileTime ();
  153. LoadDMResources ();
  154. /*
  155. * Only allow root to run xdm to avoid problems (HP 700/X version)
  156. */
  157. if (debugLevel == 0 && getuid() != 0)
  158. {
  159. fprintf(stderr,
  160. (char *)ReadCatalog(MC_ERROR_SET,MC_BAD_ROOT,MC_DEF_BAD_ROOT),
  161. argv[0]);
  162. exit (1);
  163. }
  164. dtMakeDefaultDir(); /** Create /var/dt if needed **/
  165. CheckErrorFile(); /** verify that we can open an error log **/
  166. #ifdef OSFDEBUG
  167. if (debugLevel >= 10)
  168. nofork_session = 1;
  169. #endif
  170. if (debugLevel == 0 && daemonMode)
  171. BecomeDaemon ();
  172. if ( (oldpid = StorePid ()) != 0 )
  173. {
  174. if (oldpid == (long) -1)
  175. LogError(
  176. ReadCatalog(MC_LOG_SET,MC_LOG_NO_CREATE,MC_DEF_LOG_NO_CREATE),
  177. pidFile);
  178. else
  179. LogError(ReadCatalog(MC_LOG_SET,MC_LOG_NO_LOCK,MC_DEF_LOG_NO_LOCK),
  180. pidFile, oldpid);
  181. exit (1);
  182. }
  183. /*
  184. * Check if we are restarting too fast...
  185. */
  186. CheckRestartTime();
  187. /*
  188. * Initialize error file, open XDMCP socket, and set up interrupt handlers.
  189. */
  190. InitErrorLog ();
  191. init_session_id ();
  192. CreateWellKnownSockets ();
  193. parent_pid = getpid(); /* PID of parent dtlogin process */
  194. (void) signal (SIGTERM, StopAll);
  195. (void) signal (SIGINT, StopAll);
  196. /*
  197. * Set pseudo-user to "nobody". Xserver will be run as that pseudo-user
  198. * rather than root (unless pseudo user is specifically set to another
  199. * user via the Xservers file).
  200. */
  201. if ( (p = getpwnam ("nobody")) != NULL) {
  202. puser = *p;
  203. } else {
  204. /*
  205. * This should not happen, the "nobody" user should always be present.
  206. * If it does, fall back to traditional values of the "root" user
  207. */
  208. puser.pw_uid = 0;
  209. puser.pw_gid = 1;
  210. }
  211. #ifdef __PASSWD_ETC
  212. /*
  213. * Ensure the interrupt handlers are set. The Passwd Etc. libraries
  214. * (getpwnam()) disable SIGTERM and SIGINT.
  215. */
  216. (void) signal (SIGTERM, StopAll);
  217. (void) signal (SIGINT, StopAll);
  218. #endif
  219. /*
  220. * Step 2 - Read /etc/Xservers and set up
  221. * the socket.
  222. *
  223. * Keep a sub-daemon running
  224. * for each entry
  225. */
  226. SetAccessFileTime ();
  227. ScanAccessDatabase ();
  228. #if !defined (ENABLE_DYNAMIC_LANGLIST)
  229. MakeLangList();
  230. #endif /* ENABLE_DYNAMIC_LANGLIST */
  231. ScanServers ();
  232. StartDisplays ();
  233. (void) signal (SIGHUP, RescanNotify);
  234. #if !defined(SYSV) || defined(hpux) || defined(_AIX) || defined(__linux__)
  235. (void) signal (SIGCHLD, ChildNotify);
  236. #endif
  237. while (AnyWellKnownSockets() || AnyDisplaysLeft ())
  238. {
  239. if (Rescan)
  240. {
  241. RescanServers ();
  242. Rescan = 0;
  243. }
  244. TrimErrorFile();
  245. #if defined(SYSV) && !defined(hpux) && !defined(_AIX) && !defined(__linux__)
  246. WaitForChild ();
  247. #else
  248. WaitForSomething ();
  249. #endif
  250. }
  251. UnlockPidFile();
  252. MarkShutdownTime();
  253. Debug ("Nothing left to do, exiting\n");
  254. }
  255. static SIGVAL
  256. RescanNotify( int arg )
  257. {
  258. Debug ("Caught SIGHUP\n");
  259. Rescan = 1;
  260. #if defined(SYSV) || defined(SVR4)
  261. signal (SIGHUP, RescanNotify);
  262. #endif
  263. }
  264. static int
  265. ScanServers( void )
  266. {
  267. char lineBuf[10240];
  268. int len;
  269. FILE *serversFile;
  270. struct stat statb;
  271. static DisplayType acceptableTypes[] =
  272. { { Local, Permanent, FromFile },
  273. { Foreign, Permanent, FromFile },
  274. };
  275. #define NumTypes (sizeof (acceptableTypes) / sizeof (acceptableTypes[0]))
  276. if (servers[0] == '/')
  277. {
  278. serversFile = fopen (servers, "r");
  279. if (serversFile == NULL)
  280. {
  281. LogError(
  282. ReadCatalog(MC_LOG_SET,MC_LOG_NO_SRVACC,MC_DEF_LOG_NO_SRVACC),
  283. servers);
  284. return 0;
  285. }
  286. if (ServersModTime == 0)
  287. {
  288. fstat (fileno (serversFile), &statb);
  289. ServersModTime = statb.st_mtime;
  290. }
  291. while (fgets (lineBuf, sizeof (lineBuf)-1, serversFile))
  292. {
  293. len = strlen (lineBuf);
  294. if (lineBuf[len-1] == '\n')
  295. lineBuf[len-1] = '\0';
  296. ParseDisplay (lineBuf, acceptableTypes, NumTypes, &puser);
  297. }
  298. fclose (serversFile);
  299. }
  300. else
  301. {
  302. ParseDisplay (servers, acceptableTypes, NumTypes, &puser);
  303. }
  304. return 1;
  305. }
  306. static void
  307. MarkDisplay( struct display *d )
  308. {
  309. d->state = MissingEntry;
  310. }
  311. static void
  312. KillDisplay( struct display *d )
  313. {
  314. if (d->name)
  315. Debug("Sending HUP to display %s\n", d->name);
  316. else
  317. Debug("Sending HUP to display ?\n");
  318. kill(d->pid, SIGHUP);
  319. }
  320. static void
  321. RescanServers( void )
  322. {
  323. Debug ("Rescanning servers\n");
  324. LogInfo (ReadCatalog(MC_ERROR_SET,MC_LOG_REBUILD,MC_DEF_LOG_REBUILD),
  325. DEF_NLS_DIR);
  326. #if !defined (ENABLE_DYNAMIC_LANGLIST)
  327. MakeLangList();
  328. #endif /* ENABLE_DYNAMIC_LANGLIST */
  329. LogInfo (ReadCatalog(MC_ERROR_SET,MC_LOG_RESCAN,MC_DEF_LOG_RESCAN));
  330. ForEachDisplay (MarkDisplay);
  331. ForEachDisplay (KillDisplay);
  332. ReinitResources ();
  333. LoadDMResources ();
  334. ScanServers ();
  335. SetAccessFileTime ();
  336. ScanAccessDatabase ();
  337. StartDisplays ();
  338. }
  339. static void
  340. SetConfigFileTime( void )
  341. {
  342. struct stat statb;
  343. if (stat (config, &statb) != -1)
  344. ConfigModTime = statb.st_mtime;
  345. }
  346. static void
  347. SetAccessFileTime( void )
  348. {
  349. struct stat statb;
  350. if (stat (accessFile, &statb) != -1)
  351. AccessFileModTime = statb.st_mtime;
  352. }
  353. static void
  354. RescanIfMod( void )
  355. {
  356. struct stat statb;
  357. if (stat (config, &statb) != -1)
  358. {
  359. if (statb.st_mtime != ConfigModTime)
  360. {
  361. Debug ("Config file %s has changed, rereading\n", config);
  362. LogInfo(
  363. ReadCatalog(MC_ERROR_SET,MC_LOG_REREADCFG,MC_DEF_LOG_REREADCFG),
  364. config);
  365. ConfigModTime = statb.st_mtime;
  366. ReinitResources ();
  367. LoadDMResources ();
  368. }
  369. }
  370. if (servers[0] == '/' && stat(servers, &statb) != -1)
  371. {
  372. if (statb.st_mtime != ServersModTime)
  373. {
  374. Debug ("Servers file %s has changed, rescanning\n", servers);
  375. LogInfo(
  376. ReadCatalog(MC_ERROR_SET,MC_LOG_REREADSRV,MC_DEF_LOG_REREADSRV),
  377. servers);
  378. ServersModTime = statb.st_mtime;
  379. ForEachDisplay (MarkDisplay);
  380. ScanServers ();
  381. }
  382. }
  383. if (accessFile && accessFile[0] && stat (accessFile, &statb) != -1)
  384. {
  385. if (statb.st_mtime != AccessFileModTime)
  386. {
  387. Debug ("Access file %s has changed, rereading\n", accessFile);
  388. LogInfo(
  389. ReadCatalog(MC_ERROR_SET,MC_LOG_REREADACC,MC_DEF_LOG_REREADACC),
  390. accessFile);
  391. AccessFileModTime = statb.st_mtime;
  392. ScanAccessDatabase ();
  393. }
  394. }
  395. }
  396. /*
  397. * catch a SIGTERM, kill all displays and exit
  398. */
  399. static int dt_shutdown = 0;
  400. static SIGVAL
  401. StopAll( int arg )
  402. {
  403. if (parent_pid != getpid())
  404. {
  405. /*
  406. * we got caught in a race condition - we are really a
  407. * child dtlogin process that has been killed by the parent
  408. * dtlogin process before we got a chance to return from
  409. * fork() and remove this signal handler
  410. */
  411. Debug ("Child dtlogin caught signal %d before it could become a real child\n", arg);
  412. (void) signal (arg, SIG_DFL); /* ensure no more handler */
  413. TerminateProcess (getpid(), arg); /* and send signal again */
  414. return;
  415. }
  416. Debug ("Shutting down entire manager\n");
  417. DestroyWellKnownSockets ();
  418. dt_shutdown = 1;
  419. MarkShutdownTime();
  420. ForEachDisplay (StopDisplay);
  421. #if defined(SYSV) || defined(SVR4)
  422. /* to avoid another one from killing us unceremoniously */
  423. (void) signal (SIGTERM, StopAll);
  424. (void) signal (SIGINT, StopAll);
  425. #endif
  426. }
  427. /*
  428. * notice that a child has died and may need another
  429. * sub-daemon started
  430. */
  431. int ChildReady = 0;
  432. #if !defined(SYSV) || defined(hpux) || defined(_AIX) || defined(__linux__) || defined(CSRG_BASED)
  433. static SIGVAL
  434. ChildNotify( int arg )
  435. {
  436. ChildReady = 1;
  437. }
  438. #endif
  439. /*
  440. In HP-UX, SIGCHLDs are queued rather than lost if we are in the middle
  441. of processing one (see SIGNAL(5), WARNINGS). The following code relies
  442. upon this.
  443. If we have a socket, then we are using "select" to block
  444. (WaitForSomething) rather than "wait". If a child dies, ChildReady is
  445. set and the select unblocks. We then loop, processing the child that
  446. died plus any that die while we are processing others. Finally we
  447. activate the signal handler again and go around one more time in case a
  448. child died right before activating the signal handler.
  449. */
  450. void
  451. WaitForChild( void )
  452. {
  453. int pid;
  454. waitType status;
  455. int mask;
  456. #if defined(SYSV) || defined(SVR4) || defined(hpux)
  457. if (AnyWellKnownSockets()) {
  458. while ( ChildReady ) {
  459. #ifdef SVR4
  460. while ((pid = waitpid((pid_t) -1, &status, WNOHANG)) > 0 )
  461. #else
  462. while ((pid = wait3 (&status, WNOHANG, NULL)) > 0 )
  463. #endif
  464. ProcessChildDeath(pid, status);
  465. ChildReady = 0;
  466. (void) signal (SIGCHLD, ChildNotify);
  467. sleep(1);
  468. }
  469. }
  470. else {
  471. /* XXX classic sysV signal race condition here with RescanNotify */
  472. if ((pid = wait (&status)) != -1)
  473. ProcessChildDeath(pid, status);
  474. }
  475. #else
  476. mask = sigblock (sigmask (SIGCHLD) | sigmask (SIGHUP));
  477. Debug ("Signals blocked, mask was 0x%x\n", mask);
  478. if (!ChildReady && !Rescan)
  479. sigpause (mask);
  480. ChildReady = 0;
  481. sigsetmask (mask);
  482. while ((pid = wait3 (&status, WNOHANG, (struct rusage *) 0)) > 0)
  483. ProcessChildDeath(pid, status);
  484. #endif
  485. StartDisplays ();
  486. }
  487. static void
  488. ProcessChildDeath( int pid, waitType status )
  489. {
  490. struct display *d;
  491. Debug ("Processing child death, pid = %d\n", pid);
  492. if (autoRescan)
  493. RescanIfMod ();
  494. if ( (d = FindDisplayByPid (pid)) != 0 ) {
  495. d->pid = -1;
  496. /*
  497. * do process accounting...
  498. */
  499. #if !defined(CSRG_BASED)
  500. Account(d, NULL, NULL, pid, DEAD_PROCESS, status);
  501. #endif
  502. /*
  503. * make sure authorization file is deleted...
  504. */
  505. /*
  506. if (d->authorization && d->authFile) {
  507. (void) unlink (d->authFile);
  508. }
  509. */
  510. /*
  511. * reset "startTries" ...
  512. *
  513. * Local displays: Only for clean exits of the server
  514. * Foreign displays: Always except for OPENFAILED_DISPLAY
  515. *
  516. * Note: if startTries expires and a "getty" is run on the local
  517. * display, startTries will be reset to zero before
  518. * attempting to restart the server.
  519. */
  520. switch (waitVal (status)) {
  521. case OBEYSESS_DISPLAY:
  522. case RESERVER_DISPLAY:
  523. d->startTries = 0;
  524. break;
  525. case OPENFAILED_DISPLAY:
  526. break;
  527. default:
  528. if (d->displayType.location != Local )
  529. d->startTries = 0;
  530. break;
  531. }
  532. /*
  533. * process exit status...
  534. */
  535. switch (waitVal (status)) {
  536. case UNMANAGE_DISPLAY:
  537. Debug ("Display exited with UNMANAGE_DISPLAY\n");
  538. StopDisplay (d);
  539. break;
  540. case OBEYSESS_DISPLAY:
  541. Debug ("Display exited with (check)OBEYSESS_DISPLAY\n");
  542. if (d->displayType.lifetime != Permanent || d->status == zombie)
  543. StopDisplay (d);
  544. else
  545. RestartDisplay (d, FALSE);
  546. break;
  547. default:
  548. Debug ("Display exited with unknown status %d\n", waitVal(status));
  549. LogError ((unsigned char *)"Unknown session exit code %d from process %d\n",
  550. waitVal (status), pid);
  551. StopDisplay (d);
  552. break;
  553. case OPENFAILED_DISPLAY:
  554. Debug ("Display exited with OPENFAILED_DISPLAY\n");
  555. if (d->displayType.origin == FromXDMCP)
  556. SendFailed (d, "Cannot open display");
  557. if (d->displayType.location != Local)
  558. d->startTries++;
  559. if (d->displayType.origin == FromXDMCP ||
  560. d->status == zombie ||
  561. d->startTries >= d->startAttempts)
  562. StopDisplay (d);
  563. else
  564. RestartDisplay (d, TRUE);
  565. break;
  566. case RESERVER_DISPLAY:
  567. Debug ("Display exited with RESERVER_DISPLAY\n");
  568. if (d->displayType.origin == FromXDMCP || d->status == zombie)
  569. StopDisplay(d);
  570. else
  571. RestartDisplay (d, TRUE);
  572. break;
  573. case waitCompose (SIGTERM,0,0):
  574. Debug ("Display exited on SIGTERM\n");
  575. if (d->displayType.origin == FromXDMCP || d->status == zombie)
  576. StopDisplay(d);
  577. else
  578. RestartDisplay (d, TRUE);
  579. break;
  580. case REMANAGE_DISPLAY:
  581. Debug ("Display exited with REMANAGE_DISPLAY\n");
  582. /*
  583. * XDMCP will restart the session if the display
  584. * requests it
  585. */
  586. if (d->displayType.origin == FromXDMCP || d->status == zombie)
  587. StopDisplay(d);
  588. else
  589. RestartDisplay (d, FALSE);
  590. break;
  591. case SUSPEND_DISPLAY:
  592. Debug ("Display exited with SUSPEND_DISPLAY\n");
  593. if (d->displayType.location == Local)
  594. StopDisplay(d);
  595. else
  596. RestartDisplay (d, FALSE);
  597. break;
  598. }
  599. }
  600. else if ( (d = FindDisplayByServerPid (pid)) != 0 )
  601. {
  602. d->serverPid = -1;
  603. /*
  604. * do process accounting...
  605. */
  606. #if !defined(CSRG_BASED)
  607. Account(d, NULL, NULL, pid, DEAD_PROCESS, status);
  608. #endif
  609. switch (d->status)
  610. {
  611. case zombie:
  612. Debug ("Zombie server reaped, removing display %s\n", d->name);
  613. RemoveDisplay (d);
  614. break;
  615. case phoenix:
  616. Debug ("Phoenix server arises, restarting display %s\n", d->name);
  617. d->status = notRunning;
  618. break;
  619. case running:
  620. Debug ("Server for display %s terminated unexpectedly, status %d\n", d->name, waitVal (status));
  621. LogError ((unsigned char *)"Server for display %s terminated unexpectedly %d\n",
  622. d->name, waitVal(status) );
  623. if (d->pid != -1)
  624. {
  625. Debug ("Terminating session pid %d\n", d->pid);
  626. TerminateProcess (d->pid, SIGTERM);
  627. }
  628. break;
  629. case notRunning:
  630. Debug ("Server exited for notRunning session on display %s\n", d->name);
  631. break;
  632. case suspended:
  633. Debug ("Server for display %s is suspended\n", d->name);
  634. if (!StartGetty(d))
  635. d->status = notRunning;
  636. break;
  637. }
  638. }
  639. else
  640. {
  641. Debug ("Unknown child termination, status %d\n", waitVal (status));
  642. }
  643. }
  644. static void
  645. CheckDisplayStatus( struct display *d )
  646. {
  647. if (d->displayType.origin == FromFile)
  648. {
  649. switch (d->state) {
  650. case MissingEntry:
  651. dt_shutdown = 1;
  652. StopDisplay (d);
  653. dt_shutdown = 0;
  654. break;
  655. case NewEntry:
  656. d->state = OldEntry;
  657. case OldEntry:
  658. Debug("Check %s: status=%d wakeupTime=%d\n", d->name,
  659. d->status, wakeupTime);
  660. if (d->status == suspended && wakeupTime >= 0)
  661. if ( GettyRunning(d) || (d->gettyLine && (strcmp(d->gettyLine,"??") == 0)) )
  662. if ( wakeupTime == 0 ) {
  663. Debug("Polling of suspended server %s started.\n",
  664. d->name);
  665. wakeupTime = (wakeupInterval < 10
  666. ? 3 * wakeupInterval
  667. : 2 * wakeupInterval );
  668. }
  669. else {
  670. Debug("Polling of suspended server %s stopped.\n",
  671. d->name);
  672. wakeupTime = -1; /* disable polling */
  673. d->status = notRunning; /* restart server */
  674. d->startTries = 0;
  675. if ( !dt_shutdown ) GettyMessage(d,2);
  676. }
  677. else {
  678. Debug("Polling of suspended server %s continued.\n",
  679. d->name);
  680. wakeupTime = wakeupInterval; /* continue polling*/
  681. }
  682. if (d->status == notRunning)
  683. StartDisplay (d);
  684. break;
  685. }
  686. }
  687. }
  688. void
  689. StartDisplays( void )
  690. {
  691. ForEachDisplay (CheckDisplayStatus);
  692. }
  693. int
  694. StartDisplay(
  695. struct display *d )
  696. {
  697. waitType status;
  698. int pid;
  699. char* authFile_str;
  700. char start_fbconsole[1024];
  701. char buff[128];
  702. Debug ("StartDisplay(): %s\n", d->name);
  703. bzero(&status, sizeof(waitType));
  704. if (d->authFile == NULL)
  705. authFile_str = "NULL";
  706. else
  707. authFile_str = d->authFile;
  708. Debug("(Old StartDisplay) d->authfile %s; authDir %s\n",
  709. authFile_str, authDir);
  710. /*
  711. * The following call to RemoveDisplay is to catch race conditions during
  712. * shutdown. There is no point in starting a display if Dtlogin is in the
  713. * process of shutting down...
  714. */
  715. if (d->displayType.origin == FromFile && dt_shutdown ) {
  716. RemoveDisplay(d);
  717. return 0;
  718. }
  719. {
  720. /* make a backup of the authFile before loading resources and */
  721. /* copy it back to authFile field od display structure for X server */
  722. /* to reread the host database list on reset */
  723. /* RK 11.22.93 */
  724. char bkup[50];
  725. bkup[0] = '\0';
  726. if (d->authFile)
  727. snprintf(bkup, sizeof(bkup), "%s", d->authFile);
  728. LoadDisplayResources (d);
  729. /* The Xserver may NOT have been killed, so reuse the authFile. */
  730. if (NULL == d->authFile &&
  731. 0 < strlen(bkup) &&
  732. 0 == strncmp(authDir, bkup, strlen(authDir)))
  733. d->authFile= (char *) strdup(bkup);
  734. if (d->authFile == NULL)
  735. authFile_str = "NULL";
  736. else
  737. authFile_str = d->authFile;
  738. Debug("(Mid StartDisplay) d->authfile %s; authDir %s; bkup %s\n",
  739. authFile_str, authDir, bkup);
  740. }
  741. if (d->displayType.location == Local)
  742. {
  743. /* don't bother pinging local displays; we'll
  744. * certainly notice when they exit
  745. */
  746. d->pingInterval = 0;
  747. if (d->authorize)
  748. {
  749. Debug ("SetLocalAuthorization %s, auth %s\n",
  750. d->name, d->authNames);
  751. SetLocalAuthorization (d);
  752. /*
  753. * reset the server after writing the authorization information
  754. * to make it read the file (for compatibility with old
  755. * servers which read auth file only on reset instead of
  756. * at first connection)
  757. */
  758. if (d->serverPid != -1 && d->resetForAuth && d->resetSignal)
  759. kill (d->serverPid, d->resetSignal);
  760. }
  761. /*
  762. * initialize d->utmpId. Check to see if anyone else is using
  763. * the requested ID. Always allow the first request for "dt" to
  764. * succeed as utmp may have become corrupted.
  765. */
  766. if (d->utmpId == NULL) {
  767. static int firsttime = 1;
  768. static char letters[] = "0123456789abcdefghijklmnopqrstuvwxyzz";
  769. char *t;
  770. d->utmpId = malloc(5);
  771. strcpy(d->utmpId, UTMPREC_PREFIX);
  772. d->utmpId[4] = '\0';
  773. t = letters;
  774. do {
  775. if ( firsttime || UtmpIdOpen(d->utmpId)) {
  776. firsttime = 0;
  777. break;
  778. }
  779. else {
  780. strncpy(&(d->utmpId[strlen(d->utmpId)]), t++, 1);
  781. }
  782. } while (*t != '\0');
  783. if (*t == '\0') {
  784. Debug ("All DT utmp IDs already in use. Removing display %s\n",
  785. d->name);
  786. LogError ((unsigned char *)"All DT utmp IDs already in use. Removing display %s\n",
  787. d->name);
  788. RemoveDisplay(d);
  789. return 0;
  790. }
  791. }
  792. /*
  793. * set d->gettyLine to "console" for display ":0" if it is not
  794. * already set...
  795. */
  796. if (! d->gettyLine || strlen(d->gettyLine) == 0 ) {
  797. char *p;
  798. if ( (p = index(d->name,':')) != NULL &&
  799. ( strncmp(++p,"0",1) == 0 )) {
  800. d->gettyLine = (char *) malloc(8);
  801. strcpy(d->gettyLine, "console");
  802. }
  803. else {
  804. d->gettyLine = (char *) malloc(3);
  805. strcpy(d->gettyLine, "??");
  806. }
  807. }
  808. /*
  809. * if gettyLine is set to "console", set gettySpeed to "console" also
  810. */
  811. if (d->gettyLine && (strcmp(d->gettyLine, "console") == 0 ) ) {
  812. if (d->gettySpeed)
  813. free((char *) d->gettySpeed);
  814. d->gettySpeed = (char *) malloc(8);
  815. if (d->gettySpeed)
  816. strcpy(d->gettySpeed, "console");
  817. }
  818. /*
  819. * start server. If it cannot be started and this is the console,
  820. * run a getty...
  821. */
  822. Debug("Attempting to start server for %s. startTries = %d\n",
  823. d->name, d->startTries);
  824. if (d->serverPid == -1) {
  825. static int bootup = 0;
  826. while (bootup++ < 5) {
  827. if (GettyRunning(d)) {
  828. GettyMessage(d,3);
  829. bootup = 5;
  830. break;
  831. }
  832. else {
  833. sleep(1);
  834. }
  835. }
  836. }
  837. if (d->serverPid == -1 &&
  838. (d->startTries++ >= d->startAttempts ||
  839. !StartServer (d)))
  840. {
  841. LogError ((unsigned char *)"Server for display %s can't be started.\n", d->name);
  842. d->serverPid = -1;
  843. GettyMessage(d,4);
  844. if (!StartGetty(d))
  845. RemoveDisplay (d);
  846. return 0;
  847. }
  848. }
  849. else
  850. {
  851. /* this will only happen when using XDMCP */
  852. if (d->authorizations)
  853. SaveServerAuthorizations (d, d->authorizations, d->authNum);
  854. /*
  855. * Generate a utmp ID address for a foreign display. Use the last
  856. * four characters of the DISPLAY name, shifting left if they
  857. * are already in use...
  858. */
  859. #if !defined(CSRG_BASED)
  860. if (d->utmpId == NULL) {
  861. int i;
  862. char *p, *q;
  863. struct utmp *u;
  864. d->utmpId = malloc(sizeof(u->ut_id) +1);
  865. i = strlen (d->name);
  866. if (i >= sizeof (u->ut_id))
  867. i -= sizeof (u->ut_id);
  868. else
  869. i = 0;
  870. for ( p = d->name, q = d->name + i; p <= q; q-- ) {
  871. (void) strncpy (d->utmpId, q, sizeof (u->ut_id));
  872. d->utmpId[sizeof(u->ut_id)] = '\0';
  873. if (UtmpIdOpen(d->utmpId))
  874. break;
  875. }
  876. #ifdef DEF_NETWORK_DEV
  877. /*
  878. * If "networkDev" does not start with "/dev/" then foreign
  879. * accounting is turned off. Return utmpId to NULL.
  880. */
  881. if (networkDev && strncmp(networkDev,"/dev/",5) !=0 ) {
  882. free(d->utmpId);
  883. d->utmpId = NULL;
  884. }
  885. #endif
  886. }
  887. #endif
  888. }
  889. if (NULL == d->authFile)
  890. authFile_str = "NULL";
  891. else
  892. authFile_str = d->authFile;
  893. Debug("(New StartDisplay) d->authfile %s; authDir %s\n",
  894. authFile_str, authDir);
  895. /*
  896. * make sure stderr is pointing to the current error log file...
  897. */
  898. SyncErrorFile(0);
  899. #ifdef OSFDEBUG
  900. if (!nofork_session)
  901. pid = fork ();
  902. else
  903. pid = 0;
  904. switch (pid)
  905. #else
  906. switch (pid = fork ())
  907. #endif
  908. {
  909. case 0:
  910. #ifdef OSFDEBUG
  911. if (!nofork_session) {
  912. CleanUpChild ();
  913. signal (SIGPIPE, SIG_IGN);
  914. }
  915. #else
  916. CleanUpChild ();
  917. signal (SIGPIPE, SIG_IGN);
  918. #endif
  919. /*
  920. * set global display name for Debug()
  921. */
  922. {
  923. char *p, *s, *t;
  924. p = DisplayName;
  925. strncpy(p, d->name, sizeof(DisplayName) - 1);
  926. DisplayName[sizeof(DisplayName)-1] = '\0';
  927. if ( (s = strchr(p,':')) != NULL )
  928. if ( (t = strchr(p,'.')) != NULL )
  929. strcpy(t,s);
  930. }
  931. SetAuthorization (d);
  932. /*
  933. * do process accounting...
  934. */
  935. {
  936. char *line = (d->displayType.location==Local)
  937. ? d->gettyLine : d->name;
  938. #ifdef DEF_NETWORK_DEV
  939. if (d->displayType.location != Local &&
  940. networkDev && !strncmp(networkDev,"/dev/",5))
  941. {
  942. char *devname;
  943. int devexists;
  944. struct stat devinfo;
  945. devname = networkDev; /* networkDev resource */
  946. devexists = (lstat(devname,&devinfo)==0);
  947. if (!devexists && (MK_NETWORK_DEV(devname) < 0)) {
  948. Debug("Creation of file '%s' failed:\n %s (%d)\n",
  949. devname,strerror(errno),errno);
  950. } else {
  951. for (line=devname; *line; line++);
  952. while (line>devname && *line!='/') line--;
  953. if (*line=='/') line++;
  954. Debug("Using pseudo-tty %s; line=%s\n",
  955. devname,line);
  956. }
  957. }
  958. #endif
  959. #if !defined(CSRG_BASED)
  960. Account(d, "LOGIN", line, getpid(), LOGIN_PROCESS, status);
  961. #endif
  962. }
  963. if (!WaitForServer (d))
  964. exit (OPENFAILED_DISPLAY);
  965. /*
  966. * start the fallback console, if the display is local..
  967. *
  968. * if the display is remote, fbconsole should be started on
  969. * remote host.
  970. */
  971. #ifdef sun
  972. if (d->displayType.location==Local) {
  973. if (d->authFile && strlen(d->authFile) > 0 ) {
  974. strcpy(buff, "XAUTHORITY=");
  975. strcat(buff, d->authFile);
  976. putenv(buff);
  977. }
  978. sprintf(start_fbconsole,"%s -d %s &",FBCONSOLE, d->name);
  979. if(system(start_fbconsole) == -1)
  980. Debug("Failed to start the fallback console - %s\n",FBCONSOLE);
  981. }
  982. #endif
  983. if (d->useChooser)
  984. RunChooser (d);
  985. else
  986. ManageSession (d);
  987. exit (REMANAGE_DISPLAY);
  988. case -1:
  989. break;
  990. default:
  991. Debug ("Child manager process started for %s. pid = %d\n",
  992. d->name, pid);
  993. d->pid = pid;
  994. d->status = running;
  995. break;
  996. }
  997. return 1;
  998. }
  999. static void
  1000. TerminateProcess(int pid, int sig )
  1001. {
  1002. kill (pid, sig);
  1003. #ifdef SIGCONT
  1004. kill (pid, SIGCONT);
  1005. #endif
  1006. }
  1007. /*
  1008. * transition from running to zombie, suspended, or deleted
  1009. */
  1010. void
  1011. StopDisplay( struct display *d )
  1012. {
  1013. waitType status;
  1014. bzero(&status, sizeof(waitType));
  1015. Debug("StopDisplay(): %s, server pid = %d, manager pid = %d, dt_shutdown = %d\n",
  1016. d->name, d->serverPid, d->pid, dt_shutdown);
  1017. if (d->serverPid != -1)
  1018. /* don't remove the console */
  1019. if ((d->displayType.location == Local) && !dt_shutdown )
  1020. d->status = suspended;
  1021. else
  1022. d->status = zombie; /* be careful about race conditions */
  1023. if (d->pid != -1)
  1024. TerminateProcess (d->pid, SIGTERM);
  1025. if (d->serverPid != -1) {
  1026. TerminateProcess (d->serverPid, d->termSignal);
  1027. #ifdef sun
  1028. {
  1029. int kbd_fd;
  1030. int translate=TR_ASCII;
  1031. Debug ("Resetting keyboard\n");
  1032. if ((kbd_fd = open("/dev/kbd", O_RDONLY, 0)) < 0) {
  1033. Debug("/dev/kbd open failed\n");
  1034. } else if (ioctl(kbd_fd, KIOCTRANS, (caddr_t) &translate)) {
  1035. Debug("Could not set /dev/kbd back to ASCII mode\n");
  1036. }
  1037. }
  1038. #endif
  1039. }
  1040. else
  1041. if ((d->displayType.location == Local) || !dt_shutdown ) {
  1042. /* don't remove the console */
  1043. #if !defined(CSRG_BASED)
  1044. Account(d, NULL, NULL, 0, DEAD_PROCESS, status);
  1045. #endif
  1046. RemoveDisplay (d);
  1047. }
  1048. }
  1049. /*
  1050. * transition from running to phoenix or notRunning
  1051. */
  1052. static void
  1053. RestartDisplay( struct display *d, int forceReserver )
  1054. {
  1055. if (d->serverPid != -1 && (forceReserver || d->terminateServer))
  1056. {
  1057. TerminateProcess (d->serverPid, d->termSignal);
  1058. d->status = phoenix;
  1059. }
  1060. else
  1061. {
  1062. d->status = notRunning;
  1063. }
  1064. }
  1065. static FD_TYPE CloseMask;
  1066. static int max;
  1067. void
  1068. RegisterCloseOnFork( int fd )
  1069. {
  1070. FD_SET (fd, &CloseMask);
  1071. if (fd > max)
  1072. max = fd;
  1073. }
  1074. #if 0 /* utility routine: activate if needed... */
  1075. int
  1076. CloseOnFork( void )
  1077. {
  1078. FD_CLR (fd, &CloseMask);
  1079. if (fd == max) {
  1080. while (--fd >= 0)
  1081. if (FD_ISSET (fd, &CloseMask))
  1082. break;
  1083. max = fd;
  1084. }
  1085. }
  1086. #endif
  1087. int
  1088. CloseOnFork (void)
  1089. {
  1090. int fd;
  1091. for (fd = 0; fd <= max; fd++)
  1092. if (FD_ISSET (fd, &CloseMask))
  1093. close (fd);
  1094. FD_ZERO (&CloseMask);
  1095. max = 0;
  1096. return 0;
  1097. }
  1098. static int pidFd;
  1099. static FILE *pidFilePtr;
  1100. static long
  1101. StorePid( void )
  1102. {
  1103. long oldpid;
  1104. if (pidFile && pidFile[0] != '\0') {
  1105. pidFd = open (pidFile, 2);
  1106. if (pidFd == -1 && errno == ENOENT)
  1107. {
  1108. /*
  1109. * A Legacy OS wouldn't allow an fdopen
  1110. * of a file descriptor handed back by creat(2).
  1111. * The workaround is to close the created file, and
  1112. * open it Read/Write. This will be transparent to HP-UX.
  1113. * This code needs to be cleaned up - 05/22/18 - C
  1114. */
  1115. pidFd = creat (pidFile, 0644);
  1116. if(pidFd != -1) {
  1117. close( pidFd );
  1118. }
  1119. pidFd = open (pidFile, 2);
  1120. }
  1121. if (pidFd == -1 || !(pidFilePtr = fdopen (pidFd, "r+")))
  1122. {
  1123. LogError ((unsigned char *)"Process ID file %s cannot be opened\n",
  1124. pidFile);
  1125. return -1;
  1126. }
  1127. if (fscanf (pidFilePtr, "%ld", &oldpid) != 1)
  1128. oldpid = -1;
  1129. fseek (pidFilePtr, 0l, 0);
  1130. if (lockPidFile)
  1131. {
  1132. #if defined (SYSV) || defined (SVR4)
  1133. if (lockf (pidFd, F_TLOCK, 0) == -1)
  1134. {
  1135. if ((errno == EAGAIN) || (errno == EACCES))
  1136. return oldpid;
  1137. else
  1138. return -1;
  1139. }
  1140. #else
  1141. if (flock (pidFd, LOCK_EX|LOCK_NB) == -1)
  1142. {
  1143. if (errno == EWOULDBLOCK)
  1144. return oldpid;
  1145. else
  1146. return -1;
  1147. }
  1148. #endif
  1149. }
  1150. /*
  1151. * HPUX releases the lock on ANY close of the file, not just the
  1152. * one that established the lock. -prr
  1153. */
  1154. /* close(creat(pidFile, 0644)); */
  1155. (void) creat(pidFile, 0644);
  1156. fprintf (pidFilePtr, "%ld\n", (long)getpid ());
  1157. (void) fflush(pidFilePtr);
  1158. RegisterCloseOnFork(pidFd);
  1159. }
  1160. return 0;
  1161. }
  1162. static void
  1163. UnlockPidFile( void )
  1164. {
  1165. if (lockPidFile)
  1166. #if defined (SYSV) || defined (SVR4)
  1167. lockf (pidFd, F_ULOCK, 0);
  1168. #else
  1169. flock (pidFd, LOCK_UN);
  1170. #endif
  1171. close (pidFd);
  1172. fclose (pidFilePtr);
  1173. }
  1174. int
  1175. SetTitle( char *name, char *ptr )
  1176. {
  1177. #ifndef NOXDMTITLE
  1178. char *p, *s, *t;
  1179. int length;
  1180. /*
  1181. * remove domain qualifiers and screens from name...
  1182. */
  1183. if ( (p = malloc(strlen(name) + 1)) == NULL) return 0;
  1184. strcpy(p, name);
  1185. if ( (s = strchr(p,':')) == NULL ) {
  1186. free(p);
  1187. return 0;
  1188. }
  1189. if ( (t = strchr(s,'.')) != NULL )
  1190. *t = '\0';
  1191. if ( (t = strchr(p,'.')) != NULL )
  1192. strcpy(t,s);
  1193. /*
  1194. * if there is enough room shift program name to left,
  1195. * then append display name in remaining space.
  1196. */
  1197. s = Title;
  1198. length = strlen(s);
  1199. t = strrchr(s, '/');
  1200. if ( (t != NULL) && ((t-s+1) >= (strlen(p) + 3)) ) {
  1201. t++;
  1202. strcpy(s,t); /* "program" */
  1203. strcat(s," <"); /* "program <" */
  1204. strcat(s,p); /* "program <displayName" */
  1205. strcat(s,">"); /* "program <displayName>" */
  1206. t = s + strlen(s);
  1207. length = length - strlen(s);
  1208. while (length > 0){
  1209. *t++ = ' ';
  1210. length--;
  1211. }
  1212. }
  1213. free(p);
  1214. #endif
  1215. return 1;
  1216. }
  1217. /*****************************************************************************
  1218. * StartGetty
  1219. *
  1220. * Start a "getty" running on the console...
  1221. *
  1222. *****************************************************************************/
  1223. #if defined (_AIX) && defined (_POWER)
  1224. #define GETTYPATH "/usr/sbin/getty"
  1225. #elif defined(__OpenBSD__)
  1226. #define GETTYPATH "/usr/libexec/getty"
  1227. #elif defined(__linux__)
  1228. #define GETTYPATH "/sbin/getty"
  1229. #else
  1230. #define GETTYPATH "/etc/getty"
  1231. #endif
  1232. static int
  1233. StartGetty( struct display *d )
  1234. {
  1235. int pid;
  1236. char tynm[20];
  1237. waitType status;
  1238. Debug ("StartGetty(): %s\n", d->name);
  1239. bzero(&status, sizeof(waitType));
  1240. /*
  1241. * ensure that server is known dead...
  1242. */
  1243. d->serverPid = -1;
  1244. #if !defined(GETTYPATH)
  1245. return FALSE;
  1246. #else
  1247. /*
  1248. * check to see if we have a valid device (at least a non-null name)...
  1249. */
  1250. if ( d->gettyLine &&
  1251. (strlen(d->gettyLine) > 0) &&
  1252. (strcmp(d->gettyLine,"??") != 0) )
  1253. ;
  1254. else
  1255. return FALSE;
  1256. /*
  1257. * if there is already a getty running on the device, set up
  1258. * to start watching it. When it exits, restart the server...
  1259. */
  1260. if ( GettyRunning(d) ) {
  1261. d->status = suspended; /* set up to restart server */
  1262. wakeupTime = 0; /* enable polling */
  1263. sleep(1); /* wait for fbconsole to go away */
  1264. GettyMessage(d,1); /* print a help message */
  1265. return TRUE;
  1266. }
  1267. /*
  1268. * there is no getty running on the device, try to start one...
  1269. */
  1270. d->status = phoenix; /* set up to restart server */
  1271. d->startTries = 0;
  1272. switch (pid = fork ()) {
  1273. case 0:
  1274. CleanUpChild ();
  1275. /*
  1276. * do process accounting...
  1277. */
  1278. #if !defined(CSRG_BASED)
  1279. Account(d, "LOGIN", NULL, getpid(), LOGIN_PROCESS, status);
  1280. #endif
  1281. #ifdef _AIX
  1282. /* The tty argument for getty on AIX must be of the form "/dev/any tty"
  1283. and so the following logic
  1284. Raghu krovvidi 07.07.93
  1285. */
  1286. strcpy(tynm,"/dev/");
  1287. strcat(tynm,d->gettyLine);
  1288. #else
  1289. strcpy(tynm, d->gettyLine);
  1290. #endif
  1291. Debug(" execing getty on %s\n",tynm);
  1292. execl(GETTYPATH, "getty", tynm, d->gettySpeed, (char *)0);
  1293. LogError ((unsigned char *)"Can not execute %s for %s: errno = %d\n",
  1294. GETTYPATH, d->name, errno);
  1295. exit (UNMANAGE_DISPLAY);
  1296. case -1:
  1297. Debug ("Fork of /etc/getty failed %s\n", d->name);
  1298. LogError ((unsigned char *)"Can not fork to execute /etc/getty %s\n", d->name);
  1299. return FALSE;
  1300. default:
  1301. break;
  1302. }
  1303. Debug ("/etc/getty started on %s\n", d->name);
  1304. d->serverPid = pid;
  1305. return TRUE;
  1306. #endif /* GETTYPATH not defined */
  1307. }
  1308. /***************************************************************************
  1309. *
  1310. * GettyMessage
  1311. *
  1312. * Print a message on the display device when going into No Windows mode.
  1313. *
  1314. ***************************************************************************/
  1315. void
  1316. GettyMessage( struct display *d, int msgnum )
  1317. {
  1318. FILE *tf;
  1319. char buf[128];
  1320. if (quiet) return;
  1321. snprintf(buf, sizeof(buf), "/dev/%s", d->gettyLine);
  1322. if ( (tf = fopen (buf, "a")) != NULL) {
  1323. fprintf (tf,
  1324. "\r\n\r\n*****************************************************************************\r\n*\r\n");
  1325. switch (msgnum) {
  1326. case 1:
  1327. fprintf(tf, "%s", (char *)ReadCatalog(MC_LABEL_SET,MC_SUS1_LABEL,MC_DEF_SUS1_LABEL));
  1328. fprintf(tf, "%s", (char *)ReadCatalog(MC_LABEL_SET,MC_SUS2_LABEL,MC_DEF_SUS2_LABEL));
  1329. fprintf(tf, "%s", (char *)ReadCatalog(MC_LABEL_SET,MC_SUS3_LABEL,MC_DEF_SUS3_LABEL));
  1330. break;
  1331. case 2:
  1332. fprintf(tf, "%s", (char *)ReadCatalog(MC_LABEL_SET,MC_RES_LABEL,MC_DEF_RES_LABEL));
  1333. break;
  1334. case 3:
  1335. fprintf(tf,
  1336. (char *)ReadCatalog(MC_LABEL_SET,MC_START_LBLDPY,MC_DEF_START_LBLDPY),
  1337. d->name);
  1338. fprintf(tf, "%s", (char *)ReadCatalog(MC_LABEL_SET,MC_WAIT_LABEL,MC_DEF_WAIT_LABEL));
  1339. break;
  1340. case 4:
  1341. fprintf(tf,(char *)ReadCatalog(MC_LABEL_SET,MC_X_LABEL,MC_DEF_X_LABEL),
  1342. d->name);
  1343. break;
  1344. }
  1345. fprintf (tf,
  1346. "*****************************************************************************\r\n");
  1347. fclose (tf);
  1348. }
  1349. }
  1350. /***************************************************************************
  1351. *
  1352. * GettyRunning
  1353. *
  1354. * See if a getty process is running against the display device. This
  1355. * routine may need to be rewritten on other platforms if a different
  1356. * mechanism is needed to make the determination.
  1357. *
  1358. * Output: TRUE == a login process is active on the requested device
  1359. * FALSE == a login process is not active on the device.
  1360. *
  1361. * Sets d->gettyState:
  1362. * NONE - no getty running or don't care
  1363. * LOGIN - getty running
  1364. * USER - user logged in on getty
  1365. *
  1366. * Note: The check for a getty process running is made by scanning
  1367. * /etc/utmp, looking for a login process on the respective device.
  1368. * However, the child Dtlogin spawned by the master Dtlogin to
  1369. * handle this display also is a "login process" according to
  1370. * /etc/utmp. It provides a login path and therefore must register
  1371. * itself as so. If a getty is also running, there are actually two
  1372. * login processes running against the same device at the same time.
  1373. *
  1374. * The child Dtlogin dies before the scan of /etc/utmp is made.
  1375. * Provided /etc/utmp is updated correctly, the Dtlogin entry will
  1376. * be marked as dead and will not show up in the scan of /etc/utmp.
  1377. ***************************************************************************/
  1378. int
  1379. GettyRunning( struct display *d )
  1380. {
  1381. #if defined(__FreeBSD__) && OSMAJORVERSION > 8
  1382. struct utmpx utmp; /* local struct for new entry */
  1383. struct utmpx *u; /* pointer to entry in utmp file */
  1384. #else
  1385. struct utmp utmp; /* local struct for new entry */
  1386. struct utmp *u; /* pointer to entry in utmp file */
  1387. #endif
  1388. int rvalue; /* return value (TRUE or FALSE) */
  1389. char buf[32];
  1390. d->gettyState = DM_GETTY_NONE;
  1391. /*
  1392. * check to see if we have a valid device (at least a non-null name)...
  1393. */
  1394. if ( d->gettyLine &&
  1395. (strlen(d->gettyLine) > 0) &&
  1396. (strcmp(d->gettyLine,"??") != 0) )
  1397. ;
  1398. else
  1399. return FALSE;
  1400. #if defined(__FreeBSD__) && OSMAJORVERSION > 8
  1401. bzero(&utmp, sizeof(struct utmpx));
  1402. #else
  1403. bzero(&utmp, sizeof(struct utmp));
  1404. #endif
  1405. #ifdef _AIX
  1406. if (!strcmp(d->gettyLine,"console")) {
  1407. char *ttynm;
  1408. int fd=0;
  1409. fd = open("/dev/console",O_RDONLY);
  1410. ttynm = ttyname(fd);
  1411. ttynm += 5;
  1412. strcpy(utmp.ut_line,ttynm);
  1413. close(fd);
  1414. }
  1415. else
  1416. {
  1417. strncpy(utmp.ut_line, d->gettyLine, sizeof(utmp.ut_line) - 1);
  1418. utmp.ut_line[sizeof(utmp.ut_line) - 1] = 0;
  1419. }
  1420. #else
  1421. strncpy(utmp.ut_line, d->gettyLine, sizeof(utmp.ut_line) - 1);
  1422. utmp.ut_line[sizeof(utmp.ut_line) - 1] = 0;
  1423. #endif
  1424. Debug("Checking for a getty on line %s.\n", utmp.ut_line);
  1425. #if !defined(CSRG_BASED)
  1426. setutent();
  1427. rvalue = FALSE;
  1428. while ( (u = getutent()) != NULL ) {
  1429. if ((strncmp(u->ut_line, utmp.ut_line, sizeof(u->ut_line)) != 0) ||
  1430. (strncmp(u->ut_id, d->utmpId, sizeof(u->ut_id)) == 0) )
  1431. continue;
  1432. switch (u->ut_type) {
  1433. case INIT_PROCESS: strcpy(buf, "INIT_PROCESS"); break;
  1434. case LOGIN_PROCESS: strcpy(buf, "LOGIN_PROCESS"); break;
  1435. case USER_PROCESS: strcpy(buf, "USER_PROCESS"); break;
  1436. case DEAD_PROCESS: strcpy(buf, "DEAD_PROCESS"); break;
  1437. default: strcpy(buf, "UNKNOWN"); break;
  1438. }
  1439. Debug("Utmp info: id=%.4s, user=%s, line=%s, pid=%d, type=%s\n",
  1440. u->ut_id, u->ut_user, u->ut_line, u->ut_pid, buf);
  1441. if ( u->ut_type == INIT_PROCESS || u->ut_type == LOGIN_PROCESS) {
  1442. d->gettyState = DM_GETTY_LOGIN;
  1443. }
  1444. else if (wakeupTime <= 0 && u->ut_type == USER_PROCESS) {
  1445. d->gettyState = DM_GETTY_USER;
  1446. }
  1447. if (d->gettyState != DM_GETTY_NONE)
  1448. {
  1449. rvalue = TRUE;
  1450. break;
  1451. }
  1452. }
  1453. endutent();
  1454. #endif /* !CSRG_BASED */
  1455. return rvalue;
  1456. }
  1457. /***************************************************************************
  1458. *
  1459. * CheckRestartTime
  1460. *
  1461. * Check if enough time has elapsed since shutdown.
  1462. *
  1463. * This is primarily to work with /etc/shutdown. When shutdown kills
  1464. * dtlogin (/etc/killall), init immediately restarts it. Shutdown kills
  1465. * it again and init restarts it. At each restart, the X-server may start
  1466. * on the local display and then subsequently be killed. The user sees a
  1467. * flashing screen and sometimes the console is left in an unreset state.
  1468. *
  1469. * When Dtlogin shuts down, it touches the access time on the Xservers
  1470. * file. (MarkShutdownTime()). This time is then used to determine if
  1471. * sufficient time has elapsed before restarting.
  1472. *
  1473. ***************************************************************************/
  1474. static void
  1475. CheckRestartTime( void )
  1476. {
  1477. struct stat statb;
  1478. int sleeptime;
  1479. if (servers[0] == '/' && stat(servers, &statb) != -1) {
  1480. Debug("Checking restart time.\n");
  1481. #ifdef OSFDEBUG
  1482. /* only those other systems are this slow :-) */
  1483. sleeptime = 6 - (int) (time((time_t *) 0) - statb.st_atime);
  1484. #else
  1485. sleeptime = 30 - (int) (time((time_t *) 0) - statb.st_atime);
  1486. #endif
  1487. if ( sleeptime > 30 ) sleeptime = 30;
  1488. if ( sleeptime > 0 ) {
  1489. Debug("Restarting too soon after shutdown. Sleeping %d seconds.\n",
  1490. sleeptime);
  1491. sleep (sleeptime);
  1492. }
  1493. }
  1494. }
  1495. /***************************************************************************
  1496. *
  1497. * MarkShutdownTime
  1498. *
  1499. * Save the time when we shut down to check later for too fast of a restart.
  1500. *
  1501. ***************************************************************************/
  1502. static void
  1503. MarkShutdownTime( void )
  1504. {
  1505. struct stat statb;
  1506. struct utimbuf timebuf;
  1507. if (servers[0] == '/' && stat(servers, &statb) != -1) {
  1508. Debug("Marking shutdown time.\n");
  1509. timebuf.actime = time((time_t *) 0 );
  1510. timebuf.modtime = statb.st_mtime;
  1511. if ( (utime(servers, &timebuf)) != 0 ) {
  1512. Debug("MarkShutdownTime(): utime() error = %d\n", errno);
  1513. }
  1514. }
  1515. }
  1516. /***************************************************************************
  1517. *
  1518. * dtMakeDefaultDir
  1519. *
  1520. * Make the default dt directory "/var/dt" if needed.
  1521. *
  1522. ***************************************************************************/
  1523. static void
  1524. dtMakeDefaultDir( void )
  1525. {
  1526. dtmkdir("/var", 0755, 0);
  1527. dtmkdir("/var/dt", 0755, 1);
  1528. dtmkdir("/var/dt/tmp", 0755, 1);
  1529. dtmkdir("/var/dt/appconfig", 0755, 1);
  1530. dtmkdir("/var/dt/appconfig/appmanager", 0755, 1);
  1531. }
  1532. static void
  1533. dtmkdir(char *dir, mode_t dir_mode, int force)
  1534. {
  1535. struct stat file_status;
  1536. if ( stat(dir, &file_status) != 0) {
  1537. /** try to create it **/
  1538. if ( mkdir(dir, dir_mode) == 0) {
  1539. chmod(dir, dir_mode); /** since umask is non-zero **/
  1540. Debug("Created dir %s\n", dir);
  1541. } else {
  1542. LogError((unsigned char *)"Unable to create dir %s\n", dir);
  1543. }
  1544. } else {
  1545. if ( force && (file_status.st_mode & dir_mode) != dir_mode) {
  1546. /** try to set correct permissions **/
  1547. if ( chmod(dir, file_status.st_mode | dir_mode) == 0) {
  1548. Debug("Set permissions on %s\n", dir);
  1549. } else {
  1550. LogError((unsigned char *)
  1551. "Unable to set permissions on %s\n", dir);
  1552. }
  1553. }
  1554. }
  1555. }