5 * Author: Tatu Ylonen <ylo@cs.hut.fi>
7 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
10 * Created: Fri Mar 24 14:51:08 1995 ylo
12 * This file performs some of the things login(1) normally does. We cannot
13 * easily use something like login -p -h host -f user, because there are
14 * several different logins around, and it is hard to determined what kind of
15 * login the current system has. Also, we want to be able to execute commands
23 #if defined(HAVE_UTMPX_H) && defined(USE_UTMPX)
42 * Returns the time when the user last logged in. Returns 0 if the
43 * information is not available. This must be called before record_login.
44 * The host the user logged in from will be returned in buf.
48 * Returns the time when the user last logged in (or 0 if no previous login
49 * is found). The name of the host used last time is returned in buf.
53 get_last_login_time(uid_t uid, const char *logname,
54 char *buf, unsigned int bufsize)
56 #if defined(_PATH_LASTLOG) && !defined(DISABLE_LASTLOG)
61 lastlog = _PATH_LASTLOG;
64 fd = open(lastlog, O_RDONLY);
67 lseek(fd, (off_t) ((long) uid * sizeof(ll)), SEEK_SET);
68 if (read(fd, &ll, sizeof(ll)) != sizeof(ll)) {
73 if (bufsize > sizeof(ll.ll_host) + 1)
74 bufsize = sizeof(ll.ll_host) + 1;
75 strncpy(buf, ll.ll_host, bufsize - 1);
79 #else /* defined(_PATH_LASTLOG) && !defined(DISABLE_LASTLOG) */
80 /* Look in wtmp for the last login */
82 char *wt_file = _PATH_WTMP;
86 if ( (fd1 = open(wt_file, O_RDONLY)) < 0 ) {
87 error("Couldn't open %.100s to find last login time.", wt_file);
91 /* seek to last record of file */
92 lseek(fd1, (off_t)(0-sizeof(struct utmp)), SEEK_END);
94 /* loop through wtmp for our last user login record */
96 if (read(fd1, &wt, sizeof(wt)) != sizeof(wt)) {
101 if ( wt.ut_type == USER_PROCESS) {
102 if ( !strncmp(logname, wt.ut_user, 8) ) {
103 t = (unsigned long) wt.ut_time;
104 #ifdef HAVE_HOST_IN_UTMP
105 if (bufsize > sizeof(wt.ut_host) + 1)
106 bufsize = sizeof(wt.ut_host) + 1;
107 strncpy(buf, wt.ut_host, bufsize - 1);
108 buf[bufsize - 1] = 0;
109 #else /* HAVE_HOST_IN_UTMP */
111 #endif /* HAVE_HOST_IN_UTMP */
115 if (lseek(fd1, (off_t)(0-2*sizeof(struct utmp)), SEEK_CUR) == -1)
120 #endif /* defined(_PATH_LASTLOG) && !defined(DISABLE_LASTLOG) */
124 * Records that the user has logged in. I these parts of operating systems
125 * were more standardized.
129 record_login(int pid, const char *ttyname, const char *user, uid_t uid,
130 const char *host, struct sockaddr_in * addr)
132 #if defined(_PATH_LASTLOG) && !defined(DISABLE_LASTLOG)
135 #endif /* defined(_PATH_LASTLOG) && !defined(DISABLE_LASTLOG) */
137 #if defined(HAVE_UTMPX_H) && defined(USE_UTMPX)
141 /* Construct an utmp/wtmp entry. */
142 memset(&u, 0, sizeof(u));
143 strncpy(u.ut_line, ttyname + 5, sizeof(u.ut_line));
144 #if defined(HAVE_ID_IN_UTMP)
145 strncpy(u.ut_id, ttyname + 8, sizeof(u.ut_id));
146 #endif /* defined(HAVE_ID_IN_UTMP) */
147 strncpy(u.ut_name, user, sizeof(u.ut_name));
148 #if defined(HAVE_TV_IN_UTMP)
149 (void)gettimeofday(&u.ut_tv, NULL);
150 #else /* defined(HAVE_TV_IN_UTMP) */
151 u.ut_time = time(NULL);
152 #endif /* defined(HAVE_TV_IN_UTMP) */
153 #if defined(HAVE_PID_IN_UTMP)
154 u.ut_pid = (pid_t)pid;
155 #endif /* HAVE_PID_IN_UTMP */
156 #if defined(HAVE_TYPE_IN_UTMP)
157 u.ut_type = (uid == -1)?DEAD_PROCESS:USER_PROCESS;
158 #endif /* HAVE_TYPE_IN_UTMP */
159 #if defined(HAVE_HOST_IN_UTMP)
160 strncpy(u.ut_host, host, sizeof(u.ut_host));
163 #if defined(HAVE_UTMPX_H) && defined(USE_UTMPX)
164 memset(&utx, 0, sizeof(utx));
165 strncpy(utx.ut_user, user, sizeof(utx.ut_name));
166 strncpy(utx.ut_line, ttyname + 5, sizeof(utx.ut_line));
167 strncpy(utx.ut_id, ttyname + 8, sizeof(utx.ut_id));
168 utx.ut_pid = (pid_t)pid;
169 (void)gettimeofday(&utx.ut_tv, NULL);
170 utx.ut_type = (uid == -1)?DEAD_PROCESS:USER_PROCESS;
171 # ifdef HAVE_HOST_IN_UTMPX
172 # ifdef HAVE_SYSLEN_IN_UTMPX
173 utx.ut_syslen = strlen(host);
174 strncpy(utx.ut_host, host, utx.ut_syslen);
176 strncpy(utx.ut_host, host, sizeof(utx.ut_host));
177 # endif /* HAVE_SYSLEN_IN_UTMPX */
179 #endif /* defined(HAVE_UTMPX_H) && defined(USE_UTMPX) */
181 /*#if defined(HAVE_UTMPX_H) && defined(USE_UTMPX) && !defined(HAVE_LOGIN)*/
182 #if defined(HAVE_UTMPX_H) && defined(USE_UTMPX)
184 #else /* defined(HAVE_UTMPX_H) && defined(USE_UTMPX) */
186 #endif /* defined(HAVE_UTMPX_H) && defined(USE_UTMPX) */
188 #if defined(_PATH_LASTLOG) && !defined(DISABLE_LASTLOG)
189 lastlog = _PATH_LASTLOG;
191 /* Update lastlog unless actually recording a logout. */
192 if (strcmp(user, "") != 0) {
195 * It is safer to bzero the lastlog structure first because
196 * some systems might have some extra fields in it (e.g. SGI)
198 memset(&ll, 0, sizeof(ll));
200 /* Update lastlog. */
201 ll.ll_time = time(NULL);
202 strncpy(ll.ll_line, ttyname + 5, sizeof(ll.ll_line));
203 strncpy(ll.ll_host, host, sizeof(ll.ll_host));
204 fd = open(lastlog, O_RDWR);
206 lseek(fd, (off_t) ((long) uid * sizeof(ll)), SEEK_SET);
207 if (write(fd, &ll, sizeof(ll)) != sizeof(ll))
208 log("Could not write %.100s: %.100s", lastlog, strerror(errno));
212 #endif /* defined(_PATH_LASTLOG) && !defined(DISABLE_LASTLOG) */
215 /* Records that the user has logged out. */
218 record_logout(int pid, const char *ttyname)
220 #ifdef HAVE_LIBUTIL_LOGIN
221 const char *line = ttyname + 5; /* /dev/ttyq8 -> ttyq8 */
223 logwtmp(line, "", "");
224 #else /* HAVE_LIBUTIL_LOGIN */
225 record_login(pid, ttyname, "", -1, "", NULL);
226 #endif /* HAVE_LIBUTIL_LOGIN */