Changeset 3232 in MondoRescue for branches/3.2/mindi-busybox/coreutils/echo.c
- Timestamp:
- Jan 1, 2014, 12:47:38 AM (10 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/3.2/mindi-busybox/coreutils/echo.c
r2725 r3232 24 24 */ 25 25 26 //usage:#define echo_trivial_usage 27 //usage: IF_FEATURE_FANCY_ECHO("[-neE] ") "[ARG]..." 28 //usage:#define echo_full_usage "\n\n" 29 //usage: "Print the specified ARGs to stdout" 30 //usage: IF_FEATURE_FANCY_ECHO( "\n" 31 //usage: "\n -n Suppress trailing newline" 32 //usage: "\n -e Interpret backslash escapes (i.e., \\t=tab)" 33 //usage: "\n -E Don't interpret backslash escapes (default)" 34 //usage: ) 35 //usage: 36 //usage:#define echo_example_usage 37 //usage: "$ echo \"Erik is cool\"\n" 38 //usage: "Erik is cool\n" 39 //usage: IF_FEATURE_FANCY_ECHO("$ echo -e \"Erik\\nis\\ncool\"\n" 40 //usage: "Erik\n" 41 //usage: "is\n" 42 //usage: "cool\n" 43 //usage: "$ echo \"Erik\\nis\\ncool\"\n" 44 //usage: "Erik\\nis\\ncool\n") 45 26 46 #include "libbb.h" 27 47 … … 29 49 30 50 /* NB: can be used by shell even if not enabled as applet */ 51 52 /* 53 * NB2: we don't use stdio, we need better error handing. 54 * Examples include writing into non-opened stdout and error on write. 55 * 56 * With stdio, output gets shoveled into stdout buffer, and even 57 * fflush cannot clear it out. It seems that even if libc receives 58 * EBADF on write attempts, it feels determined to output data no matter what. 59 * If echo is called by shell, it will try writing again later, and possibly 60 * will clobber future output. Not good. 61 * 62 * Solaris has fpurge which discards buffered input. glibc has __fpurge. 63 * But this function is not standard. 64 */ 31 65 32 66 int echo_main(int argc UNUSED_PARAM, char **argv) 33 67 { 68 char **pp; 34 69 const char *arg; 70 char *out; 71 char *buffer; 72 unsigned buflen; 35 73 #if !ENABLE_FEATURE_FANCY_ECHO 36 74 enum { … … 39 77 }; 40 78 41 /* We must check that stdout is not closed. 42 * The reason for this is highly non-obvious. 43 * echo_main is used from shell. Shell must correctly handle "echo foo" 44 * if stdout is closed. With stdio, output gets shoveled into 45 * stdout buffer, and even fflush cannot clear it out. It seems that 46 * even if libc receives EBADF on write attempts, it feels determined 47 * to output data no matter what. So it will try later, 48 * and possibly will clobber future output. Not good. */ 49 // TODO: check fcntl() & O_ACCMODE == O_WRONLY or O_RDWR? 50 if (fcntl(1, F_GETFL) == -1) 51 return 1; /* match coreutils 6.10 (sans error msg to stderr) */ 52 //if (dup2(1, 1) != 1) - old way 53 // return 1; 54 55 arg = *++argv; 56 if (!arg) 57 goto newline_ret; 79 argv++; 58 80 #else 59 const char *p;60 81 char nflag = 1; 61 82 char eflag = 0; 62 83 63 /* We must check that stdout is not closed. */ 64 if (fcntl(1, F_GETFL) == -1) 65 return 1; 66 67 while (1) { 68 arg = *++argv; 69 if (!arg) 70 goto newline_ret; 71 if (*arg != '-') 72 break; 84 while ((arg = *++argv) != NULL) { 85 char n, e; 86 87 if (arg[0] != '-') 88 break; /* not an option arg, echo it */ 73 89 74 90 /* If it appears that we are handling options, then make sure … … 76 92 * Otherwise, the string should just be echoed. 77 93 */ 78 p = arg + 1; 79 if (!*p) /* A single '-', so echo it. */ 80 goto just_echo; 81 94 arg++; 95 n = nflag; 96 e = eflag; 82 97 do { 83 if (!strrchr("neE", *p)) 98 if (*arg == 'n') 99 n = 0; 100 else if (*arg == 'e') 101 e = '\\'; 102 else if (*arg != 'E') { 103 /* "-ccc" arg with one of c's invalid, echo it */ 104 /* arg consisting from just "-" also handled here */ 84 105 goto just_echo; 85 } while (*++p); 86 87 /* All of the options in this arg are valid, so handle them. */ 88 p = arg + 1; 89 do { 90 if (*p == 'n') 91 nflag = 0; 92 if (*p == 'e') 93 eflag = '\\'; 94 } while (*++p); 106 } 107 } while (*++arg); 108 nflag = n; 109 eflag = e; 95 110 } 96 111 just_echo: 97 112 #endif 98 while (1) { 99 /* arg is already == *argv and isn't NULL */ 113 114 buflen = 0; 115 pp = argv; 116 while ((arg = *pp) != NULL) { 117 buflen += strlen(arg) + 1; 118 pp++; 119 } 120 out = buffer = xmalloc(buflen + 1); /* +1 is needed for "no args" case */ 121 122 while ((arg = *argv) != NULL) { 100 123 int c; 101 124 102 125 if (!eflag) { 103 126 /* optimization for very common case */ 104 fputs(arg, stdout); 105 } else while ((c = *arg++)) { 106 if (c == eflag) { /* Check for escape seq. */ 127 out = stpcpy(out, arg); 128 } else 129 while ((c = *arg++) != '\0') { 130 if (c == eflag) { 131 /* This is an "\x" sequence */ 132 107 133 if (*arg == 'c') { 108 /* '\c'means cancel newline and134 /* "\c" means cancel newline and 109 135 * ignore all subsequent chars. */ 110 goto ret; 111 } 112 #if !ENABLE_FEATURE_FANCY_ECHO 113 /* SUSv3 specifies that octal escapes must begin with '0'. */ 114 if ( ((int)(unsigned char)(*arg) - '0') >= 8) /* '8' or bigger */ 115 #endif 136 goto do_write; 137 } 138 /* Since SUSv3 mandates a first digit of 0, 4-digit octals 139 * of the form \0### are accepted. */ 140 if (*arg == '0') { 141 if ((unsigned char)(arg[1] - '0') < 8) { 142 /* 2nd char is 0..7: skip leading '0' */ 143 arg++; 144 } 145 } 146 /* bb_process_escape_sequence handles NUL correctly 147 * ("...\" case). */ 116 148 { 117 /* Since SUSv3 mandates a first digit of 0, 4-digit octals 118 * of the form \0### are accepted. */ 119 if (*arg == '0') { 120 /* NB: don't turn "...\0" into "...\" */ 121 if (arg[1] && ((unsigned char)(arg[1]) - '0') < 8) { 122 arg++; 123 } 124 } 125 /* bb_process_escape_sequence handles NUL correctly 126 * ("...\" case). */ 127 c = bb_process_escape_sequence(&arg); 149 /* optimization: don't force arg to be on-stack, 150 * use another variable for that. ~30 bytes win */ 151 const char *z = arg; 152 c = bb_process_escape_sequence(&z); 153 arg = z; 128 154 } 129 155 } 130 bb_putchar(c);156 *out++ = c; 131 157 } 132 158 133 arg = *++argv; 134 if (!arg) 159 if (!*++argv) 135 160 break; 136 bb_putchar(' '); 137 } 138 139 newline_ret: 161 *out++ = ' '; 162 } 163 140 164 if (nflag) { 141 bb_putchar('\n'); 142 } 143 ret: 144 return fflush_all(); 165 *out++ = '\n'; 166 } 167 168 do_write: 169 /* Careful to error out on partial writes too (think ENOSPC!) */ 170 errno = 0; 171 /*r =*/ full_write(STDOUT_FILENO, buffer, out - buffer); 172 free(buffer); 173 if (/*WRONG:r < 0*/ errno) { 174 bb_perror_msg(bb_msg_write_error); 175 return 1; 176 } 177 return 0; 145 178 } 146 179 147 /* -180 /* 148 181 * Copyright (c) 1991, 1993 149 182 * The Regents of the University of California. All rights reserved. … … 231 264 232 265 do { 233 if (!str rchr("neE", *p))266 if (!strchr("neE", *p)) 234 267 goto just_echo; 235 268 } while (*++p); … … 257 290 p += strlen(arg); 258 291 } else while ((c = *arg++)) { 259 if (c == eflag) { /* Check for escape seq. */ 292 if (c == eflag) { 293 /* This is an "\x" sequence */ 294 260 295 if (*arg == 'c') { 261 /* '\c'means cancel newline and296 /* "\c" means cancel newline and 262 297 * ignore all subsequent chars. */ 263 298 cur_io->iov_len = p - (char*)cur_io->iov_base; … … 265 300 goto ret; 266 301 } 267 #if !ENABLE_FEATURE_FANCY_ECHO 268 /* SUSv3 specifies that octal escapes must begin with '0'. */ 269 if ( (((unsigned char)*arg) - '1') >= 7) 270 #endif 271 { 272 /* Since SUSv3 mandates a first digit of 0, 4-digit octals 273 * of the form \0### are accepted. */ 274 if (*arg == '0' && ((unsigned char)(arg[1]) - '0') < 8) { 275 arg++; 276 } 277 /* bb_process_escape_sequence can handle nul correctly */ 278 c = bb_process_escape_sequence( (void*) &arg); 279 } 302 /* Since SUSv3 mandates a first digit of 0, 4-digit octals 303 * of the form \0### are accepted. */ 304 if (*arg == '0' && (unsigned char)(arg[1] - '0') < 8) { 305 arg++; 306 } 307 /* bb_process_escape_sequence can handle nul correctly */ 308 c = bb_process_escape_sequence( (void*) &arg); 280 309 } 281 310 *p++ = c;
Note:
See TracChangeset
for help on using the changeset viewer.