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 /*
24 * Copyright 1996 Sun Microsystems, Inc. All rights reserved.
25 * Use is subject to license terms.
26 */
27
28 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
29 /* All Rights Reserved */
30
31 #if defined(sun)
32 #pragma ident "@(#)echo.c 1.17 05/09/13 SMI"
33 #endif
34
35 #include "defs.h"
36
37 /*
38 * Copyright 2008-2019 J. Schilling
39 *
40 * @(#)echo.c 1.19 19/01/08 2008-2019 J. Schilling
41 */
42 #ifndef lint
43 static UConst char sccsid[] =
44 "@(#)echo.c 1.19 19/01/08 2008-2019 J. Schilling";
45 #endif
46
47 /*
48 * UNIX shell
49 */
50
51 #define exit(a) flushb(); return (a)
52
53 int echo __PR((int argc, unsigned char **argv));
54 unsigned char *escape_char __PR((unsigned char *cp, unsigned char *res,
55 int echomode));
56
57 int
echo(argc,argv)58 echo(argc, argv)
59 int argc;
60 unsigned char **argv;
61 {
62 unsigned char *cp;
63 int i;
64 int nflg = 0;
65 int len;
66 wchar_t wc;
67
68 #ifdef _iBCS2 /* SCO compatibility support */
69 struct namnod *sysv3;
70 int do_sysv3 = 0;
71
72 if ((flags & ppath) == 0) {
73 sysv3 = findnam((unsigned char *)"SYSV3");
74 if (sysv3 && (sysv3->namflg & (N_EXPORT | N_ENVNAM)))
75 do_sysv3 = 1;
76 }
77
78 /* Do the -n parsing if sysv3 is set or if ucb_builtsin is set */
79 if (ucb_builtins && !do_sysv3 && ((flags & ppath) == 0)) {
80 #else
81 if (ucb_builtins && ((flags & ppath) == 0)) {
82 #endif /* _iBCS2 */
83
84 nflg = 0;
85 if (argc > 1 && argv[1][0] == '-' &&
86 argv[1][1] == 'n' && argv[1][2] == '\0') {
87 nflg++;
88 argc--;
89 argv++;
90 }
91
92 for (i = 1; i < argc; i++) {
93 sigchk();
94
95 for (cp = argv[i]; *cp; cp++) {
96 prc_buff(*cp);
97 }
98
99 if (i < argc-1)
100 prc_buff(' ');
101 }
102
103 if (nflg == 0)
104 prc_buff('\n');
105 exit(0);
106 } else {
107 if (--argc == 0) {
108 prc_buff('\n');
109 exit(0);
110 }
111 #ifdef _iBCS2
112 if (do_sysv3) {
113 if (argc > 1 && argv[1][0] == '-' &&
114 argv[1][1] == 'n' && argv[1][2] == '\0') {
115 nflg++;
116 /* Step past the -n */
117 argc--;
118 argv++;
119 }
120 }
121 #endif /* _iBCS2 */
122
123 for (i = 1; i <= argc; i++) {
124 sigchk();
125 (void) mbtowc(NULL, NULL, 0);
126 for (cp = argv[i]; *cp; cp++) {
127 if ((len = mbtowc(&wc, (char *)cp,
128 MB_LEN_MAX)) <= 0) {
129 (void) mbtowc(NULL, NULL, 0);
130 prc_buff(*cp);
131 continue;
132 }
133
134 if (wc == '\\') {
135 unsigned char cc;
136
137 cp = escape_char(cp, &cc, TRUE);
138 if (cp == NULL) {
139 exit(0);
140 }
141 prc_buff(cc);
142 continue;
143 } else {
144 for (; len > 0; len--)
145 prc_buff(*cp++);
146 cp--;
147 continue;
148 }
149 }
150 #ifdef _iBCS2
151 /* Don't do if don't want newlines & out of args */
152 if (!(nflg && i == argc))
153 #endif /* _iBCS2 */
154 prc_buff(i == argc? '\n': ' ');
155 }
156 exit(0);
157 }
158 }
159
160 unsigned char *
escape_char(cp,res,echomode)161 escape_char(cp, res, echomode)
162 unsigned char *cp;
163 unsigned char *res;
164 int echomode; /* echo mode vs. C mode */
165 {
166 int j;
167 int wd;
168 unsigned char c;
169
170 switch (*++cp) {
171 #if defined(DO_SYSPRINTF) || defined(DO_ECHO_A)
172 case 'a': c = ALERT; break;
173 #endif
174 case 'b': c = '\b'; break;
175 case 'c': if (echomode)
176 return (NULL);
177 goto norm;
178 case 'f': c = '\f'; break;
179 case 'n': c = '\n'; break;
180 case 'r': c = '\r'; break;
181 case 't': c = '\t'; break;
182 case 'v': c = '\v'; break;
183 case '\\': c = '\\'; break;
184
185 case '0':
186 j = wd = 0;
187 if (!echomode) /* '\0123' must be '\n3' */
188 j = 1;
189 oct:
190 while ((*++cp >= '0' &&
191 *cp <= '7') && j++ < 3) {
192 wd <<= 3;
193 wd |= (*cp - '0');
194 }
195 c = wd;
196 --cp;
197 break;
198
199 case '1': case '2': case '3': case '4':
200 case '5': case '6': case '7':
201 if (!echomode) {
202 j = 1;
203 wd = (*cp - '0');
204 goto oct;
205 }
206 /* FALLTHRU */
207 default:
208 norm:
209 c = *--cp;
210 }
211 *res = c;
212 return (cp);
213 }
214