2018-08-15 04:07:33 +03:00
|
|
|
/* vim: tabstop=4 shiftwidth=4 noexpandtab
|
|
|
|
* This file is part of ToaruOS and is released under the terms
|
2018-03-02 15:25:22 +03:00
|
|
|
* of the NCSA / University of Illinois License - see LICENSE.md
|
2018-05-01 11:12:56 +03:00
|
|
|
* Copyright (C) 2013-2018 K. Lange
|
2018-03-02 15:25:22 +03:00
|
|
|
*
|
2018-08-15 04:07:33 +03:00
|
|
|
* echo - Print arguments to stdout.
|
2018-03-02 15:25:22 +03:00
|
|
|
*
|
2018-08-15 04:07:33 +03:00
|
|
|
* Prints arguments to stdout, possibly interpreting escape
|
|
|
|
* sequences in the arguments.
|
2018-03-02 15:25:22 +03:00
|
|
|
*/
|
2018-10-05 13:15:08 +03:00
|
|
|
#include <ctype.h>
|
2018-03-02 15:25:22 +03:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
2018-08-15 04:07:33 +03:00
|
|
|
#include <unistd.h>
|
2018-03-02 15:25:22 +03:00
|
|
|
|
2018-08-15 04:07:33 +03:00
|
|
|
void show_usage(char * argv[]) {
|
|
|
|
printf(
|
|
|
|
"echo - print arguments\n"
|
|
|
|
"\n"
|
|
|
|
"usage: %s [-ne] ARG...\n"
|
|
|
|
"\n"
|
|
|
|
" -n \033[3mdo not output a new line at the end\033[0m\n"
|
|
|
|
" -e \033[3mprocess escape sequences\033[0m\n"
|
|
|
|
" -? \033[3mshow this help text\033[0m\n"
|
|
|
|
"\n", argv[0]);
|
2018-03-02 15:25:22 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
int main(int argc, char ** argv) {
|
|
|
|
int use_newline = 1;
|
|
|
|
int process_escapes = 0;
|
|
|
|
|
2018-08-15 04:07:33 +03:00
|
|
|
int opt;
|
|
|
|
while ((opt = getopt(argc, argv, "enh?")) != -1) {
|
|
|
|
switch (opt) {
|
|
|
|
case '?':
|
|
|
|
case 'h':
|
|
|
|
show_usage(argv);
|
2018-03-02 15:25:22 +03:00
|
|
|
return 1;
|
2018-08-15 04:07:33 +03:00
|
|
|
case 'n':
|
2018-03-02 15:25:22 +03:00
|
|
|
use_newline = 0;
|
2018-08-15 04:07:33 +03:00
|
|
|
break;
|
|
|
|
case 'e':
|
2018-03-02 15:25:22 +03:00
|
|
|
process_escapes = 1;
|
2018-08-15 04:07:33 +03:00
|
|
|
break;
|
2018-03-02 15:25:22 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-15 04:07:33 +03:00
|
|
|
for (int i = optind; i < argc; ++i) {
|
2018-03-02 15:25:22 +03:00
|
|
|
if (process_escapes) {
|
2018-10-05 13:15:08 +03:00
|
|
|
char * c = argv[i];
|
|
|
|
while (*c) {
|
|
|
|
if (*c == '\\') {
|
|
|
|
c++;
|
|
|
|
switch (*c) {
|
|
|
|
case '\\':
|
|
|
|
putchar('\\');
|
|
|
|
break;
|
|
|
|
case 'a':
|
|
|
|
putchar('\a');
|
|
|
|
break;
|
|
|
|
case 'b':
|
|
|
|
putchar('\b');
|
|
|
|
break;
|
|
|
|
case 'c':
|
|
|
|
return 0;
|
|
|
|
case 'e':
|
|
|
|
putchar('\033');
|
|
|
|
break;
|
|
|
|
case 'f':
|
|
|
|
putchar('\f');
|
|
|
|
break;
|
|
|
|
case 'n':
|
|
|
|
putchar('\n');
|
|
|
|
break;
|
|
|
|
case 't':
|
|
|
|
putchar('\t');
|
|
|
|
break;
|
|
|
|
case 'v':
|
|
|
|
putchar('\v');
|
|
|
|
break;
|
|
|
|
case '0':
|
|
|
|
{
|
|
|
|
int i = 0;
|
|
|
|
if (!isdigit(*(c+1)) || *(c+1) > '7') {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
c++;
|
|
|
|
i = *c - '0';
|
|
|
|
if (isdigit(*(c+1)) && *(c+1) <= '7') {
|
|
|
|
c++;
|
|
|
|
i = (i << 3) | (*c - '0');
|
|
|
|
if (isdigit(*(c+1)) && *(c+1) <= '7') {
|
|
|
|
c++;
|
|
|
|
i = (i << 3) | (*c - '0');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
putchar(i);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
putchar('\\');
|
|
|
|
putchar(*c);
|
|
|
|
break;
|
2018-03-02 15:25:22 +03:00
|
|
|
}
|
2018-10-05 13:15:08 +03:00
|
|
|
} else {
|
|
|
|
putchar(*c);
|
2018-03-02 15:25:22 +03:00
|
|
|
}
|
2018-10-05 13:15:08 +03:00
|
|
|
c++;
|
2018-03-02 15:25:22 +03:00
|
|
|
}
|
2018-10-05 13:15:08 +03:00
|
|
|
} else {
|
|
|
|
printf("%s",argv[i]);
|
2018-03-02 15:25:22 +03:00
|
|
|
}
|
|
|
|
if (i != argc - 1) {
|
|
|
|
printf(" ");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (use_newline) {
|
|
|
|
printf("\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
fflush(stdout);
|
|
|
|
return 0;
|
|
|
|
}
|