2 * Copyright (c) 1989 - 1994, Julianne Frances Haugh
3 * Copyright (c) 1996 - 1999, Marek Michałkiewicz
4 * Copyright (c) 2001 - 2005, Tomasz Kłoczko
5 * Copyright (c) 2008 , Nicolas François
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. The name of the copyright holders or contributors may not be used to
17 * endorse or promote products derived from this software without
18 * specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
23 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 #include "prototypes.h"
55 _("No utmp entry. You must exec \"login\" from the lowest level \"sh\"")
57 _("Unable to determine your tty name.")
60 * checkutmp - see if utmp file is correct for this process
62 * System V is very picky about the contents of the utmp file
63 * and requires that a slot for the current process exist.
64 * The utmp file is scanned for an entry with the same process
65 * ID. If no entry exists the process exits with a message.
67 * The "picky" flag is for network and other logins that may
68 * use special flags. It allows the pid checks to be overridden.
69 * This means that getty should never invoke login with any
73 #if defined(__linux__) /* XXX */
75 void checkutmp (int picky)
79 pid_t pid = getpid ();
83 /* First, try to find a valid utmp entry for this process. */
84 while ((ut = getutent ()))
85 if (ut->ut_pid == pid && ut->ut_line[0] && ut->ut_id[0] &&
86 (ut->ut_type == LOGIN_PROCESS
87 || ut->ut_type == USER_PROCESS))
90 /* If there is one, just use it, otherwise create a new one. */
103 if (strncmp (line, "/dev/", 5) == 0)
105 memset ((void *) &utent, 0, sizeof utent);
106 utent.ut_type = LOGIN_PROCESS;
108 strncpy (utent.ut_line, line, sizeof utent.ut_line);
109 /* XXX - assumes /dev/tty?? */
110 strncpy (utent.ut_id, utent.ut_line + 3, sizeof utent.ut_id);
111 strcpy (utent.ut_user, "LOGIN");
112 utent.ut_time = time (NULL);
116 #elif defined(LOGIN_PROCESS)
118 void checkutmp (bool picky)
126 pid_t pid = getpid ();
135 while ((utx = getutxent ()))
136 if (utx->ut_pid == pid)
142 while ((ut = getutent ()))
143 if (ut->ut_pid == pid)
161 * If there is no ut_line value in this record, fill
162 * it in by getting the TTY name and stuffing it in
163 * the structure. The UNIX/PC is broken in this regard
167 if (utent.ut_line[0] == '\0')
170 if (!(line = ttyname (0))) {
174 if (strncmp (line, "/dev/", 5) == 0)
176 strncpy (utent.ut_line, line, sizeof utent.ut_line);
178 strncpy (utxent.ut_line, line, sizeof utxent.ut_line);
182 if (!(line = ttyname (0))) {
186 if (strncmp (line, "/dev/", 5) == 0)
189 strncpy (utent.ut_line, line, sizeof utent.ut_line);
190 if ((ut = getutline (&utent)))
191 strncpy (utent.ut_id, ut->ut_id, sizeof ut->ut_id);
193 strcpy (utent.ut_user, "LOGIN");
194 utent.ut_pid = getpid ();
195 utent.ut_type = LOGIN_PROCESS;
196 utent.ut_time = time (NULL);
198 strncpy (utxent.ut_line, line, sizeof utxent.ut_line);
199 if ((utx = getutxline (&utxent)))
200 strncpy (utxent.ut_id, utx->ut_id, sizeof utxent.ut_id);
202 strcpy (utxent.ut_user, "LOGIN");
203 utxent.ut_pid = utent.ut_pid;
204 utxent.ut_type = utent.ut_type;
205 if (sizeof (utxent.ut_tv) == sizeof (struct timeval))
206 gettimeofday ((struct timeval *) &utxent.ut_tv, NULL);
210 gettimeofday (&tv, NULL);
211 utxent.ut_tv.tv_sec = tv.tv_sec;
212 utxent.ut_tv.tv_usec = tv.tv_usec;
214 utent.ut_time = utxent.ut_tv.tv_sec;
223 * Some systems already have updwtmp() and possibly updwtmpx(). Others
224 * don't, so we re-implement these functions if necessary. --marekm
228 static void updwtmp (const char *filename, const struct utmp *ut)
232 fd = open (filename, O_APPEND | O_WRONLY, 0);
234 write (fd, (const char *) ut, sizeof (*ut));
238 #endif /* ! HAVE_UPDWTMP */
241 #ifndef HAVE_UPDWTMPX
242 static void updwtmpx (const char *filename, const struct utmpx *utx)
246 fd = open (filename, O_APPEND | O_WRONLY, 0);
248 write (fd, (const char *) utx, sizeof (*utx));
252 #endif /* ! HAVE_UPDWTMPX */
253 #endif /* ! HAVE_UTMPX_H */
257 * setutmp - put a USER_PROCESS entry in the utmp file
259 * setutmp changes the type of the current utmp entry to
260 * USER_PROCESS. the wtmp file will be updated as well.
263 #if defined(__linux__) /* XXX */
265 void setutmp (const char *name, const char *line, const char *host)
267 utent.ut_type = USER_PROCESS;
268 strncpy (utent.ut_user, name, sizeof utent.ut_user);
269 utent.ut_time = time (NULL);
270 /* other fields already filled in by checkutmp above */
274 updwtmp (_WTMP_FILE, &utent);
279 void setutmp (const char *name, const char *line, const char *host)
281 struct utmp *utmp, utline;
282 struct utmpx *utmpx, utxline;
283 pid_t pid = getpid ();
284 bool found_utmpx = false, found_utmp = false;
287 * The canonical device name doesn't include "/dev/"; skip it
288 * if it is already there.
291 if (strncmp (line, "/dev/", 5) == 0)
295 * Update utmpx. We create an empty entry in case there is
296 * no matching entry in the utmpx file.
302 while (utmpx = getutxent ()) {
303 if (utmpx->ut_pid == pid) {
308 while (utmp = getutent ()) {
309 if (utmp->ut_pid == pid) {
316 * If the entry matching `pid' cannot be found, create a new
317 * entry with the device name in it.
321 memset ((void *) &utxline, 0, sizeof utxline);
322 strncpy (utxline.ut_line, line, sizeof utxline.ut_line);
323 utxline.ut_pid = getpid ();
326 if (strncmp (utxline.ut_line, "/dev/", 5) == 0) {
327 memmove (utxline.ut_line, utxline.ut_line + 5,
328 sizeof utxline.ut_line - 5);
329 utxline.ut_line[sizeof utxline.ut_line - 5] = '\0';
333 memset ((void *) &utline, 0, sizeof utline);
334 strncpy (utline.ut_line, utxline.ut_line,
335 sizeof utline.ut_line);
336 utline.ut_pid = utxline.ut_pid;
339 if (strncmp (utline.ut_line, "/dev/", 5) == 0) {
340 memmove (utline.ut_line, utline.ut_line + 5,
341 sizeof utline.ut_line - 5);
342 utline.ut_line[sizeof utline.ut_line - 5] = '\0';
347 * Fill in the fields in the utmpx entry and write it out. Do
348 * the utmp entry at the same time to make sure things don't
352 strncpy (utxline.ut_user, name, sizeof utxline.ut_user);
353 strncpy (utline.ut_user, name, sizeof utline.ut_user);
355 utline.ut_type = utxline.ut_type = USER_PROCESS;
357 if (sizeof (utxline.ut_tv) == sizeof (struct timeval))
358 gettimeofday ((struct timeval *) &utxline.ut_tv, NULL);
362 gettimeofday (&tv, NULL);
363 utxline.ut_tv.tv_sec = tv.tv_sec;
364 utxline.ut_tv.tv_usec = tv.tv_usec;
366 utline.ut_time = utxline.ut_tv.tv_sec;
368 strncpy (utxline.ut_host, host ? host : "", sizeof utxline.ut_host);
370 pututxline (&utxline);
372 /* TODO: log failures */
374 updwtmpx (_WTMP_FILE "x", &utxline);
375 updwtmp (_WTMP_FILE, &utline);