#include #include #include #include // I want to perform some sort of hack using errno for flag passing static char should_stop = 0; char* ScreenString(const char* str) { size_t len = strlen(str); char* buf = malloc(len + 1); size_t i, buf_idx = 0; for(i = 0; i < len - 1; i++) { if (str[i] == '\\') { switch(str[i+1]) { case 'a': buf[buf_idx++] = '\a'; break; case 'b': buf[buf_idx++] = '\b'; break; case 'c': buf[buf_idx] = '\0'; should_stop = 1; return buf; case 'f': buf[buf_idx++] = '\f'; break; case 'n': buf[buf_idx++] = '\n'; break; case 'r': buf[buf_idx++] = '\r'; break; case 't': buf[buf_idx++] = '\t'; break; case 'v': buf[buf_idx++] = '\v'; break; case '\\': buf[buf_idx++] = '\\'; break; case '0': unsigned int c = 0; int offset = 0; if (sscanf(str + i + 1, "%3o%n", &c, &offset)) { buf[buf_idx++] = c; i += offset; } break; default: buf[buf_idx++] = '\\'; continue; } i++; } else { buf[buf_idx++] = str[i]; } } if (i < len) buf[buf_idx] = str[i]; errno = 0; return buf; } int main(int argc, const char **argv) { char newline = 1; if (argc > 1) { if (strcmp(argv[1], "-n") == 0) { newline = 0; argv++; argc--; } for (int i = 1; i < argc; i++) { char* screened = ScreenString(argv[i]); fputs(screened, stdout); free(screened); if (should_stop) return 0; if (i < argc - 1) putchar(' '); } } /* https://pubs.opengroup.org/onlinepubs/009604599/utilities/echo.html */ /* This version does not support -n option and escape-sequences */ /* https://gist.github.com/fogus/1094067/ */ /* It seems like escape sequences are supported only by GNU's one */ /* I'd implemented them anyway but you may like not to include them */ /* Or to switch them with a flag */ if (newline) putchar('\n'); return 0; }