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 ("CDDL"), version 1.0.
6  * You may use this file only in accordance with the terms of version
7  * 1.0 of the CDDL.
8  *
9  * A full copy of the text of the CDDL should have accompanied this
10  * source.  A copy of the CDDL is also available via the Internet at
11  * http://www.opensource.org/licenses/cddl1.txt
12  * See the License for the specific language governing permissions
13  * and limitations under the License.
14  *
15  * When distributing Covered Code, include this CDDL HEADER in each
16  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
17  * If applicable, add the following below this CDDL HEADER, with the
18  * fields enclosed by brackets "[]" replaced with your own identifying
19  * information: Portions Copyright [yyyy] [name of copyright owner]
20  *
21  * CDDL HEADER END
22  */
23 /* Copyright (c) 1988 AT&T */
24 /* All Rights Reserved */
25 /*
26  * Copyright 2002 Sun Microsystems, Inc. All rights reserved.
27  * Use is subject to license terms.
28  */
29 /*
30  * Copyright 2006-2020 J. Schilling
31  *
32  * @(#)help.c	1.13 20/06/01 J. Schilling
33  */
34 #if defined(sun)
35 #pragma ident "@(#)help.c 1.13 20/06/01 J. Schilling"
36 #endif
37 /*
38  * @(#)help2.c 1.10 06/12/12
39  */
40 
41 #if defined(sun)
42 #pragma ident	"@(#)help.c"
43 #pragma ident	"@(#)sccs:cmd/help.c"
44 #endif
45 #include	<defines.h>
46 #include	<i18n.h>
47 #include	<ccstypes.h>
48 
49 /*
50  *	Program to locate helpful info in an ascii file.
51  *	The program accepts a variable number of arguments.
52  *
53  *	I18N changes are as follows:
54  *
55  *	First determine the appropriate directory to search for help text
56  *	files corresponding to the user's locale.  Consistent with the
57  *	setlocale() routine algorithm, environment variables are here
58  *	searched in the following order of descending priority: LC_ALL,
59  *	LC_MESSAGES, LANG.  The first one found to be defined is used
60  *	as the locale for help messages.  If this directory does in fact
61  *	not exist, a fallback to the (default) "C" locale is done.
62  *
63  *	The file to be searched is determined from the argument. If the
64  *	argument does not contain numerics, the search
65  *	will be attempted on '/usr/ccs/lib/help/cmds', with the search key
66  *	being the whole argument. This is used for SCCS command help.
67  *
68  *	If the argument begins with non-numerics but contains
69  *	numerics (e.g, zz32) the file /usr/ccs/lib/help/helploc
70  *	will be checked for a file corresponding to the non numeric prefix,
71  *	That file will then be seached for the mesage. If
72  *	/usr/ccs/lib/help/helploc
73  *	does not exist or the prefix is not found there the search will
74  *	be attempted on '/usr/ccs/lib/help/<non-numeric prefix>',
75  *	(e.g., /usr/ccs/lib/help/zz), with the search key
76  *	being <remainder of arg>, (e.g., 32).
77  *	If the argument is all numeric, or if the file as
78  *	determined above does not exist, the search will be attempted on
79  *	'/usr/ccs/lib/help/default' with the search key being
80  *	the entire argument.
81  *	In no case will more than one search per argument be performed.
82  *
83  *	File is formatted as follows:
84  *
85  *		* comment
86  *		* comment
87  *		-str1
88  *		text
89  *		-str2
90  *		text
91  *		* comment
92  *		text
93  *		-str3
94  *		text
95  *
96  *	The "str?" that matches the key is found and
97  *	the following text lines are printed.
98  *	Comments are ignored.
99  *
100  *	If the argument is omitted, the program requests it.
101  */
102 
103 
104 	int	main __PR((int argc, char **argv));
105 static char	*ask __PR((void));
106 
107 
108 int
main(argc,argv)109 main(argc, argv)
110 	int	argc;
111 	char	*argv[];
112 {
113 	register int	i;
114 		int	numerrs = 0;
115 #ifdef	PROTOTYPES
116 	char default_locale[] = NOGETTEXT("C"); /* Default English. */
117 #else
118 	char *default_locale = NOGETTEXT("C"); /* Default English. */
119 #endif
120 	char *helpdir = NOGETTEXT("/" SCCS_BIN_PRE "lib/help/locale/");
121 	char help_dir[200]; /* Directory to search for help text. */
122 	char *locale = NULL; /* User's locale. */
123 
124 
125 	/*
126 	 * Set locale for all categories.
127 	 */
128 	setlocale(LC_ALL, NOGETTEXT(""));
129 
130 	sccs_setinsbase(INS_BASE);
131 
132 #ifdef	LC_MESSAGES
133 	/*
134 	 * Returns the locale value for the LC_MESSAGES category.  This
135 	 * will be used to set the path to retrieve the appropriate
136 	 * help files in "/.../help.d/locale/<locale>".
137 	 */
138 	locale = setlocale(LC_MESSAGES, NOGETTEXT(""));
139 	if (locale == NULL) {
140 		locale = default_locale;
141 	}
142 #else
143 	locale = default_locale;
144 #endif
145 
146 	/*
147 	 * Set directory to search for general l10n SCCS messages.
148 	 */
149 #ifdef	PROTOTYPES
150 	(void) bindtextdomain(NOGETTEXT("SUNW_SPRO_SCCS"),
151 	    NOGETTEXT(INS_BASE "/" SCCS_BIN_PRE "lib/locale/"));
152 #else
153 	(void) bindtextdomain(NOGETTEXT("SUNW_SPRO_SCCS"),
154 	    NOGETTEXT("/usr/ccs/lib/locale/"));
155 #endif
156 	(void) textdomain(NOGETTEXT("SUNW_SPRO_SCCS"));
157 
158 #ifdef	SCHILY_BUILD
159 	save_args(argc, argv);
160 #endif
161 	Fflags = FTLMSG;
162 #ifdef	SCCS_FATALHELP
163 	Fflags |= FTLFUNC;
164 	Ffunc = sccsfatalhelp;
165 #endif
166 
167 	/*
168 	 * Set directory to search for SCCS help text, not general
169 	 * message text wrapped with "gettext()".
170 	 */
171 	strlcpy(help_dir, sccs_insbase?sccs_insbase:"/usr", sizeof (help_dir));
172 	strlcat(help_dir, helpdir, sizeof (help_dir));
173 	strlcat(help_dir, locale, sizeof (help_dir));
174 
175 	/*
176 	 * The text of the printf statement below should not be wrapped
177 	 * with gettext().  Since we don't know what the locale is, we
178 	 * don't know how to get the proper translation text.
179 	 */
180 	if (stat(help_dir, &Statbuf) != 0) { /* Does help directory exist? */
181 		printf(gettext(
182 		    "No help for locale '%s' ... setting to English.\n"),
183 		    locale);
184 	}
185 
186 	if (argc == 1) {
187 		char	*he = ask();
188 		if (*he == '\0') {
189 			numerrs += sccshelp(stdout, "intro");
190 		} else {
191 			numerrs += sccshelp(stdout, he);
192 		}
193 	} else {
194 		for (i = 1; i < argc; i++)
195 			numerrs += sccshelp(stdout, argv[i]);
196 	}
197 	return ((numerrs == (argc-1)) ? 1 : 0);
198 }
199 
200 static char *
ask()201 ask()
202 {
203 	static char resp[51];
204 		FILE	*iop;
205 
206 	iop = stdin;
207 
208 	printf(gettext("Enter the message number or SCCS command name: "));
209 	fgets(resp, sizeof (resp), iop);
210 	return (repl(resp, '\n', '\0'));
211 }
212