00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include <stdio.h>
00033 #include <stdlib.h>
00034 #include <unistd.h>
00035 #include <getopt.h>
00036 #include <str.h>
00037 #include <fcntl.h>
00038 #include <io/console.h>
00039 #include <io/color.h>
00040 #include <io/style.h>
00041 #include <io/keycode.h>
00042 #include <errno.h>
00043 #include <vfs/vfs.h>
00044 #include <assert.h>
00045
00046 #include "config.h"
00047 #include "util.h"
00048 #include "errors.h"
00049 #include "entry.h"
00050 #include "cat.h"
00051 #include "cmds.h"
00052
00053 static const char *cmdname = "cat";
00054 #define CAT_VERSION "0.0.1"
00055 #define CAT_DEFAULT_BUFLEN 1024
00056
00057 static const char *cat_oops = "That option is not yet supported\n";
00058 static const char *hexchars = "0123456789abcdef";
00059
00060 static bool paging_enabled = false;
00061 static size_t chars_remaining = 0;
00062 static size_t lines_remaining = 0;
00063 static sysarg_t console_cols = 0;
00064 static sysarg_t console_rows = 0;
00065 static bool should_quit = false;
00066
00067 static struct option const long_options[] = {
00068 { "help", no_argument, 0, 'h' },
00069 { "version", no_argument, 0, 'v' },
00070 { "head", required_argument, 0, 'H' },
00071 { "tail", required_argument, 0, 't' },
00072 { "buffer", required_argument, 0, 'b' },
00073 { "more", no_argument, 0, 'm' },
00074 { "hex", no_argument, 0, 'x' },
00075 { 0, 0, 0, 0 }
00076 };
00077
00078
00079 void help_cmd_cat(unsigned int level)
00080 {
00081 if (level == HELP_SHORT) {
00082 printf("`%s' shows the contents of files\n", cmdname);
00083 } else {
00084 help_cmd_cat(HELP_SHORT);
00085 printf(
00086 "Usage: %s [options] <file1> [file2] [...]\n"
00087 "Options:\n"
00088 " -h, --help A short option summary\n"
00089 " -v, --version Print version information and exit\n"
00090 " -H, --head ## Print only the first ## bytes\n"
00091 " -t, --tail ## Print only the last ## bytes\n"
00092 " -b, --buffer ## Set the read buffer size to ##\n"
00093 " -m, --more Pause after each screen full\n"
00094 " -x, --hex Print bytes as hex values\n"
00095 "Currently, %s is under development, some options don't work.\n",
00096 cmdname, cmdname);
00097 }
00098
00099 return;
00100 }
00101
00102 static void waitprompt()
00103 {
00104 console_set_pos(fphone(stdout), 0, console_rows-1);
00105 console_set_color(fphone(stdout), COLOR_BLUE, COLOR_WHITE, 0);
00106 printf("ENTER/SPACE/PAGE DOWN - next page, "
00107 "ESC/Q - quit, C - continue unpaged");
00108 fflush(stdout);
00109 console_set_style(fphone(stdout), STYLE_NORMAL);
00110 }
00111
00112 static void waitkey()
00113 {
00114 console_event_t ev;
00115
00116 while (true) {
00117 if (!console_get_event(fphone(stdin), &ev)) {
00118 return;
00119 }
00120 if (ev.type == KEY_PRESS) {
00121 if (ev.key == KC_ESCAPE || ev.key == KC_Q) {
00122 should_quit = true;
00123 return;
00124 }
00125 if (ev.key == KC_C) {
00126 paging_enabled = false;
00127 return;
00128 }
00129 if (ev.key == KC_ENTER || ev.key == KC_SPACE ||
00130 ev.key == KC_PAGE_DOWN) {
00131 return;
00132 }
00133 }
00134 }
00135 assert(false);
00136 }
00137
00138 static void newpage()
00139 {
00140 console_clear(fphone(stdout));
00141 chars_remaining = console_cols;
00142 lines_remaining = console_rows-1;
00143 }
00144
00145 static void paged_char(wchar_t c)
00146 {
00147 putchar(c);
00148 if (paging_enabled) {
00149 chars_remaining--;
00150 if (c == '\n' || chars_remaining == 0) {
00151 chars_remaining = console_cols;
00152 lines_remaining--;
00153 }
00154 if (lines_remaining == 0) {
00155 fflush(stdout);
00156 waitprompt();
00157 waitkey();
00158 newpage();
00159 }
00160 }
00161 }
00162
00163 static unsigned int cat_file(const char *fname, size_t blen, bool hex)
00164 {
00165 int fd, bytes = 0, count = 0, reads = 0;
00166 char *buff = NULL;
00167 int i;
00168 size_t offset = 0;
00169
00170 fd = open(fname, O_RDONLY);
00171 if (fd < 0) {
00172 printf("Unable to open %s\n", fname);
00173 return 1;
00174 }
00175
00176 if (NULL == (buff = (char *) malloc(blen + 1))) {
00177 close(fd);
00178 printf("Unable to allocate enough memory to read %s\n",
00179 fname);
00180 return 1;
00181 }
00182
00183 do {
00184 bytes = read(fd, buff, blen);
00185 if (bytes > 0) {
00186 count += bytes;
00187 buff[bytes] = '\0';
00188 offset = 0;
00189 for (i = 0; i < bytes && !should_quit; i++) {
00190 if (hex) {
00191 paged_char(hexchars[((uint8_t)buff[i])/16]);
00192 paged_char(hexchars[((uint8_t)buff[i])%16]);
00193 }
00194 else {
00195 wchar_t c = str_decode(buff, &offset, bytes);
00196 if (c == 0) {
00197
00198 break;
00199 }
00200 paged_char(c);
00201 }
00202
00203 }
00204 reads++;
00205 }
00206 } while (bytes > 0 && !should_quit);
00207
00208 close(fd);
00209 if (bytes == -1) {
00210 printf("Error reading %s\n", fname);
00211 free(buff);
00212 return 1;
00213 }
00214
00215 free(buff);
00216
00217 return 0;
00218 }
00219
00220
00221 int cmd_cat(char **argv)
00222 {
00223 unsigned int argc, i, ret = 0, buffer = 0;
00224 int c, opt_ind;
00225 bool hex = false;
00226 bool more = false;
00227 sysarg_t rows, cols;
00228 int rc;
00229
00230
00231
00232
00233
00234 paging_enabled = false;
00235 chars_remaining = 0;
00236 lines_remaining = 0;
00237 console_cols = 0;
00238 console_rows = 0;
00239 should_quit = false;
00240
00241 argc = cli_count_args(argv);
00242
00243 for (c = 0, optind = 0, opt_ind = 0; c != -1;) {
00244 c = getopt_long(argc, argv, "xhvmH:t:b:", long_options, &opt_ind);
00245 switch (c) {
00246 case 'h':
00247 help_cmd_cat(HELP_LONG);
00248 return CMD_SUCCESS;
00249 case 'v':
00250 printf("%s\n", CAT_VERSION);
00251 return CMD_SUCCESS;
00252 case 'H':
00253 printf("%s", cat_oops);
00254 return CMD_FAILURE;
00255 case 't':
00256 printf("%s", cat_oops);
00257 return CMD_FAILURE;
00258 case 'b':
00259 printf("%s", cat_oops);
00260 break;
00261 case 'm':
00262 more = true;
00263 break;
00264 case 'x':
00265 hex = true;
00266 break;
00267 }
00268 }
00269
00270 argc -= optind;
00271
00272 if (argc < 1) {
00273 printf("%s - incorrect number of arguments. Try `%s --help'\n",
00274 cmdname, cmdname);
00275 return CMD_FAILURE;
00276 }
00277
00278 if (buffer <= 0)
00279 buffer = CAT_DEFAULT_BUFLEN;
00280
00281 if (more) {
00282 rc = console_get_size(fphone(stdout), &cols, &rows);
00283 if (rc != EOK) {
00284 printf("%s - cannot get console size\n", cmdname);
00285 return CMD_FAILURE;
00286 }
00287 console_cols = cols;
00288 console_rows = rows;
00289 paging_enabled = true;
00290 newpage();
00291 }
00292
00293 for (i = optind; argv[i] != NULL && !should_quit; i++)
00294 ret += cat_file(argv[i], buffer, hex);
00295
00296 if (ret)
00297 return CMD_FAILURE;
00298 else
00299 return CMD_SUCCESS;
00300 }
00301