1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
23 /* All Rights Reserved */
24
25 /*
26 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
27 * Use is subject to license terms.
28 */
29 #pragma ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.9 */
30
31 /*
32 * convert device to linename (as in /dev/linename)
33 * return ptr to LSZ-byte string, "?" if not found
34 * device must be character device
35 * maintains small list in tlist structure for speed
36 */
37
38 #include <stdio.h>
39 #include <sys/types.h>
40 #include <sys/param.h>
41 #include "acctdef.h"
42 #include <dirent.h>
43 #include <string.h>
44 #include <sys/stat.h>
45
46 static int tsize1;
47 static struct tlist {
48 char tname[LSZ]; /* linename */
49 dev_t tdev; /* device */
50 } tl[TSIZE1];
51
52 char *strncpy();
53 dev_t lintodev();
54
55 static char dev_dir[] = "/dev";
56 static char *def_srch_dirs[] = { "/dev/term",
57 "/dev/pts",
58 "/dev/xt",
59 NULL };
60 char file_name[MAX_DEV_PATH]; /* name being returned */
61
62 static int srch_dir();
63
64 char *
devtolin(device)65 devtolin(device)
66 dev_t device;
67 {
68 register struct tlist *tp;
69 char **srch_dirs; /* priority directories to search first */
70 int found = 0;
71 int dirno = 0;
72
73 for (tp = tl; tp < &tl[tsize1]; tp++)
74 if (device == tp->tdev)
75 return(tp->tname);
76
77 srch_dirs = def_srch_dirs;
78
79 while ((!found) && (srch_dirs[dirno] != NULL)) {
80 /* if /dev is one of the priority directories we should only
81 search its top level for now (set depth = MAX_SEARCH_DEPTH) */
82
83 found = srch_dir(device, srch_dirs[dirno],
84 ((strcmp(srch_dirs[dirno], dev_dir) == 0) ?
85 MAX_SRCH_DEPTH : 1),
86 NULL);
87 dirno++;
88 }
89
90 /* if not yet found search remaining /dev directory skipping the
91 priority directories */
92
93 if (!found)
94 found = srch_dir(device, dev_dir, 0, srch_dirs);
95
96 /* if found then put it (without the "/dev/" prefix) in the tlist
97 structure and return the path name without the "/dev/" prefix */
98
99 if (found) {
100 if (tsize1 < TSIZE1) {
101 tp->tdev = device;
102 CPYN(tp->tname, file_name+5);
103 tsize1++;
104 }
105 return(file_name+5);
106 } else
107 /* if not found put "?" in the tlist structure for that device and
108 return "?" */
109
110 if (tsize1 < TSIZE1) {
111 tp->tdev = device;
112 CPYN(tp->tname, "?");
113 tsize1++;
114 }
115 return("?");
116
117 }
118
119 static int
srch_dir(device,path,depth,skip_dirs)120 srch_dir(device, path, depth, skip_dirs)
121 dev_t device; /* device we are looking for */
122 char *path; /* current path */
123 int depth; /* current depth */
124 char *skip_dirs[]; /* directories that don't need searched */
125 {
126 DIR *fdev;
127 struct dirent *d;
128 int dirno = 0;
129 int found = 0;
130 int path_len;
131 char *last_comp;
132 struct stat sb;
133
134 /* do we need to search this directory? */
135
136 if ((skip_dirs != NULL) && (depth != 0))
137 while (skip_dirs[dirno] != NULL)
138 if (strcmp(skip_dirs[dirno++], path) == 0)
139 return(0);
140
141
142 /* open the directory */
143
144 if ((fdev = opendir(path)) == NULL)
145 return(0);
146
147 /* initialize file name using path name */
148
149 path_len = strlen(path);
150 strcpy(file_name, path);
151 last_comp = file_name + path_len;
152 *last_comp++ = '/';
153
154 /* start searching this directory */
155
156 while ((!found) && ((d = readdir(fdev)) != NULL))
157 if (d->d_ino != 0) {
158
159 /* if name would not be too long append it to
160 directory name, otherwise skip this entry */
161
162 if ((int) (path_len + strlen(d->d_name) + 2) > MAX_DEV_PATH)
163 continue;
164 else
165 strcpy(last_comp, d->d_name);
166
167 /* if this directory entry has the device number we need,
168 then the name is found. Otherwise if it's a directory
169 (not . or ..) and we haven't gone too deep, recurse. */
170
171 if (lintodev(file_name+5) == device) {
172 found = 1;
173 break;
174 } else if ((depth < MAX_SRCH_DEPTH) &&
175 (strcmp(d->d_name, ".") != 0) &&
176 (strcmp(d->d_name, "..") != 0) &&
177 (stat(file_name, &sb) != -1) &&
178 ((sb.st_mode & S_IFMT) == S_IFDIR))
179 found = srch_dir(device, file_name, depth+1, skip_dirs);
180 }
181 closedir(fdev);
182 return(found);
183 }
184