2 * utmp.c Routines to read/write the utmp and wtmp files.
3 * Basically just wrappers around the library routines.
5 * Version: @(#)utmp.c 2.77 09-Jun-1999 miquels@cistron.nl
7 * Copyright (C) 1999 Miquel van Smoorenburg.
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 #include <sys/types.h>
26 #include <sys/ioctl.h>
27 #include <sys/utsname.h>
42 #if defined(__GLIBC__)
43 # if (__GLIBC__ == 2) && (__GLIBC_MINOR__ == 0) && defined(__powerpc__)
44 # define HAVE_UPDWTMP 0
46 # define HAVE_UPDWTMP 1
49 # define HAVE_UPDWTMP 0
54 * Log an event in the wtmp file (reboot, runlevel)
57 char *user
, /* name of user */
58 char *id
, /* inittab ID */
59 int pid
, /* PID of process */
60 int type
, /* TYPE of entry */
61 char *line
) /* Which line is this */
65 struct utsname uname_buf
;
69 * Try to open the wtmp file. Note that we even try
70 * this if we have updwtmp() so we can see if the
71 * wtmp file is accessible.
73 if ((fd
= open(WTMP_FILE
, O_WRONLY
|O_APPEND
)) < 0) return;
77 * Note if we are going to write a boot record.
79 if (type
== BOOT_TIME
) wrote_wtmp_reboot
++;
82 * See if we need to write a reboot record. The reason that
83 * we are being so paranoid is that when we first tried to
84 * write the reboot record, /var was possibly not mounted
85 * yet. As soon as we can open WTMP we write a delayed boot record.
87 if (wrote_wtmp_reboot
== 0 && type
!= BOOT_TIME
)
88 write_wtmp("reboot", "~~", 0, BOOT_TIME
, "~");
92 * Zero the fields and enter new fields.
94 memset(&utmp
, 0, sizeof(utmp
));
95 #if defined(__GLIBC__)
96 gettimeofday(&tv
, NULL
);
97 utmp
.ut_tv
.tv_sec
= tv
.tv_sec
;
98 utmp
.ut_tv
.tv_usec
= tv
.tv_usec
;
104 strncpy(utmp
.ut_name
, user
, sizeof(utmp
.ut_name
));
105 strncpy(utmp
.ut_id
, id
, sizeof(utmp
.ut_id
));
106 strncpy(utmp
.ut_line
, line
, sizeof(utmp
.ut_line
));
108 /* Put the OS version in place of the hostname */
109 if (uname(&uname_buf
) == 0)
110 strncpy(utmp
.ut_host
, uname_buf
.release
, sizeof(utmp
.ut_host
));
113 updwtmp(WTMP_FILE
, &utmp
);
115 write(fd
, (char *)&utmp
, sizeof(utmp
));
121 * Write an entry to the UTMP file. For DEAD_PROCESS, put
122 * the previous ut_line into oldline if oldline != NULL.
124 static void write_utmp(
125 char *user
, /* name of user */
126 char *id
, /* inittab ID */
127 int pid
, /* PID of process */
128 int type
, /* TYPE of entry */
129 char *line
, /* LINE if used. */
130 char *oldline
) /* Line of old utmp entry. */
138 * Can't do much if UTMP_FILE is not present.
140 if (access(UTMP_FILE
, F_OK
) < 0)
145 * Note if we are going to write a boot record.
147 if (type
== BOOT_TIME
) wrote_utmp_reboot
++;
150 * See if we need to write a reboot record. The reason that
151 * we are being so paranoid is that when we first tried to
152 * write the reboot record, /var was possibly not mounted
153 * yet. As soon as we can open WTMP we write a delayed boot record.
155 if (wrote_utmp_reboot
== 0 && type
!= BOOT_TIME
)
156 write_utmp("reboot", "~~", 0, BOOT_TIME
, "~", NULL
);
160 * Fill out an utmp struct.
162 memset(&utmp
, 0, sizeof(utmp
));
165 strncpy(utmp
.ut_id
, id
, sizeof(utmp
.ut_id
));
166 #if defined(__GLIBC__)
167 gettimeofday(&tv
, NULL
);
168 utmp
.ut_tv
.tv_sec
= tv
.tv_sec
;
169 utmp
.ut_tv
.tv_usec
= tv
.tv_usec
;
173 strncpy(utmp
.ut_user
, user
, UT_NAMESIZE
);
174 if (line
) strncpy(utmp
.ut_line
, line
, UT_LINESIZE
);
177 * We might need to find the existing entry first, to
178 * find the tty of the process (for wtmp accounting).
180 if (type
== DEAD_PROCESS
) {
182 * Find existing entry for the tty line.
186 if ((utmptr
= getutid(&tmp
)) != NULL
) {
187 strncpy(utmp
.ut_line
, utmptr
->ut_line
, UT_LINESIZE
);
189 strncpy(oldline
, utmptr
->ut_line
, UT_LINESIZE
);
194 * Update existing utmp file.
202 * Write a record to both utmp and wtmp.
204 void write_utmp_wtmp(
205 char *user
, /* name of user */
206 char *id
, /* inittab ID */
207 int pid
, /* PID of process */
208 int type
, /* TYPE of entry */
209 char *line
) /* LINE if used. */
211 char oldline
[UT_LINESIZE
];
214 * For backwards compatibility we just return
215 * if user == NULL (means : clean up utmp file).
221 write_utmp(user
, id
, pid
, type
, line
, oldline
);
222 write_wtmp(user
, id
, pid
, type
, line
&& line
[0] ? line
: oldline
);