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 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 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 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 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 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 * 282 syserr() 283 { 284 return (strerror(errno)); 285 } 286