]>
git.wh0rd.org - sysvinit.git/blob - src/utmp.c
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 * Can't do much if WTMP_FILE is not present or not writable.
71 if (access(WTMP_FILE
, W_OK
) < 0)
75 * Try to open the wtmp file. Note that we even try
76 * this if we have updwtmp() so we can see if the
77 * wtmp file is accessible.
79 if ((fd
= open(WTMP_FILE
, O_WRONLY
|O_APPEND
)) < 0) return;
83 * Note if we are going to write a boot record.
85 if (type
== BOOT_TIME
) wrote_wtmp_reboot
++;
88 * See if we need to write a reboot record. The reason that
89 * we are being so paranoid is that when we first tried to
90 * write the reboot record, /var was possibly not mounted
91 * yet. As soon as we can open WTMP we write a delayed boot record.
93 if (wrote_wtmp_reboot
== 0 && type
!= BOOT_TIME
)
94 write_wtmp("reboot", "~~", 0, BOOT_TIME
, "~");
97 * Note if we are going to write a runlevel record.
99 if (type
== RUN_LVL
) wrote_wtmp_rlevel
++;
102 * See if we need to write a runlevel record. The reason that
103 * we are being so paranoid is that when we first tried to
104 * write the reboot record, /var was possibly not mounted
105 * yet. As soon as we can open WTMP we write a delayed runlevel record.
107 if (wrote_wtmp_rlevel
== 0 && type
!= RUN_LVL
) {
108 int runlevel
= thislevel
;
109 int oldlevel
= prevlevel
;
110 write_wtmp("runlevel", "~~", runlevel
+ 256 * oldlevel
, RUN_LVL
, "~");
115 * Zero the fields and enter new fields.
117 memset(&utmp
, 0, sizeof(utmp
));
118 #if defined(__GLIBC__)
119 gettimeofday(&tv
, NULL
);
120 utmp
.ut_tv
.tv_sec
= tv
.tv_sec
;
121 utmp
.ut_tv
.tv_usec
= tv
.tv_usec
;
127 strncpy(utmp
.ut_name
, user
, sizeof(utmp
.ut_name
));
128 strncpy(utmp
.ut_id
, id
, sizeof(utmp
.ut_id
));
129 strncpy(utmp
.ut_line
, line
, sizeof(utmp
.ut_line
));
131 /* Put the OS version in place of the hostname */
132 if (uname(&uname_buf
) == 0)
133 strncpy(utmp
.ut_host
, uname_buf
.release
, sizeof(utmp
.ut_host
));
136 updwtmp(WTMP_FILE
, &utmp
);
138 write(fd
, (char *)&utmp
, sizeof(utmp
));
144 * Write an entry to the UTMP file. For DEAD_PROCESS, put
145 * the previous ut_line into oldline if oldline != NULL.
147 static void write_utmp(
148 char *user
, /* name of user */
149 char *id
, /* inittab ID */
150 int pid
, /* PID of process */
151 int type
, /* TYPE of entry */
152 char *line
, /* LINE if used. */
153 char *oldline
) /* Line of old utmp entry. */
161 * Can't do much if UTMP_FILE is not present or not writable.
163 if (access(UTMP_FILE
, W_OK
) < 0)
168 * Note if we are going to write a boot record.
170 if (type
== BOOT_TIME
) wrote_utmp_reboot
++;
173 * See if we need to write a reboot record. The reason that
174 * we are being so paranoid is that when we first tried to
175 * write the reboot record, /var was possibly not mounted
176 * yet. As soon as we can open UTMP we write a delayed boot record.
178 if (wrote_utmp_reboot
== 0 && type
!= BOOT_TIME
)
179 write_utmp("reboot", "~~", 0, BOOT_TIME
, "~", NULL
);
182 * Note if we are going to write a runlevel record.
184 if (type
== RUN_LVL
) wrote_utmp_rlevel
++;
187 * See if we need to write a runlevel record. The reason that
188 * we are being so paranoid is that when we first tried to
189 * write the reboot record, /var was possibly not mounted
190 * yet. As soon as we can open UTMP we write a delayed runlevel record.
192 if (wrote_utmp_rlevel
== 0 && type
!= RUN_LVL
) {
193 int runlevel
= thislevel
;
194 int oldlevel
= prevlevel
;
195 write_utmp("runlevel", "~~", runlevel
+ 256 * oldlevel
, RUN_LVL
, "~", NULL
);
200 * Fill out an utmp struct.
202 memset(&utmp
, 0, sizeof(utmp
));
205 strncpy(utmp
.ut_id
, id
, sizeof(utmp
.ut_id
));
206 #if defined(__GLIBC__)
207 gettimeofday(&tv
, NULL
);
208 utmp
.ut_tv
.tv_sec
= tv
.tv_sec
;
209 utmp
.ut_tv
.tv_usec
= tv
.tv_usec
;
213 strncpy(utmp
.ut_user
, user
, UT_NAMESIZE
);
214 if (line
) strncpy(utmp
.ut_line
, line
, UT_LINESIZE
);
217 * We might need to find the existing entry first, to
218 * find the tty of the process (for wtmp accounting).
220 if (type
== DEAD_PROCESS
) {
222 * Find existing entry for the tty line.
226 if ((utmptr
= getutid(&tmp
)) != NULL
) {
227 strncpy(utmp
.ut_line
, utmptr
->ut_line
, UT_LINESIZE
);
229 strncpy(oldline
, utmptr
->ut_line
, UT_LINESIZE
);
234 * Update existing utmp file.
242 * Write a record to both utmp and wtmp.
244 void write_utmp_wtmp(
245 char *user
, /* name of user */
246 char *id
, /* inittab ID */
247 int pid
, /* PID of process */
248 int type
, /* TYPE of entry */
249 char *line
) /* LINE if used. */
251 char oldline
[UT_LINESIZE
];
254 * For backwards compatibility we just return
255 * if user == NULL (means : clean up utmp file).
261 write_utmp(user
, id
, pid
, type
, line
, oldline
);
262 write_wtmp(user
, id
, pid
, type
, line
&& line
[0] ? line
: oldline
);