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 /*
23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
29
30 #include <stdio.h>
31 #include <dirent.h>
32 #include <regexpr.h>
33 #include <string.h>
34 #include <errno.h>
35 #include <fcntl.h>
36 #include <locale.h>
37 #include <sys/types.h>
38 #include <sys/file.h>
39 #include <sys/mman.h>
40 #include <sys/stat.h>
41 #include <unistd.h>
42
43 #define P_locale "/usr/lib/locale/"
44 #define L_locale (sizeof (P_locale))
45 #define MESSAGES "/LC_MESSAGES/"
46 #define ESIZE BUFSIZ
47
48 /* External functions */
49
50 extern int getopt();
51 extern void exit();
52 extern char *strecpy();
53 extern char *strrchr();
54 extern char *strchr();
55
56
57 /* External variables */
58
59 extern char *optarg;
60 extern int optind;
61
62 /* Internal functions */
63
64 static void usage();
65 static void prnt_str();
66 static int attach();
67 static void find_msgs();
68 static char *syserr();
69
70 /* Internal variables */
71
72 static char *cmdname; /* points to the name of the command */
73 static int lflg; /* set if locale is specified on command line */
74 static int mflg; /* set if message file is specified on */
75 /* command line */
76 static char locale[15]; /* save name of current locale */
77 static char *msgfile; /* points to the argument immediately */
78 /* following the m option */
79 static char *text; /* pointer to search pattern */
80 static int textflg; /* set if text pattern is specified on */
81 /* command line */
82 static int sflg; /* set if the s option is specified */
83 static char *fname; /* points to message file name */
84 static int msgnum; /* message number */
85
86 int
main(int argc,char ** argv)87 main(int argc, char **argv)
88 {
89 int ch;
90 char *end;
91 int addr;
92 int len;
93 int len1;
94 int fd;
95 size_t size;
96 char pathname[128];
97 char *cp;
98 char ebuf[ESIZE];
99 DIR *dirp;
100 struct dirent *dp;
101
102 /* find last level of path in command name */
103 if (cmdname = strrchr(*argv, '/'))
104 ++cmdname;
105 else
106 cmdname = *argv;
107
108 /* parse command line */
109 while ((ch = getopt(argc, argv, "sl:m:")) != -1)
110 switch (ch) {
111 case 'l':
112 lflg++;
113 (void) strcpy(locale, optarg);
114 continue;
115 case 'm':
116 mflg++;
117 msgfile = optarg;
118 continue;
119 case 's':
120 sflg++;
121 continue;
122 default:
123 usage();
124 }
125 if (mflg && optind < argc) {
126 text = argv[optind++];
127 textflg++;
128 }
129 if (optind != argc)
130 usage();
131
132 /* create full path name to message files */
133 if (!lflg)
134 (void) strcpy(locale, setlocale(LC_MESSAGES, ""));
135 (void) strcpy(pathname, P_locale);
136 (void) strcpy(&pathname[L_locale - 1], locale);
137 (void) strcat(pathname, MESSAGES);
138 len = strlen(pathname);
139
140 if (textflg) {
141 /* compile regular expression */
142 if (compile(text, &ebuf[0], &ebuf[ESIZE]) == (char *)NULL) {
143 (void) fprintf(stderr,
144 "%s: ERROR: regular expression compile failed\n",
145 cmdname);
146 exit(1);
147 }
148 }
149
150 /* access message files */
151 if (mflg) {
152 end = msgfile + strlen(msgfile) + 1;
153 if (*msgfile == ',' || *(end - 2) == ',')
154 usage();
155 while ((fname = strtok(msgfile, ",\0")) != NULL) {
156 if (strchr(fname, '/') != (char *)NULL) {
157 cp = fname;
158 len1 = 0;
159 } else {
160 cp = pathname;
161 len1 = len;
162 }
163 msgfile = msgfile + strlen(fname) + 1;
164 if ((addr = attach(cp, len1, &fd, &size)) == -1) {
165 (void) fprintf(stderr,
166 "%s: ERROR: failed to access message file '%s'\n", cmdname, cp);
167 if (end != msgfile)
168 continue;
169 else
170 break;
171 }
172 find_msgs(addr, ebuf);
173 (void) munmap((caddr_t)addr, size);
174 (void) close(fd);
175 if (end == msgfile)
176 break;
177 }
178 } else { /* end if (mflg) */
179 if ((dirp = opendir(pathname)) == NULL) {
180 (void) fprintf(stderr, "%s: ERROR: %s %s\n",
181 cmdname, pathname, syserr());
182 exit(1);
183 }
184 while ((dp = readdir(dirp)) != NULL) {
185 if (dp->d_name[0] == '.')
186 continue;
187 fname = dp->d_name;
188 if ((addr = attach(pathname, len, &fd, &size)) == -1) {
189 (void) fprintf(stderr,
190 "%s: ERROR: failed to access message file '%s'\n", cmdname, pathname);
191 continue;
192 }
193 find_msgs(addr, ebuf);
194 (void) munmap((caddr_t)addr, size);
195 (void) close(fd);
196 }
197 (void) closedir(dirp);
198 }
199 return (0);
200 }
201
202
203 /* print usage message */
204 static void
usage()205 usage()
206 {
207 (void) fprintf(stderr,
208 "usage: srchtxt [-s]\n srchtxt [-s] -l locale\n"
209 " srchtxt [-s] [-l locale] [-m msgfile,...] [text]\n");
210 exit(1);
211 }
212
213 /*
214 * print string - non-graphic characters are printed as alphabetic
215 * escape sequences
216 */
217 static void
prnt_str(instring)218 prnt_str(instring)
219 char *instring;
220 {
221 char outstring[1024];
222
223 (void) strecpy(outstring, instring, NULL);
224 if (sflg)
225 (void) fprintf(stdout, "%s\n", outstring);
226 else
227 (void) fprintf(stdout, "<%s:%d>%s\n", fname, msgnum, outstring);
228 }
229
230 /* mmap a message file to the address space */
231 static int
attach(path,len,fdescr,size)232 attach(path, len, fdescr, size)
233 char *path;
234 int len;
235 int *fdescr;
236 size_t *size;
237 {
238 int fd = -1;
239 caddr_t addr;
240 struct stat sb;
241
242 (void) strcpy(&path[len], fname);
243 if ((fd = open(path, O_RDONLY)) != -1 &&
244 fstat(fd, &sb) != -1 &&
245 (addr = mmap(0, sb.st_size,
246 PROT_READ, MAP_SHARED,
247 fd, 0)) != (caddr_t)-1) {
248 *fdescr = fd;
249 *size = sb.st_size;
250 return ((int)addr);
251 } else {
252 if (fd == -1)
253 (void) close(fd);
254 return (-1);
255 }
256 }
257
258
259 /* find messages in message files */
260 static void
find_msgs(addr,regexpr)261 find_msgs(addr, regexpr)
262 int addr;
263 char *regexpr;
264 {
265 int num_msgs;
266 char *msg;
267
268 num_msgs = *(int *)addr;
269 for (msgnum = 1; msgnum <= num_msgs; msgnum++) {
270 msg = (char *)(*(int *)(addr + sizeof (int) * msgnum) + addr);
271 if (textflg) {
272 if (step(msg, regexpr))
273 prnt_str(msg);
274 continue;
275 }
276 prnt_str(msg);
277 }
278 }
279
280 /* print description of error */
281 static char *
syserr()282 syserr()
283 {
284 return (strerror(errno));
285 }
286