1 /*
2  *                           TERMS AND CONDITIONS
3  *                                   FOR
4  *                         OPEN SOURCE CODE LICENSE
5  *                               Version 1.1
6  *
7  * Japan Registry Services Co., Ltd. ("JPRS"), a Japanese corporation
8  * having its head office at Chiyoda First Bldg. East 13F 3-8-1 Nishi-Kanda,
9  * Chiyoda-ku, Tokyo 101-0065, Japan, grants you the license for open source
10  * code specified in EXHIBIT A the "Code" subject to the following Terms and
11  * Conditions ("OSCL").
12  *
13  * 1. License Grant.
14  *   JPRS hereby grants you a worldwide, royalty-free, non-exclusive
15  *   license, subject to third party intellectual property claims:
16  *   (a) under intellectual property rights (other than patent or
17  *       trademark) licensable by JPRS to use, reproduce, modify, display,
18  *       perform, sublicense and distribute the Code (or portions thereof)
19  *       with or without modifications, and/or as part of a derivative work;
20  *       or
21  *   (b) under claims of the infringement through the making, using,
22  *       offering to sell and/or otherwise disposing the JPRS Revised Code
23  *       (or portions thereof);
24  *   (c) the licenses granted in this Section 1(a) and (b) are effective on
25  *       the date JPRS first distributes the Code to you under the terms of
26  *       this OSCL;
27  *   (d) Notwithstanding the above stated terms, no patent license is
28  *       granted:
29  *       1)  for a code that you delete from the Code;
30  *       2)  separate from the Code; or
31  *       3)  for infringements caused by:
32  *            i) modification of the Code; or
33  *           ii) combination of the Code with other software or devices.
34  *
35  * 2. Consents.
36  *   You agree that:
37  *   (a) you must include a copy of this OSCL and the notice set forth in
38  *       EXHIBIT A with every copy of the Code you distribute;
39  *   (b) you must include a copy of this OSCL and the notice set forth in
40  *       EXHIBIT A with every copy of binary form of the Code in the
41  *       documentation and/or other materials provided with the distribution;
42  *   (c) you may not offer or impose any terms on any source code version
43  *       that alters or restricts the applicable version of this OSCL or
44  *       the recipients' rights hereunder.
45  *   (d) If the terms and conditions are set forth in EXHIBIT A, you must
46  *       comply with those terms and conditions.
47  *
48  * 3. Proprietary Information.
49  *   All trademarks, service marks, patents, copyrights, trade secrets, and
50  *   other proprietary rights in or related to the Code are and will remain
51  *   the exclusive property of JPRS or its licensors, whether or not
52  *   specifically recognized or perfected under local law except specified
53  *   in this OSCL; provided however you agree and understand that the JPRS
54  *   name may not be used to endorse or promote this Code without prior
55  *   written approval of JPRS.
56  *
57  * 4. WARRANTY DISCLAIMER.
58  *   JPRS MAKES NO REPRESENTATIONS AND WARRANTIES REGARDING THE USE OF THE
59  *   CODE, NOR DOES JPRS MAKE ANY REPRESENTATIONS THAT THE CODE WILL BECOME
60  *   COMMERCIALLY AVAILABLE. JPRS, ITS AFFILIATES, AND ITS SUPPLIERS DO NOT
61  *   WARRANT OR REPRESENT THAT THE CODE IS FREE OF ERRORS OR THAT THE CODE
62  *   IS SUITABLE FOR TRANSLATION AND/OR LOCALIZATION. THE CODE IS PROVIDED
63  *   ON AN "AS IS" BASIS AND JPRS AND ITS SUPPLIERS HAVE NO OBLIGATION TO
64  *   CORRECT ERRORS OR TO SUPPORT THE CODE UNDER THIS OSCL FOR ANY REASON.
65  *   TO THE FULL EXTENT PERMITTED BY LAW, ALL OBLIGATIONS ARE HEREBY
66  *   EXCLUDED WHETHER EXPRESS, STATUTORY OR IMPLIED UNDER LAW, COURSE OF
67  *   DEALING, CUSTOM, TRADE USAGE, ORAL OR WRITTEN STATEMENT OR OTHERWISE,
68  *   INCLUDING BUT NOT LIMITED TO ANY IMPLIED WARRANTIES OF MERCHANTABILITY
69  *   OR FITNESS FOR A PARTICULAR PURPOSE CONCERNING THE CODE.
70  *
71  * 5. NO LIABILITY.
72  *   UNDER NO CIRCUMSTANCES SHALL JPRS AND/OR ITS AFFILIATES, LICENSORS, OR
73  *   REPRESENTATIVES BE LIABLE FOR ANY DAMAGES INCLUDING BUT NOT LIMITED TO
74  *   CONSEQUENTIAL, INDIRECT, SPECIAL, PUNITIVE OR INCIDENTAL DAMAGES,
75  *   WHETHER FORESEEABLE OR UNFORESEEABLE, BASED ON YOUR CLAIMS, INCLUDING,
76  *   BUT NOT LIMITED TO, CLAIMS FOR LOSS OF DATA, GOODWILL, PROFITS, USE OF
77  *   MONEY, INTERRUPTION IN USE OR AVAILABILITY OF DATA, STOPPAGE, IMPLIED
78  *   WARRANTY, BREACH OF CONTRACT, MISREPRESENTATION, NEGLIGENCE, STRICT
79  *   LIABILITY IN TORT, OR OTHERWISE.
80  *
81  * 6. Indemnification.
82  *   You hereby agree to indemnify, defend, and hold harmless JPRS for any
83  *   liability incurred by JRPS due to your terms of warranty, support,
84  *   indemnity, or liability offered by you to any third party.
85  *
86  * 7. Termination.
87  * 7.1 This OSCL shall be automatically terminated in the events that:
88  *   (a) You fail to comply with the terms herein and fail to cure such
89  *       breach within 30 days of becoming aware of the breach;
90  *   (b) You initiate patent or copyright infringement litigation against
91  *       any party (including a cross-claim or counterclaim in a lawsuit)
92  *       alleging that the Code constitutes a direct or indirect patent or
93  *       copyright infringement, in such case, this OSCL to you shall
94  *       terminate as of the date such litigation is filed;
95  * 7.2 In the event of termination under Sections 7.1(a) or 7.1(b) above,
96  *     all end user license agreements (excluding distributors and
97  *     resellers) which have been validly granted by You or any distributor
98  *     hereunder prior to termination shall survive termination.
99  *
100  *
101  * 8. General.
102  *   This OSCL shall be governed by, and construed and enforced in
103  *   accordance with, the laws of Japan. Any litigation or arbitration
104  *   between the parties shall be conducted exclusively in Tokyo, Japan
105  *   except written consent of JPRS provides other venue.
106  *
107  *
108  *                                EXHIBIT A
109  *
110  * The original open source code of idnkit-2 is idnkit-1.0 developed and
111  * conceived by Japan Network Information Center ("JPNIC"), a Japanese
112  * association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
113  * Chiyoda-ku, Tokyo 101-0047, Japan, and JPRS modifies above original code
114  * under following Terms and Conditions set forth by JPNIC.
115  *
116  *                                  JPNIC
117  *
118  * Copyright (c) 2000-2002 Japan Network Information Center.  All rights reserved.
119  *
120  * By using this file, you agree to the terms and conditions set forth bellow.
121  *
122  *                       LICENSE TERMS AND CONDITIONS
123  *
124  * The following License Terms and Conditions apply, unless a different
125  * license is obtained from Japan Network Information Center ("JPNIC"),
126  * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
127  * Chiyoda-ku, Tokyo 101-0047, Japan.
128  *
129  * 1. Use, Modification and Redistribution (including distribution of any
130  *    modified or derived work) in source and/or binary forms is permitted
131  *    under this License Terms and Conditions.
132  *
133  * 2. Redistribution of source code must retain the copyright notices as they
134  *    appear in each source code file, this License Terms and Conditions.
135  *
136  * 3. Redistribution in binary form must reproduce the Copyright Notice,
137  *    this License Terms and Conditions, in the documentation and/or other
138  *    materials provided with the distribution. For the purposes of binary
139  *    distribution the "Copyright Notice" refers to the following language:
140  *    "Copyright (c) 2000-2002 Japan Network Information Center.  All rights reserved."
141  *
142  * 4. The name of JPNIC may not be used to endorse or promote products
143  *    derived from this Software without specific prior written approval of
144  *    JPNIC.
145  *
146  * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
147  *    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
148  *    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
149  *    PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
150  *    FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
151  *    CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
152  *    SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
153  *    BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
154  *    WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
155  *    OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
156  *    ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
157  *
158  *
159  *                        JPRS Public License Notice
160  *                                   For
161  *                                idnkit-2.
162  *
163  * The contents of this file are subject to the Terms and Conditions for
164  * the Open Source Code License (the "OSCL"). You may not use this file
165  * except in compliance with above terms and conditions. A copy of the OSCL
166  * is available at <http://jprs.co.jp/idn/>.
167  * The JPRS Revised Code is idnkit-2.
168  * The Initial Developer of the JPRS Revised Code is Japan Network
169  * Information Center ("JPNIC"), a Japanese association,
170  * Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda, Chiyoda-ku, Tokyo
171  * 101-0047, Japan.
172  * "Copyright (c) 2000-2002 Japan Network Information Center.  All rights reserved."
173  * "Copyright (c) 2010-2012 Japan Registry Services Co., Ltd.  All rights reserved."
174  * Contributor(s): ______________________________________.
175  *
176  * If you wish to allow use of your version of this file only under the
177  * above License(s) and not to allow others to use your version of this
178  * file, please indicate your decision by deleting the relevant provisions
179  * above and replacing them with the notice and other provisions required
180  * by the above License(s). If you do not delete the relevant provisions,
181  * a recipient may use your version of this file under either the above
182  * License(s).
183  */
184 
185 /*
186  * idncheck -- Check an internatinalized domain name and print the result.
187  */
188 
189 #include <config.h>
190 
191 #include <stddef.h>
192 #include <stdarg.h>
193 #include <stdio.h>
194 #include <stdlib.h>
195 #include <string.h>
196 #include <errno.h>
197 #ifdef HAVE_LOCALE_H
198 #include <locale.h>
199 #endif
200 
201 #include <idn/result.h>
202 #include <idn/punycode.h>
203 #include <idn/res.h>
204 #include <idn/resconf.h>
205 #include <idn/util.h>
206 #include <idn/utf8.h>
207 #include <idn/version.h>
208 
209 /*
210  * Exit codes.
211  */
212 #define IDNCHECK_EXITCODE_SUCCESS	0
213 #define IDNCHECK_EXITCODE_CHECKERROR	2
214 #define IDNCHECK_EXITCODE_FAILURE	3
215 
216 /*
217  * Domain name registration / lookup procotols.
218  */
219 typedef enum idncheck_protocol {
220 	idncheck_lookup = 0,
221 	idncheck_registration = 1
222 } idncheck_protocol_t;
223 
224 /*
225  * Parsing result of command line arguments.
226  */
227 typedef struct {
228 	char *in_code;
229 	char *conf_file;
230 	int no_conf;
231 	idncheck_protocol_t protocol;
232 	char *localcheck_file;
233 	idn_action_t skip_actions;
234 	char *name;
235 	int quiet;
236 	int test;
237 }  idncheck_option_t;
238 
239 /*
240  * Quiet mode flag.
241  */
242 int quiet_mode = 0;
243 
244 static void	idncheck_option_init(idncheck_option_t *option);
245 static int	parse_command_line(int ac, char **av,
246 				   idncheck_option_t *option);
247 static int	parse_skip(const char *s, idn_action_t *action);
248 static int	create_resconf(idn_resconf_t *resconf, int no_conf,
249 			       const char *conf_file,
250 			       const char *localencoding,
251 			       const char *localcheck_file);
252 static void	print_test_status(idn_resconf_t conf);
253 static void	print_version(void);
254 static void	print_usage(void);
255 static void	errormsg(const char *fmt, ...);
256 
257 int
main(int ac,char ** av)258 main(int ac, char **av) {
259 	idn_result_t r;
260 	int exit_code = IDNCHECK_EXITCODE_SUCCESS;
261 	idncheck_option_t option;
262 	idn_action_t actions;
263 	idn_resconf_t resconf = NULL;
264 
265 #ifdef HAVE_SETLOCALE
266 	setlocale(LC_ALL, "");
267 #endif
268 
269 	/*
270 	 * Parse command line options.
271 	 */
272 	idncheck_option_init(&option);
273 	if (!parse_command_line(ac, av, &option)) {
274 		errormsg("try 'idncheck -help' for more information.\n");
275 		exit_code = IDNCHECK_EXITCODE_FAILURE;
276 		goto ret;
277 	}
278 
279 	quiet_mode = option.quiet;
280 
281 	/*
282 	 * Initialize idnkit library.
283 	 */
284 	r = idn_resconf_initialize();
285 	if (r != idn_success) {
286 		errormsg("error initializing library\n");
287 		exit_code = IDNCHECK_EXITCODE_FAILURE;
288 		goto ret;
289 	}
290 
291 	/*
292 	 * Create a resource context.
293 	 */
294 	if (!create_resconf(&resconf, option.no_conf, option.conf_file,
295 			    option.in_code, option.localcheck_file)) {
296 		exit_code = IDNCHECK_EXITCODE_FAILURE;
297 		goto ret;
298 	}
299 
300 	/*
301 	 * Determine main actions.
302 	 */
303 	if (option.protocol == idncheck_registration)
304 		actions = IDN_CHECK_REGIST & ~option.skip_actions;
305 	else
306 		actions = IDN_CHECK_LOOKUP & ~option.skip_actions;
307 	if (option.localcheck_file != NULL &&
308 	    !(option.skip_actions & ~IDN_LOCALCHECK)) {
309 		actions |= IDN_LOCALCHECK;
310 	}
311 
312 	/*
313 	 * Test mode.
314 	 */
315 	if (option.test) {
316 		print_test_status(resconf);
317 		goto ret;
318 	}
319 
320 	/*
321 	 * Encode two names and compare them.
322 	 */
323 	r = idn_res_checkname(resconf, actions, option.name);
324 
325 	if (r == idn_success) {
326 		errormsg("passed.\n");
327 	} else if (r == idn_prohcheck_error ||
328 		   r == idn_unascheck_error ||
329 		   r == idn_nfccheck_error ||
330 		   r == idn_prefcheck_error ||
331 		   r == idn_hyphcheck_error ||
332 		   r == idn_combcheck_error ||
333 		   r == idn_ctxjcheck_error ||
334 		   r == idn_ctxocheck_error ||
335 		   r == idn_bidicheck_error ||
336 		   r == idn_localcheck_error ||
337 		   r == idn_lencheck_error ||
338 		   r == idn_rtcheck_error ||
339 		   r == idn_tr46check_error) {
340 		errormsg("%s\n", idn_result_tostring(r));
341 		exit_code = IDNCHECK_EXITCODE_CHECKERROR;
342 	} else if (r != idn_success) {
343 		errormsg("%s\n", idn_result_tostring(r));
344 		exit_code = IDNCHECK_EXITCODE_FAILURE;
345 	}
346 
347 ret:
348 	if (resconf != NULL)
349 		idn_resconf_destroy(resconf);
350 
351 	return (exit_code);
352 }
353 
354 static void
idncheck_option_init(idncheck_option_t * option)355 idncheck_option_init(idncheck_option_t *option) {
356 	option->in_code         = NULL;
357 	option->conf_file       = NULL;
358 	option->no_conf         = 0;
359 	option->protocol        = idncheck_registration;
360 	option->localcheck_file = NULL;
361 	option->skip_actions    = 0;
362 	option->name            = NULL;
363 	option->quiet           = 0;
364 	option->test            = 0;
365 }
366 
367 /*
368  * Parse command line arguments.
369  */
370 static int
parse_command_line(int ac,char ** av,idncheck_option_t * option)371 parse_command_line(int ac, char **av, idncheck_option_t *option) {
372 	ac--;
373 	av++;
374 	while (ac > 0 && **av == '-') {
375 		if (strcmp(*av, "--") == 0) {
376 			ac--;
377 			av++;
378 			break;
379 		} else if (strcmp(*av, "-in") == 0 ||
380 		    strcmp(*av, "-i") == 0) {
381 			if (ac < 2) {
382 				errormsg("option '%s' requires an argument.\n", *av);
383 				return (0);
384 			}
385 			option->in_code = av[1];
386 			ac--;
387 			av++;
388 		} else if (strcmp(*av, "-conf") == 0 ||
389 			   strcmp(*av, "-c") == 0) {
390 			if (ac < 2) {
391 				errormsg("option '%s' requires an argument.\n", *av);
392 				return (0);
393 			}
394 			option->conf_file = av[1];
395 			ac--;
396 			av++;
397 		} else if (strcmp(*av, "-noconf") == 0 ||
398 			   strcmp(*av, "-C") == 0) {
399 			option->no_conf = 1;
400 		} else if (strcmp(*av, "-registration") == 0 ||
401 			   strcmp(*av, "-g") == 0) {
402 			option->protocol = idncheck_registration;
403 		} else if (strcmp(*av, "-lookup") == 0 ||
404 			   strcmp(*av, "-l") == 0) {
405 			option->protocol = idncheck_lookup;
406 		} else if (strcmp(*av, "-nomap") == 0 ||
407 			   strcmp(*av, "-M") == 0) {
408 			if (!parse_skip("map", &option->skip_actions))
409 				return (0);
410 		} else if (strcmp(*av, "-skip") == 0) {
411 			if (ac < 2) {
412 				errormsg("option '%s' requires an argument.\n", *av);
413 				return (0);
414 			}
415 			if (!parse_skip(av[1], &option->skip_actions)) {
416 				errormsg("invalid argument to option '-skip'.\n", *av);
417 				return (0);
418 			}
419 			ac--;
420 			av++;
421 		} else if (strcmp(*av, "-localcheck") == 0 ||
422 			   strcmp(*av, "-e") == 0) {
423 			if (ac < 2) {
424 				errormsg("option '%s' requires an argument.\n", *av);
425 				return (0);
426 			}
427 			option->localcheck_file = av[1];
428 			ac--;
429 			av++;
430 		} else if (strcmp(*av, "-quiet") == 0 ||
431 			   strcmp(*av, "-q") == 0) {
432 			option->quiet = 1;
433 		} else if (strcmp(*av, "-test") == 0 ||
434 			   strcmp(*av, "-t") == 0) {
435 			option->test = 1;
436 		} else if (strcmp(*av, "-version") == 0 ||
437 			   strcmp(*av, "-v") == 0) {
438 			print_version();
439 			exit(IDNCHECK_EXITCODE_SUCCESS);
440 		} else if (strcmp(*av, "-help") == 0 ||
441 			   strcmp(*av, "-h") == 0) {
442 			print_usage();
443 			exit(IDNCHECK_EXITCODE_SUCCESS);
444 		} else {
445 			errormsg("unrecognized option '%s'.\n", *av);
446 			return (0);
447 		}
448 		ac--;
449 		av++;
450 	}
451 
452 	if (option->test) {
453 		option->name = "";
454 	} else if (ac > 1) {
455 		errormsg("too many arguments.\n");
456 		return (0);
457 	} else if (ac < 1) {
458 		errormsg("too few argument.\n");
459 		return (0);
460 	} else {
461 		option->name = av[0];
462 	}
463 
464 	/*
465 	 * Resolve conflicts between options.
466 	 */
467 	if (option->no_conf && option->conf_file != NULL)
468 		option->conf_file = NULL;
469 
470 	return (1);
471 }
472 
473 struct idncheck_actionmap {
474 	char *name;
475 	idn_action_t value;
476 };
477 
478 static const struct idncheck_actionmap action_maps[] = {
479 	{"map", 		IDN_MAP},
480 	{"asclower", 		IDN_ASCLOWER},
481 	{"rtconv", 		IDN_RTCONV},
482 	{"prohcheck", 		IDN_PROHCHECK},
483 	{"unascheck", 		IDN_UNASCHECK},
484 	{"nfccheck", 		IDN_NFCCHECK},
485 	{"prefcheck", 		IDN_PREFCHECK},
486 	{"hyphcheck", 		IDN_HYPHCHECK},
487 	{"combcheck", 		IDN_COMBCHECK},
488 	{"ctxjcheck", 		IDN_CTXJCHECK},
489 	{"ctxocheck", 		IDN_CTXOCHECK},
490 	{"ctxolitecheck", 	IDN_CTXOLITECHECK},
491 	{"bidicheck", 		IDN_BIDICHECK},
492 	{"idnconv",		IDN_IDNCONV},
493 	{"lencheck",		IDN_LENCHECK},
494 	{"rtcheck",		IDN_RTCHECK},
495 	{NULL, 			0}
496 };
497 
498 static int
parse_skip(const char * arg,idn_action_t * action)499 parse_skip(const char *arg, idn_action_t *action) {
500 	const struct idncheck_actionmap *mapp;
501 	int found;
502 
503 	while (*arg != '\0') {
504 		found = 0;
505 		for (mapp = action_maps; mapp->name != NULL; mapp++) {
506 			const char *s1 = arg;
507 			const char *s2 = mapp->name;
508 
509 			while (*s1 != ',' && *s1 != '\0') {
510 				if (*s1 != *s2 || *s2 == '\0')
511 					break;
512 				s1++;
513 				s2++;
514 			}
515 			if (*s1 == ',' && *s2 == '\0') {
516 				if (*(s1 + 1) == '\0')
517 					return (0);
518 				*action |= mapp->value;
519 				arg = s1 + 1;
520 				found = 1;
521 				break;
522 			} else if (*s1 == '\0' && *s2 == '\0') {
523 				*action |= mapp->value;
524 				arg = s1;
525 				found = 1;
526 				break;
527 			}
528 		}
529 		if (!found)
530 			return (0);
531 	}
532 	return (1);
533 }
534 
535 static int
create_resconf(idn_resconf_t * resconf,int no_conf,const char * conf_file,const char * localencoding,const char * localcheck_file)536 create_resconf(idn_resconf_t *resconf, int no_conf,
537 	       const char *conf_file, const char *localencoding,
538 	       const char *localcheck_file) {
539 	idn_result_t r;
540 
541 	r = idn_resconf_create(resconf);
542 	if (r != idn_success) {
543 		errormsg("failed to initialize configuration "
544 			"contexts, %s\n", idn_result_tostring(r));
545 		return (0);
546 	}
547 
548 	if (!no_conf) {
549 		r = idn_resconf_loadfile(*resconf, conf_file);
550 		if (r != idn_success &&
551 		    (r != idn_nofile || conf_file != NULL)) {
552 			errormsg("failed to read a configuration file, "
553 				"%s\n", idn_result_tostring(r));
554 			return (0);
555 		}
556 	}
557 
558 	/*
559 	 * For backward compatibility to idnkit-1.0, 'Punycode' specified
560 	 * as local encoding, we assumes it as UTF-8.
561 	 */
562 	if (localencoding != NULL &&
563 	    strcmp(localencoding, IDN__PUNYCODE_ACENAME) == 0)
564 		localencoding = IDN__UTF8_ENCODINGNAME;
565 
566 	r = idn_resconf_setlocalencoding(*resconf, localencoding);
567 	if (r != idn_success) {
568 		errormsg("failed to set the local encoding, %s\n",
569 			idn_result_tostring(r));
570 		return (0);
571 	}
572 
573 	r = idn_resconf_setlocalcheckfile(*resconf, localcheck_file);
574 	if (r != idn_success) {
575 		errormsg("failed to set the localcheck file, %s\n",
576 			idn_result_tostring(r));
577 		return (0);
578 	}
579 
580 	return (1);
581 }
582 
583 static char *options[] = {
584 	"Usage: idncheck [options..] name",
585 	"  -in INPUT-CODESET   : specifies input codeset name.",
586 	"  -i INPUT-CODESET    : synonym for -in",
587 	"  -conf CONF-FILE     : specifies idnkit configuration file.",
588 	"  -c CONF-FILE        : synonym for -conf",
589 	"  -noconf             : do not load idnkit configuration file.",
590 	"  -C                  : synonym for -noconf",
591 	"  -registration       : convert regions with the Domain Name Registration",
592 	"                        protocol. (default)",
593 	"  -g                  : synonym for -registration",
594 	"  -lookup             : convert regions with the Domain Name Lookup",
595 	"                        protocol.",
596 	"  -l                  : synonym for -lookup",
597 	"  -nomap              : do not perform mappings.",
598 	"  -M                  : synonym for -nomap",
599 	"  -skip ACTION,...    : do not perform ACTION.",
600 	"                        the following action names are recognized:",
601 	"                        map         : mappings",
602 	"                        asclower    : ASCII uppercase letters to lowercase",
603 	"                        rtconv      : conversion from Punycode to Unicode",
604 	"                                      for round trip check",
605 	"                        prohcheck   : prohibited code point check",
606 	"                        unascheck   : unassigned code point check",
607 	"                        nfccheck    : NFC conformance check",
608 	"                        prefcheck   : ACE prefix check",
609 	"                        hyphcheck   : hyphen check",
610 	"                        combcheck   : combining character check",
611 	"                        ctxjcheck   : CONTEXTJ code point check",
612 	"                        ctxocheck   : CONTEXTO code point check for the",
613 	"                                      Domain Name Registration protocol",
614 	"                        ctxolitecheck",
615 	"                                    : CONTEXTO code point check for the",
616 	"                                      Domain Name Lookup protocol",
617 	"                        bidicheck   : Bidi check",
618 	"                        localcheck  : local check",
619 	"                        idnconv     : conversion from/to Punycode",
620 	"                        lencheck    : label length check",
621 	"                        rtcheck     : round trip check",
622 	"  -quiet              : suppress a result message; yield exit status only.",
623 	"  -q                  : synonym for -quiet",
624 	"  -localcheck FILE    : perform local check with a code point table FILE.",
625 	"  -e FILE             : synonym for -localcheck",
626 	"  -test               : output language and local encoding status,",
627 	"                        then exit.",
628 	"  -t                    synonym for -test",
629 	"  -version            : print version number, then exit.",
630 	"  -v                  : synonym for -version",
631 	"  -help               : print this help, then exit.",
632 	"  -h                  : synonym for -help",
633 	NULL
634 };
635 
636 static void
print_test_status(idn_resconf_t conf)637 print_test_status(idn_resconf_t conf) {
638 	printf("language = %s\n", idn_resconf_getlanguage(conf));
639 	printf("input encoding = %s\n", idn_resconf_getlocalencoding(conf));
640 }
641 
642 static void
print_version(void)643 print_version(void) {
644 	printf("idncheck (idnkit) version: %s\n", IDNKIT_VERSION);
645 	printf("%s\n", idn_version_getstring());
646 }
647 
648 static void
print_usage(void)649 print_usage(void) {
650 	int i;
651 
652 	for (i = 0; options[i] != NULL; i++)
653 		printf("%s\n", options[i]);
654 }
655 
656 static void
errormsg(const char * fmt,...)657 errormsg(const char *fmt, ...) {
658 	va_list args;
659 
660 	if (quiet_mode)
661 		return;
662 
663 	va_start(args, fmt);
664 	vfprintf(stderr, fmt, args);
665 	va_end(args);
666 }
667