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 (bool picky)
79 pid_t pid = getpid ();
83 /* First, try to find a valid utmp entry for this process. */
84 while ((ut = getutent ()) != NULL)
85 if ( (ut->ut_pid == pid)
86 && ('\0' != ut->ut_line[0])
87 && ('\0' != ut->ut_id[0])
88 && ( (LOGIN_PROCESS == ut->ut_type)
89 || (USER_PROCESS == ut->ut_type))) {
93 /* If there is one, just use it, otherwise create a new one. */
98 (void) puts (NO_UTENT);
103 (void) puts (NO_TTY);
106 if (strncmp (line, "/dev/", 5) == 0) {
109 memset ((void *) &utent, 0, sizeof utent);
110 utent.ut_type = LOGIN_PROCESS;
112 strncpy (utent.ut_line, line, sizeof utent.ut_line);
113 /* XXX - assumes /dev/tty?? */
114 strncpy (utent.ut_id, utent.ut_line + 3, sizeof utent.ut_id);
115 strcpy (utent.ut_user, "LOGIN");
116 utent.ut_time = time (NULL);
120 #elif defined(LOGIN_PROCESS)
122 void checkutmp (bool picky)
130 pid_t pid = getpid ();
139 while ((utx = getutxent ()) != NULL) {
140 if (utx->ut_pid == pid) {
149 while ((ut = getutent ()) != NULL) {
150 if (ut->ut_pid == pid) {
165 (void) puts (NO_UTENT);
171 * If there is no ut_line value in this record, fill
172 * it in by getting the TTY name and stuffing it in
173 * the structure. The UNIX/PC is broken in this regard
177 if (utent.ut_line[0] == '\0')
182 (void) puts (NO_TTY);
185 if (strncmp (line, "/dev/", 5) == 0) {
188 strncpy (utent.ut_line, line, sizeof utent.ut_line);
190 strncpy (utxent.ut_line, line, sizeof utxent.ut_line);
196 (void) puts (NO_TTY);
199 if (strncmp (line, "/dev/", 5) == 0) {
203 strncpy (utent.ut_line, line, sizeof utent.ut_line);
204 ut = getutline (&utent);
206 strncpy (utent.ut_id, ut->ut_id, sizeof ut->ut_id);
209 strcpy (utent.ut_user, "LOGIN");
210 utent.ut_pid = getpid ();
211 utent.ut_type = LOGIN_PROCESS;
212 utent.ut_time = time (NULL);
214 strncpy (utxent.ut_line, line, sizeof utxent.ut_line);
215 utx = getutxline (&utxent);
217 strncpy (utxent.ut_id, utx->ut_id, sizeof utxent.ut_id);
220 strcpy (utxent.ut_user, "LOGIN");
221 utxent.ut_pid = utent.ut_pid;
222 utxent.ut_type = utent.ut_type;
223 if (sizeof (utxent.ut_tv) == sizeof (struct timeval)) {
224 gettimeofday ((struct timeval *) &utxent.ut_tv, NULL);
228 gettimeofday (&tv, NULL);
229 utxent.ut_tv.tv_sec = tv.tv_sec;
230 utxent.ut_tv.tv_usec = tv.tv_usec;
232 utent.ut_time = utxent.ut_tv.tv_sec;
241 * Some systems already have updwtmp() and possibly updwtmpx(). Others
242 * don't, so we re-implement these functions if necessary. --marekm
246 static void updwtmp (const char *filename, const struct utmp *ut)
250 fd = open (filename, O_APPEND | O_WRONLY, 0);
252 write (fd, (const char *) ut, sizeof (*ut));
256 #endif /* ! HAVE_UPDWTMP */
259 #ifndef HAVE_UPDWTMPX
260 static void updwtmpx (const char *filename, const struct utmpx *utx)
264 fd = open (filename, O_APPEND | O_WRONLY, 0);
266 write (fd, (const char *) utx, sizeof (*utx));
270 #endif /* ! HAVE_UPDWTMPX */
271 #endif /* ! HAVE_UTMPX_H */
275 * setutmp - put a USER_PROCESS entry in the utmp file
277 * setutmp changes the type of the current utmp entry to
278 * USER_PROCESS. the wtmp file will be updated as well.
281 #if defined(__linux__) /* XXX */
283 int setutmp (const char *name, const char unused(*line), const char unused(*host))
286 utent.ut_type = USER_PROCESS;
287 strncpy (utent.ut_user, name, sizeof utent.ut_user);
288 utent.ut_time = time (NULL);
289 /* other fields already filled in by checkutmp above */
291 if (pututline (&utent) == NULL) {
295 updwtmp (_WTMP_FILE, &utent);
302 int setutmp (const char *name, const char *line, const char *host)
304 struct utmp *utmp, utline;
305 struct utmpx *utmpx, utxline;
306 pid_t pid = getpid ();
307 bool found_utmpx = false;
308 bool found_utmp = false;
312 * The canonical device name doesn't include "/dev/"; skip it
313 * if it is already there.
316 if (strncmp (line, "/dev/", 5) == 0) {
321 * Update utmpx. We create an empty entry in case there is
322 * no matching entry in the utmpx file.
328 while ((utmpx = getutxent ()) != NULL) {
329 if (utmpx->ut_pid == pid) {
334 while ((utmp = getutent ()) != NULL) {
335 if (utmp->ut_pid == pid) {
342 * If the entry matching `pid' cannot be found, create a new
343 * entry with the device name in it.
347 memset ((void *) &utxline, 0, sizeof utxline);
348 strncpy (utxline.ut_line, line, sizeof utxline.ut_line);
349 utxline.ut_pid = getpid ();
352 if (strncmp (utxline.ut_line, "/dev/", 5) == 0) {
353 memmove (utxline.ut_line, utxline.ut_line + 5,
354 sizeof utxline.ut_line - 5);
355 utxline.ut_line[sizeof utxline.ut_line - 5] = '\0';
359 memset ((void *) &utline, 0, sizeof utline);
360 strncpy (utline.ut_line, utxline.ut_line,
361 sizeof utline.ut_line);
362 utline.ut_pid = utxline.ut_pid;
365 if (strncmp (utline.ut_line, "/dev/", 5) == 0) {
366 memmove (utline.ut_line, utline.ut_line + 5,
367 sizeof utline.ut_line - 5);
368 utline.ut_line[sizeof utline.ut_line - 5] = '\0';
373 * Fill in the fields in the utmpx entry and write it out. Do
374 * the utmp entry at the same time to make sure things don't
378 strncpy (utxline.ut_user, name, sizeof utxline.ut_user);
379 strncpy (utline.ut_user, name, sizeof utline.ut_user);
381 utline.ut_type = utxline.ut_type = USER_PROCESS;
383 if (sizeof (utxline.ut_tv) == sizeof (struct timeval)) {
384 gettimeofday ((struct timeval *) &utxline.ut_tv, NULL);
388 gettimeofday (&tv, NULL);
389 utxline.ut_tv.tv_sec = tv.tv_sec;
390 utxline.ut_tv.tv_usec = tv.tv_usec;
392 utline.ut_time = utxline.ut_tv.tv_sec;
394 strncpy (utxline.ut_host, (NULL != host) ? host : "",
395 sizeof utxline.ut_host);
397 if ( (pututxline (&utxline) == NULL)
398 || (pututline (&utline) == NULL)) {
402 updwtmpx (_WTMP_FILE "x", &utxline);
403 updwtmp (_WTMP_FILE, &utline);