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  * 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 
24 /*
25  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
26  * Use is subject to license terms.
27  */
28 
29 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
30 /*	  All Rights Reserved  	*/
31 
32 #if defined(sun)
33 #pragma ident	"@(#)msg.c	1.15	06/06/20 SMI"
34 #endif
35 
36 #include "defs.h"
37 #include <schily/errno.h>
38 
39 /*
40  * Copyright 2008-2019 J. Schilling
41  *
42  * @(#)msg.c	1.80 19/04/17 2008-2019 J. Schilling
43  */
44 #ifndef lint
45 static	UConst char sccsid[] =
46 	"@(#)msg.c	1.80 19/04/17 2008-2019 J. Schilling";
47 #endif
48 
49 /*
50  *	UNIX shell
51  */
52 
53 #include	"sym.h"
54 
55 /*
56  * error messages
57  */
58 #ifndef __STDC__
59 #define	const
60 #endif
61 
62 const char	badopt[]	= "bad option(s)";
63 const char	mailmsg[]	= "you have mail\n";
64 const char	nospace[]	= "no space";
65 const char	nostack[]	= "no stack space";
66 const char	synmsg[]	= "syntax error";
67 
68 const char	badnum[]	= "bad number";
69 const char	badsig[]	= "bad signal";
70 const char	badid[]		= "invalid id";
71 const char	badparam[]	= "parameter null or not set";
72 const char	unset[]		= "parameter not set";
73 const char	badsub[]	= "bad substitution";
74 const char	badcreate[]	= "cannot create";
75 #ifdef	DO_NOCLOBBER
76 const char	eclobber[]	= "file already exists";
77 #endif
78 const char	nofork[]	= "fork failed - too many processes";
79 const char	noswap[]	= "cannot fork: no swap space";
80 const char	restricted[]	= "restricted";
81 const char	piperr[]	= "cannot make pipe";
82 const char	badopen[]	= "cannot open";
83 const char	coredump[]	= " - core dumped";
84 const char	arglist[]	= "arg list too long";
85 #ifdef	ETXTBSY
86 const char	txtbsy[]	= "text busy";
87 #endif
88 const char	toobig[]	= "too big";
89 const char	badexec[]	= "cannot execute";
90 const char	notfound[]	= "not found";
91 const char	badfile[]	= "bad file number";
92 const char	badshift[]	= "cannot shift";
93 const char	baddir[]	= "bad directory";
94 const char	badoff[]	= "bad offset";
95 const char	emptystack[]	= "stack empty";
96 const char	badtrap[]	= "bad trap";
97 const char	wtfailed[]	= "is read only";
98 const char	notid[]		= "is not an identifier";
99 const char	badulimit[]	= "exceeds allowable limit";
100 #ifdef	DO_POSIX_RETURN
101 const char	badreturn[]	=
102 			"cannot return when not in function or sourced script";
103 #else
104 const char	badreturn[]	= "cannot return when not in function";
105 #endif
106 #ifndef	DO_POSIX_UNSET
107 const char	badexport[]	= "cannot export functions";
108 #endif
109 #ifndef	DO_POSIX_UNSET
110 const char	badunset[]	= "cannot unset";
111 #endif
112 const char	nohome[]	= "no home directory";
113 const char	badperm[]	= "execute permission denied";
114 const char	longpwd[]	= "sh error: pwd too long";
115 const char	mssgargn[]	= "missing arguments";
116 const char	toomanyargs[]	= "too many arguments";
117 #ifdef	ELIBACC
118 const char	libacc[]	= "can't access a needed shared library";
119 #endif
120 #ifdef	ELIBBAD
121 const char	libbad[]	= "accessing a corrupted shared library";
122 #endif
123 #ifdef	ELIBSCN
124 const char	libscn[]	= ".lib section in a.out corrupted";
125 #endif
126 #ifdef	ELIBMAX
127 const char	libmax[]	= "attempting to link in too many libs";
128 #endif
129 #ifdef	EMULTIHOP
130 const char	emultihop[]	= "Multihop attempted";
131 #endif
132 const char	nulldir[]	= "null directory";
133 const char	enotdir[]	= "not a directory";
134 const char	eisdir[]	= "is a directory";
135 const char	enoent[]	= "does not exist";
136 const char	eacces[]	= "permission denied";
137 #ifdef	ENOLINK
138 const char	enolink[]	= "remote link inactive";
139 #endif
140 const char	exited[]	= "Done";
141 const char	running[]	= "Running";
142 const char	ambiguous[]	= "ambiguous";
143 const char	usage[]		= "usage";
144 const char	nojc[]		= "no job control";
145 #ifdef	DO_SYSALIAS
146 #if	defined(DO_GLOBALALIASES) || defined(DO_LOCALALIASES)
147 const char	aliasuse[]	=
148 		"alias [-a] [-e] [-g] [-l] [-p] [-r] [--raw] [name[=value]...]";
149 const char	unaliasuse[]	= "unalias [-a] [-g] [-l] [-p] [name...]";
150 #else
151 const char	aliasuse[]	=
152 		"alias [-a] [-e] [-p] [--raw] [name[=value]...]";
153 const char	unaliasuse[]	= "unalias [-a] [-p] [name...]";
154 #endif
155 #endif
156 #ifdef	DO_SYSREPEAT
157 const char	repuse[]	= "repeat [-c count] [-d delay] cmd [args]";
158 #endif
159 #ifdef	DO_SYSBUILTIN
160 const char	builtinuse[]	=
161 		"builtin [-d] [-f lib] [-i] [-s] [pathname...]";
162 #endif
163 const char	stopuse[]	= "stop id ...";
164 #ifdef	DO_POSIX_TRAP
165 const char	trapuse[]	= "trap -p [ [action] condition ...]";
166 #endif
167 const char	ulimuse[]	=
168 		"ulimit [ -HSakcdefiklmnoqrstuvwLMPR ] [ limit ]";
169 #ifdef	DO_SYSLIMIT
170 const char	limuse[]	=
171 		"limit [ -HS ] [ resource [ limit ]]";
172 #endif
173 const char	killuse[]	=
174 		"kill [ [ -sig | -s sig ] id ... | -l [ signo ... ] ]";
175 const char	jobsuse[]	= "jobs [ [ -l | -p ] [ id ... ] | -x cmd ]";
176 const char	nosuchjob[]	= "no such job";
177 const char	nosuchpid[]	= "no such process";
178 const char	nosuchpgid[]	= "no such process group";
179 const char	nocurjob[]	= "no current job";
180 const char	jobsstopped[]	= "there are stopped jobs";
181 const char	jobsrunning[]	= "there are running jobs";
182 const char	loginsh[]	= "cannot stop login shell";
183 const char	nlorsemi[]	= "newline or ;";
184 const char	signalnum[]	= "Signal ";
185 const char	badpwd[]	= "cannot determine current directory";
186 const char	badlocale[]	= "couldn't set locale correctly\n";
187 const char	nobracket[]	= "] missing";
188 const char	noparen[]	= ") expected";
189 const char	noarg[]		= "argument expected";
190 const char	unimplemented[]	= "unimplemented";
191 #if	defined(DO_DOL_PAREN) || defined(DO_SYSATEXPR)
192 const char	divzero[]	= "division by zero";
193 #endif
194 
195 /*
196  * messages for 'builtin' functions
197  */
198 const char	btest[]		= "test";
199 const char	badop[]		= "unknown operator ";
200 const char	badumask[]	= "bad umask";
201 
202 /*
203  * built in names
204  */
205 const char	pathname[]	= "PATH";
206 const char	ppidname[]	= "PPID";
207 const char	cdpname[]	= "CDPATH";
208 const char	envname[]	= "ENV";
209 const char	fcename[]	= "FCEDIT";
210 const char	homename[]	= "HOME";
211 const char	mailname[]	= "MAIL";
212 const char	ifsname[]	= "IFS";
213 const char	ps1name[]	= "PS1";
214 const char	ps2name[]	= "PS2";
215 const char	ps3name[]	= "PS3";
216 const char	ps4name[]	= "PS4";
217 const char	linenoname[]	= "LINENO";
218 const char	mchkname[]	= "MAILCHECK";
219 const char	opwdname[]	= "OLDPWD";
220 const char	pwdname[]	= "PWD";
221 const char	repname[]	= "REPLY";
222 const char	acctname[]	= "SHACCT";
223 const char	mailpname[]	= "MAILPATH";
224 const char	timefmtname[]	= "TIMEFORMAT";
225 
226 /*
227  * string constants
228  */
229 const char	nullstr[]	= "";
230 const char	sptbnl[]	= " \t\n";
231 const char	defpath[]	= "/usr/bin::";
232 #ifdef	DO_SYSCOMMAND
233 /*
234  * The correct POSIX default PATH for Solaris + "/bin" after "/usr/bin" should
235  * be sufficient for all platforms.
236  */
237 const char	defppath[]	=
238 "/usr/xpg6/bin:/usr/xpg4/bin:/usr/ccs/bin:/usr/bin:/bin:/opt/SUNWspro/bin::";
239 #endif
240 const char	colon[]		= ": ";
241 const char	minus[]		= "-";
242 const char	endoffile[]	= "end of file";
243 const char	unexpected[]	= " unexpected";
244 const char	atline[]	= " at line ";
245 const char	devnull[]	= "/dev/null";
246 const char	execpmsg[]	= "+ ";
247 const char	selectmsg[]	= "#? ";
248 const char	readmsg[]	= "> ";
249 const char	stdprompt[]	= "$ ";
250 const char	supprompt[]	= "# ";
251 const char	profile[]	= ".profile";
252 const char	sysprofile[]	= "/etc/profile";
253 #ifdef	DO_SHRCFILES
254 const char	rcfile[]	= "$HOME/.shrc";
255 const char	sysrcfile[]	= "/etc/sh.shrc";
256 #endif
257 const char	globalname[]	= ".globals";
258 const char	localname[]	= ".locals";
259 const unsigned char shname[]	= "sh (Schily Bourne Shell)";
260 #ifdef	DO_SYSFC
261 const char	fcedit[]	= "/bin/ed";
262 #endif
263 
264 /*
265  * locale testing
266  *
267  * Since localedir may not be the same for all target architectures
268  * we just disable this check for a non-Solaris environment.
269  */
270 #if	defined(IS_SUN) || defined(DO_SPLIT_ROOT)
271 const char	localedir[]	= "/usr/lib/locale";
272 #endif
273 int		localedir_exists;
274 
275 /*
276  * tables
277  */
278 
279 const struct sysnod reserved[] =
280 {
281 #ifdef	DO_NOTSYM
282 	{ "!",		NOTSYM	},
283 #endif
284 	{ "case",	CASYM	},
285 	{ "do",		DOSYM	},
286 	{ "done",	ODSYM	},
287 	{ "elif",	EFSYM	},
288 	{ "else",	ELSYM	},
289 	{ "esac",	ESSYM	},
290 	{ "fi",		FISYM	},
291 	{ "for",	FORSYM	},
292 	{ "if",		IFSYM	},
293 	{ "in",		INSYM	},
294 #ifdef	DO_SELECT
295 	{ "select",	SELSYM	},
296 #endif
297 	{ "then",	THSYM	},
298 #ifdef	DO_TIME
299 	{ "time",	TIMSYM	},
300 #endif
301 	{ "until",	UNSYM	},
302 	{ "while",	WHSYM	},
303 	{ "{",		BRSYM	},
304 	{ "}",		KTSYM	}
305 };
306 
307 const int no_reserved = sizeof (reserved)/sizeof (struct sysnod);
308 
309 const char	export[] = "export";
310 const char	readonly[] = "readonly";
311 
312 const struct sysnod test_ops[] =
313 {
314 	{ "!=",		TEST_SNEQ	},
315 	{ "-a",		TEST_AND	},
316 #ifdef	DO_EXT_TEST
317 	{ "-ef",	TEST_EF		},
318 #endif
319 	{ "-eq",	TEST_EQ		},
320 	{ "-ge",	TEST_GE		},
321 	{ "-gt",	TEST_GT		},
322 	{ "-le",	TEST_LE		},
323 	{ "-lt",	TEST_LT		},
324 	{ "-ne",	TEST_NE		},
325 #ifdef	DO_EXT_TEST
326 	{ "-nt",	TEST_NT		},
327 #endif
328 	{ "-o",		TEST_OR		},
329 #ifdef	DO_EXT_TEST
330 	{ "-ot",	TEST_OT		},
331 #endif
332 	{ "=",		TEST_SEQ	},
333 };
334 const int no_test_ops = sizeof (test_ops)/sizeof (struct sysnod);
335 
336 /*
337  * In the POSIX teleconferences from November and December 2014, we
338  * tried to create a new notation for shell builtins and the rules
339  * they need to follow.
340  *
341  * Special built-in utilities and intrinsic utilities are called before any
342  * attempt for a PATH search is done.
343  * Special built-in utilities in addition keep variable assignement in effect
344  * after the builtin completes.
345  * See http://austingroupbugs.net/view.php?id=854#c2495 for the new POSIX
346  * classification of shell builtins.
347  *
348  * Built-ins marked with "S" are POSIX special built-in utilities.
349  * Built-ins marked with "I" are POSIX intrinsic utilities.
350  * Built-ins marked with "i" may not be permitted intrincics in the future.
351  * Built-ins marked with "-" do not follow utility syntax guidelines.
352  * Built-ins marked with "U" follow utility syntax guidelines and support --.
353  */
354 const struct sysnod commands[] =
355 {
356 	{ ".",		SYSDOT,		BLT_SPC	},	/* S - */
357 	{ ":",		SYSNULL,	BLT_SPC	},	/* S - */
358 #ifdef DO_SYSATEXPR
359 	{ "@",		SYSEXPR,	0	},
360 #endif
361 #ifndef RES
362 	{ "[",		SYSTST,		0 },		/*  i  */
363 #endif
364 #ifdef	DO_SYSALIAS
365 	{ "alias",	SYSALIAS,	BLT_INT },	/*  I  */
366 #endif
367 #ifdef	DO_SYSALLOC
368 	{ "alloc",	SYSALLOC,	0 },
369 #endif
370 	{ "bg",		SYSFGBG,	BLT_INT },	/*  I  */
371 	{ "break",	SYSBREAK,	BLT_SPC },	/* S - */
372 #ifdef	DO_SYSBUILTIN
373 	{ "builtin",	SYSBUILTIN },
374 #endif
375 	{ "cd",		SYSCD,		BLT_INT },	/*  I  */
376 	{ "chdir",	SYSCD,		0 },
377 #ifdef	DO_SYSCOMMAND
378 	{ "command",	SYSCOMMAND,	BLT_INT },	/*  I  */
379 #endif
380 	{ "continue",	SYSCONT,	BLT_SPC	},	/* S - */
381 #ifdef	DO_SYSPUSHD
382 	{ "dirs",	SYSDIRS,	0 },
383 #endif
384 #ifdef	DO_SYSDOSH
385 	{ "dosh",	SYSDOSH,	0 },
386 #endif
387 	{ "echo",	SYSECHO,	0 },		/*  i  */
388 #ifdef	DO_SYSERRSTR
389 	{ "errstr",	SYSERRSTR,	0 },
390 #endif
391 	{ "eval",	SYSEVAL,	BLT_SPC	},	/* S - */
392 	{ "exec",	SYSEXEC,	BLT_SPC	},	/* S - */
393 	{ "exit",	SYSEXIT,	BLT_SPC	},	/* S - */
394 	{ "export",	SYSXPORT,	BLT_SPC },	/* S U */
395 #ifdef	DO_SYSTRUE
396 	{ "false",	SYSFALSE,	0 },		/*  i  */
397 #endif
398 #ifdef	DO_SYSFC
399 	{ "fc",		SYSFC,		BLT_INT },	/*  I  */
400 #endif
401 	{ "fg",		SYSFGBG,	BLT_INT },	/*  I  */
402 #ifdef	DO_SYSFIND
403 	{ "find",	SYSFIND },
404 #endif
405 	{ "getopts",	SYSGETOPT,	BLT_INT },	/*  I  */
406 	{ "hash",	SYSHASH,	BLT_INT },	/*  I  */
407 #ifdef	INTERACTIVE
408 	{ "history",	SYSHISTORY,	0 },
409 #endif
410 	{ "jobs",	SYSJOBS,	BLT_INT },	/*  I  */
411 	{ "kill",	SYSKILL,	BLT_INT },	/*  I  */
412 #ifdef	DO_SYSKILLPG
413 	{ "killpg",	SYSKILL,	0 },
414 #endif
415 #ifdef	DO_SYSLIMIT
416 	{ "limit",	SYSULIMIT,	0 },
417 #endif
418 #ifdef	DO_SYSLOCAL
419 	{ "local",	SYSLOCAL,	0 },
420 #endif
421 #ifdef RES
422 	{ "login",	SYSLOGIN,	0 },
423 #endif
424 #ifdef	INTERACTIVE
425 	{ "map",	SYSMAP,		0 },
426 #endif
427 #ifdef RES
428 	{ "newgrp",	SYSLOGIN,	0 },
429 #else
430 	{ "newgrp",	SYSNEWGRP,	0 },		/*  i  */
431 #endif
432 
433 #ifdef	DO_SYSPGRP
434 	{ "pgrp",	SYSPGRP,	0 },
435 #endif
436 #ifdef	DO_SYSPUSHD
437 	{ "popd",	SYSPOPD,	0 },
438 #endif
439 #ifdef	DO_SYSPRINTF
440 	{ "printf",	SYSPRINTF,	0 },		/*  i  */
441 #endif
442 #ifdef	DO_SYSPUSHD
443 	{ "pushd",	SYSPUSHD,	0 },
444 #endif
445 	{ "pwd",	SYSPWD,		0 },		/*  i  */
446 	{ "read",	SYSREAD,	BLT_INT },	/*  I  */
447 	{ "readonly",	SYSRDONLY,	BLT_SPC },	/* S U */
448 #ifdef	DO_SYSREPEAT
449 	{ "repeat",	SYSREPEAT,	0 },
450 #endif
451 	{ "return",	SYSRETURN,	BLT_SPC },	/* S - */
452 #ifdef	INTERACTIVE
453 	{ "savehistory", SYSSAVEHIST,	0 },
454 #endif
455 	{ "set",	SYSSET,		BLT_SPC	},	/* S U */
456 	{ "shift",	SYSSHFT,	BLT_SPC	},	/* S - */
457 	{ "stop",	SYSSTOP,	0 },
458 	{ "suspend",	SYSSUSP,	0 },
459 #ifdef	DO_SYSSYNC
460 	{ "sync",	SYSSYNC,	0 },
461 #endif
462 	{ "test",	SYSTST,		0 },		/*  i  */
463 	{ "times",	SYSTIMES,	BLT_SPC },	/* S - */
464 	{ "trap",	SYSTRAP,	BLT_SPC	},	/* S U */
465 #ifdef	DO_SYSTRUE
466 	{ "true",	SYSTRUE,	0 },		/*  i  */
467 #endif
468 	{ "type",	SYSTYPE,	BLT_INT },	/*  I  */
469 
470 
471 #ifndef RES
472 	{ "ulimit",	SYSULIMIT,	BLT_INT },	/*  I  */
473 	{ "umask",	SYSUMASK,	BLT_INT },	/*  I  */
474 #endif
475 #ifdef	DO_SYSALIAS
476 	{ "unalias",	SYSUNALIAS,	BLT_INT },	/*  I  */
477 #endif
478 
479 	{ "unset",	SYSUNS,		BLT_SPC },	/* S U */
480 	{ "wait",	SYSWAIT,	BLT_INT }	/*  I  */
481 };
482 
483 const int no_commands = sizeof (commands)/sizeof (struct sysnod);
484