8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / cmd / mkmsgs / mkmsgs.c
blob09e86ed2cf4047e2862bb1427c52ae926fbedbc3
1 /*
2 * CDDL HEADER START
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.
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.
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]
20 * CDDL HEADER END
23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
31 #pragma ident "%Z%%M% %I% %E% SMI"
33 /*
34 * Create message files in a specific format.
35 * the gettxt message retrieval function must know the format of
36 * the data file created by this utility.
38 * FORMAT OF MESSAGE FILES
40 __________________________
41 | Number of messages |
42 --------------------------
43 | offset to the 1st mesg |
44 --------------------------
45 | offset to the 2nd mesg |
46 --------------------------
47 | offset to the 3rd mesg |
48 --------------------------
49 | . |
50 | . |
51 | . |
52 --------------------------
53 | offset to the nth mesg |
54 --------------------------
55 | message #1
56 --------------------------
57 | message #2
58 --------------------------
59 | message #3
60 --------------------------
64 --------------------------
65 | message #n
66 --------------------------
70 #include <stdio.h>
71 #include <stdlib.h>
72 #include <unistd.h>
73 #include <string.h>
74 #include <sys/types.h>
75 #include <sys/stat.h>
76 #include <signal.h>
77 #include <errno.h>
78 #include <libgen.h>
80 /*
81 * Definitions
84 #define LINESZ 2048 /* max line in input base */
85 #define STDERR 2
86 #define P_locale "/usr/lib/locale/" /* locale info directory */
87 #define L_locale sizeof(P_locale)
88 #define MESSAGES "/LC_MESSAGES/" /* messages category */
91 * internal functions
94 static char *syserr(void); /* Returns description of error */
95 static void usage(void); /* Displays valid invocations */
96 static int mymkdir(char *); /* Creates sub-directories */
97 static void clean(int); /* removes work file */
100 * static variables
103 static char *cmdname; /* Last qualifier of arg0 */
104 static char *workp; /* name of the work file */
107 main(argc, argv)
108 int argc;
109 char *argv[];
111 int c; /* contains option letter */
112 char *ifilep; /* input file name */
113 char *ofilep; /* output file name */
114 char *localep; /* locale name */
115 char *localedirp; /* full-path name of parent directory
116 * of the output file */
117 char *outfilep; /* full-path name of output file */
118 FILE *fp_inp; /* input file FILE pointer */
119 FILE *fp_outp; /* output file FILE pointer */
120 char *bufinp, *bufworkp; /* pointers to input and work areas */
121 int *bufoutp; /* pointer to the output area */
122 char *msgp; /* pointer to the a message */
123 int num_msgs; /* number of messages in input file */
124 int iflag; /* -i option was specified */
125 int oflag; /* -o option was slecified */
126 int nitems; /* number of bytes to write */
127 char *pathoutp; /* full-path name of output file */
128 struct stat buf; /* buffer to stat the work file */
129 unsigned size; /* used for argument to malloc */
130 int i;
132 /* Initializations */
134 localep = (char *)NULL;
135 num_msgs = 0;
136 iflag = 0;
137 oflag = 0;
139 /* Get name of command */
141 if (cmdname = strrchr(argv[0], '/'))
142 ++cmdname;
143 else
144 cmdname = argv[0];
146 /* Check for invalid number of arguments */
148 if (argc < 3 && argc > 6)
149 usage();
151 /* Get command line options */
153 while ((c = getopt(argc, argv, "oi:")) != EOF) {
154 switch (c) {
155 case 'o':
156 oflag++;
157 break;
158 case 'i':
159 iflag++;
160 localep = optarg;
161 break;
162 case '?':
163 usage();
164 break;
168 /* Initialize pointers to input and output file names */
170 ifilep = argv[optind];
171 ofilep = argv[optind + 1];
173 /* check for invalid invocations */
175 if (iflag && oflag && argc != 6)
176 usage();
177 if (iflag && ! oflag && argc != 5)
178 usage();
179 if (! iflag && oflag && argc != 4)
180 usage();
181 if (! iflag && ! oflag && argc != 3)
182 usage();
184 /* Construct a full-path to the output file */
186 if (localep) {
187 size = L_locale + strlen(localep) +
188 sizeof(MESSAGES) + strlen(ofilep);
189 if ((pathoutp = malloc(2 * (size + 1))) == NULL) {
190 (void)fprintf(stderr, "%s: malloc error (size = %d)\n",
191 cmdname, size);
192 exit(1);
194 localedirp = pathoutp + size + 1;
195 (void)strcpy(pathoutp, P_locale);
196 (void)strcpy(&pathoutp[L_locale - 1], localep);
197 (void)strcat(pathoutp, MESSAGES);
198 (void)strcpy(localedirp, pathoutp);
199 (void)strcat(pathoutp, ofilep);
202 /* Check for overwrite error conditions */
204 if (! oflag) {
205 if (iflag) {
206 if (access(pathoutp, 0) == 0) {
207 (void)fprintf(stderr, "%s: Message file \"%s\" already exists;\ndid not overwrite it\n", cmdname, pathoutp);
208 if (localep)
209 free(pathoutp);
210 exit(1);
213 else
214 if (access(ofilep, 0) == 0) {
215 (void)fprintf(stderr, "%s: Message file \"%s\" already exists;\ndid not overwrite it\n", cmdname, ofilep);
216 if (localep)
217 free(pathoutp);
218 exit(1);
222 /* Open input file */
223 if ((fp_inp = fopen(ifilep, "r")) == NULL) {
224 (void)fprintf(stderr, "%s: %s: %s\n",
225 cmdname, ifilep, syserr());
226 exit(1);
229 /* Allocate buffer for input and work areas */
231 if ((bufinp = malloc(2 * LINESZ)) == NULL) {
232 (void)fprintf(stderr, "%s: malloc error (size = %d)\n",
233 cmdname, 2 * LINESZ);
234 exit(1);
236 bufworkp = bufinp + LINESZ;
238 if (sigset(SIGINT, SIG_IGN) == SIG_DFL)
239 (void)sigset(SIGINT, clean);
241 /* Open work file */
243 workp = tempnam(".", "xx");
244 if ((fp_outp = fopen(workp, "a+")) == NULL) {
245 (void)fprintf(stderr, "%s: %s: %s\n", cmdname, workp, syserr());
246 if (localep)
247 free(pathoutp);
248 free(bufinp);
249 exit(1);
252 /* Search for C-escape sequences in input file and
253 * replace them by the appropriate characters.
254 * The modified lines are copied to the work area
255 * and written to the work file */
257 for(;;) {
258 if (!fgets(bufinp, LINESZ, fp_inp)) {
259 if (!feof(fp_inp)) {
260 (void)fprintf(stderr,"%s: %s: %s\n",
261 cmdname, ifilep, syserr());
262 free(bufinp);
263 if (localep)
264 free(pathoutp);
265 exit(1);
267 break;
269 if(*(bufinp+strlen(bufinp)-1) != '\n') {
270 (void)fprintf(stderr, "%s: %s: data base file: error on line %d\n", cmdname, ifilep, num_msgs);
271 free(bufinp);
272 exit(1);
274 *(bufinp + strlen(bufinp) -1) = (char)0; /* delete newline */
275 num_msgs++;
276 (void)strccpy(bufworkp, bufinp);
277 nitems = strlen(bufworkp) + 1;
278 if (fwrite(bufworkp, sizeof(*bufworkp), nitems, fp_outp) != nitems) {
279 (void)fprintf(stderr, "%s: %s: %s\n",
280 cmdname, workp, syserr());
281 exit(1);
284 free(bufinp);
285 (void)fclose(fp_outp);
287 /* Open and stat the work file */
289 if ((fp_outp = fopen(workp, "r")) == NULL) {
290 (void)fprintf(stderr, "%s: %s: %s\n", cmdname, workp, syserr());
291 exit(1);
293 if ((stat(workp, &buf)) != 0) {
294 (void)fprintf(stderr, "%s: %s: %s\n", cmdname, workp, syserr());
297 /* Find the size of the output message file
298 * and copy the control information and the messages
299 * to the output file */
301 size = sizeof(int) + num_msgs * sizeof(int) + buf.st_size;
303 if ( (bufoutp = (int *)malloc((uint)size)) == NULL ) {
304 (void)fprintf(stderr, "%s: malloc error (size = %d)\n",
305 cmdname, size);
306 exit(1);
308 bufinp = (char *)bufoutp;
309 if ( (fread(bufinp + sizeof(int) + num_msgs * sizeof(int), sizeof(*bufinp), buf.st_size, fp_outp)) != buf.st_size ) {
310 free(bufinp);
311 (void) fprintf(stderr, "%s: %s: %s\n", cmdname, workp, syserr());
313 (void) fclose(fp_outp);
314 (void) unlink(workp);
315 free(workp);
316 msgp = bufinp + sizeof(int) + num_msgs * sizeof(int);
317 *bufoutp = num_msgs;
318 *(bufoutp + 1) = (bufinp + sizeof(int) + num_msgs * sizeof(int)) - bufinp;
320 for(i = 2; i <= num_msgs; i++) {
321 *(bufoutp + i) = (msgp + strlen(msgp) + 1) - bufinp;
322 msgp = msgp + strlen(msgp) + 1;
325 if (iflag) {
326 outfilep = pathoutp;
327 if (mymkdir(localedirp) == 0) {
328 free(bufinp);
329 if (localep)
330 free(pathoutp);
331 exit(1);
334 else
335 outfilep = ofilep;
337 if ((fp_outp = fopen(outfilep, "w")) == NULL) {
338 (void)fprintf(stderr, "%s: %s: %s\n",
339 cmdname, outfilep, syserr());
340 free(bufinp);
341 if (localep)
342 free(pathoutp);
343 exit(1);
346 if (fwrite((char *)bufinp, sizeof(*bufinp), size, fp_outp) != size) {
347 (void)fprintf(stderr, "%s: %s: %s\n",
348 cmdname, ofilep, syserr());
349 free(bufinp);
350 if (localep)
351 free(pathoutp);
352 exit(1);
354 free(bufinp);
355 if (localep)
356 free(pathoutp);
357 return (0);
361 * syserr()
363 * Return a pointer to a system error message.
365 static char *
366 syserr()
368 return (strerror(errno));
371 static void
372 usage()
374 (void)fprintf(stderr, "Usage: %s [-o] inputstrings outputmsgs\n",
375 cmdname);
376 (void)fprintf(stderr, " %s [-o] [-i locale] inputstrings outputmsgs\n", cmdname);
377 exit(1);
380 static int
381 mymkdir(localdir)
382 char *localdir;
384 char *dirp;
385 char *s1 = localdir;
386 char *path;
388 if ((path = malloc(strlen(localdir)+1)) == NULL)
389 return(0);
390 *path = '\0';
391 while( (dirp = strtok(s1, "/")) != NULL ) {
392 s1 = (char *)NULL;
393 (void)strcat(path, "/");
394 (void)strcat(path, dirp);
395 if (access(path, 3) == 0)
396 continue;
397 if (mkdir(path, 0777) == -1) {
398 (void)fprintf(stderr, "%s: %s: %s\n",
399 cmdname, path, syserr());
400 free(path);
401 return(0);
404 free(path);
405 return(1);
408 /* ARGSUSED */
409 static void
410 clean(int sig)
412 (void)sigset(SIGINT, SIG_IGN);
413 if (workp)
414 (void) unlink(workp);
415 exit(1);