(main): `quote' the offending argument.
[coreutils.git] / src / echo.c
blobdeb22bda1bcebf6e855f64953758048ee58c55c4
1 /* echo.c, derived from code echo.c in Bash.
2 Copyright (C) 87,89, 1991-1997, 1999, 2000 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software Foundation,
16 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
18 #include <config.h>
19 #include <stdio.h>
20 #include <sys/types.h>
21 #include "system.h"
22 #include "closeout.h"
23 #include "long-options.h"
25 /* The official name of this program (e.g., no `g' prefix). */
26 #define PROGRAM_NAME "echo"
28 #define AUTHORS "FIXME unknown"
30 /* echo [-neE] [arg ...]
31 Output the ARGs. If -n is specified, the trailing newline is
32 suppressed. If the -e option is given, interpretation of the
33 following backslash-escaped characters is turned on:
34 \a alert (bell)
35 \b backspace
36 \c suppress trailing newline
37 \f form feed
38 \n new line
39 \r carriage return
40 \t horizontal tab
41 \v vertical tab
42 \\ backslash
43 \num the character whose ASCII code is NUM (octal).
45 You can explicitly turn off the interpretation of the above characters
46 on System V systems with the -E option.
49 /* If defined, interpret backslash escapes if -e is given. */
50 #define V9_ECHO
52 /* If defined, interpret backslash escapes unless -E is given.
53 V9_ECHO must also be defined. */
54 /* #define V9_DEFAULT */
56 #if defined (V9_ECHO)
57 # if defined (V9_DEFAULT)
58 # define VALID_ECHO_OPTIONS "neE"
59 # else
60 # define VALID_ECHO_OPTIONS "ne"
61 # endif /* !V9_DEFAULT */
62 #else /* !V9_ECHO */
63 # define VALID_ECHO_OPTIONS "n"
64 #endif /* !V9_ECHO */
66 /* The name this program was run with. */
67 char *program_name;
69 void
70 usage (int status)
72 if (status != 0)
73 fprintf (stderr, _("Try `%s --help' for more information.\n"),
74 program_name);
75 else
77 printf (_("Usage: %s [OPTION]... [STRING]...\n"), program_name);
78 printf (_("\
79 Echo the STRING(s) to standard output.\n\
80 \n\
81 -n do not output the trailing newline\n\
82 -e enable interpretation of the backslash-escaped characters\n\
83 listed below\n\
84 -E disable interpretation of those sequences in STRINGs\n\
85 --help display this help and exit (should be alone)\n\
86 --version output version information and exit (should be alone)\n\
87 \n\
88 Without -E, the following sequences are recognized and interpolated:\n\
89 \n\
90 \\NNN the character whose ASCII code is NNN (octal)\n\
91 \\\\ backslash\n\
92 \\a alert (BEL)\n\
93 \\b backspace\n\
94 \\c suppress trailing newline\n\
95 \\f form feed\n\
96 \\n new line\n\
97 \\r carriage return\n\
98 \\t horizontal tab\n\
99 \\v vertical tab\n\
100 "));
101 puts (_("\nReport bugs to <bug-sh-utils@gnu.org>."));
103 exit (status);
106 /* Print the words in LIST to standard output. If the first word is
107 `-n', then don't print a trailing newline. We also support the
108 echo syntax from Version 9 unix systems. */
111 main (int argc, char **argv)
113 int display_return = 1, do_v9 = 0;
114 int allow_options = 1;
116 program_name = argv[0];
117 setlocale (LC_ALL, "");
118 bindtextdomain (PACKAGE, LOCALEDIR);
119 textdomain (PACKAGE);
121 atexit (close_stdout);
123 /* Don't recognize --help or --version if POSIXLY_CORRECT is set. */
124 if (getenv ("POSIXLY_CORRECT") == NULL)
125 parse_long_options (argc, argv, PROGRAM_NAME, GNU_PACKAGE, VERSION,
126 AUTHORS, usage);
127 else
128 allow_options = 0;
130 /* System V machines already have a /bin/sh with a v9 behaviour. We
131 use the identical behaviour for these machines so that the
132 existing system shell scripts won't barf. */
133 #if defined (V9_ECHO) && defined (V9_DEFAULT)
134 do_v9 = allow_options;
135 #endif
137 --argc;
138 ++argv;
140 while (argc > 0 && *argv[0] == '-')
142 register char *temp;
143 register int i;
145 /* If it appears that we are handling options, then make sure that
146 all of the options specified are actually valid. Otherwise, the
147 string should just be echoed. */
148 temp = argv[0] + 1;
150 for (i = 0; temp[i]; i++)
152 if (strrchr (VALID_ECHO_OPTIONS, temp[i]) == 0)
153 goto just_echo;
156 if (!*temp)
157 goto just_echo;
159 /* All of the options in TEMP are valid options to ECHO.
160 Handle them. */
161 while (*temp)
163 if (allow_options && *temp == 'n')
164 display_return = 0;
165 #if defined (V9_ECHO)
166 else if (allow_options && *temp == 'e')
167 do_v9 = 1;
168 # if defined (V9_DEFAULT)
169 else if (allow_options && *temp == 'E')
170 do_v9 = 0;
171 # endif /* V9_DEFAULT */
172 #endif /* V9_ECHO */
173 else
174 goto just_echo;
176 temp++;
178 argc--;
179 argv++;
182 just_echo:
184 if (argc > 0)
186 #if defined (V9_ECHO)
187 if (do_v9)
189 while (argc > 0)
191 register char *s = argv[0];
192 register int c;
194 while ((c = *s++))
196 if (c == '\\' && *s)
198 switch (c = *s++)
200 case 'a': c = '\007'; break;
201 case 'b': c = '\b'; break;
202 case 'c': display_return = 0; continue;
203 case 'f': c = '\f'; break;
204 case 'n': c = '\n'; break;
205 case 'r': c = '\r'; break;
206 case 't': c = '\t'; break;
207 case 'v': c = (int) 0x0B; break;
208 case '0': case '1': case '2': case '3':
209 case '4': case '5': case '6': case '7':
210 c -= '0';
211 if (*s >= '0' && *s <= '7')
212 c = c * 8 + (*s++ - '0');
213 if (*s >= '0' && *s <= '7')
214 c = c * 8 + (*s++ - '0');
215 break;
216 case '\\': break;
217 default: putchar ('\\'); break;
220 putchar(c);
222 argc--;
223 argv++;
224 if (argc > 0)
225 putchar(' ');
228 else
229 #endif /* V9_ECHO */
231 while (argc > 0)
233 fputs (argv[0], stdout);
234 argc--;
235 argv++;
236 if (argc > 0)
237 putchar (' ');
241 if (display_return)
242 putchar ('\n');
243 exit (0);