Use `updwtmp' function insteead of writing the record ourself.
[kopensolaris-gnu/glibc.git] / login / login.c
1 /* Copyright (C) 1996 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
4
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Library General Public License as
7    published by the Free Software Foundation; either version 2 of the
8    License, or (at your option) any later version.
9
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Library General Public License for more details.
14
15    You should have received a copy of the GNU Library General Public
16    License along with the GNU C Library; see the file COPYING.LIB.  If not,
17    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18    Boston, MA 02111-1307, USA.  */
19
20 #include <errno.h>
21 #include <limits.h>
22 #include <string.h>
23 #include <unistd.h>
24 #include <stdlib.h>
25 #include <utmp.h>
26
27 #ifndef _LIBC
28 #define __set_errno(val) errno = (val)
29 #endif
30
31 /* Return the result of ttyname in the buffer pointed to by TTY, which should
32    be of length BUF_LEN.  If it is too long to fit in this buffer, a
33    sufficiently long buffer is allocated using malloc, and returned in TTY.
34    0 is returned upon success, -1 otherwise.  */
35 static int
36 tty_name (int fd, char **tty, size_t buf_len)
37 {
38   int rv;                       /* Return value.  0 = success.  */
39   char *buf = *tty;             /* Buffer for ttyname, initially the user's. */
40
41   for (;;)
42     {
43       char *new_buf;
44
45       if (buf_len)
46         {
47           rv = ttyname_r (fd, buf, buf_len);
48
49           if (rv < 0 || memchr (buf, '\0', buf_len))
50             /* We either got an error, or we succeeded and the
51                returned name fit in the buffer.  */
52             break;
53
54           /* Try again with a longer buffer.  */
55           buf_len += buf_len;   /* Double it */
56         }
57       else
58         /* No initial buffer; start out by mallocing one.  */
59         buf_len = 128;          /* First time guess.  */
60
61       if (buf != *tty)
62         /* We've already malloced another buffer at least once.  */
63         new_buf = realloc (buf, buf_len);
64       else
65         new_buf = malloc (buf_len);
66       if (! new_buf)
67         {
68           rv = -1;
69           __set_errno (ENOMEM);
70           break;
71         }
72     }
73
74   if (rv == 0)
75     *tty = buf;         /* Return buffer to the user.  */
76   else if (buf != *tty)
77     free (buf);         /* Free what we malloced when returning an error.  */
78
79   return rv;
80 }
81 \f
82 void
83 login (const struct utmp *ut)
84 {
85 #ifdef PATH_MAX
86   char _tty[PATH_MAX + UT_LINESIZE];
87 #else
88   char _tty[512 + UT_LINESIZE];
89 #endif
90   char *tty = _tty;
91   int found_tty;
92   const char *ttyp;
93   struct utmp copy = *ut;
94   struct utmp utbuf;
95
96   /* Fill in those fields we supply.  */
97 #if _HAVE_UT_TYPE - 0
98   copy.ut_type = USER_PROCESS;
99 #endif
100 #if _HAVE_UT_PID - 0
101   copy.ut_pid = getpid ();
102 #endif
103
104   /* Seek tty.  */
105   found_tty = tty_name (STDIN_FILENO, &tty, sizeof (_tty));
106   if (found_tty < 0)
107     found_tty = tty_name (STDOUT_FILENO, &tty, sizeof (_tty));
108   if (found_tty < 0)
109     found_tty = tty_name (STDERR_FILENO, &tty, sizeof (_tty));
110
111   if (found_tty >= 0)
112     {
113       /* We only want to insert the name of the tty without path.  */
114       ttyp = basename (tty);
115
116       /* Position to record for this tty.  */
117       strncpy (copy.ut_line, ttyp, UT_LINESIZE);
118
119       /* Tell that we want to use the UTMP file.  */
120       if (utmpname (_PATH_UTMP) != 0)
121         {
122           struct utmp *old;
123
124           /* Open UTMP file.  */
125           setutent ();
126
127           /* Read the record.  */
128           getutline_r (&copy, &utbuf, &old);
129
130           /* Write the entry.  */
131           pututline (&copy);
132
133           /* Close UTMP file.  */
134           endutent ();
135         }
136
137       if (tty != _tty)
138         free (tty);             /* Free buffer malloced by tty_name.  */
139     }
140
141   /* Update the WTMP file.  Here we have to add a new entry.  */
142   updwtmp (_PATH_WTMP, &copy);
143 }