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