4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #pragma ident "%Z%%M% %I% %E% SMI"
31 * lc_utils contains utility functions used by both the basic and extended
32 * accounting components of lastcomm. getdev(), on its first call, builds
33 * the set of tty device name to dev_t mappings.
36 #define N_DEVS 43 /* hash value for device names */
37 #define NDEVS 500 /* max number of file names in /dev */
39 #define HASH(d) (((int)d) % N_DEVS) /* hash function */
43 char dev_name
[PATHNAMLEN
];
44 struct devhash
*dev_nxt
;
47 static struct devhash
*dev_hash
[N_DEVS
];
48 static struct devhash
*dev_chain
;
49 static int ndevs
= NDEVS
;
50 static struct devhash
*hashtab
;
53 * Default search list, used if /etc/ttysrch unavailable or unparsable.
55 static char *def_srch_dirs
[] = {
61 static char *raw_sf
; /* buffer containing raw image of the search file */
63 #define SRCH_FILE_NAME "/etc/ttysrch"
65 * /etc/ttysrch tokens.
67 #define COMMENT_CHAR '#'
70 * /etc/ttysrch parser states.
73 #define COMMENT_STATE 2
74 #define DIRNAME_STATE 3
77 * The following 2 routines are modified version of get_pri_dirs
78 * and srch_dir in ttyname.c.
85 int sf_lines
= 0; /* number of lines in search file */
89 char **pri_dirs
; /* priority search list */
90 char *sfp
; /* pointer inside the raw image buffer */
91 struct stat sfsb
; /* search file's stat structure buffer */
94 if ((sf
= fopen(SRCH_FILE_NAME
, "r")) == NULL
)
95 return (def_srch_dirs
);
96 if (stat(SRCH_FILE_NAME
, &sfsb
) < 0) {
98 return (def_srch_dirs
);
100 raw_sf
= malloc(sfsb
.st_size
+ 1);
102 while ((bcount
++ < sfsb
.st_size
) && ((c
= getc(sf
)) != EOF
)) {
109 pri_dirs
= malloc(++sf_lines
* sizeof (char *));
116 if (*sfp
== COMMENT_CHAR
) {
117 state
= COMMENT_STATE
;
118 } else if (!isspace(*sfp
)) {
119 state
= DIRNAME_STATE
;
120 pri_dirs
[dirno
++] = sfp
;
131 } else if (isspace(*sfp
)) {
133 state
= COMMENT_STATE
;
142 pri_dirs
[dirno
] = NULL
;
147 * Build a chain of character devices in dev_chain, starting with the given
154 struct dirent
*direntp
;
156 char file_name
[PATHNAMLEN
];
158 if ((dirp
= opendir(path
)) == NULL
)
161 if ((readdir(dirp
) == NULL
) || (readdir(dirp
) == NULL
))
164 while ((direntp
= readdir(dirp
)) != NULL
) {
165 (void) strcpy(file_name
, path
);
166 (void) strcat(file_name
, "/");
167 (void) strcat(file_name
, direntp
->d_name
);
168 if (stat((const char *)file_name
, &st
) < 0)
170 if ((st
.st_mode
& S_IFMT
) == S_IFCHR
) {
171 (void) strcpy(hashtab
->dev_name
,
172 file_name
+ strlen("/dev/"));
173 hashtab
->dev_nxt
= dev_chain
;
180 (void) closedir(dirp
);
191 hashtab
= malloc(NDEVS
* sizeof (struct devhash
));
192 if (hashtab
== NULL
) {
193 (void) fprintf(stderr
, gettext("No memory for device table\n"));
197 srch_dirs
= get_pri_dirs();
199 while (srch_dirs
[dirno
] != NULL
) {
200 if (srch_dir(srch_dirs
[dirno
]) < 0)
206 while (srch_dirs
[dirno
] != NULL
) {
207 if (strcmp("/dev", srch_dirs
[dirno
]) == 0)
209 * Don't search /dev twice.
219 struct devhash
*hp
, *nhp
;
221 char name
[PATHNAMLEN
];
222 static dev_t lastdev
= (dev_t
)-1;
223 static char *lastname
;
235 for (hp
= dev_hash
[HASH(dev
)]; hp
; hp
= hp
->dev_nxt
)
236 if (hp
->dev_dev
== dev
) {
238 return (lastname
= hp
->dev_name
);
241 for (hp
= dev_chain
; hp
; hp
= nhp
) {
243 (void) strcpy(name
, "/dev/");
244 (void) strcat(name
, hp
->dev_name
);
245 if (stat(name
, &statb
) < 0) /* name truncated usually */
247 if ((statb
.st_mode
& S_IFMT
) != S_IFCHR
)
249 hp
->dev_dev
= statb
.st_rdev
;
250 hp
->dev_nxt
= dev_hash
[HASH(hp
->dev_dev
)];
251 dev_hash
[HASH(hp
->dev_dev
)] = hp
;
252 if (hp
->dev_dev
== dev
) {
255 return (lastname
= hp
->dev_name
);
266 static char flags
[20];
268 #define BIT(flag, ch) flags[i++] = (f & flag) ? ch : ' '
280 static char uidname
[NMAX
];
282 if ((pw
= getpwuid(uid
)) == NULL
) {
283 (void) sprintf(uidname
, "%u", uid
);
286 return (pw
->pw_name
);