xref: /illumos-gate/usr/src/cmd/gettext/gettext.c (revision 581cede61ac9c14d8d4ea452562a567189eead78)
1 /*
2  * CDDL HEADER START
3  *
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.
8  *
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.
13  *
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]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*	Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T	*/
28 /*	  All Rights Reserved  	*/
29 
30 /*
31  * Portions of this source code were derived from Berkeley 4.3 BSD
32  * under license from the Regents of the University of California.
33  */
34 
35 #pragma ident	"%Z%%M%	%I%	%E% SMI"
36 
37 #include <stdlib.h>
38 #include <unistd.h>
39 #include <stdio.h>
40 #include <string.h>
41 #include <locale.h>
42 
43 /*
44  * TEXTDOMAIN should be defined in Makefile
45  * in case it isn't, define it here
46  */
47 #if !defined(TEXT_DOMAIN)
48 #define	TEXT_DOMAIN "SYS_TEST"
49 #endif
50 
51 static char *
52 expand_metas(char *in)	/* walk thru string interpreting \n etc. */
53 {
54 	register char *out, *cp;
55 
56 	for (cp = out = in; *in != NULL; out++, in++) {
57 		if (*in == '\\') {
58 			switch (*++in) {
59 			case 'b' :
60 				*out = '\b';
61 				break;
62 			case 'f' :
63 				*out = '\f';
64 				break;
65 			case 'n' :
66 				*out = '\n';
67 				break;
68 			case 'r' :
69 				*out = '\r';
70 				break;
71 			case 't' :
72 				*out = '\t';
73 				break;
74 			case 'v' :
75 				*out = '\v';
76 				break;
77 			default:
78 				*out = *in;
79 				break;
80 			}
81 		} else
82 			*out = *in;
83 	}
84 	*out = NULL;
85 	return (cp);
86 }
87 
88 #define	ERR_USAGE \
89 	"Usage: gettext [-d domainname | --domain=domainname ]  " \
90 		"[domain] \"msgid\"\n" \
91 	"       gettext -s [-d domainname | --domain=domainname] [-e] [-n] "\
92 		"\"msgid\" ...\n"
93 
94 static void
95 usage(void) {
96 	(void) fprintf(stderr, gettext(ERR_USAGE));
97 	exit(-1);
98 }
99 
100 int
101 main(int argc, char *argv[])	/* shell script equivalent of gettext(3) */
102 {
103 	char	*domainpath, *msgid;
104 	char	*domain = NULL;
105 	char	c, *arg;
106 	int	exp_flag = 0;
107 	int	no_newline = 0;
108 	int	echo_flag = 0;
109 
110 	(void) setlocale(LC_ALL, "");
111 	(void) textdomain(TEXT_DOMAIN);
112 
113 	argv++;
114 	while (--argc > 1) {
115 		arg = *argv;
116 		if (*arg == '-') {
117 			if (!*(arg + 1)) {
118 				/* not an option */
119 				break;
120 			}
121 loop:
122 			if ((c = *++arg) == '\0') {
123 				/* next argument */
124 				argv++;
125 				continue;
126 			} else if (c != '-') {
127 				switch (c) {
128 				case 'd':
129 					/* domainname */
130 					if (*(arg + 1)) {
131 						/*
132 						 * no spaces between -d and
133 						 * optarg
134 						 */
135 						domain = ++arg;
136 						argv++;
137 						continue;
138 					}
139 					if (--argc > 1) {
140 						domain = *++argv;
141 						argv++;
142 						continue;
143 					}
144 					/* not enough args */
145 					usage();
146 					/* NOTREACHED */
147 					break;
148 				case 'e':
149 					/* enable escape sequence expansion */
150 					exp_flag = 1;
151 					goto loop;
152 					/* NOTREACHED */
153 				case 'n':
154 					/* suppress tailing newline */
155 					no_newline = 1;
156 					goto loop;
157 					/* NOTREACHED */
158 				case 's':
159 					echo_flag = 1;
160 					goto loop;
161 					/* NOTREACHED */
162 				default:
163 					/* illegal option */
164 					usage();
165 					/* NOTREACHED */
166 					break;
167 				}
168 				/* NOTREACHED */
169 			}
170 			/* c == '-' */
171 			if (*(arg + 1) == '\0') {
172 				/* "--" found, option end */
173 				argv++;
174 				argc--;
175 				break;
176 			}
177 
178 			/* long option */
179 			arg++;
180 			if (strncmp(arg, "domain=", 7) == 0) {
181 				/* domainname */
182 				arg += 7;
183 				if (*arg == '\0') {
184 					/* illegal option */
185 					usage();
186 					/* NOTREACHED */
187 				}
188 				domain = arg;
189 				argv++;
190 				continue;
191 			}
192 			/* illegal option */
193 			usage();
194 			/* NOTREACHED */
195 		}
196 		break;
197 	}
198 	if (argc == 0) {
199 		usage();
200 		/* NOTREACHED */
201 	}
202 
203 	domainpath = getenv("TEXTDOMAINDIR");
204 	if (!echo_flag) {
205 		/* traditional mode */
206 		if (argc == 2) {
207 			/*
208 			 * textdomain is specified by the argument.
209 			 */
210 			domain = *argv++;
211 		} else if (!domain) {
212 			/*
213 			 * textdomain is not specified by the argument.
214 			 * TEXTDOMAIN will be used.
215 			 */
216 			domain = getenv("TEXTDOMAIN");
217 			if (!domain) {
218 				/*
219 				 * no domain specified
220 				 * Just print the argument given.
221 				 */
222 				(void) printf("%s", expand_metas(*argv));
223 				exit(1);
224 			}
225 		}
226 		if (domainpath) {
227 			(void) bindtextdomain(domain, domainpath);
228 		}
229 		msgid = expand_metas(*argv);
230 		(void) fputs(dgettext(domain, msgid), stdout);
231 		exit(*domain == NULL);
232 	}
233 	/* echo mode */
234 	if (!domain) {
235 		domain = getenv("TEXTDOMAIN");
236 	}
237 	if (domainpath && domain) {
238 		(void) bindtextdomain(domain, domainpath);
239 	}
240 	while (argc-- > 0) {
241 		if (exp_flag)
242 			msgid = expand_metas(*argv++);
243 		else
244 			msgid = *argv++;
245 		(void) fputs(domain ? dgettext(domain, msgid) : msgid,
246 			stdout);
247 
248 		if (argc > 0)
249 			(void) fputc(' ', stdout);
250 	}
251 	if (!no_newline)
252 		(void) fputc('\n', stdout);
253 
254 	return ((domain == NULL) || (*domain == NULL));
255 }
256