home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume26 / screen-3.5 / part03 / attacher.c next >
C/C++ Source or Header  |  1993-07-25  |  19KB  |  835 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.3 1993/07/21 15:42:48 mlschroe 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.       pause();
  553.       debug("attacher: huh! a signal!\n");
  554. #ifdef DEBUG
  555.       if (AttacherPanic)
  556.         {
  557.       fcntl(0, F_SETFL, 0);
  558.       SetTTY(0, &attach_Mode);
  559.       printf("\nSuddenly the Dungeon collapses!! - You die...\n");
  560.       eexit(1);
  561.         }
  562. #endif
  563. #ifdef BSDJOBS
  564.       if (SuspendPlease)
  565.     {
  566.       SuspendPlease = 0;
  567. #if defined(MULTIUSER) && defined(NOREUID)
  568.       if (multiattach)
  569.         exit(SIG_STOP);
  570. #endif
  571.       signal(SIGTSTP, SIG_DFL);
  572.       debug("attacher: killing myself SIGTSTP\n");
  573.       kill(getpid(), SIGTSTP);
  574.       debug("attacher: continuing from stop\n");
  575.       signal(SIG_STOP, SigStop);
  576.       (void) Attach(MSG_CONT);
  577.     }
  578. #endif
  579. #ifdef LOCK
  580.       if (LockPlease)
  581.     {
  582.       LockPlease = 0;
  583. #if defined(MULTIUSER) && defined(NOREUID)
  584.       if (multiattach)
  585.         exit(SIG_LOCK);
  586. #endif
  587.       LockTerminal();
  588. # ifdef SYSVSIGS
  589.       signal(SIG_LOCK, DoLock);
  590. # endif
  591.       (void) Attach(MSG_CONT);
  592.     }
  593. #endif    /* LOCK */
  594. #if defined(SIGWINCH) && defined(TIOCGWINSZ)
  595.       if (SigWinchPlease)
  596.     {
  597.       SigWinchPlease = 0;
  598. # ifdef SYSVSIGS
  599.       signal(SIGWINCH, AttacherWinch);
  600. # endif
  601.       (void) Attach(MSG_WINCH);
  602.     }
  603. #endif    /* SIGWINCH */
  604.     }
  605. }
  606.  
  607. #ifdef LOCK
  608.  
  609. /* ADDED by Rainer Pruy 10/15/87 */
  610. /* POLISHED by mls. 03/10/91 */
  611.  
  612. static char LockEnd[] = "Welcome back to screen !!\n";
  613.  
  614. static sig_t
  615. LockHup(SIGDEFARG)
  616. {
  617.   int ppid = getppid();
  618.   setuid(real_uid);
  619.   setgid(real_gid);
  620.   if (ppid > 1)
  621.     Kill(ppid, SIGHUP);
  622.   exit(0);
  623. }
  624.  
  625. static void
  626. LockTerminal()
  627. {
  628.   char *prg;
  629.   int sig, pid;
  630.   sig_t (*sigs[NSIG])__P(SIGPROTOARG);
  631.  
  632.   for (sig = 1; sig < NSIG; sig++)
  633.     {
  634.       sigs[sig] = signal(sig, SIG_IGN);
  635.     }
  636.   signal(SIGHUP, LockHup);
  637.   printf("\n");
  638.  
  639.   prg = getenv("LOCKPRG");
  640.   if (prg && strcmp(prg, "builtin") && !access(prg, X_OK))
  641.     {
  642.       signal(SIGCHLD, SIG_DFL);
  643.       debug1("lockterminal: '%s' seems executable, execl it!\n", prg);
  644.       if ((pid = fork()) == 0)
  645.         {
  646.           /* Child */
  647.           setuid(real_uid);    /* this should be done already */
  648.           setgid(real_gid);
  649.           closeallfiles(0);    /* important: /etc/shadow may be open */
  650.           execl(prg, "SCREEN-LOCK", NULL);
  651.           exit(errno);
  652.         }
  653.       if (pid == -1)
  654.         {
  655. #ifdef NETHACK
  656.           if (nethackflag)
  657.             Msg(errno, "Cannot fork terminal - lock failed");
  658.           else
  659. #endif
  660.           Msg(errno, "Cannot lock terminal - fork failed");
  661.         }
  662.       else
  663.         {
  664. #ifdef BSDWAIT
  665.           union wait wstat;
  666. #else
  667.           int wstat;
  668. #endif
  669.           int wret;
  670.  
  671. #ifdef hpux
  672.           signal(SIGCHLD, SIG_DFL);
  673. #endif
  674.           errno = 0;
  675.           while (((wret = wait(&wstat)) != pid) ||
  676.              ((wret == -1) && (errno == EINTR))
  677.              )
  678.         errno = 0;
  679.     
  680.           if (errno)
  681.         {
  682.           Msg(errno, "Lock");
  683.           sleep(2);
  684.         }
  685.       else if (WTERMSIG(wstat) != 0)
  686.         {
  687.           fprintf(stderr, "Lock: %s: Killed by signal: %d%s\n", prg,
  688.               WTERMSIG(wstat), WIFCORESIG(wstat) ? " (Core dumped)" : "");
  689.           sleep(2);
  690.         }
  691.       else if (WEXITSTATUS(wstat))
  692.         {
  693.           debug2("Lock: %s: return code %d\n", prg, WEXITSTATUS(wstat));
  694.         }
  695.           else
  696.         printf(LockEnd);
  697.         }
  698.     }
  699.   else
  700.     {
  701.       if (prg)
  702.     {
  703.           debug1("lockterminal: '%s' seems NOT executable, we use our builtin\n", prg);
  704.     }
  705.       else
  706.     {
  707.       debug("lockterminal: using buitin.\n");
  708.     }
  709.       screen_builtin_lck();
  710.     }
  711.   /* reset signals */
  712.   for (sig = 1; sig < NSIG; sig++)
  713.     {
  714.       if (sigs[sig] != (sig_t(*)__P(SIGPROTOARG)) -1)
  715.     signal(sig, sigs[sig]);
  716.     }
  717. }                /* LockTerminal */
  718.  
  719. /* -- original copyright by Luigi Cannelloni 1985 (luigi@faui70.UUCP) -- */
  720. static void
  721. screen_builtin_lck()
  722. {
  723.   char fullname[100], *cp1, message[BUFSIZ];
  724.   char c, *pass, mypass[9];
  725. #ifdef SHADOWPW
  726.   struct spwd *sss = NULL;
  727. #endif
  728.   int t;
  729.  
  730. #ifdef undef
  731.   /* get password entry */
  732.   if ((ppp = getpwuid(real_uid)) == NULL)
  733.     {
  734.       fprintf(stderr, "screen_builtin_lck: No passwd entry.\007\n");
  735.       sleep(2);
  736.       return;
  737.     }
  738.   if (!isatty(0))
  739.     {
  740.       fprintf(stderr, "screen_builtin_lck: Not a tty.\007\n");
  741.       sleep(2);
  742.       return;
  743.     }
  744. #endif
  745.   pass = ppp->pw_passwd;
  746. #ifdef SHADOWPW
  747. realpw:
  748. #endif /* SHADOWPW */
  749.   for (t = 0; t < 13; t++)
  750.     {
  751.       c = pass[t];
  752.       if (!(c == '.' || c == '/' ||
  753.             (c >= '0' && c <= '9') || 
  754.             (c >= 'a' && c <= 'z') || 
  755.             (c >= 'A' && c <= 'Z'))) 
  756.         break;
  757.     }
  758.   if (t < 13)
  759.     {
  760.       debug("builtin_lock: ppp->pw_passwd bad, has it a shadow?\n");
  761. #ifdef SHADOWPW
  762.       setspent(); /* rewind shadow file */
  763.       if ((sss == NULL) && (sss = getspnam(ppp->pw_name)))
  764.         {
  765.           pass = sss->sp_pwdp;
  766.           goto realpw;
  767.         }
  768. #endif /* SHADOWPW */
  769.       if ((pass = getpass("Key:   ")))
  770.         {
  771.           strncpy(mypass, pass, 8);
  772.           mypass[8] = 0;
  773.           if (*mypass == 0)
  774.             return;
  775.           if ((pass = getpass("Again: ")))
  776.             {
  777.               if (strcmp(mypass, pass))
  778.                 {
  779.                   fprintf(stderr, "Passwords don't match.\007\n");
  780.                   sleep(2);
  781.                   return;
  782.                 }
  783.             }
  784.         }
  785.       if (pass == 0)
  786.         {
  787.           fprintf(stderr, "Getpass error.\007\n");
  788.           sleep(2);
  789.           return;
  790.         }
  791.       pass = 0;
  792.     }
  793.  
  794.   debug("screen_builtin_lck looking in gcos field\n");
  795.   strcpy(fullname, ppp->pw_gecos);
  796.   if ((cp1 = index(fullname, ',')) != NULL)
  797.     *cp1 = '\0';
  798.   if ((cp1 = index(fullname, '&')) != NULL)
  799.     {
  800.       sprintf(cp1, "%s", ppp->pw_name);
  801.       if (*cp1 >= 'a' && *cp1 <= 'z')
  802.     *cp1 -= 'a' - 'A';
  803.     }
  804.  
  805.   sprintf(message, "Screen used by %s <%s>.\nPassword:\007",
  806.           fullname, ppp->pw_name);
  807.  
  808.   /* loop here to wait for correct password */
  809.   for (;;)
  810.     {
  811.       debug("screen_builtin_lck awaiting password\n");
  812.       errno = 0;
  813.       if ((cp1 = getpass(message)) == NULL)
  814.         {
  815.           AttacherFinit(SIGARG);
  816.           /* NOTREACHED */
  817.         }
  818.       debug3("getpass(%d): %x == %s\n", errno, (unsigned int)cp1, cp1);
  819.       if (pass)
  820.         {
  821.           if (!strcmp(crypt(cp1, pass), pass))
  822.             break;
  823.         }
  824.       else
  825.         {
  826.           if (!strcmp(cp1, mypass))
  827.             break;
  828.         }
  829.       debug("screen_builtin_lck: NO!!!!!\n");
  830.     }
  831.   debug("password ok.\n");
  832. }
  833.  
  834. #endif    /* LOCK */
  835.