smgl/simpleinit-msb: initial commit
[grimoire-witchcraft.git] / smgl / simpleinit-msb / patches / last.c.diff
blob0390d5d63e87ba2e7b3d057d887209ad0412c4ad
1 --- last.c 2001-09-26 12:59:46.000000000 +0200
2 +++ ../../sysvinit-2.86.ds1/src/last.c 2004-07-30 14:16:26.000000000 +0200
3 @@ -6,10 +6,10 @@
5 * Author: Miquel van Smoorenburg, miquels@cistron.nl
7 - * Version: @(#)last 2.79 13-Jun-2001 miquels@cistron.nl
8 + * Version: @(#)last 2.85 30-Jul-2004 miquels@cistron.nl
10 * This file is part of the sysvinit suite,
11 - * Copyright 1991-2001 Miquel van Smoorenburg.
12 + * Copyright 1991-2004 Miquel van Smoorenburg.
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 @@ -40,7 +40,7 @@
17 # define SHUTDOWN_TIME 254
18 #endif
20 -char *Version = "@(#) last 2.79 11-Sep-2000 miquels";
21 +char *Version = "@(#) last 2.85 31-Apr-2004 miquels";
23 #define CHOP_DOMAIN 0 /* Define to chop off local domainname. */
24 #define NEW_UTMP 1 /* Fancy & fast utmp read code. */
25 @@ -128,16 +128,16 @@
26 * Initialize and position.
28 utsize = oldfmt ? sizeof(uto) : sizeof(struct utmp);
29 - fseek(fp, 0L, SEEK_END);
30 - fpos = ftell(fp);
31 + fseeko(fp, 0, SEEK_END);
32 + fpos = ftello(fp);
33 if (fpos == 0)
34 return 0;
35 o = ((fpos - 1) / UCHUNKSIZE) * UCHUNKSIZE;
36 - if (fseek(fp, o, SEEK_SET) < 0) {
37 + if (fseeko(fp, o, SEEK_SET) < 0) {
38 fprintf(stderr, "%s: seek failed!\n", progname);
39 return 0;
41 - bpos = fpos - o;
42 + bpos = (int)(fpos - o);
43 if (fread(buf, bpos, 1, fp) != 1) {
44 fprintf(stderr, "%s: read failed!\n", progname);
45 return 0;
46 @@ -170,7 +170,7 @@
47 * Copy whatever is left in the buffer.
49 memcpy(tmp + (-bpos), buf, utsize + bpos);
50 - if (fseek(fp, fpos, SEEK_SET) < 0) {
51 + if (fseeko(fp, fpos, SEEK_SET) < 0) {
52 perror("fseek");
53 return 0;
55 @@ -207,25 +207,25 @@
56 int uread(FILE *fp, struct utmp *u, int *quit)
58 struct oldutmp uto;
59 - int r;
60 + off_t r;
62 if (u == NULL) {
63 r = oldfmt ? sizeof(struct oldutmp) : sizeof(struct utmp);
64 - fseek(fp, -1L * r, SEEK_END);
65 + fseek(fp, -1 * r, SEEK_END);
66 return 1;
69 if (!oldfmt) {
70 r = fread(u, sizeof(struct utmp), 1, fp);
71 if (r == 1) {
72 - if (fseek(fp, -2L * sizeof(struct utmp), SEEK_CUR) < 0)
73 + if (fseeko(fp, -2 * sizeof(struct utmp), SEEK_CUR) < 0)
74 if (quit) *quit = 1;
76 return r;
78 r = fread(&uto, sizeof(struct oldutmp), 1, fp);
79 if (r == 1) {
80 - if (fseek(fp, -2L * sizeof(struct oldutmp), SEEK_CUR) < 0)
81 + if (fseeko(fp, -2 * sizeof(struct oldutmp), SEEK_CUR) < 0)
82 if (quit) *quit = 1;
83 uconv(&uto, u);
85 @@ -300,29 +300,48 @@
87 * Lookup a host with DNS.
89 -int dns_lookup(char *result, int size, char *org, unsigned int ip)
90 +int dns_lookup(char *result, int size, int useip, int32_t *a)
92 - struct hostent *h;
94 - /*
95 - * Try to catch illegal IP numbers
96 - */
97 - if (ip == 0 || (int)ip == -1 || (ip >> 24) == 0 || (ip & 255) == 0) {
98 - if (size > UT_HOSTSIZE) size = UT_HOSTSIZE+1;
99 - strncpy(result, org, size - 1);
100 - result[size-1] = 0;
101 - return 0;
104 - if ((h = gethostbyaddr((char *)&ip, 4, AF_INET)) == NULL) {
105 - strncpy(result, inet_ntoa(*(struct in_addr *)&ip), size);
106 - result[size-1] = 0;
107 - return 0;
108 + struct sockaddr_in sin;
109 + struct sockaddr_in6 sin6;
110 + struct sockaddr *sa;
111 + int salen, flags;
112 + unsigned int topnibble;
113 + int mapped = 0;
115 + flags = useip ? NI_NUMERICHOST : 0;
117 + /*
118 + * IPv4 or IPv6 ? We use 2 heuristics:
119 + * 1. Current IPv6 range uses 2000-3fff. Outside of
120 + * that is illegal and must be IPv4.
121 + * 2. If last 3 bytes are 0, must be IPv4
122 + * 3. If IPv6 in IPv4, handle as IPv4
124 + * Ugly.
125 + */
126 + if (a[0] == 0 && a[1] == 0 && a[2] == htonl (0xffff))
127 + mapped = 1;
128 + topnibble = ntohl((unsigned int)a[0]) >> 28;
129 + if (topnibble < 2 || topnibble > 3 || mapped ||
130 + (a[1] == 0 && a[2] == 0 && a[3] == 0)) {
131 + /* IPv4 */
132 + sin.sin_family = AF_INET;
133 + sin.sin_port = 0;
134 + sin.sin_addr.s_addr = mapped ? a[3] : a[0];
135 + sa = (struct sockaddr *)&sin;
136 + salen = sizeof(sin);
137 + } else {
138 + /* IPv6 */
139 + memset(&sin6, 0, sizeof(sin6));
140 + sin6.sin6_family = AF_INET6;
141 + sin6.sin6_port = 0;
142 + memcpy(sin6.sin6_addr.s6_addr, a, 16);
143 + sa = (struct sockaddr *)&sin6;
144 + salen = sizeof(sin6);
146 - strncpy(result, h->h_name, size-1);
147 - result[size-1] = 0;
149 - return 0;
150 + return getnameinfo(sa, salen, result, size, NULL, 0, flags);
154 @@ -330,22 +349,22 @@
156 int list(struct utmp *p, time_t t, int what)
158 - struct in_addr in;
159 - char logintime[32];
160 - char logouttime[32];
161 - char length[32];
162 - char final[128];
163 - char utline[UT_LINESIZE+1];
164 - char domain[256];
165 - time_t secs, tmp;
166 - int mins, hours, days;
167 - char *s, **walk;
168 + time_t secs, tmp;
169 + char logintime[32];
170 + char logouttime[32];
171 + char length[32];
172 + char final[128];
173 + char utline[UT_LINESIZE+1];
174 + char domain[256];
175 + char *s, **walk;
176 + int mins, hours, days;
177 + int r, len;
180 * uucp and ftp have special-type entries
182 - strncpy(utline, p->ut_line, UT_LINESIZE);
183 - utline[UT_LINESIZE - 1] = 0;
184 + utline[0] = 0;
185 + strncat(utline, p->ut_line, UT_LINESIZE);
186 if (strncmp(utline, "ftp", 3) == 0 && isdigit(utline[3]))
187 utline[3] = 0;
188 if (strncmp(utline, "uucp", 4) == 0 && isdigit(utline[4]))
189 @@ -412,14 +431,14 @@
191 * Look up host with DNS if needed.
193 - if (usedns)
194 - dns_lookup(domain, sizeof(domain), p->ut_host, p->ut_addr);
195 - if (useip) {
196 - in.s_addr = p->ut_addr;
197 - strcpy(domain, inet_ntoa(in));
198 - } else {
199 - strncpy(domain, p->ut_host, UT_HOSTSIZE);
200 - domain[UT_HOSTSIZE-1] = 0;
201 + r = -1;
202 + if (usedns || useip)
203 + r = dns_lookup(domain, sizeof(domain), useip, p->ut_addr_v6);
204 + if (r < 0) {
205 + len = UT_HOSTSIZE;
206 + if (len >= sizeof(domain)) len = sizeof(domain) - 1;
207 + domain[0] = 0;
208 + strncat(domain, p->ut_host, len);
211 if (showhost) {
212 @@ -472,10 +491,48 @@
213 void usage(char *s)
215 fprintf(stderr, "Usage: %s [-num | -n num] [-f file] "
216 + "[-t YYYYMMDDHHMMSS] "
217 "[-R] [-x] [-o] [username..] [tty..]\n", s);
218 exit(1);
221 +time_t parsetm(char *ts)
223 + struct tm u = {0}, origu;
224 + time_t tm;
226 + if (sscanf(ts, "%4d%2d%2d%2d%2d%2d", &u.tm_year,
227 + &u.tm_mon, &u.tm_mday, &u.tm_hour, &u.tm_min,
228 + &u.tm_sec) != 6)
229 + return (time_t)-1;
231 + u.tm_year -= 1900;
232 + u.tm_mon -= 1;
233 + u.tm_isdst = -1;
235 + origu = u;
237 + if ((tm = mktime(&u)) == (time_t)-1)
238 + return tm;
240 + /*
241 + * Unfortunately mktime() is much more forgiving than
242 + * it should be. For example, it'll gladly accept
243 + * "30" as a valid month number. This behavior is by
244 + * design, but we don't like it, so we want to detect
245 + * it and complain.
246 + */
247 + if (u.tm_year != origu.tm_year ||
248 + u.tm_mon != origu.tm_mon ||
249 + u.tm_mday != origu.tm_mday ||
250 + u.tm_hour != origu.tm_hour ||
251 + u.tm_min != origu.tm_min ||
252 + u.tm_sec != origu.tm_sec)
253 + return (time_t)-1;
255 + return tm;
258 int main(int argc, char **argv)
260 FILE *fp; /* Filepointer of wtmp file */
261 @@ -499,10 +556,12 @@
262 int extended = 0; /* Lots of info. */
263 char *altufile = NULL;/* Alternate wtmp */
265 + time_t until = 0; /* at what time to stop parsing the file */
267 progname = mybasename(argv[0]);
269 /* Process the arguments. */
270 - while((c = getopt(argc, argv, "f:n:Rxadio0123456789")) != EOF)
271 + while((c = getopt(argc, argv, "f:n:Rxadiot:0123456789")) != EOF)
272 switch(c) {
273 case 'R':
274 showhost = 0;
275 @@ -533,6 +592,13 @@
276 case 'a':
277 altlist++;
278 break;
279 + case 't':
280 + if ((until = parsetm(optarg)) == (time_t)-1) {
281 + fprintf(stderr, "%s: Invalid time value \"%s\"\n",
282 + progname, optarg);
283 + usage(progname);
285 + break;
286 case '0': case '1': case '2': case '3': case '4':
287 case '5': case '6': case '7': case '8': case '9':
288 maxrecs = 10*maxrecs + c - '0';
289 @@ -631,6 +697,9 @@
290 if (uread(fp, &ut, &quit) != 1)
291 break;
293 + if (until && until < ut.ut_time)
294 + continue;
296 if (memcmp(&ut, &oldut, sizeof(struct utmp)) == 0) continue;
297 memcpy(&oldut, &ut, sizeof(struct utmp));
298 lastdate = ut.ut_time;