home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume27 / screen-3.5.1 / part03 / attacher.c next >
C/C++ Source or Header  |  1993-08-08  |  19KB  |  846 lines

  1. /* Copyright (c) 1993
  2.  *      Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
  3.  *      Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
  4.  * Copyright (c) 1987 Oliver Laumann
  5.  *
  6.  * This program is free software; you can redistribute it and/or modify
  7.  * it under the terms of the GNU General Public License as published by
  8.  * the Free Software Foundation; either version 2, or (at your option)
  9.  * any later version.
  10.  *
  11.  * This program is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  * GNU General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU General Public License
  17.  * along with this program (see the file COPYING); if not, write to the
  18.  * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  *
  20.  ****************************************************************
  21.  */
  22.  
  23. #include "rcs.h"
  24. RCS_ID("$Id: attacher.c,v 1.5 1993/08/03 22:22:37 jnweiger Exp $ FAU")
  25.  
  26. #include <sys/types.h>
  27. #include <sys/stat.h>
  28. #include <fcntl.h>
  29. #include <signal.h>
  30. #include <pwd.h>
  31. #include "config.h"
  32. #include "screen.h"
  33. #include "extern.h"
  34.  
  35. #ifdef SHADOWPW
  36. # include <shadow.h>
  37. #endif /* SHADOWPW */
  38.  
  39. static sig_t AttacherSigInt __P(SIGPROTOARG);
  40. #ifdef PASSWORD
  41. static void  trysend __P((int, struct msg *, char *));
  42. #endif
  43. #if defined(SIGWINCH) && defined(TIOCGWINSZ)
  44. static sig_t AttacherWinch __P(SIGPROTOARG);
  45. #endif
  46. #ifdef LOCK
  47. static sig_t DoLock __P(SIGPROTOARG);
  48. static void  LockTerminal __P((void));
  49. static sig_t LockHup __P(SIGPROTOARG);
  50. static void  screen_builtin_lck __P((void));
  51. #endif
  52. #ifdef DEBUG
  53. static sig_t AttacherChld __P(SIGPROTOARG);
  54. #endif
  55.  
  56. extern int real_uid, real_gid, eff_uid, eff_gid;
  57. extern char *SockName, *SockNamePtr, SockPath[];
  58. extern struct passwd *ppp;
  59. extern char *attach_tty, *attach_term, *LoginName;
  60. extern int xflag, dflag, rflag, quietflag, adaptflag;
  61. extern struct mode attach_Mode;
  62. extern int MasterPid;
  63. extern int nethackflag;
  64.  
  65. #ifdef MULTIUSER
  66. extern char *multi;
  67. extern int multiattach, multi_uid, own_uid;
  68. extern int tty_mode, tty_oldmode;
  69. # ifdef NOREUID
  70. static int multipipe[2];
  71. # endif
  72. #endif
  73.  
  74.  
  75.  
  76. /*
  77.  *  Send message to a screen backend.
  78.  *  returns 1 if we could attach one, or 0 if none.
  79.  */
  80.  
  81. int
  82. Attach(how)
  83. int how;
  84. {
  85.   int lasts;
  86.   struct msg m;
  87.   struct stat st;
  88.   char *s;
  89.  
  90.   debug2("Attach: how=%d, tty=%s\n", how, attach_tty);
  91. #ifdef MULTIUSER
  92. # ifdef NOREUID
  93.   while ((how == MSG_ATTACH || how == MSG_CONT) && multiattach)
  94.     {
  95.       int ret;
  96.  
  97.       if (pipe(multipipe))
  98.     Panic(errno, "pipe");
  99.       eff_uid = -1;    /* make UserContext fork */
  100.       real_uid = multi_uid;
  101.       if ((ret = UserContext()) <= 0)
  102.     {
  103.       char dummy;
  104.           eff_uid = 0;
  105.       real_uid = own_uid;
  106.       if (ret < 0)
  107.         Panic(errno, "UserContext");
  108.       close(multipipe[1]);
  109.       read(multipipe[0], &dummy, 1);
  110.       if (tty_oldmode >= 0)
  111.         {
  112.           chmod(attach_tty, tty_oldmode);
  113.           tty_oldmode = -1;
  114.         }
  115.       ret = UserStatus();
  116. #ifdef LOCK
  117.       if (ret == SIG_LOCK)
  118.         LockTerminal();
  119.       else
  120. #endif
  121. #ifdef SIGTSTP
  122.       if (ret == SIG_STOP)
  123.         kill(getpid(), SIGTSTP);
  124.       else
  125. #endif
  126.       if (ret == SIG_POWER_BYE)
  127.         {
  128.           int ppid;
  129.           setuid(real_uid);
  130.           setgid(real_gid);
  131.           if ((ppid = getppid()) > 1)
  132.         Kill(ppid, SIGHUP);
  133.           exit(0);
  134.         }
  135.       else
  136.             exit(ret);
  137.       dflag = 0;
  138. #ifdef MULTI
  139.       xflag = 1;
  140. #endif
  141.       how = MSG_ATTACH;
  142.       continue;
  143.     }
  144.       close(multipipe[0]);
  145.       eff_uid  = real_uid;
  146.       break;
  147.     }
  148. # else /* NOREUID */
  149.   if ((how == MSG_ATTACH || how == MSG_CONT) && multiattach)
  150.     {
  151.       real_uid = multi_uid;
  152.       eff_uid  = own_uid;
  153.       setreuid(real_uid, eff_uid);
  154.       if (chmod(attach_tty, 0666))
  155.     Panic(errno, "chmod %s", attach_tty);
  156.       tty_oldmode = tty_mode;
  157.     }
  158. # endif /* NOREUID */
  159. #endif /* MULTIUSER */
  160.  
  161.   bzero((char *) &m, sizeof(m));
  162.   m.type = how;
  163.   strcpy(m.m_tty, attach_tty);
  164.  
  165.   if (how == MSG_WINCH)
  166.     {
  167.       if ((lasts = MakeClientSocket(0, SockName)) >= 0)
  168.     {
  169.           write(lasts, (char *)&m, sizeof(m));
  170.           close(lasts);
  171.     }
  172.       return 0;
  173.     }
  174.  
  175.   if (how == MSG_CONT)
  176.     {
  177.       if ((lasts = MakeClientSocket(0, SockName)) < 0)
  178.         {
  179.           Panic(0, "Sorry, cannot contact session \"%s\" again\r\n",
  180.                  SockName ? SockName : "<NULL>");
  181.         }
  182.     }
  183.   else
  184.     {
  185.       switch (FindSocket(how, &lasts))
  186.     {
  187.     case 0:
  188.       if (rflag == 2)
  189.         return 0;
  190.       if (quietflag)
  191.         eexit(10);
  192.       Panic(0, SockName && *SockName ? "There is no screen to be %sed matching %s." : "There is no screen to be %sed.",
  193.         xflag ? "attach" :
  194.         dflag ? "detach" :
  195.                         "resum", SockName);
  196.       /* NOTREACHED */
  197.     case 1:
  198.       break;
  199.     default:
  200.       Panic(0, "Type \"screen [-d] -r [pid.]tty.host\" to resume one of them.");
  201.       /* NOTREACHED */
  202.     }
  203.     }
  204.   /*
  205.    * Go in UserContext. Advantage is, you can kill your attacher
  206.    * when things go wrong. Any disadvantages? jw.
  207.    * Do this before the attach to prevent races!
  208.    */
  209. #ifdef MULTIUSER
  210.   if (!multiattach)
  211. #endif
  212.     setuid(real_uid);
  213. #if defined(MULTIUSER) && !defined(NOREUID)
  214.   else
  215.     setreuid(eff_uid, real_uid);
  216. #endif
  217.   setgid(real_gid);
  218.  
  219.   debug2("Attach: uid %d euid %d\n", getuid(), geteuid());
  220.   SockName = SockNamePtr;
  221.   MasterPid = 0;
  222.   while (*SockName)
  223.     {
  224.       if (*SockName > '9' || *SockName < '0')
  225.     break;
  226.       MasterPid = 10 * MasterPid + *SockName - '0';
  227.       SockName++;
  228.     }
  229.   SockName = SockNamePtr;
  230.   debug1("Attach decided, it is '%s'\n", SockPath);
  231.   debug1("Attach found MasterPid == %d\n", MasterPid);
  232.   if (stat(SockPath, &st) == -1)
  233.     Panic(errno, "stat %s", SockPath);
  234.   if ((st.st_mode & 0600) != 0600)
  235.     Panic(0, "Socket is in wrong mode (%03o)", st.st_mode);
  236.   if ((dflag || !xflag) && (st.st_mode & 0700) != (dflag ? 0700 : 0600))
  237.     Panic(0, "That screen is %sdetached.", dflag ? "already " : "not ");
  238. #ifdef REMOTE_DETACH
  239.   if (dflag &&
  240.       (how == MSG_ATTACH || how == MSG_DETACH || how == MSG_POW_DETACH))
  241.     {
  242.       m.m.detach.dpid = getpid();
  243.       strncpy(m.m.detach.duser, LoginName, sizeof(m.m.detach.duser) - 1); 
  244.       m.m.detach.duser[sizeof(m.m.detach.duser) - 1] = 0;
  245. # ifdef POW_DETACH
  246.       if (dflag == 2)
  247.     m.type = MSG_POW_DETACH;
  248.       else
  249. # endif
  250.     m.type = MSG_DETACH;
  251.       if (write(lasts, (char *) &m, sizeof(m)) != sizeof(m))
  252.     Panic(errno, "write");
  253.       close(lasts);
  254.       if (how != MSG_ATTACH)
  255.     return 0;    /* we detached it. jw. */
  256.       sleep(1);    /* we dont want to overrun our poor backend. jw. */
  257.       if ((lasts = MakeClientSocket(0, SockName)) == -1)
  258.     Panic(0, "Cannot contact screen again. Shit.");
  259.       m.type = how;
  260.     }
  261. #endif
  262.   strcpy(m.m.attach.envterm, attach_term);
  263.   debug1("attach: sending %d bytes... ", sizeof m);
  264.  
  265.   strncpy(m.m.attach.auser, LoginName, sizeof(m.m.attach.auser) - 1); 
  266.   m.m.attach.auser[sizeof(m.m.attach.auser) - 1] = 0;
  267.   m.m.attach.apid = getpid();
  268.   m.m.attach.adaptflag = adaptflag;
  269.   m.m.attach.lines = m.m.attach.columns = 0;
  270.   if ((s = getenv("LINES")))
  271.     m.m.attach.lines = atoi(s);
  272.   if ((s = getenv("COLUMNS")))
  273.     m.m.attach.columns = atoi(s);
  274.  
  275. #ifdef PASSWORD
  276.   if (how == MSG_ATTACH || how == MSG_CONT)
  277.     trysend(lasts, &m, m.m.attach.password);
  278.   else
  279. #endif
  280.     {
  281.       if (write(lasts, (char *) &m, sizeof(m)) != sizeof(m))
  282.     Panic(errno, "write");
  283.       close(lasts);
  284.     }
  285.   debug1("Attach(%d): sent\n", m.type);
  286. #ifdef MULTIUSER
  287.   if (multi && (how == MSG_ATTACH || how == MSG_CONT))
  288.     {
  289. # ifndef PASSWORD
  290.       pause();
  291. # endif
  292. # ifdef NOREUID
  293.       close(multipipe[1]);
  294. # else
  295.       setreuid(real_uid, eff_uid);
  296.       if (tty_oldmode >= 0)
  297.         if (chmod(attach_tty, tty_oldmode))
  298.           Panic(errno, "chmod %s", attach_tty);
  299.       tty_oldmode = -1;
  300.       setreuid(eff_uid, real_uid);
  301. # endif
  302.     }
  303. #endif
  304.   rflag = 0;
  305.   return 1;
  306. }
  307.  
  308.  
  309. #ifdef PASSWORD
  310.  
  311. static trysendstatok, trysendstatfail;
  312.  
  313. static sig_t
  314. trysendok(SIGDEFARG)
  315. {
  316.   trysendstatok = 1;
  317. }
  318.  
  319. static sig_t
  320. trysendfail(SIGDEFARG)
  321. {
  322. # ifdef SYSVSIGS
  323.   signal(SIG_PW_FAIL, trysendfail);
  324. # endif /* SYSVSIGS */
  325.   trysendstatfail = 1;
  326. }
  327.  
  328. static char screenpw[9];
  329.  
  330. static void
  331. trysend(fd, m, pwto)
  332. int fd;
  333. struct msg *m;
  334. char *pwto;
  335. {
  336.   char *npw = NULL;
  337.   sig_t (*sighup)__P(SIGPROTOARG);
  338.   sig_t (*sigusr1)__P(SIGPROTOARG);
  339.   int tries;
  340.  
  341.   sigusr1 = signal(SIG_PW_OK, trysendok);
  342.   sighup = signal(SIG_PW_FAIL, trysendfail);
  343.   for (tries = 0; ; )
  344.     {
  345.       strcpy(pwto, screenpw);
  346.       trysendstatok = trysendstatfail = 0;
  347.       if (write(fd, (char *) m, sizeof(*m)) != sizeof(*m))
  348.     Panic(errno, "write");
  349.       close(fd);
  350.       while (trysendstatok == 0 && trysendstatfail == 0)
  351.     pause();
  352.       if (trysendstatok)
  353.     {
  354.       signal(SIG_PW_OK, sigusr1);
  355.       signal(SIG_PW_FAIL, sighup);
  356.       if (trysendstatfail)
  357.         kill(getpid(), SIG_PW_FAIL);
  358.       return;
  359.     }
  360.       if (++tries > 1 || (npw = getpass("Screen Password:")) == 0 || *npw == 0)
  361.     {
  362. #ifdef NETHACK
  363.       if (nethackflag)
  364.         Panic(0, "The guard slams the door in your face.");
  365.       else
  366. #endif
  367.       Panic(0, "Password incorrect.");
  368.     }
  369.       strncpy(screenpw, npw, 8);
  370.       if ((fd = MakeClientSocket(0, SockName)) == -1)
  371.     Panic(0, "Cannot contact screen again. Shit.");
  372.     }
  373. }
  374. #endif /* PASSWORD */
  375.  
  376.  
  377. #ifdef DEBUG
  378. static int AttacherPanic;
  379.  
  380. static sig_t
  381. AttacherChld(SIGDEFARG)
  382. {
  383.   AttacherPanic=1;
  384. #ifndef SIGVOID
  385.   return((sig_t) 0);
  386. #endif
  387. }
  388. #endif
  389.  
  390. /*
  391.  * the frontend's Interrupt handler
  392.  * we forward SIGINT to the poor backend
  393.  */
  394. static sig_t 
  395. AttacherSigInt(SIGDEFARG)
  396. {
  397.   signal(SIGINT, AttacherSigInt);
  398.   Kill(MasterPid, SIGINT);
  399. # ifndef SIGVOID
  400.   return (sig_t) 0;
  401. # endif
  402. }
  403.  
  404. /*
  405.  * Unfortunatelly this is also the SIGHUP handler, so we have to
  406.  * check, if the backend is already detached.
  407.  */
  408.  
  409. sig_t
  410. AttacherFinit(SIGDEFARG)
  411. {
  412.   struct stat statb;
  413.   struct msg m;
  414.   int s;
  415.  
  416.   debug("AttacherFinit();\n");
  417.   signal(SIGHUP, SIG_IGN);
  418.   /* Check if signal comes from backend */
  419.   if (SockName)
  420.     {
  421.       strcpy(SockNamePtr, SockName);
  422.       if (stat(SockPath, &statb) == 0 && (statb.st_mode & 0777) != 0600)
  423.     {
  424.       debug("Detaching backend!\n");
  425.       bzero((char *) &m, sizeof(m));
  426.       strcpy(m.m_tty, attach_tty);
  427.           debug1("attach_tty is %s\n", attach_tty);
  428.       m.m.detach.dpid = getpid();
  429.       m.type = MSG_HANGUP;
  430.       if ((s = MakeClientSocket(0, SockName)) >= 0)
  431.         {
  432.           write(s, (char *)&m, sizeof(m));
  433.           close(s);
  434.         }
  435.     }
  436.     }
  437. #ifdef MULTIUSER
  438.   if (tty_oldmode >= 0)
  439.     {
  440.       setuid(own_uid);
  441.       chmod(attach_tty, tty_oldmode);
  442.     }
  443. #endif
  444.   exit(0);
  445. #ifndef SIGVOID
  446.   return((sig_t) 0);
  447. #endif
  448. }
  449.  
  450. #ifdef POW_DETACH
  451. static sig_t
  452. AttacherFinitBye(SIGDEFARG)
  453. {
  454.   int ppid;
  455.   debug("AttacherFintBye()\n");
  456. #if defined(MULTIUSER) && defined(NOREUID)
  457.   if (multiattach)
  458.     exit(SIG_POWER_BYE);
  459. #endif
  460. #ifdef MULTIUSER
  461.   setuid(own_uid);
  462. #else
  463.   setuid(real_uid);
  464. #endif
  465.   setgid(real_gid);
  466.   /* we don't want to disturb init (even if we were root), eh? jw */
  467.   if ((ppid = getppid()) > 1)
  468.     Kill(ppid, SIGHUP);        /* carefully say good bye. jw. */
  469.   exit(0);
  470. #ifndef SIGVOID
  471.   return((sig_t) 0);
  472. #endif
  473. }
  474. #endif
  475.  
  476. static int SuspendPlease;
  477.  
  478. static sig_t
  479. SigStop(SIGDEFARG)
  480. {
  481.   debug("SigStop()\n");
  482.   SuspendPlease = 1;
  483. #ifndef SIGVOID
  484.   return((sig_t) 0);
  485. #endif
  486. }
  487.  
  488. #ifdef LOCK
  489. static int LockPlease;
  490.  
  491. static sig_t
  492. DoLock(SIGDEFARG)
  493. {
  494. # ifdef SYSVSIGS
  495.   signal(SIG_LOCK, DoLock);
  496. # endif
  497.   debug("DoLock()\n");
  498.   LockPlease = 1;
  499. # ifndef SIGVOID
  500.   return((sig_t) 0);
  501. # endif
  502. }
  503. #endif
  504.  
  505. #if defined(SIGWINCH) && defined(TIOCGWINSZ)
  506. static int SigWinchPlease;
  507.  
  508. static sig_t
  509. AttacherWinch(SIGDEFARG)
  510. {
  511.   debug("AttacherWinch()\n");
  512.   SigWinchPlease = 1;
  513. # ifndef SIGVOID
  514.   return((sig_t) 0);
  515. # endif
  516. }
  517. #endif
  518.  
  519.  
  520. /*
  521.  *  Attacher loop - no return
  522.  */
  523.  
  524. void
  525. Attacher()
  526. {
  527.   signal(SIGHUP, AttacherFinit);
  528.   signal(SIG_BYE, AttacherFinit);
  529. #ifdef POW_DETACH
  530.   signal(SIG_POWER_BYE, AttacherFinitBye);
  531. #endif
  532. #ifdef LOCK
  533.   signal(SIG_LOCK, DoLock);
  534. #endif
  535.   signal(SIGINT, AttacherSigInt);
  536. #ifdef BSDJOBS
  537.   signal(SIG_STOP, SigStop);
  538. #endif
  539. #if defined(SIGWINCH) && defined(TIOCGWINSZ)
  540.   signal(SIGWINCH, AttacherWinch);
  541. #endif
  542. #ifdef DEBUG
  543.   signal(SIGCHLD, AttacherChld);
  544. #endif
  545.   debug("attacher: going for a nap.\n");
  546.   dflag = 0;
  547. #ifdef MULTI
  548.   xflag = 1;
  549. #endif
  550.   for (;;)
  551.     {
  552. #ifdef DEBUG
  553.       sleep(30);
  554.       if (kill(MasterPid, 0) < 0 && errno != EPERM)
  555.         {
  556.       debug1("attacher: Panic! MasterPid %d does not exist.\n", MasterPid);
  557.       AttacherPanic++;
  558.     }
  559. #else
  560.       pause();
  561. #endif
  562. /*
  563.       debug("attacher: ding!\n");
  564. */
  565. #ifdef DEBUG
  566.       if (AttacherPanic)
  567.         {
  568.       fcntl(0, F_SETFL, 0);
  569.       SetTTY(0, &attach_Mode);
  570.       printf("\nSuddenly the Dungeon collapses!! - You die...\n");
  571.       eexit(1);
  572.         }
  573. #endif
  574. #ifdef BSDJOBS
  575.       if (SuspendPlease)
  576.     {
  577.       SuspendPlease = 0;
  578. #if defined(MULTIUSER) && defined(NOREUID)
  579.       if (multiattach)
  580.         exit(SIG_STOP);
  581. #endif
  582.       signal(SIGTSTP, SIG_DFL);
  583.       debug("attacher: killing myself SIGTSTP\n");
  584.       kill(getpid(), SIGTSTP);
  585.       debug("attacher: continuing from stop\n");
  586.       signal(SIG_STOP, SigStop);
  587.       (void) Attach(MSG_CONT);
  588.     }
  589. #endif
  590. #ifdef LOCK
  591.       if (LockPlease)
  592.     {
  593.       LockPlease = 0;
  594. #if defined(MULTIUSER) && defined(NOREUID)
  595.       if (multiattach)
  596.         exit(SIG_LOCK);
  597. #endif
  598.       LockTerminal();
  599. # ifdef SYSVSIGS
  600.       signal(SIG_LOCK, DoLock);
  601. # endif
  602.       (void) Attach(MSG_CONT);
  603.     }
  604. #endif    /* LOCK */
  605. #if defined(SIGWINCH) && defined(TIOCGWINSZ)
  606.       if (SigWinchPlease)
  607.     {
  608.       SigWinchPlease = 0;
  609. # ifdef SYSVSIGS
  610.       signal(SIGWINCH, AttacherWinch);
  611. # endif
  612.       (void) Attach(MSG_WINCH);
  613.     }
  614. #endif    /* SIGWINCH */
  615.     }
  616. }
  617.  
  618. #ifdef LOCK
  619.  
  620. /* ADDED by Rainer Pruy 10/15/87 */
  621. /* POLISHED by mls. 03/10/91 */
  622.  
  623. static char LockEnd[] = "Welcome back to screen !!\n";
  624.  
  625. static sig_t
  626. LockHup(SIGDEFARG)
  627. {
  628.   int ppid = getppid();
  629.   setuid(real_uid);
  630.   setgid(real_gid);
  631.   if (ppid > 1)
  632.     Kill(ppid, SIGHUP);
  633.   exit(0);
  634. }
  635.  
  636. static void
  637. LockTerminal()
  638. {
  639.   char *prg;
  640.   int sig, pid;
  641.   sig_t (*sigs[NSIG])__P(SIGPROTOARG);
  642.  
  643.   for (sig = 1; sig < NSIG; sig++)
  644.     {
  645.       sigs[sig] = signal(sig, SIG_IGN);
  646.     }
  647.   signal(SIGHUP, LockHup);
  648.   printf("\n");
  649.  
  650.   prg = getenv("LOCKPRG");
  651.   if (prg && strcmp(prg, "builtin") && !access(prg, X_OK))
  652.     {
  653.       signal(SIGCHLD, SIG_DFL);
  654.       debug1("lockterminal: '%s' seems executable, execl it!\n", prg);
  655.       if ((pid = fork()) == 0)
  656.         {
  657.           /* Child */
  658.           setuid(real_uid);    /* this should be done already */
  659.           setgid(real_gid);
  660.           closeallfiles(0);    /* important: /etc/shadow may be open */
  661.           execl(prg, "SCREEN-LOCK", NULL);
  662.           exit(errno);
  663.         }
  664.       if (pid == -1)
  665.         {
  666. #ifdef NETHACK
  667.           if (nethackflag)
  668.             Msg(errno, "Cannot fork terminal - lock failed");
  669.           else
  670. #endif
  671.           Msg(errno, "Cannot lock terminal - fork failed");
  672.         }
  673.       else
  674.         {
  675. #ifdef BSDWAIT
  676.           union wait wstat;
  677. #else
  678.           int wstat;
  679. #endif
  680.           int wret;
  681.  
  682. #ifdef hpux
  683.           signal(SIGCHLD, SIG_DFL);
  684. #endif
  685.           errno = 0;
  686.           while (((wret = wait(&wstat)) != pid) ||
  687.              ((wret == -1) && (errno == EINTR))
  688.              )
  689.         errno = 0;
  690.     
  691.           if (errno)
  692.         {
  693.           Msg(errno, "Lock");
  694.           sleep(2);
  695.         }
  696.       else if (WTERMSIG(wstat) != 0)
  697.         {
  698.           fprintf(stderr, "Lock: %s: Killed by signal: %d%s\n", prg,
  699.               WTERMSIG(wstat), WIFCORESIG(wstat) ? " (Core dumped)" : "");
  700.           sleep(2);
  701.         }
  702.       else if (WEXITSTATUS(wstat))
  703.         {
  704.           debug2("Lock: %s: return code %d\n", prg, WEXITSTATUS(wstat));
  705.         }
  706.           else
  707.         printf(LockEnd);
  708.         }
  709.     }
  710.   else
  711.     {
  712.       if (prg)
  713.     {
  714.           debug1("lockterminal: '%s' seems NOT executable, we use our builtin\n", prg);
  715.     }
  716.       else
  717.     {
  718.       debug("lockterminal: using buitin.\n");
  719.     }
  720.       screen_builtin_lck();
  721.     }
  722.   /* reset signals */
  723.   for (sig = 1; sig < NSIG; sig++)
  724.     {
  725.       if (sigs[sig] != (sig_t(*)__P(SIGPROTOARG)) -1)
  726.     signal(sig, sigs[sig]);
  727.     }
  728. }                /* LockTerminal */
  729.  
  730. /* -- original copyright by Luigi Cannelloni 1985 (luigi@faui70.UUCP) -- */
  731. static void
  732. screen_builtin_lck()
  733. {
  734.   char fullname[100], *cp1, message[BUFSIZ];
  735.   char c, *pass, mypass[9];
  736. #ifdef SHADOWPW
  737.   struct spwd *sss = NULL;
  738. #endif
  739.   int t;
  740.  
  741. #ifdef undef
  742.   /* get password entry */
  743.   if ((ppp = getpwuid(real_uid)) == NULL)
  744.     {
  745.       fprintf(stderr, "screen_builtin_lck: No passwd entry.\007\n");
  746.       sleep(2);
  747.       return;
  748.     }
  749.   if (!isatty(0))
  750.     {
  751.       fprintf(stderr, "screen_builtin_lck: Not a tty.\007\n");
  752.       sleep(2);
  753.       return;
  754.     }
  755. #endif
  756.   pass = ppp->pw_passwd;
  757. #ifdef SHADOWPW
  758. realpw:
  759. #endif /* SHADOWPW */
  760.   for (t = 0; t < 13; t++)
  761.     {
  762.       c = pass[t];
  763.       if (!(c == '.' || c == '/' ||
  764.             (c >= '0' && c <= '9') || 
  765.             (c >= 'a' && c <= 'z') || 
  766.             (c >= 'A' && c <= 'Z'))) 
  767.         break;
  768.     }
  769.   if (t < 13)
  770.     {
  771.       debug("builtin_lock: ppp->pw_passwd bad, has it a shadow?\n");
  772. #ifdef SHADOWPW
  773.       setspent(); /* rewind shadow file */
  774.       if ((sss == NULL) && (sss = getspnam(ppp->pw_name)))
  775.         {
  776.           pass = sss->sp_pwdp;
  777.           goto realpw;
  778.         }
  779. #endif /* SHADOWPW */
  780.       if ((pass = getpass("Key:   ")))
  781.         {
  782.           strncpy(mypass, pass, 8);
  783.           mypass[8] = 0;
  784.           if (*mypass == 0)
  785.             return;
  786.           if ((pass = getpass("Again: ")))
  787.             {
  788.               if (strcmp(mypass, pass))
  789.                 {
  790.                   fprintf(stderr, "Passwords don't match.\007\n");
  791.                   sleep(2);
  792.                   return;
  793.                 }
  794.             }
  795.         }
  796.       if (pass == 0)
  797.         {
  798.           fprintf(stderr, "Getpass error.\007\n");
  799.           sleep(2);
  800.           return;
  801.         }
  802.       pass = 0;
  803.     }
  804.  
  805.   debug("screen_builtin_lck looking in gcos field\n");
  806.   strcpy(fullname, ppp->pw_gecos);
  807.   if ((cp1 = index(fullname, ',')) != NULL)
  808.     *cp1 = '\0';
  809.   if ((cp1 = index(fullname, '&')) != NULL)
  810.     {
  811.       sprintf(cp1, "%s", ppp->pw_name);
  812.       if (*cp1 >= 'a' && *cp1 <= 'z')
  813.     *cp1 -= 'a' - 'A';
  814.     }
  815.  
  816.   sprintf(message, "Screen used by %s <%s>.\nPassword:\007",
  817.           fullname, ppp->pw_name);
  818.  
  819.   /* loop here to wait for correct password */
  820.   for (;;)
  821.     {
  822.       debug("screen_builtin_lck awaiting password\n");
  823.       errno = 0;
  824.       if ((cp1 = getpass(message)) == NULL)
  825.         {
  826.           AttacherFinit(SIGARG);
  827.           /* NOTREACHED */
  828.         }
  829.       debug3("getpass(%d): %x == %s\n", errno, (unsigned int)cp1, cp1);
  830.       if (pass)
  831.         {
  832.           if (!strcmp(crypt(cp1, pass), pass))
  833.             break;
  834.         }
  835.       else
  836.         {
  837.           if (!strcmp(cp1, mypass))
  838.             break;
  839.         }
  840.       debug("screen_builtin_lck: NO!!!!!\n");
  841.     }
  842.   debug("password ok.\n");
  843. }
  844.  
  845. #endif    /* LOCK */
  846.