echo.c 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. /* vim: tabstop=4 shiftwidth=4 noexpandtab
  2. * This file is part of ToaruOS and is released under the terms
  3. * of the NCSA / University of Illinois License - see LICENSE.md
  4. * Copyright (C) 2013-2018 K. Lange
  5. *
  6. * echo - Print arguments to stdout.
  7. *
  8. * Prints arguments to stdout, possibly interpreting escape
  9. * sequences in the arguments.
  10. */
  11. #include <ctype.h>
  12. #include <stdio.h>
  13. #include <string.h>
  14. #include <unistd.h>
  15. void show_usage(char * argv[]) {
  16. printf(
  17. "echo - print arguments\n"
  18. "\n"
  19. "usage: %s [-ne] ARG...\n"
  20. "\n"
  21. " -n \033[3mdo not output a new line at the end\033[0m\n"
  22. " -e \033[3mprocess escape sequences\033[0m\n"
  23. " -? \033[3mshow this help text\033[0m\n"
  24. "\n", argv[0]);
  25. }
  26. int main(int argc, char ** argv) {
  27. int use_newline = 1;
  28. int process_escapes = 0;
  29. int opt;
  30. while ((opt = getopt(argc, argv, "enh?")) != -1) {
  31. switch (opt) {
  32. case '?':
  33. case 'h':
  34. show_usage(argv);
  35. return 1;
  36. case 'n':
  37. use_newline = 0;
  38. break;
  39. case 'e':
  40. process_escapes = 1;
  41. break;
  42. }
  43. }
  44. for (int i = optind; i < argc; ++i) {
  45. if (process_escapes) {
  46. char * c = argv[i];
  47. while (*c) {
  48. if (*c == '\\') {
  49. c++;
  50. switch (*c) {
  51. case '\\':
  52. putchar('\\');
  53. break;
  54. case 'a':
  55. putchar('\a');
  56. break;
  57. case 'b':
  58. putchar('\b');
  59. break;
  60. case 'c':
  61. return 0;
  62. case 'e':
  63. putchar('\033');
  64. break;
  65. case 'f':
  66. putchar('\f');
  67. break;
  68. case 'n':
  69. putchar('\n');
  70. break;
  71. case 't':
  72. putchar('\t');
  73. break;
  74. case 'v':
  75. putchar('\v');
  76. break;
  77. case '0':
  78. {
  79. int i = 0;
  80. if (!isdigit(*(c+1)) || *(c+1) > '7') {
  81. break;
  82. }
  83. c++;
  84. i = *c - '0';
  85. if (isdigit(*(c+1)) && *(c+1) <= '7') {
  86. c++;
  87. i = (i << 3) | (*c - '0');
  88. if (isdigit(*(c+1)) && *(c+1) <= '7') {
  89. c++;
  90. i = (i << 3) | (*c - '0');
  91. }
  92. }
  93. putchar(i);
  94. }
  95. break;
  96. default:
  97. putchar('\\');
  98. putchar(*c);
  99. break;
  100. }
  101. } else {
  102. putchar(*c);
  103. }
  104. c++;
  105. }
  106. } else {
  107. printf("%s",argv[i]);
  108. }
  109. if (i != argc - 1) {
  110. printf(" ");
  111. }
  112. }
  113. if (use_newline) {
  114. printf("\n");
  115. }
  116. fflush(stdout);
  117. return 0;
  118. }