]>
Commit | Line | Data |
---|---|---|
a74aeac6 PR |
1 | /* |
2 | * utmp.c Routines to read/write the utmp and wtmp files. | |
3 | * Basically just wrappers around the library routines. | |
4 | * | |
5 | * Version: @(#)utmp.c 2.77 09-Jun-1999 miquels@cistron.nl | |
6 | * | |
7 | * Copyright (C) 1999 Miquel van Smoorenburg. | |
8 | * | |
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. | |
13 | * | |
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. | |
18 | * | |
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 | |
22 | * | |
23 | */ | |
24 | #include <sys/types.h> | |
25 | #include <sys/stat.h> | |
26 | #include <sys/ioctl.h> | |
27 | #include <sys/utsname.h> | |
28 | #include <stdlib.h> | |
29 | #include <unistd.h> | |
30 | #include <errno.h> | |
31 | #include <stdio.h> | |
32 | #include <time.h> | |
33 | #include <fcntl.h> | |
34 | #include <string.h> | |
35 | #include <utmp.h> | |
36 | ||
37 | #include "init.h" | |
38 | #include "initreq.h" | |
39 | #include "paths.h" | |
40 | ||
41 | ||
42 | #if defined(__GLIBC__) | |
43 | # if (__GLIBC__ == 2) && (__GLIBC_MINOR__ == 0) && defined(__powerpc__) | |
44 | # define HAVE_UPDWTMP 0 | |
45 | # else | |
46 | # define HAVE_UPDWTMP 1 | |
47 | # endif | |
48 | #else | |
49 | # define HAVE_UPDWTMP 0 | |
50 | #endif | |
51 | ||
52 | ||
53 | /* | |
54 | * Log an event in the wtmp file (reboot, runlevel) | |
55 | */ | |
56 | void write_wtmp( | |
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 */ | |
62 | { | |
63 | int fd; | |
64 | struct utmp utmp; | |
65 | struct utsname uname_buf; | |
66 | struct timeval tv; | |
67 | ||
68 | /* | |
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. | |
72 | */ | |
73 | if ((fd = open(WTMP_FILE, O_WRONLY|O_APPEND)) < 0) return; | |
74 | ||
75 | #ifdef INIT_MAIN | |
76 | /* | |
77 | * Note if we are going to write a boot record. | |
78 | */ | |
79 | if (type == BOOT_TIME) wrote_wtmp_reboot++; | |
80 | ||
81 | /* | |
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. | |
86 | */ | |
87 | if (wrote_wtmp_reboot == 0 && type != BOOT_TIME) | |
88 | write_wtmp("reboot", "~~", 0, BOOT_TIME, "~"); | |
89 | #endif | |
90 | ||
91 | /* | |
92 | * Zero the fields and enter new fields. | |
93 | */ | |
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; | |
99 | #else | |
100 | time(&utmp.ut_time); | |
101 | #endif | |
102 | utmp.ut_pid = pid; | |
103 | utmp.ut_type = type; | |
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)); | |
107 | ||
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)); | |
111 | ||
112 | #if HAVE_UPDWTMP | |
113 | updwtmp(WTMP_FILE, &utmp); | |
114 | #else | |
115 | write(fd, (char *)&utmp, sizeof(utmp)); | |
116 | #endif | |
117 | close(fd); | |
118 | } | |
119 | ||
120 | /* | |
121 | * Write an entry to the UTMP file. For DEAD_PROCESS, put | |
122 | * the previous ut_line into oldline if oldline != NULL. | |
123 | */ | |
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. */ | |
131 | { | |
132 | struct utmp utmp; | |
133 | struct utmp tmp; | |
134 | struct utmp *utmptr; | |
135 | struct timeval tv; | |
136 | ||
137 | /* | |
138 | * Can't do much if UTMP_FILE is not present. | |
139 | */ | |
140 | if (access(UTMP_FILE, F_OK) < 0) | |
141 | return; | |
142 | ||
143 | #ifdef INIT_MAIN | |
144 | /* | |
145 | * Note if we are going to write a boot record. | |
146 | */ | |
147 | if (type == BOOT_TIME) wrote_utmp_reboot++; | |
148 | ||
149 | /* | |
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. | |
154 | */ | |
155 | if (wrote_utmp_reboot == 0 && type != BOOT_TIME) | |
156 | write_utmp("reboot", "~~", 0, BOOT_TIME, "~", NULL); | |
157 | #endif | |
158 | ||
159 | /* | |
160 | * Fill out an utmp struct. | |
161 | */ | |
162 | memset(&utmp, 0, sizeof(utmp)); | |
163 | utmp.ut_type = type; | |
164 | utmp.ut_pid = pid; | |
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; | |
170 | #else | |
171 | time(&utmp.ut_time); | |
172 | #endif | |
173 | strncpy(utmp.ut_user, user, UT_NAMESIZE); | |
174 | if (line) strncpy(utmp.ut_line, line, UT_LINESIZE); | |
175 | ||
176 | /* | |
177 | * We might need to find the existing entry first, to | |
178 | * find the tty of the process (for wtmp accounting). | |
179 | */ | |
180 | if (type == DEAD_PROCESS) { | |
181 | /* | |
182 | * Find existing entry for the tty line. | |
183 | */ | |
184 | setutent(); | |
185 | tmp = utmp; | |
186 | if ((utmptr = getutid(&tmp)) != NULL) { | |
187 | strncpy(utmp.ut_line, utmptr->ut_line, UT_LINESIZE); | |
188 | if (oldline) | |
189 | strncpy(oldline, utmptr->ut_line, UT_LINESIZE); | |
190 | } | |
191 | } | |
192 | ||
193 | /* | |
194 | * Update existing utmp file. | |
195 | */ | |
196 | setutent(); | |
197 | pututline(&utmp); | |
198 | endutent(); | |
199 | } | |
200 | ||
201 | /* | |
202 | * Write a record to both utmp and wtmp. | |
203 | */ | |
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. */ | |
210 | { | |
211 | char oldline[UT_LINESIZE]; | |
212 | ||
213 | /* | |
214 | * For backwards compatibility we just return | |
215 | * if user == NULL (means : clean up utmp file). | |
216 | */ | |
217 | if (user == NULL) | |
218 | return; | |
219 | ||
220 | oldline[0] = 0; | |
221 | write_utmp(user, id, pid, type, line, oldline); | |
222 | write_wtmp(user, id, pid, type, line && line[0] ? line : oldline); | |
223 | } | |
224 |