#include <stdio.h>
#include <dirent.h>
#include <regexpr.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <locale.h>
#include <sys/types.h>
#include <sys/file.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
#define P_locale "/usr/lib/locale/"
#define L_locale (sizeof (P_locale))
#define MESSAGES "/LC_MESSAGES/"
#define ESIZE BUFSIZ
extern int getopt();
extern void exit();
extern char *strecpy();
extern char *strrchr();
extern char *strchr();
extern char *optarg;
extern int optind;
static void usage();
static void prnt_str();
static int attach();
static void find_msgs();
static char *syserr();
static char *cmdname;
static int lflg;
static int mflg;
static char locale[15];
static char *msgfile;
static char *text;
static int textflg;
static int sflg;
static char *fname;
static int msgnum;
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;
if (cmdname = strrchr(*argv, '/'))
++cmdname;
else
cmdname = *argv;
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();
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) {
if (compile(text, &ebuf[0], &ebuf[ESIZE]) == (char *)NULL) {
(void) fprintf(stderr,
"%s: ERROR: regular expression compile failed\n",
cmdname);
exit(1);
}
}
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 {
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);
}
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);
}
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);
}
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);
}
}
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);
}
}
static char *
syserr()
{
return (strerror(errno));
}