home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume27 / screen-3.5.1 / part03 / utmp.c < prev   
C/C++ Source or Header  |  1993-08-08  |  19KB  |  776 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: utmp.c,v 1.6 1993/08/05 14:24:12 mlschroe Exp $ FAU")
  25.  
  26.  
  27. /*
  28.  * An explanation of some weird things:
  29.  *
  30.  *  linux should have GETUTENT, but their pututline() doesn't have
  31.  *  a return value.
  32.  * 
  33.  *  UTNOKEEP: A (ugly) hack for apollo, that does two things:
  34.  *    1) Always close and reopen the utmp file descriptor. (I don't know
  35.  *       for what reason this is done...)
  36.  *    2) Implement an unsortet utmp file much like GETUTENT.
  37.  *  (IMHO these two features should be split!)
  38.  */
  39.  
  40.  
  41. #include <sys/types.h>
  42. #include <sys/stat.h>
  43. #include <fcntl.h>
  44.  
  45. #include "config.h"
  46. #include "screen.h"
  47. #include "extern.h"
  48.  
  49.  
  50. extern struct display *display;
  51. extern struct win *fore;
  52. extern char *LoginName;
  53. #ifdef NETHACK
  54. extern nethackflag;
  55. #endif
  56.  
  57. #ifdef UTMPOK
  58.  
  59. static slot_t TtyNameSlot __P((char *));
  60. static int utmpok, utmpfd = -1;
  61. static char UtmpName[] = UTMPFILE;
  62.  
  63.  
  64. # if defined(GETUTENT) && !defined(SVR4)
  65. #  if defined(hpux) /* cruel hpux release 8.0 */
  66. #   define pututline _pututline
  67. #  endif /* hpux */
  68. extern struct utmp *getutline(), *pututline();
  69. #  if defined(_SEQUENT_)
  70. extern struct utmp *ut_add_user(), *ut_delete_user();
  71. extern char *ut_find_host();
  72. #   define UTHOST        /* _SEQUENT_ has got ut_find_host() */
  73. #  endif /* _SEQUENT_ */
  74. # endif /* GETUTENT && !SVR4 */
  75.  
  76. # if defined (GETTTYENT) && !defined(GETUTENT)
  77. #   include <ttyent.h>
  78. # endif /* GETUTENT */
  79.  
  80. # if !defined(GETTTYENT) && !defined(GETUTENT) && !defined(UTNOKEEP)
  81. struct ttyent
  82. {
  83.   char *ty_name;
  84. };
  85. static void setttyent __P((void));
  86. static struct ttyent *getttyent __P((void));
  87. static char *tt, *ttnext;
  88. static char ttys[] = "/etc/ttys";
  89. # endif /* !GETTTYENT && !GETUTENT && !UTNOKEEP */
  90.  
  91. #endif /* UTMPOK */
  92.  
  93.  
  94.  
  95. /*
  96.  * SlotToggle - modify the utmp slot of the fore window.
  97.  *
  98.  * how > 0    do try to set a utmp slot.
  99.  * how = 0    try to withdraw a utmp slot.
  100.  *
  101.  * w_slot = -1  window not logged in.
  102.  * w_slot = 0   window not logged in, but should be logged in. 
  103.  *              (unable to write utmp, or detached).
  104.  */
  105. void
  106. SlotToggle(how)
  107. int how;
  108. {
  109.   debug1("SlotToggle %d\n", how);
  110. #ifdef UTMPOK
  111.   if (how)
  112.     {
  113.       debug(" try to log in\n");
  114.       if ((fore->w_slot == (slot_t) -1) || (fore->w_slot == (slot_t) 0))
  115.     {
  116. # ifdef USRLIMIT
  117.           if (CountUsers() >= USRLIMIT)
  118.             Msg(0, "User limit reached.");
  119.           else
  120. # endif
  121.             {
  122.               if (SetUtmp(fore) == 0)
  123.                 Msg(0, "This window is now logged in.");
  124.               else
  125.                 Msg(0, "This window should now be logged in.");
  126.             }
  127.     }
  128.       else
  129.     Msg(0, "This window is already logged in.");
  130.     }
  131.   else
  132.     {
  133.       debug(" try to log out\n");
  134.       if (fore->w_slot == (slot_t) -1)
  135.     Msg(0, "This window is already logged out\n");
  136.       else if (fore->w_slot == (slot_t) 0)
  137.     {
  138.       debug("What a relief! In fact, it was not logged in\n");
  139.       Msg(0, "This window is not logged in.");
  140.       fore->w_slot = (slot_t) -1;
  141.     }
  142.       else
  143.     {
  144.       RemoveUtmp(fore);
  145.       if (fore->w_slot != (slot_t) -1)
  146.         Msg(0, "What? Cannot remove Utmp slot?");
  147.       else
  148.         Msg(0, "This window is no longer logged in.");
  149.     }
  150.     }
  151. #else    /* !UTMPOK */
  152.   Msg(0, "Unable to modify %s.\n", UTMPFILE);
  153. #endif
  154. }
  155.  
  156.  
  157. #ifdef UTMPOK
  158.  
  159.  
  160. void
  161. InitUtmp()
  162. {
  163.   debug1("InitUtmp testing '%s'...\n", UtmpName);
  164.   if ((utmpfd = open(UtmpName, O_RDWR)) == -1)
  165.     {
  166.       if (errno != EACCES)
  167.     Msg(errno, UtmpName);
  168.       debug("InitUtmp failed.\n");
  169.       utmpok = 0;
  170.       return;
  171.     }
  172. # ifdef GETUTENT
  173.   close(utmpfd);    /* it was just a test */
  174.   utmpfd = -1;
  175. # endif /* GETUTENT */
  176.   utmpok = 1;
  177. }
  178.  
  179.  
  180. #ifdef USRLIMIT
  181. int
  182. CountUsers()
  183. {
  184. # ifdef GETUTENT
  185.   struct utmp *ut, *getutent();
  186. # else /* GETUTENT */
  187.   struct utmp utmpbuf;
  188. # endif /* GETUTENT */
  189.   int UserCount;
  190.  
  191. # ifdef UTNOKEEP
  192.   InitUtmp();
  193. # endif /* UTNOKEEP */
  194.   debug1("CountUsers() - utmpok=%d\n", utmpok);
  195.   if (!utmpok)
  196.     return(0);
  197.   UserCount = 0;
  198. # ifdef GETUTENT
  199.   setutent();
  200.   while (ut = getutent())
  201.     if (ut->ut_type == USER_PROCESS)
  202.       UserCount++;
  203. # else /* GETUTENT */
  204.   (void) lseek(utmpfd, (off_t) 0, 0);
  205.   while (read(utmpfd, &utmpbuf, sizeof(struct utmp)) > 0)
  206.     {
  207.       if (utmpbuf.ut_name[0] != '\0')
  208.        UserCount++;
  209.     }
  210. # endif /* GETUTENT */
  211. # ifdef UTNOKEEP
  212.   close(utmpfd);
  213. # endif /* UTNOKEEP */
  214.   return(UserCount);
  215. }
  216. #endif /* USRLIMIT */
  217.  
  218.  
  219.  
  220. /*
  221.  * the utmp entry for tty is located and removed.
  222.  * it is stored in d_utmp_logintty.
  223.  */
  224. void
  225. RemoveLoginSlot()
  226. {
  227. # ifdef GETUTENT
  228.   struct utmp *uu;
  229. # endif /* GETUTENT */
  230.   struct utmp u;    /* 'empty' slot that we write back */
  231. # ifdef _SEQUENT_
  232.   char *p;
  233. # endif /* _SEQUENT_ */
  234.  
  235.   ASSERT(display);
  236.   debug("RemoveLoginSlot: removing your logintty\n");
  237.   d_loginslot = TtyNameSlot(d_usertty);
  238. # ifdef UTNOKEEP
  239.   InitUtmp();
  240. # endif /* UTNOKEEP */
  241.   if (!utmpok)
  242.     {
  243.       debug("RemoveLoginSlot: utmpok == 0\n");
  244.       return;
  245.     }
  246.   if (d_loginslot == (slot_t)0 || d_loginslot == (slot_t)-1)
  247.     {
  248.       return;
  249.     }
  250. # ifdef _SEQUENT_
  251.   if (p = ut_find_host(d_loginslot))
  252.     strncpy(d_loginhost, p, sizeof(d_loginhost) - 1);
  253.   d_loginhost[sizeof(d_loginhost) - 1] = 0;
  254. # endif /* _SEQUENT_ */
  255.  
  256.   bzero((char *) &u, sizeof u);
  257.  
  258. # ifdef GETUTENT
  259.   setutent();
  260.   strncpy(u.ut_line, d_loginslot, sizeof(u.ut_line));
  261.   if ((uu = getutline(&u)) == 0)
  262.     {
  263.       Msg(0, "Utmp slot not found -> not removed");
  264.       return;
  265.     }
  266.   d_utmp_logintty = *uu;
  267. #  ifdef _SEQUENT_
  268.   if (ut_delete_user(d_loginslot, uu->ut_pid, 0, 0) == 0)
  269. #  else /* _SEQUENT_ */
  270.   u = *uu;
  271.   u.ut_type = DEAD_PROCESS;
  272.   u.ut_exit.e_termination = 0;
  273.   u.ut_exit.e_exit= 0;
  274.   if (pututline(&u) == 0)
  275. #  endif /* _SEQUENT_ */
  276.  
  277. # else /* GETUTENT */
  278.  
  279.   (void) lseek(utmpfd, (off_t) (d_loginslot * sizeof u), 0);
  280.   bzero((char *)&d_utmp_logintty, sizeof u);
  281.   if (read(utmpfd, (char *) &d_utmp_logintty, sizeof u) != sizeof u)
  282.     {
  283.       Msg(errno, "cannot read %s ??", UTMPFILE);
  284.       sleep(1);
  285.     }
  286.   (void) lseek(utmpfd, (off_t) (d_loginslot * sizeof u), 0);
  287. #  ifdef UTNOKEEP
  288.   /* 
  289.    * as the utmp file is not sorted, we want to mark this slot occupied,
  290.    * as RestoreLoginSlot() will write exactly here.
  291.    */
  292.   bcopy((char *)&d_utmp_logintty, (char *)&u, sizeof u);
  293.   bzero(u.ut_name, sizeof(u.ut_name));
  294.   bzero(u.ut_host, sizeof(u.ut_host));
  295. #  endif /* UTNOKEEP */
  296.   if (write(utmpfd, (char *) &u, sizeof u) != sizeof u)
  297.  
  298. # endif /* GETUTENT */
  299.  
  300.     {
  301. # ifdef NETHACK
  302.       if (nethackflag)
  303.     {
  304.       Msg(errno, "%s is too hard to dig in", UTMPFILE); 
  305.     }
  306.       else
  307. # endif /* NETHACK */
  308.     {
  309.       Msg(errno, "Could not write %s", UTMPFILE);
  310.     }
  311.     }
  312. # ifdef UTNOKEEP
  313.   close(utmpfd);
  314. # endif /* UTNOKEEP */
  315.   debug1(" slot %d zapped\n", (int)d_loginslot);
  316. }
  317.  
  318. /*
  319.  * d_utmp_logintty is reinserted into utmp
  320.  */
  321. void
  322. RestoreLoginSlot()
  323. {
  324.   debug("RestoreLoginSlot()\n");
  325.   ASSERT(display);
  326. # ifdef UTNOKEEP
  327.   InitUtmp();
  328. # endif /* UTNOKEEP */
  329.   if (utmpok && d_loginslot != (slot_t)0 && d_loginslot != (slot_t)-1)
  330.     {
  331. # ifdef GETUTENT
  332. #  ifdef _SEQUENT_
  333.       int fail;
  334.       debug1(" logging you in again (slot %s)\n", d_loginslot);
  335. /*
  336.  * We have problems if we add the console and use ut_add_user()
  337.  * because the id will be 'scon' instead of 'co'. So we
  338.  * restore it with pututline(). The reason why we don't use
  339.  * pututline all the time is that we want to set the host field.
  340.  * Unfortunatelly this can only be done with ut_add_user().
  341.  */
  342.       if (*d_loginhost)
  343.         {
  344.           fail = (ut_add_user(d_utmp_logintty.ut_name, d_loginslot, d_utmp_logintty.ut_pid,
  345.                               *d_loginhost ? d_loginhost : (char *)0) == 0);
  346.         }
  347.       else
  348.         {
  349.           setutent();
  350.           fail = (pututline(&d_utmp_logintty) == 0);
  351.         }
  352.       if (fail)
  353. #  else    /* _SEQUENT_ */
  354.       debug1(" logging you in again (slot %s)\n", d_loginslot);
  355.       setutent();
  356.       if (pututline(&d_utmp_logintty)==0)
  357. #  endif    /* _SEQUENT */
  358. # else    /* GETUTENT */
  359.       debug1(" logging you in again (slot %d)\n", d_loginslot);
  360. #  ifdef sequent
  361.       /* 
  362.        * call sequent undocumented routine to count logins 
  363.        * and add utmp entry if possible 
  364.        */
  365.       if (add_utmp(d_loginslot, &d_utmp_logintty) == -1)
  366. #  else /* sequent */
  367.       (void) lseek(utmpfd, (off_t) (d_loginslot * sizeof(struct utmp)), 0);
  368.       if (write(utmpfd, (char *) &d_utmp_logintty, sizeof(struct utmp))
  369.       != sizeof(struct utmp))
  370. #  endif /* sequent */
  371. # endif    /* GETUTENT */
  372.         {
  373. # ifdef NETHACK
  374.           if (nethackflag)
  375.             Msg(errno, "%s is too hard to dig in", UTMPFILE);
  376.       else
  377. # endif /* NETHACK */
  378.           Msg(errno,"Could not write %s", UTMPFILE);
  379.         }
  380.     }
  381. # ifdef UTNOKEEP
  382.   close(utmpfd);
  383. # endif /* UTNOKEEP */
  384.   d_loginslot = (slot_t) 0;
  385. }
  386.  
  387.  
  388.  
  389. /*
  390.  * Construct a utmp entry for window wi.
  391.  * the hostname field reflects what we know about the d_user (i.e. display)
  392.  * location. If d_loginhost is not set, then he is local and we write
  393.  * down the name of his terminal line; else he is remote and we keep
  394.  * the hostname here. The letter S and the window id will be appended.
  395.  * A saved utmp entry in wi->w_savut serves as a template, usually.
  396.  */ 
  397.  
  398. int
  399. SetUtmp(wi)
  400. struct win *wi;
  401. {
  402.   register char *p;
  403.   register slot_t slot;
  404. # ifndef _SEQUENT_
  405.   char *line;
  406. # endif
  407.   struct utmp u;
  408.   int saved_ut;
  409. # ifdef UTHOST
  410. #  ifdef _SEQUENT_
  411.   char host[100+5];
  412. #  else /* _SEQUENT_ */
  413.   char host[sizeof(d_utmp_logintty.ut_host)+5];
  414. #  endif /* _SEQUENT_ */
  415. # endif /* UTHOST */
  416.  
  417.   wi->w_slot = (slot_t) 0;
  418.   if (!utmpok)
  419.     return -1;
  420.   if ((slot = TtyNameSlot(wi->w_tty)) == (slot_t) NULL)
  421.     {
  422.       debug1("SetUtmp failed (tty %s).\n",wi->w_tty);
  423.       return -1;
  424.     }
  425.   debug2("SetUtmp %d will get slot %d...\n", wi->w_number, (int)slot);
  426. # ifdef UTNOKEEP
  427.   /* open here, as TtyNameSlot used (and closed) our filedescriptor */
  428.   InitUtmp();
  429. # endif /* UTNOKEEP */
  430.  
  431.   bzero((char *) &u, sizeof u);
  432.   if ((saved_ut = bcmp((char *) &wi->w_savut, (char *) &u, sizeof u)))
  433.     /* restore original, of which we will adopt all fields but ut_host */
  434.     bcopy((char *) &wi->w_savut, (char *) &u, sizeof u);
  435.  
  436. # ifdef UTHOST
  437.   host[sizeof(host)-5] = '\0';
  438.   if (display)
  439.     {
  440. #  ifdef _SEQUENT_
  441.       strncpy(host, d_loginhost, sizeof(host) - 5);
  442. #  else /* _SEQUENT */
  443.       strncpy(host, d_utmp_logintty.ut_host, sizeof(host) - 5);
  444. #  endif /* _SEQUENT */
  445.       if (d_loginslot != (slot_t)0 && d_loginslot != (slot_t)-1 && host[0] != '\0')
  446.     {
  447.       /*
  448.        * we want to set our ut_host field to something like
  449.        * ":ttyhf:s.0" or
  450.        * "faui45:s.0" or
  451.        * "132.199.81.4:s.0" (even this may hurt..), but not
  452.        * "faui45.informati"......:s.0
  453.        */
  454.       for (p = host; *p; p++)
  455.         if ((*p < '0' || *p > '9') && (*p != '.'))
  456.           break;
  457.       if (*p)
  458.         {
  459.           for (p = host; *p; p++)
  460.         if (*p == '.')
  461.           {
  462.             *p = '\0';
  463.             break;
  464.           }
  465.         }
  466.     }
  467.       else
  468.     {
  469.       strncpy(host + 1, stripdev(d_usertty), sizeof(host) - 6);
  470.       host[0] = ':';
  471.     }
  472.     }
  473.   else
  474.     strncpy(host, "local", sizeof(host) - 5);
  475.   sprintf(host + strlen(host), ":S.%c", '0' + wi->w_number);
  476.   debug1("rlogin hostname: '%s'\n", host);
  477. #  if !defined(_SEQUENT_) && !defined(sequent)
  478.   strncpy(u.ut_host, host, sizeof(u.ut_host));
  479. #  endif
  480. # endif /* UTHOST */
  481.  
  482. # ifdef _SEQUENT_
  483.   if (ut_add_user(saved_ut ? u.ut_user : LoginName, slot, saved_ut ? u.ut_pid : wi->w_pid, host) == 0)
  484. # else /* _SEQUENT_ */
  485.   if (!saved_ut)
  486.     { /* make new utmp from scratch */
  487.       line = stripdev(wi->w_tty);
  488. #  ifdef GETUTENT
  489.       strncpy(u.ut_user, LoginName, sizeof(u.ut_user));
  490. #   ifdef sgi
  491.       strncpy(u.ut_id, line + 3, sizeof(u.ut_id));
  492. #   else /* sgi */
  493.       strncpy(u.ut_id, line + strlen(line) - 2, sizeof(u.ut_id));
  494. #   endif /* sgi */
  495.       strncpy(u.ut_line, line, sizeof(u.ut_line));
  496.       u.ut_pid = wi->w_pid;
  497.       u.ut_type = USER_PROCESS;
  498.       (void) time((time_t *)&u.ut_time);
  499.     } /* !saved_ut {-: */
  500.   setutent();
  501.   if (pututline(&u) == 0)
  502. #  else    /* GETUTENT */
  503.       strncpy(u.ut_line, line, sizeof(u.ut_line));
  504.       strncpy(u.ut_name, LoginName, sizeof(u.ut_name));
  505. #   if defined(linux)    /* should have GETUTENT */
  506.       u.ut_type = USER_PROCESS;
  507.       u.ut_pid = wi->w_pid;
  508.       strncpy(u.ut_id, line + 3, sizeof(u.ut_id));
  509. #   endif /* linux */
  510.       (void) time((time_t *)&u.ut_time); /* cast needed for ultrix */
  511.     } /* !saved_ut */
  512. #   ifdef sequent
  513.   /*
  514.    * call sequent undocumented routine to count logins and 
  515.    * add utmp entry if possible 
  516.    */
  517.   if (add_utmp(slot, &u) == -1)
  518. #   else /* sequent */
  519.   (void) lseek(utmpfd, (off_t) (slot * sizeof u), 0);
  520.   if (write(utmpfd, (char *) &u, sizeof u) != sizeof u)
  521. #   endif /* sequent */
  522. #  endif /* GETUTENT */
  523. # endif /* _SEQUENT_ */
  524.  
  525.     {
  526. # ifdef NETHACK
  527.       if (nethackflag)
  528.         Msg(errno, "%s is too hard to dig in", UTMPFILE);
  529.       else
  530. # endif /* NETHACK */
  531.       Msg(errno,"Could not write %s", UTMPFILE);
  532. # ifdef UTNOKEEP
  533.       close(utmpfd);
  534. # endif /* UTNOKEEP */
  535.       return -1;
  536.     }
  537.   debug("SetUtmp successful\n");
  538.   wi->w_slot = slot;
  539. # ifdef UTNOKEEP
  540.   close(utmpfd);
  541. # endif /* UTNOKEEP */
  542.   bcopy((char *) &u, (char *) &wi->w_savut, sizeof u);
  543.   return 0;
  544. }
  545.  
  546.  
  547.  
  548. /*
  549.  * if slot could be removed or was 0,  wi->w_slot = -1;
  550.  * else not changed.
  551.  */
  552.  
  553. int
  554. RemoveUtmp(wi)
  555. struct win *wi;
  556. {
  557. # ifdef GETUTENT
  558.   struct utmp *uu;
  559. # endif /* GETUTENT */
  560.   struct utmp u;
  561.   slot_t slot;
  562.  
  563.   slot = wi->w_slot;
  564. # ifdef GETUTENT
  565.   debug1("RemoveUtmp(%s)\n", (slot == (slot_t) 0) ?
  566.          "no slot (0)":((slot == (slot_t) -1) ? "no slot (-1)" : slot));
  567. # else /* GETUTENT */
  568.   debug1("RemoveUtmp(wi.slot: %d)\n", slot);
  569. # endif /* GETUTENT */
  570. # ifdef UTNOKEEP
  571.   InitUtmp();
  572. # endif /* UTNOKEEP */
  573.   if (!utmpok)
  574.     return -1;
  575.   if (slot == (slot_t) 0 || slot == (slot_t) -1)
  576.     {
  577.       debug1("There is no utmp-slot to be removed(%d)\n", (int)slot);
  578.       wi->w_slot = (slot_t) -1;
  579.       return 0;
  580.     }
  581.   bzero((char *) &u, sizeof u);
  582. # ifdef GETUTENT
  583.   setutent();
  584. #  ifdef sgi
  585.   bcopy((char *) &wi->w_savut, (char *) &u, sizeof u);
  586.   uu  = &u;
  587. #  else
  588.   strncpy(u.ut_line, slot, sizeof(u.ut_line));
  589.   if ((uu = getutline(&u)) == 0)
  590.     {
  591.       Msg(0, "Utmp slot not found -> not removed");
  592.       return -1;
  593.     }
  594.   bcopy((char *)uu, (char *)&wi->w_savut, sizeof(wi->w_savut));
  595. #  endif
  596. #  ifdef _SEQUENT_
  597.   if (ut_delete_user(slot, uu->ut_pid, 0, 0) == 0)
  598. #  else /* _SEQUENT_ */
  599.   u = *uu;
  600.   u.ut_type = DEAD_PROCESS;
  601.   u.ut_exit.e_termination = 0;
  602.   u.ut_exit.e_exit= 0;
  603.   if (pututline(&u) == 0)
  604. #  endif /* _SEQUENT_ */
  605. # else /* GETUTENT */
  606.   (void) lseek(utmpfd, (off_t) (slot * sizeof(u)), 0);
  607.   if (read(utmpfd, (char *) &wi->w_savut, sizeof(wi->w_savut)) != sizeof u)
  608.     {
  609.       bzero((char *)&wi->w_savut, sizeof(wi->w_savut));
  610.       Msg(errno, "cannot read %s?", UTMPFILE);
  611.       sleep(1);
  612.     }
  613.   (void) lseek(utmpfd, (off_t) (slot * sizeof(u)), 0);
  614. #  ifdef UTNOKEEP
  615.   bcopy((char *)&wi->w_savut, (char *)&u, sizeof(u));
  616.   bzero(u.ut_name, sizeof(u.ut_name));
  617.   bzero(u.ut_host, sizeof(u.ut_host));
  618. #  endif /* UTNOKEEP */
  619.   if (write(utmpfd, (char *) &u, sizeof(u)) != sizeof(u))
  620. # endif /* GETUTENT */
  621.     {
  622. # ifdef NETHACK
  623.       if (nethackflag)
  624.         Msg(errno, "%s is too hard to dig in", UTMPFILE);
  625.       else
  626. # endif /* NETHACK */
  627.       Msg(errno,"Could not write %s", UTMPFILE);
  628. # ifdef UTNOKEEP
  629.       close(utmpfd);
  630. # endif /* UTNOKEEP */
  631.       return -1;
  632.     }
  633.   debug("RemoveUtmp successfull\n");
  634.   wi->w_slot = (slot_t) -1;
  635. # ifdef UTNOKEEP
  636.   close(utmpfd);
  637. # endif /* UTNOKEEP */
  638.   return 0;
  639. }
  640.  
  641.  
  642.  
  643. /*
  644.  * TtyNameSlot:
  645.  * return an index, where the named tty is found in utmp.
  646.  */
  647.  
  648. static slot_t 
  649. TtyNameSlot(nam)
  650. char *nam;
  651. {
  652.   char *name;
  653.   register slot_t slot;
  654. # ifdef UTNOKEEP
  655.   struct utmp u;
  656. # else
  657. #  ifndef GETUTENT
  658.   register struct ttyent *tp;
  659. #  endif /* GETUTENT */
  660. # endif /* UTNOKEEP */
  661.  
  662.   debug1("TtyNameSlot(%s)\n", nam);
  663. # ifdef UTNOKEEP
  664.   InitUtmp();
  665. # endif /* UTNOKEEP */
  666.   if (!utmpok || nam == NULL)
  667.     return (slot_t)0;
  668.   name = stripdev(nam);
  669. # ifdef GETUTENT
  670.   slot = name;
  671. # else /* GETUTENT */
  672. #  ifdef UTNOKEEP
  673.   slot = 0;
  674.   while ((read(utmpfd, (char *)&u, sizeof(u)) == sizeof(u))
  675.          && (strcmp(u.ut_line, name)))
  676.     slot++;
  677.   close(utmpfd);
  678. #  else /* UTNOKEEP */
  679.   slot = 1;
  680.   setttyent();
  681.   while ((tp = getttyent()) != NULL && strcmp(name, tp->ty_name) != 0)
  682.     slot++;
  683. #  endif /* UTNOKEEP */
  684. # endif /* GETUTENT */
  685.   return slot;
  686. }
  687.  
  688.  
  689.  
  690. # if !defined(GETTTYENT) && !defined(GETUTENT) && !defined(UTNOKEEP)
  691.  
  692. static void
  693. setttyent()
  694. {
  695.   struct stat s;
  696.   register int f;
  697.   register char *p, *ep;
  698.  
  699.   if (ttnext)
  700.     {
  701.       ttnext = tt;
  702.       return;
  703.     }
  704.   if ((f = open(ttys, O_RDONLY)) == -1 || fstat(f, &s) == -1)
  705.     Panic(errno, ttys);
  706.   if ((tt = malloc((unsigned) s.st_size + 1)) == 0)
  707.     Panic(0, strnomem);
  708.   if (read(f, tt, s.st_size) != s.st_size)
  709.     Panic(errno, ttys);
  710.   close(f);
  711.   for (p = tt, ep = p + s.st_size; p < ep; ++p)
  712.     if (*p == '\n')
  713.       *p = '\0';
  714.   *p = '\0';
  715.   ttnext = tt;
  716. }
  717.  
  718. static struct ttyent *
  719. getttyent()
  720. {
  721.   static struct ttyent t;
  722.  
  723.   if (*ttnext == '\0')
  724.     return NULL;
  725.   t.ty_name = ttnext + 2;
  726.   ttnext += strlen(ttnext) + 1;
  727.   return &t;
  728. }
  729.  
  730. # endif    /* !GETTTYENT && !GETUTENT && !UTNOKEEP */
  731.  
  732.  
  733. #endif /* UTMPOK */
  734.  
  735.  
  736.  
  737. /*********************************************************************
  738.  *
  739.  *  getlogin() replacement (for SVR4 machines)
  740.  */
  741.  
  742. # if defined(BUGGYGETLOGIN)
  743. char *
  744. getlogin()
  745. {
  746.   char *tty;
  747. #ifdef utmp
  748. # undef utmp
  749. #endif
  750.   struct utmp u;
  751.   static char retbuf[sizeof(u.ut_user)+1];
  752.   int fd;
  753.  
  754.   for (fd = 0; fd <= 2 && (tty = ttyname(fd)) == NULL; fd++)
  755.     ;
  756.   if ((tty == NULL) || ((fd = open(UTMP_FILE, O_RDONLY)) < 0))
  757.     return NULL;
  758.   tty = stripdev(tty);
  759.   retbuf[0] = '\0';
  760.   while (read(fd, (char *)&u, sizeof(struct utmp)) == sizeof(struct utmp))
  761.     {
  762.       if (!strncmp(tty, u.ut_line, sizeof(u.ut_line)))
  763.     {
  764.       strncpy(retbuf, u.ut_user, sizeof(u.ut_user));
  765.       retbuf[sizeof(u.ut_user)] = '\0';
  766.       if (u.ut_type == USER_PROCESS)
  767.         break;
  768.     }
  769.     }
  770.   close(fd);
  771.  
  772.   return *retbuf ? retbuf : NULL;
  773. }
  774. # endif /* BUGGYGETLOGIN */
  775.  
  776.