1 /* $NetBSD: util.c,v 1.27 2007/05/05 16:55:17 christos Exp $ */
4 * Copyright (c) 1989, 1993
5 * The Regents of the University of California. All rights reserved.
7 * This code is derived from software contributed to Berkeley by
8 * Tony Nardo of the Johns Hopkins University/Applied Physics Lab.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * Portions Copyright (c) 1983, 1995, 1996 Eric P. Allman
38 * This code is derived from software contributed to Berkeley by
39 * Tony Nardo of the Johns Hopkins University/Applied Physics Lab.
41 * Redistribution and use in source and binary forms, with or without
42 * modification, are permitted provided that the following conditions
44 * 1. Redistributions of source code must retain the above copyright
45 * notice, this list of conditions and the following disclaimer.
46 * 2. Redistributions in binary form must reproduce the above copyright
47 * notice, this list of conditions and the following disclaimer in the
48 * documentation and/or other materials provided with the distribution.
49 * 3. All advertising materials mentioning features or use of this software
50 * must display the following acknowledgement:
51 * This product includes software developed by the University of
52 * California, Berkeley and its contributors.
53 * 4. Neither the name of the University nor the names of its contributors
54 * may be used to endorse or promote products derived from this software
55 * without specific prior written permission.
57 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
58 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
59 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
60 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
61 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
62 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
63 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
64 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
65 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
66 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
70 #include <sys/cdefs.h>
73 static char sccsid
[] = "@(#)util.c 8.3 (Berkeley) 4/28/95";
75 __RCSID("$NetBSD: util.c,v 1.27 2007/05/05 16:55:17 christos Exp $");
79 #include <sys/param.h>
95 #include "utmpentry.h"
100 static void find_idle_and_ttywrite(WHERE
*);
101 static void userinfo(PERSON
*, struct passwd
*);
102 static WHERE
*walloc(PERSON
*);
105 match(struct passwd
*pw
, char *user
)
108 char *bp
, name
[1024];
110 if (!strcasecmp(pw
->pw_name
, user
))
113 (void)strlcpy(bp
= tbuf
, pw
->pw_gecos
, sizeof(tbuf
));
115 /* Ampersands get replaced by the login name. */
116 if (!(p
= strsep(&bp
, ",")))
119 expandusername(p
, pw
->pw_name
, name
, sizeof(name
));
121 while ((p
= strsep(&bp
, "\t ")))
122 if (!strcasecmp(p
, user
))
127 /* inspired by usr.sbin/sendmail/util.c::buildfname */
129 expandusername(const char *gecos
, const char *login
, char *buf
, int buflen
)
134 /* why do we skip asterisks!?!? */
139 /* copy gecos, interpolating & to be full name */
140 for (p
= gecos
; *p
!= '\0'; p
++) {
141 if (bp
>= &buf
[buflen
- 1]) {
142 /* buffer overflow - just use login name */
143 snprintf(buf
, buflen
, "%s", login
);
144 buf
[buflen
- 1] = '\0';
148 /* interpolate full name */
149 snprintf(bp
, buflen
- (bp
- buf
), "%s", login
);
150 *bp
= toupper((unsigned char)*bp
);
160 enter_lastlog(PERSON
*pn
)
163 static int opened
, fd
;
167 /* some systems may not maintain lastlog, don't report errors. */
169 fd
= open(_PATH_LASTLOG
, O_RDONLY
, 0);
173 lseek(fd
, (off_t
)pn
->uid
* sizeof(ll
), SEEK_SET
) !=
174 (off_t
)pn
->uid
* (off_t
)sizeof(ll
) ||
175 read(fd
, (char *)&ll
, sizeof(ll
)) != sizeof(ll
)) {
176 /* as if never logged in */
177 ll
.ll_line
[0] = ll
.ll_host
[0] = '\0';
180 if ((w
= pn
->whead
) == NULL
)
182 else if (ll
.ll_time
!= 0) {
183 /* if last login is earlier than some current login */
184 for (; !doit
&& w
!= NULL
; w
= w
->next
)
185 if (w
->info
== LOGGEDIN
&& w
->loginat
< ll
.ll_time
)
188 * and if it's not any of the current logins
189 * can't use time comparison because there may be a small
190 * discrepency since login calls time() twice
192 for (w
= pn
->whead
; doit
&& w
!= NULL
; w
= w
->next
)
193 if (w
->info
== LOGGEDIN
&&
194 strncmp(w
->tty
, ll
.ll_line
, UT_LINESIZE
) == 0)
200 if ((w
->tty
= malloc(UT_LINESIZE
+ 1)) == NULL
)
202 memcpy(w
->tty
, ll
.ll_line
, UT_LINESIZE
);
203 w
->tty
[UT_LINESIZE
] = '\0';
204 if ((w
->host
= malloc(UT_HOSTSIZE
+ 1)) == NULL
)
206 memcpy(w
->host
, ll
.ll_host
, UT_HOSTSIZE
);
207 w
->host
[UT_HOSTSIZE
] = '\0';
208 w
->loginat
= ll
.ll_time
;
213 enter_where(struct utmpentry
*ep
, PERSON
*pn
)
215 WHERE
*w
= walloc(pn
);
220 w
->loginat
= (time_t)ep
->tv
.tv_sec
;
221 find_idle_and_ttywrite(w
);
225 enter_person(struct passwd
*pw
)
231 (db
= dbopen(NULL
, O_RDWR
, 0, DB_BTREE
, NULL
)) == NULL
)
234 key
.data
= (char *)pw
->pw_name
;
235 key
.size
= strlen(pw
->pw_name
);
237 switch ((*db
->get
)(db
, &key
, &data
, 0)) {
239 memmove(&pn
, data
.data
, sizeof pn
);
251 data
.size
= sizeof(PERSON
*);
253 if ((*db
->put
)(db
, &key
, &data
, 0))
260 find_person(char *name
)
269 key
.size
= strlen(name
);
271 if ((*db
->get
)(db
, &key
, &data
, 0))
273 memmove(&p
, data
.data
, sizeof p
);
282 if ((p
= malloc((u_int
) sizeof(PERSON
))) == NULL
)
292 if ((w
= malloc((u_int
) sizeof(WHERE
))) == NULL
)
294 if (pn
->whead
== NULL
)
295 pn
->whead
= pn
->wtail
= w
;
309 static char pbuf
[15];
311 /* don't touch anything if the user has their own formatting */
312 for (p
= num
; *p
; ++p
)
313 if (!isdigit((unsigned char)*p
))
318 case 11: /* +0-123-456-7890 */
323 case 10: /* 012-345-6789 */
329 case 7: /* 012-3456 */
334 case 5: /* x0-1234 */
354 find_idle_and_ttywrite(WHERE
*w
)
358 (void)snprintf(tbuf
, sizeof(tbuf
), "%s/%s", _PATH_DEV
, w
->tty
);
359 if (stat(tbuf
, &sb
) < 0) {
363 w
->idletime
= now
< sb
.st_atime
? 0 : now
- sb
.st_atime
;
365 #define TALKABLE 0220 /* tty is writable if 220 mode */
366 w
->writable
= ((sb
.st_mode
& TALKABLE
) == TALKABLE
);
370 userinfo(PERSON
*pn
, struct passwd
*pw
)
373 char *bp
, name
[1024];
376 pn
->realname
= pn
->office
= pn
->officephone
= pn
->homephone
= NULL
;
378 pn
->uid
= pw
->pw_uid
;
379 pn
->name
= strdup(pw
->pw_name
);
380 pn
->dir
= strdup(pw
->pw_dir
);
381 pn
->shell
= strdup(pw
->pw_shell
);
383 (void)strlcpy(bp
= tbuf
, pw
->pw_gecos
, sizeof(tbuf
));
385 /* ampersands get replaced by the login name */
386 if (!(p
= strsep(&bp
, ",")))
388 expandusername(p
, pw
->pw_name
, name
, sizeof(name
));
389 pn
->realname
= strdup(name
);
390 pn
->office
= ((p
= strsep(&bp
, ",")) && *p
) ?
392 pn
->officephone
= ((p
= strsep(&bp
, ",")) && *p
) ?
394 pn
->homephone
= ((p
= strsep(&bp
, ",")) && *p
) ?
396 (void)snprintf(tbuf
, sizeof(tbuf
), "%s/%s", _PATH_MAILDIR
,
398 pn
->mailrecv
= -1; /* -1 == not_valid */
399 if (stat(tbuf
, &sb
) < 0) {
400 if (errno
!= ENOENT
) {
401 (void)fprintf(stderr
,
402 "finger: %s: %s\n", tbuf
, strerror(errno
));
405 } else if (sb
.st_size
!= 0) {
406 pn
->mailrecv
= sb
.st_mtime
;
407 pn
->mailread
= sb
.st_atime
;