# # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (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 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # include ../Makefile.cmd PROG= genmsg PSRC_Y= genmsg.y C_OBJS= main.o util.o LEXARGS= LEXSRCS= genmsg.l LEXINTSRCS= lex.yy.c LEXOBJS= lex.yy.o CERRWARN += -Wno-parentheses CERRWARN += -Wno-unused-variable # because of labels from yacc genmsg.o : CERRWARN += -Wno-unused-label genmsg.o : SMATCH=off LDLIBS += -ll YFLAGS = -d CPPFLAGS = -I../head $(CPPFLAGS.master) # genmsg has a name clash with main() and libl.so.1. However, genmsg must # still export a number of "yy*" (libl) interfaces. Reduce all other symbols # to local scope. MAPFILES += $(MAPFILE.LEX) $(MAPFILE.NGB) MAPOPTS = $(MAPFILES:%=-Wl,-M%) LDFLAGS += $(MAPOPTS) OBJS = $(C_OBJS) $(PSRC_Y:%.y=%.o) $(LEXOBJS) PSRC_C = $(PSRC_Y:%.y=%.c) SRCS = $(C_OBJS:%.o=%.c) $(PSRC_C) $(LEXINTSRCS) .KEEP_STATE: all: $(PROG) install: all $(ROOTPROG) $(PROG): $(OBJS) $(MAPFILES) $(LINK.c) -o $@ $(OBJS) $(LDLIBS) $(POST_PROCESS) $(LEXINTSRCS): $(LEXSRCS) $(LEX) $(LEXARGS) $(LEXSRCS) # Hammerhead: GNU Make grouped target (was dmake +) $(PSRC_C) y.tab.h &: $(PSRC_Y) $(YACC) $(YFLAGS) $(PSRC_Y) $(MV) y.tab.c $(PSRC_C) $(OBJS): y.tab.h lex.yy.c catalog: $(POFILE) $(POFILE): $(SRCS) $(RM) $@ $(COMPILE.cpp) $(SRCS) > $(POFILE).i $(XGETTEXT) $(XGETFLAGS) $(POFILE).i $(SED) "/^domain/d" messages.po > $@ $(RM) $(POFILE).i messages.po clean: $(RM) $(OBJS) $(PSRC_C) $(LEXINTSRCS) y.tab.h *.po include ../Makefile.targ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (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 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _GENMSG_H #define _GENMSG_H #ifdef __cplusplus extern "C" { #endif /* * Boolean values. */ #define TRUE 1 #define FALSE 0 /* * Default quote character for a message file. */ #define QUOTE '"' /* * Number to be updated by the auto message numbering. */ #define NOMSGID -1 /* * Genmsg action mode is for genmsg to identify its tasks. */ #define IsActiveMode(mode) (active_mode & (mode)) #define SetActiveMode(mode) (active_mode |= (mode)) #define ResetActiveMode(mode) (active_mode &= ~(mode)) typedef long Mode; #define NoMode (0L) /* internal-mode */ #define ReplaceMode (1L<<0) /* internal-mode */ #define MessageMode (1L<<1) /* -o */ #define AppendMode (1L<<2) /* -a */ #define AutoNumMode (1L<<3) /* -l projfile */ #define ReverseMode (1L<<4) /* -r */ #define OverwriteMode (1L<<5) /* -f */ #define ProjectMode (1L<<6) /* -g new-projfile */ #define MsgCommentMode (1L<<7) /* -c comment-tag */ #define SetCommentMode (1L<<8) /* -c comment-tag */ #define BackCommentMode (1L<<9) /* -b */ #define LineInfoMode (1L<<10) /* -n */ #define PrefixMode (1L<<11) /* -m prefix */ #define SuffixMode (1L<<12) /* -M suffix */ #define TripleMode (1L<<13) /* -t */ #define DoubleLineMode (1L<<14) /* -d */ #define PreProcessMode (1L<<15) /* -p cpp-path */ #define NoErrorMode (1L<<16) /* -x */ extern Mode active_mode; extern char *srcfile; /* from main.c */ extern FILE *newfp; /* from main.c */ extern void prg_err(char *fmt, ...); extern void src_err(char *file, int line, char *fmt, ...); #ifdef __cplusplus } #endif #endif /* _GENMSG_H */ %{ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (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 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #include #include #include #include #include #include #include "genmsg.h" #include "y.tab.h" extern int is_cat_found; /* from main.c */ extern void add_comment(Mode, char *); /* from util.c */ int lineno = 1; /* * msg_line stores the line number where a msgid is to be replaced. */ int msg_line = 0; int end_of_cat = TRUE; /* * In preprocessor mode, genmsg has to parse both the original * soruce code and the code which a preprocessor generates. * While genmsg is parsing the original source code, 'pound_is_mine' * is set to TRUE. */ int pound_is_mine = FALSE; void warning(char *); #define NOLINEMSG -2 void set_linemsgid(int, int); int get_linemsgid(int); /* * cat_field indicates which token is currently parsed by lex. */ #define CatdField 0 #define SetidField 1 #define MsgidField 2 #define StrField 3 static int cat_field; /* * This will be turned on when '-' is found in the catgets message * number field. */ static int save_minus = FALSE; static char *skip_quoted(int skip_ch); static char *skip_comment(void); static void parse_cppline(char *); %} %s CAT %% [0-9a-zA-Z\_\.]catgets { if (IsActiveMode(ReplaceMode)) { (void) fprintf(newfp, "%s", yytext); } } catgets[0-9a-zA-Z\_\.] { if (IsActiveMode(ReplaceMode)) { (void) fprintf(newfp, "%s", yytext); } } catgets { if (end_of_cat) { /* * If the previous catgets * state is on, turn it off * first. */ BEGIN 0; } if (IsActiveMode(ReplaceMode)) { (void) fprintf(newfp, "%s", yytext); } if (!IsActiveMode(ReplaceMode) || !IsActiveMode(PreProcessMode)) { BEGIN CAT; end_of_cat = FALSE; cat_field = CatdField; return (CATGETS); } } \, { /* punctuation */ cat_field++; if (IsActiveMode(ReplaceMode)) { (void) fprintf(newfp, "%c", yytext[0]); } if (end_of_cat) { BEGIN 0; } else { return (yytext[0]); } } [+*/();>] { /* punctuation */ if (IsActiveMode(ReplaceMode)) { (void) fprintf(newfp, "%c", yytext[0]); } if (end_of_cat) { BEGIN 0; } else { return (yytext[0]); } } const { if (IsActiveMode(ReplaceMode)) { (void) fprintf(newfp, "%s", yytext); } if (end_of_cat) { BEGIN 0; } else { return (CONST); } } nl_catd { if (IsActiveMode(ReplaceMode)) { (void) fprintf(newfp, "%s", yytext); } if (end_of_cat) { BEGIN 0; } else { return (CATD); } } char { if (IsActiveMode(ReplaceMode)) { (void) fprintf(newfp, "%s", yytext); } if (end_of_cat) { BEGIN 0; } else { return (CHAR); } } int { if (IsActiveMode(ReplaceMode)) { (void) fprintf(newfp, "%s", yytext); } if (end_of_cat) { BEGIN 0; } else { return (INT); } } \+\+ { if (IsActiveMode(ReplaceMode)) { (void) fprintf(newfp, "%s", yytext); } if (end_of_cat) { BEGIN 0; } else { return (INC); } } \-\- { if (IsActiveMode(ReplaceMode)) { (void) fprintf(newfp, "%s", yytext); } if (end_of_cat) { BEGIN 0; } else { return (INC); } } \" { /* extract quoted string */ yylval.str = skip_quoted('"'); if (IsActiveMode(ReplaceMode)) { (void) fprintf(newfp, "\"%s\"", yylval.str); } if (end_of_cat) { /* just in case */ BEGIN 0; free(yylval.str); } else { return (QSTR); } } - { /* punctuation */ if (IsActiveMode(ReplaceMode)) { if (cat_field == MsgidField && get_linemsgid(lineno) != NOLINEMSG) { save_minus = TRUE; /* be replaced. */ } else { (void) fprintf(newfp, "%c", yytext[0]); } } if (end_of_cat) { /* just in case */ BEGIN 0; } else { return (yytext[0]); } } [0-9]+ { /* numbers */ switch (cat_field) { case SetidField: yylval.id = atoi(yytext); if (IsActiveMode(ReplaceMode)) { (void) fprintf(newfp, "%s", yytext); } if (end_of_cat) { BEGIN 0; } else { return (SETID); } break; case MsgidField: yylval.id = atoi(yytext); if (IsActiveMode(ReplaceMode)) { int id = get_linemsgid(lineno); if (id == NOLINEMSG) { (void) fprintf(newfp, "%s", yytext); } else if (id == NOMSGID && IsActiveMode(ReverseMode)) { (void) fprintf(newfp, "%d", NOMSGID); } else if (save_minus == TRUE && yylval.id == 1) { (void) fprintf(newfp, "%d", id); } else { /* just in case */ (void) fprintf(newfp, "%s", yytext); } save_minus = FALSE; } else { msg_line = lineno; } if (end_of_cat) { BEGIN 0; } else { return (MSGID); } break; default: yylval.id = atoi(yytext); if (IsActiveMode(ReplaceMode)) { (void) fprintf(newfp, "%s", yytext); } if (end_of_cat) { BEGIN 0; } else { return (DIGIT); } } } [a-zA-Z0-9_\&][a-zA-Z0-9_\>\&\.]* { if (IsActiveMode(ReplaceMode)) { (void) fprintf(newfp, "%s", yytext); } if (end_of_cat) { BEGIN 0; } else { return (STR); } } \n { lineno++; if (IsActiveMode(ReplaceMode)) { (void) fprintf(newfp, "\n"); } if (end_of_cat) { BEGIN 0; } } . { /* not interested */ if (IsActiveMode(ReplaceMode)) { (void) fprintf(newfp, "%c", yytext[0]); } if (end_of_cat) { BEGIN 0; } } -((([ \t]+)1)|1) { /* -1 */ if (end_of_cat == FALSE) { REJECT } else if (IsActiveMode(ReplaceMode)) { if (IsActiveMode(PreProcessMode)) { int id = get_linemsgid(lineno); if (id == NOLINEMSG) { (void) fprintf(newfp, "%s", yytext); } else { /* could be -1. */ (void) fprintf(newfp, "%d", id); } } else { (void) fprintf(newfp, "%s", yytext); } } } [0-9]+ { if (IsActiveMode(ReplaceMode)) { if (IsActiveMode(PreProcessMode) && IsActiveMode(ReverseMode)) { int id = get_linemsgid(lineno); if (id == NOLINEMSG) { (void) fprintf(newfp, "%s", yytext); } else if (id == NOMSGID) { (void) fprintf(newfp, "%d", id); } } else { (void) fprintf(newfp, "%s", yytext); } } } ^#[ \t]*[0-9]+.*\n { /* pound for c-preprocessor */ if (IsActiveMode(PreProcessMode)) { if (IsActiveMode(ReplaceMode)) { (void) fprintf(newfp, "%s", yytext); } else { parse_cppline(yytext); } } else if (IsActiveMode(ReplaceMode)) { (void) fprintf(newfp, "%s", yytext); } lineno++; } "/*" { /* skip a comment block */ char *comment = skip_comment(); if (IsActiveMode(ReplaceMode)) { (void) fprintf(newfp, "%s", comment); } else { if (IsActiveMode(MsgCommentMode)) { add_comment(MsgCommentMode, comment); } if (IsActiveMode(SetCommentMode)) { add_comment(SetCommentMode, comment); } } free(comment); } "//".*\n { /* skip a c++ comment */ if (IsActiveMode(ReplaceMode)) { (void) fprintf(newfp, "%s", yytext); } else { if (IsActiveMode(MsgCommentMode)) { add_comment(MsgCommentMode, yytext); } if (IsActiveMode(SetCommentMode)) { add_comment(SetCommentMode, yytext); } } lineno++; } \" { /* skip quoted string */ char *qstr = skip_quoted('"'); if (IsActiveMode(ReplaceMode)) { (void) fprintf(newfp, "\"%s\"", qstr); } free(qstr); } \' { /* skip single-quoted character */ char *qchr = skip_quoted('\''); if (IsActiveMode(ReplaceMode)) { (void) fprintf(newfp, "\'%s\'", qchr); } free(qchr); } \n { if (IsActiveMode(ReplaceMode)) { (void) fprintf(newfp, "\n"); } lineno++; } . { if (IsActiveMode(ReplaceMode)) { (void) fprintf(newfp, "%c", yytext[0]); } } %% static char * skip_quoted(int skip_ch) { char *buf, *ptr; /* saved buffer and its pointer */ int bsize = BUFSIZ; /* growing buffer size */ int i = 0; /* counter */ int c, old = 0; /* input character */ if ((buf = ptr = malloc(bsize)) == NULL) { prg_err(gettext("fatal: out of memory")); exit(EXIT_FAILURE); } for (; ; i++) { if (i == bsize) { bsize += BUFSIZ; if ((buf = realloc(buf, bsize)) == NULL) { prg_err(gettext("fatal: out of memory")); exit(EXIT_FAILURE); } ptr = buf + i; } c = input(); if (c == skip_ch && old != '\\') { break; } else if (c == '\n') { lineno++; } else if (c == 0) { if (skip_ch == '"') { warning(gettext("warning: unmatched \"")); } else if (skip_ch == '\'') { warning(gettext("warning: unmatched '")); } else { /* Should not happen */ warning(gettext( "warning: unmatched character")); } break; } *ptr++ = c; if (old == '\\') { old = '\0'; } else { old = c; } } *ptr = '\0'; return (buf); } static char * skip_comment(void) { char *buf, *ptr; /* saved buffer and its pointer */ int bsize = BUFSIZ; /* growing buffer size */ int i = 0; /* counter */ int c, old = 0; /* input character */ if ((buf = ptr = malloc(bsize)) == NULL) { prg_err(gettext("fatal: out of memory")); exit(EXIT_FAILURE); } *ptr++ = '/'; i++; *ptr++ = '*'; i++; for (; ; i++) { if (i == bsize) { bsize += BUFSIZ; if ((buf = realloc(buf, bsize)) == NULL) { prg_err(gettext("fatal: out of memory")); exit(EXIT_FAILURE); } ptr = buf + i; } c = input(); if (c == '/' && old == '*') { *ptr++ = c; break; } else if (c == '\n') { lineno++; } else if (c == 0) { warning(gettext("warning: unmatched /*")); break; } *ptr++ = old = c; } *ptr = '\0'; return (buf); } /* * parse_cppline() parses the line control information that a C * preprocessor generates to indicate the location in the original * file. See the cpp man in the details. */ static void parse_cppline(char *str) { int n, line, len; char ch; char file[BUFSIZ]; char *altfile = NULL; char *pfile; len = strlen(str); if (len >= sizeof (file)) { if ((altfile = malloc(len + 1)) == NULL) { prg_err(gettext("fatal: out of memory")); exit(EXIT_FAILURE); } pfile = altfile; } else { pfile = file; } /* LINTED: E_SEC_SCANF_UNBOUNDED_COPY */ n = sscanf(str, "%c%d%s", &ch, &line, pfile); /* 'file' is a quoted string but 'srcfile' is not. */ len = strlen(pfile) - 2; pfile++; if (n == 3 && (strncmp(pfile, srcfile, len) == 0)) { pound_is_mine = TRUE; lineno = line - 1; } else if (n == 2 && (pound_is_mine == TRUE)) { lineno = line - 1; } else { pound_is_mine = FALSE; } if (altfile) free(altfile); } typedef struct { int line; int msgid; } LineMsgID; static LineMsgID line_msgid[NL_MSGMAX]; static int line_msgcnt; void init_lex(void) { lineno = 1; end_of_cat = TRUE; pound_is_mine = FALSE; } void init_linemsgid(void) { line_msgcnt = 0; (void) memset(line_msgid, 0, sizeof (LineMsgID) * NL_MSGMAX); } void set_linemsgid(int line, int msgid) { if (line_msgcnt >= NL_MSGMAX) { return; /* oops */ } line_msgid[line_msgcnt].line = line; line_msgid[line_msgcnt].msgid = msgid; line_msgcnt++; } int get_linemsgid(int line) { int i, left, right; left = 0; right = line_msgcnt - 1; while (left <= right) { i = (left + right) >> 1; if (line < line_msgid[i].line) { right = i - 1; } else if (line > line_msgid[i].line) { left = i + 1; } else { return (line_msgid[i].msgid); } } return (NOLINEMSG); } int yyerror(const char *s) { if ((IsActiveMode(PreProcessMode) && pound_is_mine == FALSE) || IsActiveMode(ReplaceMode)) { return (0); } src_err(srcfile, lineno, gettext("%s before or at: %s"), s, yytext); return (0); } void warning(char *s) { if ((IsActiveMode(PreProcessMode) && pound_is_mine == FALSE) || IsActiveMode(ReplaceMode)) { return; } src_err(srcfile, lineno, "%s", s); } %{ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (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 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #include #include #include #include "genmsg.h" extern int is_cat_found; /* from main.c */ extern int lineno; /* genmsg.l */ extern int msg_line; /* genmsg.l */ extern int end_of_cat; /* from genmsg.l */ extern void set_linemsgid(int, int); /* from genmsg.l */ extern void add_msg(int, int, char *, char *, int, int); /* from util.c */ extern void set_msgid(int, int); extern int get_msgid(char *, int, int, char *); extern void warning(char *); extern int yyerror(const char *); extern int yylex(void); static void do_catgets(int, int, char *); static char *add_qstring(char *, char *); %} %union { char *str; int id; } %token CATGETS %token CONST %token CATD %token INT CHAR INC %token STR %token SETID MSGID DIGIT %token QSTR %type cast_setid setid cast_msgid msgid cast_digit digit %type catd arg_list arg_def arg_func arg_exp str %type cast_qstr paren_qstr qstr_list %left '-' '+' %left '*' '/' %nonassoc UMINUS %% genmsg_list: /* empty */ { if (!IsActiveMode(ReplaceMode)) { src_err(srcfile, (lineno - 1), gettext("catgets not found")); } } | genmsg { is_cat_found = TRUE; } ; genmsg: catgets { end_of_cat = TRUE; } | genmsg catgets { end_of_cat = TRUE; } ; catgets: CATGETS '(' catd ',' cast_setid ',' cast_msgid ',' cast_qstr ')' { do_catgets($5, $7, $9); free($9); } | error ; catd: '(' CATD ')' arg_list { $$ = $4; } | '(' CONST CATD ')' arg_list { $$ = $5; } | arg_list ; arg_list: arg_def | arg_list '-' '>' arg_def | '(' arg_list '-' '>' arg_def ')' { $$ = $2; } ; arg_def: arg_func | arg_exp | str ; arg_func: '(' arg_func ')' { $$ = $2; } | str '(' ')' | str '(' str ')' | str '(' cast_digit ')' | str '(' cast_qstr ')' { free($3); } ; arg_exp: '(' arg_exp ')' { $$ = $2; } | str INC | INC str { $$ = $2; } ; str: '(' str ')' { $$ = $2; } | '*' str { $$ = $2; } | STR ; cast_setid: '(' INT ')' setid { $$ = $4; } | '(' CONST INT ')' setid { $$ = $5; } | setid ; setid: setid '+' setid { $$ = $1 + $3; } | setid '-' setid { $$ = $1 - $3; } | setid '*' setid { $$ = $1 * $3; } | setid '/' setid { if ($3 == 0) { (void) yyerror(gettext("zero divide")); } else { $$ = $1 / $3; } } | '-' setid %prec UMINUS { $$ = -$2; } | '(' setid ')' { $$ = $2; } | SETID ; cast_msgid: '(' INT ')' msgid { $$ = $4; } | '(' CONST INT ')' msgid { $$ = $5; } | msgid ; msgid: msgid '+' msgid { $$ = $1 + $3; } | msgid '-' msgid { $$ = $1 - $3; } | msgid '*' msgid { $$ = $1 * $3; } | msgid '/' msgid { if ($3 == 0) { (void) yyerror(gettext("zero divide")); } else { $$ = $1 / $3; } } | '-' msgid %prec UMINUS { $$ = -$2; } | '(' msgid ')' { $$ = $2; } | MSGID ; cast_digit: '(' INT ')' digit { $$ = $4; } | '(' CONST INT ')' digit { $$ = $5; } | digit ; digit: digit '+' digit { $$ = $1 + $3; } | digit '-' digit { $$ = $1 - $3; } | digit '*' digit { $$ = $1 * $3; } | digit '/' digit { if ($3 == 0) { (void) yyerror(gettext("zero divide")); } else { $$ = $1 / $3; } } | '-' digit %prec UMINUS { $$ = -$2; } | '(' digit ')' { $$ = $2; } | DIGIT ; cast_qstr: '(' CHAR '*' ')' paren_qstr { $$ = $5; } | '(' CONST CHAR '*' ')' paren_qstr { $$ = $6; } | paren_qstr ; paren_qstr: '(' qstr_list ')' { $$ = $2; } | qstr_list ; qstr_list: QSTR | qstr_list QSTR { $$ = add_qstring($1, $2); } ; %% static void do_catgets(int setid, int msgid, char *str) { int id = msgid; if (IsActiveMode(ReplaceMode)) { return; } if (setid == 0 || setid > NL_SETMAX) { src_err(srcfile, lineno, gettext("improper set number: %d"), setid); return; } if (IsActiveMode(ProjectMode)) { set_msgid(setid, id); add_msg(setid, id, str, srcfile, lineno, TRUE); } else if (IsActiveMode(ReverseMode)) { set_linemsgid(msg_line, NOMSGID); } else if (IsActiveMode(AutoNumMode)) { if (id == NOMSGID) { id = get_msgid(srcfile, msg_line, setid, str); set_linemsgid(msg_line, id); } if (id != NOMSGID) { set_msgid(setid, id); add_msg(setid, id, str, srcfile, lineno, FALSE); } } else if (id == NOMSGID) { warning(gettext("improper message number: -1")); } else { add_msg(setid, id, str, srcfile, lineno, FALSE); } } static char * add_qstring(char *str, char *add) { int len = strlen(str) + strlen(add) + 3; /* 3 includes '\', '\n' and '\0' */ char *tmp = malloc(len); if (tmp == NULL) { prg_err(gettext("fatal: out of memory")); exit(EXIT_FAILURE); } (void) snprintf(tmp, len, "%s\\\n%s", str, add); free(str); free(add); return (tmp); } /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (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 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #include #include #include #include #include #include #include #include #include #include "genmsg.h" #define MSG_SUFFIX ".msg" #define NEW_SUFFIX ".new" #if !defined(TEXT_DOMAIN) #define TEXT_DOMAIN "genmsg" #endif /* * External functions. */ extern void write_msgfile(char *); /* from util.c */ extern int read_projfile(char *); /* from util.c */ extern void write_projfile(char *); /* from util.c */ extern void read_msgfile(char *); /* from util.c */ extern int is_writable(char *); /* from util.c */ extern int file_copy(char *, char *); /* from util.c */ extern void init_lex(void); /* from genmsg.l */ extern void init_linemsgid(void); /* from genmsg.l */ extern FILE *yyin; /* from lex */ extern int yyparse(void); /* from genmsg.l */ /* Program name. */ char *program; /* File pointer for auto-message-numbering. */ FILE *newfp = NULL; /* Input source file. */ char *srcfile; /* Tag for message comments. */ char *mctag = NULL; /* Tag for set number comments. */ char *sctag = NULL; /* Mode mask to define the genmsg tasks. */ Mode active_mode = NoMode; /* * This flag will be TRUE if a catgets() call is found * in the input file. */ int is_cat_found = FALSE; /* Suppress an error message if this flag is TRUE. */ int suppress_error = FALSE; /* Prefix and suffix of messages for testing. */ char *premsg = NULL; char *sufmsg = NULL; static void usage(void); static void validate_options(void); int main(int argc, char **argv) { int c; char *msgfile = NULL; char *projfile = NULL; char *newprojfile = NULL; char *cpppath = NULL; int do_msgfile = FALSE; int tmpfd = -1; char *cmd, *tmp; char tmpfile[32]; size_t len; program = basename(argv[0]); (void) setlocale(LC_ALL, ""); (void) textdomain(TEXT_DOMAIN); while ((c = getopt(argc, argv, "arndfg:o:l:p:c:s:m:M:txb")) != EOF) { switch (c) { case 'o': SetActiveMode(MessageMode); msgfile = optarg; break; case 'a': SetActiveMode(AppendMode); break; case 'l': projfile = optarg; SetActiveMode(AutoNumMode); break; case 'r': SetActiveMode(ReverseMode); break; case 'p': cpppath = optarg; SetActiveMode(PreProcessMode); break; case 'g': newprojfile = optarg; suppress_error = TRUE; SetActiveMode(ProjectMode); break; case 'c': mctag = optarg; SetActiveMode(MsgCommentMode); break; case 's': sctag = optarg; SetActiveMode(SetCommentMode); break; case 'b': SetActiveMode(BackCommentMode); break; case 'n': SetActiveMode(LineInfoMode); break; case 'm': premsg = optarg; SetActiveMode(PrefixMode); break; case 'M': sufmsg = optarg; SetActiveMode(SuffixMode); break; case 't': SetActiveMode(TripleMode); break; case 'd': SetActiveMode(DoubleLineMode); break; case 'f': SetActiveMode(OverwriteMode); break; case 'x': suppress_error = TRUE; SetActiveMode(NoErrorMode); break; default: usage(); break; } } if (optind >= argc) { usage(); } validate_options(); if (IsActiveMode(AutoNumMode)) { if (read_projfile(projfile)) { tmp = basename(projfile); len = strlen(tmp) + sizeof (NEW_SUFFIX); if ((newprojfile = malloc(len)) == NULL) { prg_err(gettext("fatal: out of memory")); exit(EXIT_FAILURE); } (void) snprintf(newprojfile, len, "%s%s", tmp, NEW_SUFFIX); } else { newprojfile = basename(projfile); } } if ((IsActiveMode(AutoNumMode) || IsActiveMode(ProjectMode)) && (is_writable(IsActiveMode(OverwriteMode) ? projfile : newprojfile) == FALSE)) { prg_err(gettext("cannot write \"%s\": permission denied"), IsActiveMode(OverwriteMode) ? projfile : newprojfile); exit(EXIT_FAILURE); } if (IsActiveMode(AppendMode) && msgfile != NULL) { read_msgfile(msgfile); } if (msgfile == NULL) { tmp = basename(argv[optind]); len = strlen(tmp) + sizeof (MSG_SUFFIX); if ((msgfile = malloc(len)) == NULL) { prg_err(gettext("fatal: out of memory")); exit(EXIT_FAILURE); } (void) snprintf(msgfile, len, "%s%s", tmp, MSG_SUFFIX); } while (optind < argc) { is_cat_found = FALSE; srcfile = argv[optind]; if (IsActiveMode(AutoNumMode) || IsActiveMode(ReverseMode)) { init_linemsgid(); } if (IsActiveMode(PreProcessMode)) { len = strlen(cpppath) + 1 + strlen(srcfile) + 1; if ((cmd = malloc(len)) == NULL) { prg_err(gettext("fatal: out of memory")); exit(EXIT_FAILURE); } (void) snprintf(cmd, len, "%s %s", cpppath, srcfile); if ((yyin = popen(cmd, "r")) == NULL) { prg_err( gettext("fatal: cannot execute \"%s\""), cpppath); exit(EXIT_FAILURE); } free(cmd); } else { if ((yyin = fopen(srcfile, "r")) == NULL) { prg_err( gettext("cannot open \"%s\""), srcfile); goto end; } } init_lex(); (void) yyparse(); if (IsActiveMode(PreProcessMode)) { if (pclose(yyin) != 0) { prg_err(gettext("\"%s\" failed for \"%s\""), cpppath, srcfile); goto end; } } if (is_cat_found == FALSE) { if (!IsActiveMode(PreProcessMode)) { (void) fclose(yyin); } goto end; } if (do_msgfile == FALSE) { do_msgfile = TRUE; } if (IsActiveMode(AutoNumMode) || IsActiveMode(ReverseMode)) { char *newfile; tmp = basename(srcfile); if (IsActiveMode(OverwriteMode)) { newfile = srcfile; } else { len = strlen(tmp) + sizeof (NEW_SUFFIX); if ((newfile = malloc(len)) == NULL) { prg_err( gettext("fatal: out of memory")); exit(EXIT_FAILURE); } (void) snprintf(newfile, len, "%s%s", tmp, NEW_SUFFIX); } if (is_writable(newfile) == FALSE) { prg_err(gettext( "cannot create \"%s\": permission denied"), newfile); goto end; } (void) strlcpy(tmpfile, "/tmp/gensmg.XXXXXX", sizeof (tmpfile)); if ((tmpfd = mkstemp(tmpfile)) == -1) { prg_err(gettext( "cannot create \"%s\""), tmpfile); if (!IsActiveMode(PreProcessMode)) { (void) fclose(yyin); } goto end; } if ((newfp = fdopen(tmpfd, "w")) == NULL) { prg_err(gettext( "cannot create \"%s\""), tmpfile); if (!IsActiveMode(PreProcessMode)) { (void) fclose(yyin); } (void) close(tmpfd); (void) unlink(tmpfile); goto end; } if (IsActiveMode(PreProcessMode)) { if ((yyin = fopen(srcfile, "r")) == NULL) { prg_err(gettext( "cannot open \"%s\""), srcfile); (void) fclose(newfp); (void) unlink(tmpfile); goto end; } } else { rewind(yyin); } SetActiveMode(ReplaceMode); init_lex(); (void) yyparse(); ResetActiveMode(ReplaceMode); (void) fclose(newfp); newfp = NULL; (void) fclose(yyin); (void) file_copy(tmpfile, newfile); (void) unlink(tmpfile); goto end; } if (!IsActiveMode(PreProcessMode)) { (void) fclose(yyin); } end: optind++; } if (!do_msgfile) { /* no more business. */ return (EXIT_SUCCESS); } if (!IsActiveMode(ReverseMode) && !IsActiveMode(ProjectMode)) { write_msgfile(msgfile); } if (IsActiveMode(AutoNumMode) || IsActiveMode(ProjectMode)) { write_projfile(IsActiveMode(OverwriteMode) ? projfile : newprojfile); } return (EXIT_SUCCESS); } static void validate_options(void) { /* -r doesn't work with either -a or -l. */ if (IsActiveMode(ReverseMode) && (IsActiveMode(AutoNumMode) || IsActiveMode(AppendMode))) { usage(); } /* -b should be accompanied with -c, -s, -d, and -n. */ if (IsActiveMode(BackCommentMode) && (!IsActiveMode(MsgCommentMode) && !IsActiveMode(SetCommentMode) && !IsActiveMode(DoubleLineMode) && !IsActiveMode(LineInfoMode))) { usage(); } if (IsActiveMode(ProjectMode) && (IsActiveMode(AutoNumMode) || IsActiveMode(ReverseMode) || IsActiveMode(AppendMode) || IsActiveMode(MsgCommentMode) || IsActiveMode(LineInfoMode) || IsActiveMode(OverwriteMode) || IsActiveMode(PrefixMode) || IsActiveMode(SuffixMode) || IsActiveMode(TripleMode) || IsActiveMode(DoubleLineMode) || IsActiveMode(MessageMode) || IsActiveMode(NoErrorMode))) { usage(); } } static void usage(void) { (void) fprintf(stderr, gettext( "Usage: %s [-o message-file] [-a] [-d] [-p preprocessor]\n" " [-s set-tag] [-c message-tag] [-b] [-n]\n" " [-l project-file] [-r] [-f] [-g project-file]\n" " [-m prefix] [-M suffix] [-t] [-x] files ...\n"), program); exit(EXIT_FAILURE); } /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (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 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "genmsg.h" #define SET_TOKEN "$set" #define DELSET_TOKEN "$delset" #define QUOTE_TOKEN "$quote" #define SkipSpace(s) while (*(s) == ' ' || *(s) == '\t') s++ extern char *program; /* from main.c */ extern char *mctag; /* from main.c */ extern char *sctag; /* from main.c */ extern char *premsg; /* from main.c */ extern char *sufmsg; /* from main.c */ extern int suppress_error; /* from main.c */ extern void warning(char *); /* from genmsg.l */ typedef struct _SetID *SetID; typedef struct _MsgID *MsgID; typedef struct _SetID SetIDRec; struct _SetID { int id; char *comment; MsgID top; SetID next; }; typedef struct _MsgID MsgIDRec; struct _MsgID { int no_write; int id; char *msg; int line; char *file; char *comment; MsgID next; }; /* Top pointer of the setid list. */ static SetID setid_top; /* comment for messages. */ static char *msg_comment; /* comment for set numbers. */ static char *set_comment; /* List of set number's maximum message numbers. */ static int msgid_table[NL_SETMAX+1]; /* Quote character to surround messages. */ static char quote = QUOTE; /* Internal functions. */ static void add_msgid(SetID, int, char *, char *, int, int); static void add_setid(int, int, char *, char *, int, int); static SetID lookup_setid(int); static MsgID lookup_msgid(SetID, int, char *, char *, int); static void print_prefix(FILE *, char *, int, char *); static int is_bs_terminated(char *); static char *ustrdup(char *); static void makeup_msg(char **); void add_msg(int setid, int msgid, char *msg, char *file, int line, int no_write) { SetID si; if (si = lookup_setid(setid)) { if (lookup_msgid(si, msgid, msg, file, line)) { return; /* we already have the one. */ } else { add_msgid(si, msgid, msg, file, line, no_write); } } else { add_setid(setid, msgid, msg, file, line, no_write); } } int is_writable(char *file) { struct stat buf; if (stat(file, &buf) == -1) return (TRUE); if (access(file, W_OK) == 0) return (TRUE); return (FALSE); } void write_msgfile(char *file) { FILE *fp; SetID si = setid_top; char *mode = "w"; char pquote[2]; if (is_writable(file) == FALSE) { prg_err(gettext("cannot create \"%s\": permission denied"), file); return; } if (IsActiveMode(AppendMode)) { mode = "a"; } if ((fp = fopen(file, mode)) == NULL) { prg_err(gettext("cannot create \"%s\""), file); return; } if (quote) { pquote[0] = quote; } else { pquote[0] = '\0'; } pquote[1] = '\0'; /* AppendMode is already turned off if the file doesn't exist. */ if (!IsActiveMode(AppendMode)) { (void) fprintf(fp, "\n$quote %s\n\n", pquote); } while (si) { int is_set = FALSE; MsgID mi = si->top; while (mi) { char msg[NL_TEXTMAX+32]; /* 32 is some other stuff. */ if (mi->no_write) { mi = mi->next; continue; } if (is_set == FALSE) { if (si->comment && !IsActiveMode(BackCommentMode)) { (void) fprintf(fp, "\n"); print_prefix(fp, "$ ", TRUE, si->comment); (void) fprintf(fp, "$set\t%d\n", si->id); } else { (void) fprintf(fp, "\n$set\t%d\n", si->id); } if (si->comment && IsActiveMode(BackCommentMode)) { print_prefix(fp, "$ ", TRUE, si->comment); } (void) fprintf(fp, "\n"); is_set = TRUE; } makeup_msg(&(mi->msg)); (void) snprintf(msg, sizeof (msg), "%d\t%s%s%s\n", mi->id, pquote, mi->msg, pquote); if (!IsActiveMode(BackCommentMode)) { if (mi->line && mi->file && IsActiveMode(LineInfoMode)) { (void) fprintf(fp, "$ File:%s, line:%d\n", basename(mi->file), mi->line); } if (mi->comment) { print_prefix(fp, "$ ", TRUE, mi->comment); } if (IsActiveMode(DoubleLineMode)) { print_prefix(fp, "$ ", FALSE, msg); } } (void) fprintf(fp, "%s", msg); if (IsActiveMode(BackCommentMode)) { if (mi->line && mi->file && IsActiveMode(LineInfoMode)) { (void) fprintf(fp, "$ File:%s, line:%d\n", basename(mi->file), mi->line); } if (mi->comment) { print_prefix(fp, "$ ", TRUE, mi->comment); } if (IsActiveMode(DoubleLineMode)) { print_prefix(fp, "$ ", FALSE, msg); } } (void) fprintf(fp, "\n"); mi = mi->next; } si = si->next; } (void) fclose(fp); } static SetID lookup_setid(int id) { SetID si = setid_top; while (si) { if (si->id == id) { return (si); } si = si->next; } return (NULL); } static MsgID lookup_msgid(SetID si, int msgid, char *msg, char *file, int line) { MsgID mi = si->top; while (mi) { if (mi->id == msgid) { /* same setid & msgid, but different msg. */ if (strcmp(mi->msg, msg)) { src_err(file, line, gettext( "multiple messages: set number %d, message number %d\n" " current : \"%s\"\n" " previous: \"%s\" : \"%s\", line %d"), si->id, mi->id, msg, mi->msg, mi->file, mi->line); } return (mi); } mi = mi->next; } return (NULL); } static void add_msgid(SetID si, int msgid, char *msg, char *file, int line, int no_write) { MsgID mi = si->top, newmi, prev = NULL; int len = strlen(msg); if (msgid == 0) { src_err(file, line, gettext("improper message number: %d"), msgid); return; } if (msgid > NL_MSGMAX) { src_err(file, line, gettext("too large message number: %d"), msgid); return; } if (len > NL_TEXTMAX) { src_err(file, line, gettext("too long message text")); return; } while (mi) { if (mi->id > msgid) { break; } prev = mi; mi = mi->next; } if ((newmi = malloc(sizeof (MsgIDRec))) == NULL) { prg_err(gettext("fatal: out of memory")); exit(EXIT_FAILURE); } newmi->no_write = no_write; newmi->id = msgid; newmi->msg = ustrdup(msg); newmi->file = ustrdup(file); newmi->line = line; newmi->next = mi; if (msg_comment) { newmi->comment = ustrdup(msg_comment); free(msg_comment); msg_comment = NULL; } else { newmi->comment = NULL; } if (prev == NULL) { si->top = newmi; } else { prev->next = newmi; } } static void add_setid(int setid, int msgid, char *msg, char *file, int line, int no_write) { SetID si = setid_top, newsi, prev = NULL; while (si) { if (si->id > setid) { break; } prev = si; si = si->next; } if ((newsi = malloc(sizeof (SetIDRec))) == NULL) { prg_err(gettext("fatal: out of memory")); exit(EXIT_FAILURE); } newsi->id = setid; newsi->top = NULL; newsi->next = si; if (set_comment) { newsi->comment = ustrdup(set_comment); free(set_comment); set_comment = NULL; } else { newsi->comment = NULL; } if (prev == NULL) { setid_top = newsi; } else { prev->next = newsi; } add_msgid(newsi, msgid, msg, file, line, no_write); } static void print_prefix(FILE *fp, char *prefix, int rm_blank, char *str) { (void) fprintf(fp, "%s", prefix); while (*str) { (void) fputc(*str, fp); if (*str == '\n' && *(str+1) != '\0') { (void) fprintf(fp, "%s", prefix); if (rm_blank == TRUE) { str++; SkipSpace(str); continue; } } str++; } if (*(str-1) != '\n') { (void) fputc('\n', fp); } } int read_projfile(char *file) { FILE *fp; char line[LINE_MAX]; if (file == NULL) { return (0); } if ((fp = fopen(file, "r")) == NULL) { return (0); } while (fgets(line, sizeof (line), fp) != NULL) { char *p = line; int n, setid, msgid; SkipSpace(p); if (*p == '#' || *p == '\n') { continue; } n = sscanf(p, "%d %d", &setid, &msgid); if (n == 2) { if (setid > NL_SETMAX) { prg_err(gettext("%s: too large set number: %d"), file, setid); continue; } msgid_table[setid] = msgid; } else { prg_err(gettext( "warning: %s: missing or invalid entry"), file); } } (void) fclose(fp); return (1); } void write_projfile(char *file) { FILE *fp; register int i; if (is_writable(file) == FALSE) { prg_err(gettext("cannot create \"%s\": permission denied"), file); return; } if ((fp = fopen(file, "w")) == NULL) { prg_err(gettext("cannot create \"%s\""), file); return; } for (i = 1; i <= NL_SETMAX; i++) { if (msgid_table[i] > 0) { SetID si; char *com = NULL; if (IsActiveMode(SetCommentMode) && (si = lookup_setid(i)) && si->comment) { com = si->comment; } if (com && !IsActiveMode(BackCommentMode)) { print_prefix(fp, "# ", TRUE, com); } (void) fprintf(fp, "%d\t%d\n", i, msgid_table[i]); if (com && IsActiveMode(BackCommentMode)) { print_prefix(fp, "# ", TRUE, com); } } } (void) fclose(fp); } int get_msgid(char *file, int line, int setid, char *str) { SetID si = setid_top; int id = msgid_table[setid]; while (si) { if (si->id == setid) { MsgID mi = si->top; while (mi) { if (strcmp(mi->msg, str) == 0) { return (mi->id); } mi = mi->next; } } si = si->next; } id++; if (id > NL_MSGMAX) { src_err(file, line, gettext("run out of message number in set number: %d"), setid); return (NOMSGID); } return (msgid_table[setid] = id); } void set_msgid(int setid, int msgid) { if (msgid_table[setid] < msgid) { msgid_table[setid] = msgid; } } void add_comment(Mode mode, char *str) { char *tag = (mode == MsgCommentMode) ? mctag : sctag; char **comment = (mode == MsgCommentMode) ? &msg_comment : &set_comment; if (strstr(str, tag) == NULL) { return; } if (*comment) { free(*comment); } *comment = ustrdup(str); } void read_msgfile(char *file) { FILE *fp; char c = 0; int line = 0; int inmsg = FALSE; int setid = 0, unsetid = -1, msgid = 0; struct stat buf; if ((fp = fopen(file, "r")) == NULL) { prg_err(gettext("cannot open \"%s\""), file); ResetActiveMode(AppendMode); return; } if (stat(file, &buf) == -1 && buf.st_size == 0) { ResetActiveMode(AppendMode); return; } quote = c; /*CONSTCOND*/ while (1) { char buf[LINE_MAX]; char *ptr; char msg[NL_TEXTMAX]; if (fgets(buf, sizeof (buf), fp) == NULL) { break; } line++; ptr = &buf[0]; SkipSpace(ptr); if ((*ptr == '$' && (*(ptr+1) == ' ' || *(ptr+1) == '\t')) || ((*ptr == '\n') && inmsg == FALSE)) { inmsg = FALSE; continue; } if (strncmp(ptr, SET_TOKEN, sizeof (SET_TOKEN) - 1) == 0) { if (sscanf(ptr, "%*s %d", &setid) != 1) { setid = 0; } inmsg = FALSE; continue; } else if (strncmp(ptr, DELSET_TOKEN, sizeof (DELSET_TOKEN) - 1) == 0) { if (sscanf(ptr, "%*s %d", &unsetid) != 1) { unsetid = -1; } inmsg = FALSE; continue; } else if (strncmp(ptr, QUOTE_TOKEN, sizeof (QUOTE_TOKEN) - 1) == 0) { if (sscanf(ptr, "%*s %c", &c) != 1) { c = 0; } quote = c; inmsg = FALSE; continue; } if (setid == unsetid) { continue; } if (inmsg) { if (is_bs_terminated(ptr)) { (void) strlcat(msg, ptr, sizeof (msg)); inmsg = TRUE; } else { int len = strlen(ptr); *(ptr + len - 1) = '\0'; if (c && (*(ptr + len - 2) == c)) { *(ptr + len - 2) = '\0'; } (void) strlcat(msg, ptr, sizeof (msg)); add_msg(setid, msgid, msg, file, line, TRUE); inmsg = FALSE; } continue; } if (isdigit((unsigned char)*ptr)) { char *pptr; SkipSpace(ptr); msgid = (int)strtol(ptr, &pptr, 10); ptr = pptr; SkipSpace(ptr); if (is_bs_terminated(ptr)) { (void) memset(msg, 0, sizeof (msg)); if (c && (*ptr == c)) { ptr++; } (void) strlcpy(msg, ptr, sizeof (msg)); inmsg = TRUE; } else { int len = strlen(ptr); *(ptr + len - 1) = '\0'; if (c && ((*ptr == c) && (*(ptr + len - 2) == c))) { *(ptr + len - 2) = '\0'; ptr++; } add_msg(setid, msgid, ptr, file, line, TRUE); inmsg = FALSE; } } } (void) fclose(fp); } static int is_bs_terminated(char *msg) { int len = strlen(msg); while (--len >= 0) { if (msg[len] == ' ' || msg[len] == '\t' || msg[len] == '\n') { continue; } else if (msg[len] == '\\') { len--; if (len >= 0 && msg[len] == '\\') return (0); return (1); } else { return (0); } } return (0); } static char * ustrdup(char *str) { char *tmp = strdup(str); if (tmp == NULL) { prg_err(gettext("fatal: out of memory")); exit(EXIT_FAILURE); } return (tmp); } int file_copy(char *in, char *out) { int ret = TRUE; FILE *fin, *fout; int c; sigset_t newmask, oldmask; (void) sigemptyset(&newmask); (void) sigaddset(&newmask, SIGQUIT); (void) sigaddset(&newmask, SIGINT); (void) sigaddset(&newmask, SIGHUP); (void) sigaddset(&newmask, SIGTERM); (void) sigprocmask(SIG_BLOCK, &newmask, &oldmask); if ((fin = fopen(in, "r")) == NULL) { prg_err(gettext("cannot open \"%s\""), in); ret = FALSE; goto done; } if ((fout = fopen(out, "w")) == NULL) { prg_err(gettext("cannot create \"%s\""), out); ret = FALSE; goto done; } while ((c = getc(fin)) != EOF) (void) putc(c, fout); (void) fclose(fin); (void) fclose(fout); done: (void) sigprocmask(SIG_SETMASK, &oldmask, NULL); return (ret); } static void makeup_msg(char **pmsg) { char buf[NL_TEXTMAX]; char *msg; msg = *pmsg; buf[0] = '\0'; if (IsActiveMode(TripleMode) && strchr(msg, '%') == NULL) { /* there is no '%' in message. */ int len = strlen(msg); if (msg[len-2] == '\\' && msg[len-1] == 'n') { msg[len-2] = '\0'; (void) strlcat(buf, msg, sizeof (buf)); (void) strlcat(buf, msg, sizeof (buf)); (void) strlcat(buf, msg, sizeof (buf)); (void) strlcat(buf, "\\n", sizeof (buf)); } else { (void) strlcat(buf, msg, sizeof (buf)); (void) strlcat(buf, msg, sizeof (buf)); (void) strlcat(buf, msg, sizeof (buf)); } free(msg); *pmsg = ustrdup(buf); } msg = *pmsg; buf[0] = '\0'; if (IsActiveMode(PrefixMode)) { (void) strlcat(buf, premsg, sizeof (buf)); (void) strlcat(buf, msg, sizeof (buf)); free(msg); *pmsg = ustrdup(buf); } msg = *pmsg; buf[0] = '\0'; if (IsActiveMode(SuffixMode)) { int len = strlen(msg); if (msg[len-2] == '\\' && msg[len-1] == 'n') { msg[len-2] = '\0'; (void) strlcat(buf, msg, sizeof (buf)); (void) strlcat(buf, sufmsg, sizeof (buf)); (void) strlcat(buf, "\\n", sizeof (buf)); } else { (void) strlcat(buf, msg, sizeof (buf)); (void) strlcat(buf, sufmsg, sizeof (buf)); } free(msg); *pmsg = ustrdup(buf); } } void prg_err(char *fmt, ...) { va_list ap; va_start(ap, fmt); (void) fprintf(stderr, "%s: ", program); /* LINTED: E_SEC_PRINTF_VAR_FMT */ (void) vfprintf(stderr, fmt, ap); (void) fprintf(stderr, "\n"); va_end(ap); } void src_err(char *file, int line, char *fmt, ...) { va_list ap; if (suppress_error == TRUE) { return; } va_start(ap, fmt); (void) fprintf(stderr, gettext("\"%s\", line %d: "), file, line); /* LINTED: E_SEC_PRINTF_VAR_FMT */ (void) vfprintf(stderr, fmt, ap); (void) fprintf(stderr, "\n"); va_end(ap); }