source: mainline/uspace/app/bdsh/cmds/modules/cat/cat.c@ cfc3027

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since cfc3027 was 06e724e1, checked in by Martin Decky <martin@…>, 14 years ago

remove unused variable

  • Property mode set to 100644
File size: 7.1 KB
Line 
1/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com>
2 * Copyright (c) 2011, Martin Sucha
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * Redistributions of source code must retain the above copyright notice, this
9 * list of conditions and the following disclaimer.
10 *
11 * Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 *
15 * Neither the name of the original program's authors nor the names of its
16 * contributors may be used to endorse or promote products derived from this
17 * software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32#include <stdio.h>
33#include <stdlib.h>
34#include <unistd.h>
35#include <getopt.h>
36#include <str.h>
37#include <fcntl.h>
38#include <io/console.h>
39#include <io/color.h>
40#include <io/style.h>
41#include <io/keycode.h>
42#include <errno.h>
43#include <vfs/vfs.h>
44#include <assert.h>
45
46#include "config.h"
47#include "util.h"
48#include "errors.h"
49#include "entry.h"
50#include "cat.h"
51#include "cmds.h"
52
53static const char *cmdname = "cat";
54#define CAT_VERSION "0.0.1"
55#define CAT_DEFAULT_BUFLEN 1024
56
57static const char *cat_oops = "That option is not yet supported\n";
58static const char *hexchars = "0123456789abcdef";
59
60static bool paging_enabled = false;
61static size_t chars_remaining = 0;
62static size_t lines_remaining = 0;
63static sysarg_t console_cols = 0;
64static sysarg_t console_rows = 0;
65static bool should_quit = false;
66
67static struct option const long_options[] = {
68 { "help", no_argument, 0, 'h' },
69 { "version", no_argument, 0, 'v' },
70 { "head", required_argument, 0, 'H' },
71 { "tail", required_argument, 0, 't' },
72 { "buffer", required_argument, 0, 'b' },
73 { "more", no_argument, 0, 'm' },
74 { "hex", no_argument, 0, 'x' },
75 { 0, 0, 0, 0 }
76};
77
78/* Dispays help for cat in various levels */
79void help_cmd_cat(unsigned int level)
80{
81 if (level == HELP_SHORT) {
82 printf("`%s' shows the contents of files\n", cmdname);
83 } else {
84 help_cmd_cat(HELP_SHORT);
85 printf(
86 "Usage: %s [options] <file1> [file2] [...]\n"
87 "Options:\n"
88 " -h, --help A short option summary\n"
89 " -v, --version Print version information and exit\n"
90 " -H, --head ## Print only the first ## bytes\n"
91 " -t, --tail ## Print only the last ## bytes\n"
92 " -b, --buffer ## Set the read buffer size to ##\n"
93 " -m, --more Pause after each screen full\n"
94 " -x, --hex Print bytes as hex values\n"
95 "Currently, %s is under development, some options don't work.\n",
96 cmdname, cmdname);
97 }
98
99 return;
100}
101
102static void waitprompt()
103{
104 console_set_pos(fphone(stdout), 0, console_rows-1);
105 console_set_color(fphone(stdout), COLOR_BLUE, COLOR_WHITE, 0);
106 printf("ENTER/SPACE/PAGE DOWN - next page, "
107 "ESC/Q - quit, C - continue unpaged");
108 fflush(stdout);
109 console_set_style(fphone(stdout), STYLE_NORMAL);
110}
111
112static void waitkey()
113{
114 console_event_t ev;
115
116 while (true) {
117 if (!console_get_event(fphone(stdin), &ev)) {
118 return;
119 }
120 if (ev.type == KEY_PRESS) {
121 if (ev.key == KC_ESCAPE || ev.key == KC_Q) {
122 should_quit = true;
123 return;
124 }
125 if (ev.key == KC_C) {
126 paging_enabled = false;
127 return;
128 }
129 if (ev.key == KC_ENTER || ev.key == KC_SPACE ||
130 ev.key == KC_PAGE_DOWN) {
131 return;
132 }
133 }
134 }
135 assert(false);
136}
137
138static void newpage()
139{
140 console_clear(fphone(stdout));
141 chars_remaining = console_cols;
142 lines_remaining = console_rows-1;
143}
144
145static void paged_char(wchar_t c)
146{
147 putchar(c);
148 if (paging_enabled) {
149 chars_remaining--;
150 if (c == '\n' || chars_remaining == 0) {
151 chars_remaining = console_cols;
152 lines_remaining--;
153 }
154 if (lines_remaining == 0) {
155 fflush(stdout);
156 waitprompt();
157 waitkey();
158 newpage();
159 }
160 }
161}
162
163static unsigned int cat_file(const char *fname, size_t blen, bool hex)
164{
165 int fd, bytes = 0, count = 0, reads = 0;
166 char *buff = NULL;
167 int i;
168 size_t offset = 0;
169
170 fd = open(fname, O_RDONLY);
171 if (fd < 0) {
172 printf("Unable to open %s\n", fname);
173 return 1;
174 }
175
176 if (NULL == (buff = (char *) malloc(blen + 1))) {
177 close(fd);
178 printf("Unable to allocate enough memory to read %s\n",
179 fname);
180 return 1;
181 }
182
183 do {
184 bytes = read(fd, buff, blen);
185 if (bytes > 0) {
186 count += bytes;
187 buff[bytes] = '\0';
188 offset = 0;
189 for (i = 0; i < bytes && !should_quit; i++) {
190 if (hex) {
191 paged_char(hexchars[((uint8_t)buff[i])/16]);
192 paged_char(hexchars[((uint8_t)buff[i])%16]);
193 }
194 else {
195 wchar_t c = str_decode(buff, &offset, bytes);
196 if (c == 0) {
197 // reached end of string
198 break;
199 }
200 paged_char(c);
201 }
202
203 }
204 reads++;
205 }
206 } while (bytes > 0 && !should_quit);
207
208 close(fd);
209 if (bytes == -1) {
210 printf("Error reading %s\n", fname);
211 free(buff);
212 return 1;
213 }
214
215 free(buff);
216
217 return 0;
218}
219
220/* Main entry point for cat, accepts an array of arguments */
221int cmd_cat(char **argv)
222{
223 unsigned int argc, i, ret = 0, buffer = 0;
224 int c, opt_ind;
225 bool hex = false;
226 bool more = false;
227 sysarg_t rows, cols;
228 int rc;
229
230 // reset global state
231 // TODO: move to structure?
232 paging_enabled = false;
233 chars_remaining = 0;
234 lines_remaining = 0;
235 console_cols = 0;
236 console_rows = 0;
237 should_quit = false;
238
239 argc = cli_count_args(argv);
240
241 for (c = 0, optind = 0, opt_ind = 0; c != -1;) {
242 c = getopt_long(argc, argv, "xhvmH:t:b:", long_options, &opt_ind);
243 switch (c) {
244 case 'h':
245 help_cmd_cat(HELP_LONG);
246 return CMD_SUCCESS;
247 case 'v':
248 printf("%s\n", CAT_VERSION);
249 return CMD_SUCCESS;
250 case 'H':
251 printf("%s", cat_oops);
252 return CMD_FAILURE;
253 case 't':
254 printf("%s", cat_oops);
255 return CMD_FAILURE;
256 case 'b':
257 printf("%s", cat_oops);
258 break;
259 case 'm':
260 more = true;
261 break;
262 case 'x':
263 hex = true;
264 break;
265 }
266 }
267
268 argc -= optind;
269
270 if (argc < 1) {
271 printf("%s - incorrect number of arguments. Try `%s --help'\n",
272 cmdname, cmdname);
273 return CMD_FAILURE;
274 }
275
276 if (buffer <= 0)
277 buffer = CAT_DEFAULT_BUFLEN;
278
279 if (more) {
280 rc = console_get_size(fphone(stdout), &cols, &rows);
281 if (rc != EOK) {
282 printf("%s - cannot get console size\n", cmdname);
283 return CMD_FAILURE;
284 }
285 console_cols = cols;
286 console_rows = rows;
287 paging_enabled = true;
288 newpage();
289 }
290
291 for (i = optind; argv[i] != NULL && !should_quit; i++)
292 ret += cat_file(argv[i], buffer, hex);
293
294 if (ret)
295 return CMD_FAILURE;
296 else
297 return CMD_SUCCESS;
298}
299
Note: See TracBrowser for help on using the repository browser.