Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/app/bdsh/cmds/modules/cat/cat.c

    r9d58539 ra33706e  
    5252#define CAT_VERSION "0.0.1"
    5353#define CAT_DEFAULT_BUFLEN 1024
    54 
    55 static const char *cat_oops = "That option is not yet supported\n";
     54#define CAT_FULL_FILE 0
     55
    5656static const char *hexchars = "0123456789abcdef";
    5757
     
    6262static sysarg_t console_rows = 0;
    6363static bool should_quit = false;
     64static bool dash_represents_stdin = false;
    6465
    6566static console_ctrl_t *console = NULL;
     
    7374        { "more", no_argument, 0, 'm' },
    7475        { "hex", no_argument, 0, 'x' },
     76        { "stdin", no_argument, 0, 's' },
    7577        { 0, 0, 0, 0 }
    7678};
     
    9395                "  -m, --more       Pause after each screen full\n"
    9496                "  -x, --hex        Print bytes as hex values\n"
     97                "  -s  --stdin      Treat `-' in file list as standard input\n"
    9598                "Currently, %s is under development, some options don't work.\n",
    9699                cmdname, cmdname);
     
    163166}
    164167
    165 static unsigned int cat_file(const char *fname, size_t blen, bool hex)
     168static unsigned int cat_file(const char *fname, size_t blen, bool hex,
     169    off64_t head, off64_t tail, bool tail_first)
    166170{
    167171        int fd, bytes = 0, count = 0, reads = 0;
    168172        char *buff = NULL;
    169173        int i;
    170         size_t offset = 0;
    171 
    172         fd = open(fname, O_RDONLY);
     174        size_t offset = 0, copied_bytes = 0;
     175        off64_t file_size = 0, length = 0;
     176
     177        bool reading_stdin = dash_represents_stdin && (str_cmp(fname, "-") == 0);
     178
     179        if (reading_stdin) {
     180                fd = fileno(stdin);
     181                /* Allow storing the whole UTF-8 character. */
     182                blen = STR_BOUNDS(1);
     183        } else {
     184                fd = open(fname, O_RDONLY);
     185        }
    173186        if (fd < 0) {
    174187                printf("Unable to open %s\n", fname);
     
    183196        }
    184197
     198        if (tail != CAT_FULL_FILE) {
     199                file_size = lseek(fd, 0, SEEK_END);
     200                if (head == CAT_FULL_FILE) {
     201                        head = file_size;
     202                        length = tail;
     203                } else if (tail_first) {
     204                        length = head;
     205                } else {
     206                        if (tail > head)
     207                                tail = head;
     208                        length = tail;
     209                }
     210
     211                if (tail_first) {
     212                        lseek(fd, (tail >= file_size) ? 0 : (file_size - tail), SEEK_SET);
     213                } else {
     214                        lseek(fd, ((head - tail) >= file_size) ? 0 : (head - tail), SEEK_SET);
     215                }
     216        } else
     217                length = head;
     218
    185219        do {
    186                 bytes = read(fd, buff, blen);
     220                size_t bytes_to_read;
     221                if (reading_stdin) {
     222                        bytes_to_read = 1;
     223                } else {
     224                        if ((length != CAT_FULL_FILE)
     225                            && (length - (off64_t)count <= (off64_t)(blen - copied_bytes))) {
     226                                bytes_to_read = (size_t) (length - count);
     227                        } else {
     228                                bytes_to_read = blen - copied_bytes;
     229                        }
     230                }
     231                bytes = read(fd, buff + copied_bytes, bytes_to_read);
     232                bytes += copied_bytes;
     233                copied_bytes = 0;
     234
    187235                if (bytes > 0) {
    188                         count += bytes;
    189236                        buff[bytes] = '\0';
    190237                        offset = 0;
     
    193240                                        paged_char(hexchars[((uint8_t)buff[i])/16]);
    194241                                        paged_char(hexchars[((uint8_t)buff[i])%16]);
     242                                        paged_char(((count+i+1) & 0xf) == 0 ? '\n' : ' ');
    195243                                }
    196244                                else {
     
    199247                                                /* Reached end of string */
    200248                                                break;
     249                                        } else if (c == U_SPECIAL && offset + 2 >= (size_t)bytes) {
     250                                                /* If an extended character is cut off due to the size of the buffer,
     251                                                   we will copy it over to the next buffer so it can be read correctly. */
     252                                                copied_bytes = bytes - offset + 1;
     253                                                memcpy(buff, buff + offset - 1, copied_bytes);
     254                                                break;
    201255                                        }
    202256                                        paged_char(c);
     
    204258                               
    205259                        }
     260                        count += bytes;
    206261                        reads++;
    207262                }
    208         } while (bytes > 0 && !should_quit);
     263
     264                if (reading_stdin) {
     265                        fflush(stdout);
     266                }
     267        } while (bytes > 0 && !should_quit && (count < length || length == CAT_FULL_FILE));
    209268
    210269        close(fd);
     
    223282int cmd_cat(char **argv)
    224283{
    225         unsigned int argc, i, ret = 0, buffer = 0;
     284        unsigned int argc, i, ret = 0;
     285        size_t buffer = 0;
    226286        int c, opt_ind;
     287        aoff64_t head = CAT_FULL_FILE, tail = CAT_FULL_FILE;
    227288        bool hex = false;
    228289        bool more = false;
     290        bool tailFirst = false;
    229291        sysarg_t rows, cols;
    230292        int rc;
     
    245307
    246308        for (c = 0, optind = 0, opt_ind = 0; c != -1;) {
    247                 c = getopt_long(argc, argv, "xhvmH:t:b:", long_options, &opt_ind);
     309                c = getopt_long(argc, argv, "xhvmH:t:b:s", long_options, &opt_ind);
    248310                switch (c) {
    249311                case 'h':
     
    254316                        return CMD_SUCCESS;
    255317                case 'H':
    256                         printf("%s", cat_oops);
    257                         return CMD_FAILURE;
     318                        if (!optarg || str_uint64_t(optarg, NULL, 10, false, &head) != EOK ) {
     319                                puts("Invalid head size\n");
     320                                return CMD_FAILURE;
     321                        }
     322                        break;
    258323                case 't':
    259                         printf("%s", cat_oops);
    260                         return CMD_FAILURE;
     324                        if (!optarg || str_uint64_t(optarg, NULL, 10, false, &tail) != EOK ) {
     325                                puts("Invalid tail size\n");
     326                                return CMD_FAILURE;
     327                        }
     328                        if (head == CAT_FULL_FILE)
     329                                tailFirst = true;
     330                        break;
    261331                case 'b':
    262                         printf("%s", cat_oops);
     332                        if (!optarg || str_size_t(optarg, NULL, 10, false, &buffer) != EOK ) {
     333                                puts("Invalid buffer size\n");
     334                                return CMD_FAILURE;
     335                        }
    263336                        break;
    264337                case 'm':
     
    267340                case 'x':
    268341                        hex = true;
     342                        break;
     343                case 's':
     344                        dash_represents_stdin = true;
    269345                        break;
    270346                }
     
    279355        }
    280356
    281         if (buffer <= 0)
     357        if (buffer < 4)
    282358                buffer = CAT_DEFAULT_BUFLEN;
    283359       
     
    295371
    296372        for (i = optind; argv[i] != NULL && !should_quit; i++)
    297                 ret += cat_file(argv[i], buffer, hex);
     373                ret += cat_file(argv[i], buffer, hex, head, tail, tailFirst);
    298374
    299375        if (ret)
Note: See TracChangeset for help on using the changeset viewer.