#include <sys/cdefs.h>
#include "fbsdcompat.h"
__FBSDID("$FreeBSD: src/usr.bin/gencat/gencat.c,v 1.9 2002/05/29 14:23:10 tjr Exp $");
#include <sys/file.h>
#include <sys/stat.h>
#include <err.h>
#include <paths.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "gencat.h"
static void writeIfChanged(char *, int, int);
static void
usage(void)
{
fprintf(stderr, "usage: gencat [-new] [-or] [-lang C|C++|ANSIC]\n"
" catfile msgfile [-h <header-file>]...\n");
exit(1);
}
int
main(int argc, char *argv[])
{
int ofd = -1, ifd, i;
char *catfile = NULL;
char *input = NULL;
int lang = MCLangC;
int new = FALSE;
int orConsts = FALSE;
for (i = 1; i < argc; ++i) {
if (argv[i][0] == '-') {
if (strcmp(argv[i], "-lang") == 0) {
++i;
if (strcmp(argv[i], "C") == 0) lang = MCLangC;
else if (strcmp(argv[i], "C++") == 0) lang = MCLangCPlusPlus;
else if (strcmp(argv[i], "ANSIC") == 0) lang = MCLangANSIC;
else {
errx(1, "unrecognized language: %s", argv[i]);
}
} else if (strcmp(argv[i], "-h") == 0) {
if (!input)
errx(1, "can't write to a header before reading something");
++i;
writeIfChanged(argv[i], lang, orConsts);
} else if (strcmp(argv[i], "-new") == 0) {
if (catfile)
errx(1, "you must specify -new before the catalog file name");
new = TRUE;
} else if (strcmp(argv[i], "-or") == 0) {
orConsts = ~orConsts;
} else {
usage();
}
} else {
if (!catfile) {
catfile = argv[i];
if (new) {
if ((ofd = open(catfile, O_WRONLY|O_TRUNC|O_CREAT, 0666)) < 0)
errx(1, "unable to create a new %s", catfile);
} else if ((ofd = open(catfile, O_RDONLY)) < 0) {
if ((ofd = open(catfile, O_WRONLY|O_CREAT, 0666)) < 0)
errx(1, "unable to create %s", catfile);
} else {
MCReadCat(ofd);
close(ofd);
if ((ofd = open(catfile, O_WRONLY|O_TRUNC)) < 0)
errx(1, "unable to truncate %s", catfile);
}
} else {
input = argv[i];
if ((ifd = open(input, O_RDONLY)) < 0)
errx(1, "unable to read %s", input);
MCParse(ifd);
close(ifd);
}
}
}
if (catfile) {
MCWriteCat(ofd);
exit(0);
} else {
usage();
}
return 0;
}
static void
writeIfChanged(char *fname, int lang, int orConsts)
{
char tmpname[] = _PATH_TMP"/gencat.XXXXXX";
char buf[BUFSIZ], tbuf[BUFSIZ], *cptr, *tptr;
int fd, tfd;
int diff = FALSE;
int len, tlen;
struct stat sbuf;
if (stat(fname, &sbuf)) {
if ((fd = open(fname, O_WRONLY|O_CREAT, 0666)) < 0)
errx(1, "unable to create header file %s", fname);
MCWriteConst(fd, lang, orConsts);
close(fd);
return;
}
if ((tfd = mkstemp(tmpname)) < 0)
err(1, "mkstemp");
unlink(tmpname);
MCWriteConst(tfd, lang, orConsts);
if ((fd = open(fname, O_RDONLY)) < 0)
errx(1, "unable to read header file: %s", fname);
if (lseek(tfd, (off_t)0, L_SET) < 0)
errx(1, "unable to seek in tempfile: %s", tmpname);
while ((tlen = read(tfd, tbuf, BUFSIZ)) > 0) {
if ((len = read(fd, buf, BUFSIZ)) != tlen) {
diff = TRUE;
goto done;
}
for (cptr = buf, tptr = tbuf; cptr < buf+len; ++cptr, ++tptr) {
if (*tptr != *cptr) {
diff = TRUE;
goto done;
}
}
}
done:
if (diff) {
if (lseek(tfd, (off_t)0, L_SET) < 0)
errx(1, "unable to seek in tempfile: %s", tmpname);
close(fd);
if ((fd = open(fname, O_WRONLY|O_TRUNC)) < 0)
errx(1, "unable to truncate header file: %s", fname);
while ((len = read(tfd, buf, BUFSIZ)) > 0) {
if (write(fd, buf, (size_t)len) != len)
warnx("error writing to header file: %s", fname);
}
}
close(fd);
close(tfd);
}