*** empty log message ***
[platform/upstream/coreutils.git] / src / echo.c
1 /* echo.c, derived from code echo.c in Bash.
2    Copyright (C) 87,89, 1991-1997, 1999, 2000, 2001 Free Software Foundation, Inc.
3
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.
8
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.
13
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.  */
17
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"
24
25 /* The official name of this program (e.g., no `g' prefix).  */
26 #define PROGRAM_NAME "echo"
27
28 #define AUTHORS "FIXME unknown"
29
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).
44
45 You can explicitly turn off the interpretation of the above characters
46 on System V systems with the -E option.
47 */
48
49 /* If defined, interpret backslash escapes if -e is given.  */
50 #define V9_ECHO
51
52 /* If defined, interpret backslash escapes unless -E is given.
53    V9_ECHO must also be defined.  */
54 /* #define V9_DEFAULT */
55
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 */
65
66 /* The name this program was run with. */
67 char *program_name;
68
69 void
70 usage (int status)
71 {
72   if (status != 0)
73     fprintf (stderr, _("Try `%s --help' for more information.\n"),
74              program_name);
75   else
76     {
77       printf (_("Usage: %s [OPTION]... [STRING]...\n"), program_name);
78       fputs (_("\
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 "), stdout);
86       fputs (HELP_OPTION_DESCRIPTION, stdout);
87       fputs (VERSION_OPTION_DESCRIPTION, stdout);
88       fputs (_("\
89 \n\
90 Without -E, the following sequences are recognized and interpolated:\n\
91 \n\
92   \\NNN   the character whose ASCII code is NNN (octal)\n\
93   \\\\     backslash\n\
94   \\a     alert (BEL)\n\
95   \\b     backspace\n\
96 "), stdout);
97       fputs (_("\
98   \\c     suppress trailing newline\n\
99   \\f     form feed\n\
100   \\n     new line\n\
101   \\r     carriage return\n\
102   \\t     horizontal tab\n\
103   \\v     vertical tab\n\
104 "), stdout);
105       puts (_("\nReport bugs to <bug-sh-utils@gnu.org>."));
106     }
107   exit (status);
108 }
109
110 /* Print the words in LIST to standard output.  If the first word is
111    `-n', then don't print a trailing newline.  We also support the
112    echo syntax from Version 9 unix systems. */
113
114 int
115 main (int argc, char **argv)
116 {
117   int display_return = 1, do_v9 = 0;
118   int allow_options = 1;
119
120   program_name = argv[0];
121   setlocale (LC_ALL, "");
122   bindtextdomain (PACKAGE, LOCALEDIR);
123   textdomain (PACKAGE);
124
125   atexit (close_stdout);
126
127   /* Don't recognize --help or --version if POSIXLY_CORRECT is set.  */
128   if (getenv ("POSIXLY_CORRECT") == NULL)
129     parse_long_options (argc, argv, PROGRAM_NAME, GNU_PACKAGE, VERSION,
130                       AUTHORS, usage);
131   else
132     allow_options = 0;
133
134 /* System V machines already have a /bin/sh with a v9 behaviour.  We
135    use the identical behaviour for these machines so that the
136    existing system shell scripts won't barf. */
137 #if defined (V9_ECHO) && defined (V9_DEFAULT)
138   do_v9 = allow_options;
139 #endif
140
141   --argc;
142   ++argv;
143
144   while (argc > 0 && *argv[0] == '-')
145     {
146       register char *temp;
147       register int i;
148
149       /* If it appears that we are handling options, then make sure that
150          all of the options specified are actually valid.  Otherwise, the
151          string should just be echoed. */
152       temp = argv[0] + 1;
153
154       for (i = 0; temp[i]; i++)
155         {
156           if (strrchr (VALID_ECHO_OPTIONS, temp[i]) == 0)
157             goto just_echo;
158         }
159
160       if (!*temp)
161         goto just_echo;
162
163       /* All of the options in TEMP are valid options to ECHO.
164          Handle them. */
165       while (*temp)
166         {
167           if (allow_options && *temp == 'n')
168             display_return = 0;
169 #if defined (V9_ECHO)
170           else if (allow_options && *temp == 'e')
171             do_v9 = 1;
172 # if defined (V9_DEFAULT)
173           else if (allow_options && *temp == 'E')
174             do_v9 = 0;
175 # endif /* V9_DEFAULT */
176 #endif /* V9_ECHO */
177           else
178             goto just_echo;
179
180           temp++;
181         }
182       argc--;
183       argv++;
184     }
185
186 just_echo:
187
188   if (argc > 0)
189     {
190 #if defined (V9_ECHO)
191       if (do_v9)
192         {
193           while (argc > 0)
194             {
195               register char *s = argv[0];
196               register int c;
197
198               while ((c = *s++))
199                 {
200                   if (c == '\\' && *s)
201                     {
202                       switch (c = *s++)
203                         {
204                         case 'a': c = '\007'; break;
205                         case 'b': c = '\b'; break;
206                         case 'c': display_return = 0; continue;
207                         case 'f': c = '\f'; break;
208                         case 'n': c = '\n'; break;
209                         case 'r': c = '\r'; break;
210                         case 't': c = '\t'; break;
211                         case 'v': c = (int) 0x0B; break;
212                         case '0': case '1': case '2': case '3':
213                         case '4': case '5': case '6': case '7':
214                           c -= '0';
215                           if (*s >= '0' && *s <= '7')
216                             c = c * 8 + (*s++ - '0');
217                           if (*s >= '0' && *s <= '7')
218                             c = c * 8 + (*s++ - '0');
219                           break;
220                         case '\\': break;
221                         default:  putchar ('\\'); break;
222                         }
223                     }
224                   putchar(c);
225                 }
226               argc--;
227               argv++;
228               if (argc > 0)
229                 putchar(' ');
230             }
231         }
232       else
233 #endif /* V9_ECHO */
234         {
235           while (argc > 0)
236             {
237               fputs (argv[0], stdout);
238               argc--;
239               argv++;
240               if (argc > 0)
241                 putchar (' ');
242             }
243         }
244     }
245   if (display_return)
246     putchar ('\n');
247   exit (0);
248 }