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
10 #include <sys/ioctl.h>
11 #include <sys/utsname.h>
26 #if defined(__GLIBC__)
27 # if (__GLIBC__ == 2) && (__GLIBC_MINOR__ == 0) && defined(__powerpc__)
28 # define HAVE_UPDWTMP 0
30 # define HAVE_UPDWTMP 1
33 # define HAVE_UPDWTMP 0
38 * Log an event in the wtmp file (reboot, runlevel)
41 char *user, /* name of user */
42 char *id, /* inittab ID */
43 int pid, /* PID of process */
44 int type, /* TYPE of entry */
45 char *line) /* Which line is this */
49 struct utsname uname_buf;
53 * Try to open the wtmp file. Note that we even try
54 * this if we have updwtmp() so we can see if the
55 * wtmp file is accessible.
57 if ((fd = open(WTMP_FILE, O_WRONLY|O_APPEND)) < 0) return;
61 * Note if we are going to write a boot record.
63 if (type == BOOT_TIME) wrote_wtmp_reboot++;
66 * See if we need to write a reboot record. The reason that
67 * we are being so paranoid is that when we first tried to
68 * write the reboot record, /var was possibly not mounted
69 * yet. As soon as we can open WTMP we write a delayed boot record.
71 if (wrote_wtmp_reboot == 0 && type != BOOT_TIME)
72 write_wtmp("reboot", "~~", 0, BOOT_TIME, "~");
76 * Zero the fields and enter new fields.
78 memset(&utmp, 0, sizeof(utmp));
79 #if defined(__GLIBC__)
80 gettimeofday(&tv, NULL);
81 utmp.ut_tv.tv_sec = tv.tv_sec;
82 utmp.ut_tv.tv_usec = tv.tv_usec;
88 strncpy(utmp.ut_name, user, sizeof(utmp.ut_name));
89 strncpy(utmp.ut_id , id , sizeof(utmp.ut_id ));
90 strncpy(utmp.ut_line, line, sizeof(utmp.ut_line));
92 /* Put the OS version in place of the hostname */
93 if (uname(&uname_buf) == 0)
94 strncpy(utmp.ut_host, uname_buf.release, sizeof(utmp.ut_host));
97 updwtmp(WTMP_FILE, &utmp);
99 write(fd, (char *)&utmp, sizeof(utmp));
105 * Write an entry to the UTMP file. For DEAD_PROCESS, put
106 * the previous ut_line into oldline if oldline != NULL.
108 static void write_utmp(
109 char *user, /* name of user */
110 char *id, /* inittab ID */
111 int pid, /* PID of process */
112 int type, /* TYPE of entry */
113 char *line, /* LINE if used. */
114 char *oldline) /* Line of old utmp entry. */
122 * Can't do much if UTMP_FILE is not present.
124 if (access(UTMP_FILE, F_OK) < 0)
129 * Note if we are going to write a boot record.
131 if (type == BOOT_TIME) wrote_utmp_reboot++;
134 * See if we need to write a reboot record. The reason that
135 * we are being so paranoid is that when we first tried to
136 * write the reboot record, /var was possibly not mounted
137 * yet. As soon as we can open WTMP we write a delayed boot record.
139 if (wrote_utmp_reboot == 0 && type != BOOT_TIME)
140 write_utmp("reboot", "~~", 0, BOOT_TIME, "~", NULL);
144 * Fill out an utmp struct.
146 memset(&utmp, 0, sizeof(utmp));
149 strncpy(utmp.ut_id, id, sizeof(utmp.ut_id));
150 #if defined(__GLIBC__)
151 gettimeofday(&tv, NULL);
152 utmp.ut_tv.tv_sec = tv.tv_sec;
153 utmp.ut_tv.tv_usec = tv.tv_usec;
157 strncpy(utmp.ut_user, user, UT_NAMESIZE);
158 if (line) strncpy(utmp.ut_line, line, UT_LINESIZE);
161 * We might need to find the existing entry first, to
162 * find the tty of the process (for wtmp accounting).
164 if (type == DEAD_PROCESS) {
166 * Find existing entry for the tty line.
170 if ((utmptr = getutid(&tmp)) != NULL) {
171 strncpy(utmp.ut_line, utmptr->ut_line, UT_LINESIZE);
173 strncpy(oldline, utmptr->ut_line, UT_LINESIZE);
178 * Update existing utmp file.
186 * Write a record to both utmp and wtmp.
188 void write_utmp_wtmp(
189 char *user, /* name of user */
190 char *id, /* inittab ID */
191 int pid, /* PID of process */
192 int type, /* TYPE of entry */
193 char *line) /* LINE if used. */
195 char oldline[UT_LINESIZE];
198 * For backwards compatibility we just return
199 * if user == NULL (means : clean up utmp file).
205 write_utmp(user, id, pid, type, line, oldline);
206 write_wtmp(user, id, pid, type, line && line[0] ? line : oldline);