/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2005 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ #include #include #include #include #include #include #include #include #include #include #include #include #define P_locale "/usr/lib/locale/" #define L_locale (sizeof (P_locale)) #define MESSAGES "/LC_MESSAGES/" #define ESIZE BUFSIZ /* External functions */ extern int getopt(); extern void exit(); extern char *strecpy(); extern char *strrchr(); extern char *strchr(); /* External variables */ extern char *optarg; extern int optind; /* Internal functions */ static void usage(); static void prnt_str(); static int attach(); static void find_msgs(); static char *syserr(); /* Internal variables */ static char *cmdname; /* points to the name of the command */ static int lflg; /* set if locale is specified on command line */ static int mflg; /* set if message file is specified on */ /* command line */ static char locale[15]; /* save name of current locale */ static char *msgfile; /* points to the argument immediately */ /* following the m option */ static char *text; /* pointer to search pattern */ static int textflg; /* set if text pattern is specified on */ /* command line */ static int sflg; /* set if the s option is specified */ static char *fname; /* points to message file name */ static int msgnum; /* message number */ int main(int argc, char **argv) { int ch; char *end; int addr; int len; int len1; int fd; size_t size; char pathname[128]; char *cp; char ebuf[ESIZE]; DIR *dirp; struct dirent *dp; /* find last level of path in command name */ if (cmdname = strrchr(*argv, '/')) ++cmdname; else cmdname = *argv; /* parse command line */ while ((ch = getopt(argc, argv, "sl:m:")) != -1) switch (ch) { case 'l': lflg++; (void) strcpy(locale, optarg); continue; case 'm': mflg++; msgfile = optarg; continue; case 's': sflg++; continue; default: usage(); } if (mflg && optind < argc) { text = argv[optind++]; textflg++; } if (optind != argc) usage(); /* create full path name to message files */ if (!lflg) (void) strcpy(locale, setlocale(LC_MESSAGES, "")); (void) strcpy(pathname, P_locale); (void) strcpy(&pathname[L_locale - 1], locale); (void) strcat(pathname, MESSAGES); len = strlen(pathname); if (textflg) { /* compile regular expression */ if (compile(text, &ebuf[0], &ebuf[ESIZE]) == (char *)NULL) { (void) fprintf(stderr, "%s: ERROR: regular expression compile failed\n", cmdname); exit(1); } } /* access message files */ if (mflg) { end = msgfile + strlen(msgfile) + 1; if (*msgfile == ',' || *(end - 2) == ',') usage(); while ((fname = strtok(msgfile, ",\0")) != NULL) { if (strchr(fname, '/') != (char *)NULL) { cp = fname; len1 = 0; } else { cp = pathname; len1 = len; } msgfile = msgfile + strlen(fname) + 1; if ((addr = attach(cp, len1, &fd, &size)) == -1) { (void) fprintf(stderr, "%s: ERROR: failed to access message file '%s'\n", cmdname, cp); if (end != msgfile) continue; else break; } find_msgs(addr, ebuf); (void) munmap((caddr_t)addr, size); (void) close(fd); if (end == msgfile) break; } } else { /* end if (mflg) */ if ((dirp = opendir(pathname)) == NULL) { (void) fprintf(stderr, "%s: ERROR: %s %s\n", cmdname, pathname, syserr()); exit(1); } while ((dp = readdir(dirp)) != NULL) { if (dp->d_name[0] == '.') continue; fname = dp->d_name; if ((addr = attach(pathname, len, &fd, &size)) == -1) { (void) fprintf(stderr, "%s: ERROR: failed to access message file '%s'\n", cmdname, pathname); continue; } find_msgs(addr, ebuf); (void) munmap((caddr_t)addr, size); (void) close(fd); } (void) closedir(dirp); } return (0); } /* print usage message */ static void usage() { (void) fprintf(stderr, "usage: srchtxt [-s]\n srchtxt [-s] -l locale\n" " srchtxt [-s] [-l locale] [-m msgfile,...] [text]\n"); exit(1); } /* * print string - non-graphic characters are printed as alphabetic * escape sequences */ static void prnt_str(instring) char *instring; { char outstring[1024]; (void) strecpy(outstring, instring, NULL); if (sflg) (void) fprintf(stdout, "%s\n", outstring); else (void) fprintf(stdout, "<%s:%d>%s\n", fname, msgnum, outstring); } /* mmap a message file to the address space */ static int attach(path, len, fdescr, size) char *path; int len; int *fdescr; size_t *size; { int fd = -1; caddr_t addr; struct stat sb; (void) strcpy(&path[len], fname); if ((fd = open(path, O_RDONLY)) != -1 && fstat(fd, &sb) != -1 && (addr = mmap(0, sb.st_size, PROT_READ, MAP_SHARED, fd, 0)) != (caddr_t)-1) { *fdescr = fd; *size = sb.st_size; return ((int)addr); } else { if (fd == -1) (void) close(fd); return (-1); } } /* find messages in message files */ static void find_msgs(addr, regexpr) int addr; char *regexpr; { int num_msgs; char *msg; num_msgs = *(int *)addr; for (msgnum = 1; msgnum <= num_msgs; msgnum++) { msg = (char *)(*(int *)(addr + sizeof (int) * msgnum) + addr); if (textflg) { if (step(msg, regexpr)) prnt_str(msg); continue; } prnt_str(msg); } } /* print description of error */ static char * syserr() { return (strerror(errno)); }