From: Gene Cumm <gene.cumm at gmail.com> COM32/rosh: Improvements; ls acts more like ls with -l -i and -F being understood; Lots of code clean up and user assistance. Clean up the MCONFIG file; Clean up the code to get it to pass checkpatch.pl (aside from confusion on multi-line strings); Add a little more in the error function to recognize different errors; Signed-off-by: Gene Cumm <gene.cumm at gmail.com> --- Alright, this is finally to the point of where I really wanted to post it at. Compared to the previous version, it's more user friendly. I've cleaned up a lot of C99 comments, many of which were for temporary code. Executing "ls -l" actually looks a lot like normal ls output, except that it's unsorted and the size is a hardcoded width of 10 displayed characters with a friendly look of no leading 0s. The built-in help now also provides command specific help (only for ls for now). The error function gives descriptive messages for more types of errors. I also clear errno on return from the error function. more now pays attention to the width of the terminal. After discussion on __VA_ARGS__ and ((void)0) (Thanks Peter), I've cleaned up some of the macro'd functions. If you try this out, I'd love to hear feedback, especially for improvements and fixes. At this time, SYSLINUX is the only one that it'll work well in as the COMBOOT calls are only implemented for SYSLINUX. This patch depends on all of the previous 4 submitted between yesterday and today. diff --git a/com32/rosh/MCONFIG b/com32/rosh/MCONFIG index 30029d1..2e1ca95 100644 --- a/com32/rosh/MCONFIG +++ b/com32/rosh/MCONFIG @@ -11,17 +11,8 @@ ## ----------------------------------------------------------------------- ## -## COM32 GRC configurables +## COM32 ROSH configurables ## ## Include the COM32 common configurables include ../MCONFIG - -# CFLAGS = $(GCCOPT) -W -Wall -march=i386 \ -# -fomit-frame-pointer -D__COM32__ \ -# -nostdinc -iwithprefix include \ -# -I$(com32)/libutil/include -I$(com32)/include -# -g3 -dD - -# LNXCFLAGS = -I$(com32)/libutil/include -W -Wall -O -g3 -D_GNU_SOURCE -dD -# -U__GNUC__ diff --git a/com32/rosh/rosh.c b/com32/rosh/rosh.c index 5eaa47d..d78e73a 100644 --- a/com32/rosh/rosh.c +++ b/com32/rosh/rosh.c @@ -1,6 +1,6 @@ /* ----------------------------------------------------------------------- * * - * Copyright 2008 Gene Cumm - All Rights Reserved + * Copyright 2008-2009 Gene Cumm - All Rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -22,20 +22,24 @@ * ToDos: * Change functions to use pwdstr * In rosh_run() Reparse cmdstr relative to pwdstr + * rosh_ls(): sorted; then multiple columns */ -// #define DO_DEBUG 1 - /* Uncomment the above line for debugging output; Comment to remove */ -// #define DO_DEBUG2 1 - /* Uncomment the above line for super-debugging output; Must have regular debugging enabled; Comment to remove */ - +/* #define DO_DEBUG 1 +//*/ +/* Uncomment the above line for debugging output; Comment to remove */ +/* #define DO_DEBUG2 1 +//*/ +/* Uncomment the above line for super-debugging output; Must have regular + * debugging enabled; Comment to remove. + */ #include "rosh.h" #define APP_LONGNAME "Read-Only Shell" #define APP_NAME "rosh" #define APP_AUTHOR "Gene Cumm" -#define APP_YEAR "2008" -#define APP_VER "beta-b032" +#define APP_YEAR "2009" +#define APP_VER "beta-b040" void rosh_version() { @@ -43,17 +47,6 @@ void rosh_version() APP_AUTHOR); } -void rosh_help(int type) -{ - rosh_version(); - switch (type) { - case 2: puts(rosh_help_str2); - break; - case 1: default: - puts(rosh_help_str1); - } -} - /* Determine if a character is whitespace * inc input character * returns 0 if not whitespace @@ -61,7 +54,7 @@ void rosh_help(int type) int rosh_issp(char inc) { int rv; - switch (inc){ + switch (inc) { case ' ': case '\t': rv = 1; break; default: rv = 0; @@ -129,6 +122,34 @@ int rosh_parse_sp_1(char *dest, const char *src, const int ipos) return epos; } +/* Display help + * type Help type + * cmdstr Command string + */ +void rosh_help(int type, const char *cmdstr) +{ + char *istr; + istr = cmdstr; + switch (type) { + case 2: + istr += rosh_search_nonsp(cmdstr, rosh_search_sp(cmdstr, 0)); + if ((cmdstr == NULL) || (strcmp(istr, "") == 0)) { + rosh_version(); + puts(rosh_help_str2); + } else { + switch (istr[0]) { + case 'l': puts(rosh_help_ls_str); + break; + default: printf(rosh_help_str_adv, istr); + } + } + break; + case 1: default: + rosh_version(); + puts(rosh_help_str1); + } +} + /* Handle most/all errors * ierrno Input Error number * cmdstr Command being executed to cause error @@ -138,21 +159,27 @@ void rosh_error(const int ierrno, const char *cmdstr, const char *filestr) { printf("--ERROR: %s '%s': ", cmdstr, filestr); switch (ierrno) { - case EACCES: printf("Access DENIED\n"); + case 0: puts("NO ERROR"); break; - case ENOENT: printf("not found\n"); + case ENOENT: puts("not found"); /* SYSLinux-3.72 COM32 API returns this for a directory or empty file */ ROSH_COM32(" (COM32) could be a directory or empty file\n"); break; - case ENOTDIR: printf("not a directory\n"); + case EBADF: puts("Bad File Descriptor"); + break; + case EACCES: puts("Access DENIED"); + break; + case ENOTDIR: puts("not a directory"); ROSH_COM32(" (COM32) could be directory\n"); break; - case ENOSYS: printf("not implemented"); + case EISDIR: puts("IS a directory"); + break; + case ENOSYS: puts("not implemented"); break; default: printf("returns error; errno=%d\n", ierrno); } -} +} /* rosh_error */ /* Concatenate command line arguments into one string * cmdstr Output command string @@ -216,16 +243,8 @@ void rosh_print_tc(struct termios *tio) */ void rosh_console_raw() { -// struct termios itio, ntio; -// tcgetattr(0, &itio); -// rosh_print_tc(&itio); -/* ntio = itio; - ntio.c_lflag &= ~(ICANON|ECHO); - tcsetattr(0, TCSAFLUSH, &ntio);*/ console_ansi_raw(); /* Allows get_key to get just 1 key sequence (w/o delay or display */ -// tcgetattr(0, &ntio); -// rosh_print_tc(&ntio); } /* @@ -233,9 +252,7 @@ void rosh_console_raw() */ void rosh_console_std() { -// struct termios itio, ntio; console_ansi_std(); -// tcsetattr(0, TCSANOW, &itio); } /* @@ -247,11 +264,8 @@ int rosh_getkey() int inc; inc = KEY_NONE; -// rosh_console_raw(); - while (inc == KEY_NONE){ + while (inc == KEY_NONE) inc = get_key(stdin, 6000); - } -// rosh_console_std(); return inc; } /* rosh_getkey */ @@ -297,6 +311,7 @@ void rosh_cat(const char *cmdstr, const char *pwdstr) fclose(f); } else { rosh_error(errno, "cat", filestr); + errno = 0; } cmdpos = rosh_parse_sp_1(filestr, cmdstr, cmdpos); } @@ -320,13 +335,14 @@ void rosh_cd(const char *cmdstr, char *pwdstr, const char *ipwdstr) /* skip the first word */ cmdpos = rosh_parse_sp_1(filestr, cmdstr, cmdpos); cmdpos = rosh_parse_sp_1(filestr, cmdstr, cmdpos); - ROSH_COM32(" -- cd (Change Directory) not implemented for use with run and exit.\n"); + ROSH_COM32(rosh_cd_norun_str); if (strlen(filestr) != 0) rv = chdir(filestr); else rv = chdir(ipwdstr); if (rv != 0) { rosh_error(errno, "cd", filestr); + errno = 0; } else { getcwd(pwdstr, ROSH_PATH_SZ + 1); printf(" %s\n", pwdstr); @@ -334,21 +350,263 @@ void rosh_cd(const char *cmdstr, char *pwdstr, const char *ipwdstr) } /* rosh_cd */ /* Print the syslinux config file name - * cmdstr command string to process - * pwdstr Present Working Directory string */ -void rosh_cfg(const char *cmdstr, const char *pwdstr) +void rosh_cfg() { - ROSH_DEBUG("CMD: '%s'\npwd: '%s'\n", cmdstr, pwdstr); printf("CFG: '%s'\n", syslinux_config_file()); } /* rosh_cfg */ +/* Process optstr to optarr + * optstr option string to process + * optarr option array to populate + */ +void rosh_ls_arg_opt(const char *optstr, int *optarr) +{ + char *cpos; + cpos = strchr(optstr, 'l'); + if (cpos) { + optarr[0] = cpos - optstr; + } else { + optarr[0] = -1; + } + cpos = strchr(optstr, 'F'); + if (cpos) { + optarr[1] = cpos - optstr; + } else { + optarr[1] = -1; + } + cpos = strchr(optstr, 'i'); + if (cpos) { + optarr[2] = cpos - optstr; + } else { + optarr[2] = -1; + } +} /* rosh_ls_arg_opt */ + +/* Retrieve the size of a file argument + * filestr directory name of directory entry + * de directory entry + */ +int rosh_ls_de_size(const char *filestr, struct dirent *de) +{ + int de_size; + +#ifdef __COM32__ + de_size = de->d_size; +#else /* __COM32__ */ + char filestr2[ROSH_PATH_SZ + 1]; + int fd2, file2pos; + struct stat fdstat; + int status; + + filestr2[0] = 0; + file2pos = -1; + if (filestr) { + file2pos = strlen(filestr); + memcpy(filestr2, filestr, file2pos); + filestr2[file2pos] = '/'; + } + strcpy(filestr2+file2pos+1, de->d_name); + fd2 = open(filestr2, O_RDONLY); + status = fstat(fd2, &fdstat); + fd2 = close(fd2); + de_size = (int)fdstat.st_size; +#endif /* __COM32__ */ + return de_size; +} /* rosh_ls_de_size */ + +/* Retrieve the size and mode of a file + * filestr directory name of directory entry + * de directory entry + */ +int rosh_ls_de_size_mode(const char *filestr, struct dirent *de, + mode_t *st_mode) +{ + int de_size; + +#ifdef __COM32__ + de_size = de->d_size; + *st_mode = de->d_mode; +#else /* __COM32__ */ + char filestr2[ROSH_PATH_SZ + 1]; + int file2pos; + struct stat fdstat; + int status; + + filestr2[0] = 0; + file2pos = -1; + fdstat.st_size = 0; + fdstat.st_mode = 0; + if (filestr) { + file2pos = strlen(filestr); + memcpy(filestr2, filestr, file2pos); + filestr2[file2pos] = '/'; + } + strcpy(filestr2+file2pos+1, de->d_name); + status = stat(filestr2, &fdstat); + ROSH_DEBUG2("\t--stat()=%d\terr=%d\n", status, errno); + if (errno) { + rosh_error(errno, "ls:szmd.stat", filestr2); + errno = 0; + } + de_size = (int)fdstat.st_size; + *st_mode = fdstat.st_mode; +#endif /* __COM32__ */ + return de_size; +} /* rosh_ls_de_size_mode */ + +/* Returns the Inode number if fdstat contains it + * fdstat struct to extract size from if not COM32 + */ +long rosh_ls_d_ino(struct stat *fdstat) +{ + long de_ino; +#ifdef __COM32__ + de_ino = -1; +#else /* __COM32__ */ + de_ino = fdstat->st_ino; +#endif /* __COM32__ */ + return de_ino; +} + +/* Convert a d_type to a single char by ls's prefix standards + * d_type d_type to convert + * returns ls style single character; a space if other + */ +char rosh_d_type2char_lspre(unsigned char d_type) +{ + char ret; + switch (d_type) { + case 1 : ret = 'p'; break; + case 2 : ret = 'c'; break; + case 4 : ret = 'd'; break; + case 6 : ret = 'b'; break; + case 8 : ret = '-'; break; + case 10 : ret = 'l'; break; + case 12 : ret = 's'; break; + default : ret = '?'; + } + return ret; +} /* rosh_d_type2char_lspre */ + +/* Convert a d_type to a single char by ls's classify suffix standards + * d_type d_type to convert + * returns ls style single character; a space if other + */ +char rosh_d_type2char_lssuf(unsigned char d_type) +{ + char ret; + switch (d_type) { + case 1 : ret = '|'; break; + case 4 : ret = '/'; break; + case 10 : ret = '@'; break; + case 12 : ret = '='; break; + default : ret = ' '; + } + return ret; +} /* rosh_d_type2char_lssuf */ + +/* Convert a d_type to a single char in human readable format + * d_type d_type to convert + * returns human readable single character; a space if other + */ +char rosh_d_type2char_human(unsigned char d_type) +{ + char ret; + switch (d_type) { + case 0 : ret = 'U'; break; /* Unknown */ + case 1 : ret = 'F'; break; /* FIFO */ + case 2 : ret = 'C'; break; /* Char Dev */ + case 4 : ret = 'D'; break; /* Directory */ + case 6 : ret = 'B'; break; /* Block Dev */ + case 8 : ret = 'R'; break; /* Regular File */ + case 10 : ret = 'L'; break; /* Link, Symbolic */ + case 12 : ret = 'S'; break; /* Socket */ + case 14 : ret = 'W'; break; /* UnionFS Whiteout */ + default : ret = ' '; + } + return ret; +} /* rosh_d_type2char_human */ + +/* Converts data in the "other" place of st_mode to a ls-style string + * st_mode Mode in other to analyze + * st_mode_str string to hold converted string + */ +void rosh_st_mode_am2str(mode_t st_mode, char *st_mode_str) +{ + st_mode_str[0] = ((st_mode & S_IROTH) ? 'r' : '-'); + st_mode_str[1] = ((st_mode & S_IWOTH) ? 'w' : '-'); + st_mode_str[2] = ((st_mode & S_IXOTH) ? 'x' : '-'); +} + +/* Converts st_mode to an ls-style string + * st_mode mode to convert + * st_mode_str string to hold converted string + */ +void rosh_st_mode2str(mode_t st_mode, char *st_mode_str) +{ + st_mode_str[0] = rosh_d_type2char_lspre(IFTODT(st_mode)); + rosh_st_mode_am2str((st_mode & S_IRWXU) >> 6, st_mode_str + 1); + rosh_st_mode_am2str((st_mode & S_IRWXG) >> 3, st_mode_str + 4); + rosh_st_mode_am2str(st_mode & S_IRWXO, st_mode_str + 7); + st_mode_str[10] = 0; +} /* rosh_st_mode2str */ + +/* Output a single entry + * filestr directory name to list + * de directory entry + * optarr Array of options + */ +void rosh_ls_arg_dir_de(const char *filestr, struct dirent *de, + const int *optarr) +{ + int de_size; + mode_t st_mode; + char st_mode_str[11]; + if (optarr[2] > -1) + printf("%10d ", (int)de->d_ino); + if (optarr[0] > -1) { + de_size = rosh_ls_de_size_mode(filestr, de, &st_mode); + rosh_st_mode2str(st_mode, st_mode_str); + ROSH_DEBUG2("%04X ", st_mode); + printf("%s %10d ", st_mode_str, de_size); + } + ROSH_DEBUG("'"); + printf("%s", de->d_name); + ROSH_DEBUG("'"); + if (optarr[1] > -1) + printf("%c", rosh_d_type2char_lssuf(de->d_type)); + printf("\n"); +} /* rosh_ls_arg_dir_de */ + +/* Output listing of a regular directory + * filestr directory name to list + * d the open DIR + * optarr Array of options + NOTE:This is where I could use qsort + */ +void rosh_ls_arg_dir(const char *filestr, DIR *d, const int *optarr) +{ + struct dirent *de; + int filepos; + + filepos = 0; + de = readdir(d); + while (de != NULL) { + filepos++; + rosh_ls_arg_dir_de(filestr, de, optarr); + ROSH_FREE_DIRENT(de); + de = readdir(d); + } +} /* rosh_ls_arg_dir */ + /* Simple directory listing for one argument (file/directory) based on * filestr and pwdstr * ifilstr input filename/directory name to list * pwdstr Present Working Directory string + * optarr Option Array */ -void rosh_dir_arg(const char *ifilstr, const char *pwdstr) +void rosh_ls_arg(const char *ifilstr, const char *pwdstr, const int *optarr) { struct stat fdstat; int status; @@ -356,15 +614,7 @@ void rosh_dir_arg(const char *ifilstr, const char *pwdstr) char filestr[ROSH_PATH_SZ + 1]; int filepos; DIR *d; - struct dirent *de; -#ifdef DO_DEBUG - char filestr2[ROSH_PATH_SZ + 1]; - int fd2, file2pos; -#ifdef __COM32__ -// int inchar; - char ty; -#endif /* __COM32__ */ -#endif /* DO_DEBUG */ + struct dirent de; /* Initialization; make filestr based on leading character of ifilstr and pwdstr */ @@ -376,127 +626,136 @@ void rosh_dir_arg(const char *ifilstr, const char *pwdstr) if (filestr[filepos-1] != SEP) filestr[filepos++] = SEP; strcpy(filestr + filepos, ifilstr); -ROSH_DEBUG("--'%s'\n", filestr); + ROSH_DEBUG("--'%s'\n", filestr); } - fd = open(filestr, O_RDONLY); - if (fd != -1) { - status = fstat(fd, &fdstat); + ROSH_DEBUG("\topt[0]=%d\topt[1]=%d\topt[2]=%d\n", optarr[0], optarr[1], + optarr[2]); + + /* Now, the real work */ + status = stat(filestr, &fdstat); + if (status == 0) { if (S_ISDIR(fdstat.st_mode)) { ROSH_DEBUG("PATH '%s' is a directory\n", ifilstr); - d = fdopendir(fd); - de = readdir(d); - while (de != NULL) { -#ifdef DO_DEBUG - filestr2[0] = 0; - file2pos = strlen(filestr); - memcpy(filestr2, filestr, file2pos); - filestr2[file2pos] = '/'; - strcpy(filestr2+file2pos+1, de->d_name); - fd2 = open(filestr2, O_RDONLY); - status = fstat(fd2, &fdstat); - printf("@%8d:%8d:", (int)de->d_ino, (int)fdstat.st_size); - fd2 = close(fd2); -#endif /* DO_DEBUG */ - printf("%s\n", de->d_name); -#ifdef DO_DEBUG -// inchar = fgetc(stdin); -#endif /* DO_DEBUG */ - de = readdir(d); - } + d = opendir(filestr); + rosh_ls_arg_dir(filestr, d, optarr); closedir(d); - } else if (S_ISREG(fdstat.st_mode)) { - ROSH_DEBUG("PATH '%s' is a regular file\n", ifilstr); - printf("%8d:%s\n", (int)fdstat.st_size, ifilstr); } else { - ROSH_DEBUG("PATH '%s' is some other file\n", ifilstr); - printf(" :%s\n", ifilstr); - } - } else { -#ifdef __COM32__ - if (filestr[strlen(filestr)-1] == SEP) { - /* Directory */ - filepos = 0; - d = opendir(filestr); - if (d != NULL) { -printf("DIR:'%s' %8d %8d\n", d->dd_name, d->dd_fd, d->dd_sect); - de = readdir(d); - while (de != NULL) { - filepos++; -#ifdef DO_DEBUG -// if (strlen(de->d_name) > 25) de->d_name[25] = 0; - switch (de->d_mode) { - case 16 : ty = 'D'; break; - case 32 : ty = 'F'; break; - default : ty = '*'; - } - printf("@%8d:%8d:%4d ", (int)de->d_ino, (int)de->d_size, de->d_mode); -#endif /* DO_DEBUG */ -// printf("%s\n", de->d_name); -printf("'%s'\n", de->d_name); -#ifdef DO_DEBUG -// inchar = fgetc(stdin); -// fgets(instr, ROSH_CMD_SZ, stdin); -#endif /* DO_DEBUG */ - free(de); - de = readdir(d); -// if(filepos>15){ de = NULL; printf("Force Break\n");} - } -printf("Dir.dd_fd: '%8d'\n", d->dd_fd); - closedir(d); + de.d_ino = rosh_ls_d_ino(&fdstat); + de.d_type = fdstat.st_mode >> 12; + strcpy(de.d_name, ifilstr); + if (S_ISREG(fdstat.st_mode)) { + ROSH_DEBUG("PATH '%s' is a regular file\n", + ifilstr); } else { - rosh_error(0, "dir:NULL", filestr); + ROSH_DEBUG("PATH '%s' is some other file\n", + ifilstr); } - } else { - rosh_error(errno, "dir_c32", filestr); + if (ifilstr[0] == SEP) + rosh_ls_arg_dir_de(NULL, &de, optarr); + else + rosh_ls_arg_dir_de(pwdstr, &de, optarr); } -#else - rosh_error(errno, "dir", filestr); -#endif /* __COM32__ */ + } else { + rosh_error(errno, "ls", filestr); + errno = 0; } -} /* rosh_dir_arg */ + return; +} /* rosh_ls_arg */ -/* Simple directory listing based on cmdstr and pwdstr +/* Parse options that may be present in the cmdstr + * filestr Possible option string to parse + * optstr Current options + * returns 1 if filestr does not begin with '-' else 0 + */ +int rosh_ls_parse_opt(const char *filestr, char *optstr) +{ + int ret; + if (filestr[0] == '-') { + ret = 0; + if (optstr) + strcat(optstr, filestr + 1); + } else { + ret = 1; + } + ROSH_DEBUG("ParseOpt: '%s'\n\topt: '%s'\n\tret: %d\n", filestr, optstr, + ret); + return ret; +} /* rosh_ls_parse_opt */ + +/* List Directory based on cmdstr and pwdstr * cmdstr command string to process * pwdstr Present Working Directory string */ -void rosh_dir(const char *cmdstr, const char *pwdstr) +void rosh_ls(const char *cmdstr, const char *pwdstr) { char filestr[ROSH_PATH_SZ + 1]; - int cmdpos; /* Position within cmdstr */ + char optstr[ROSH_OPT_SZ]; /* Options string */ + int cmdpos, tpos; /* Position within cmdstr, temp position */ + int numargs; /* number of non-option arguments */ + int argpos; /* number of non-option arguments processed */ + int optarr[2]; ROSH_DEBUG("CMD: '%s'\npwd: '%s'\n", cmdstr, pwdstr); /* Initialization */ filestr[0] = 0; + optstr[0] = 0; cmdpos = 0; + numargs = 0; + argpos = 0; /* skip the first word */ cmdpos = rosh_parse_sp_1(filestr, cmdstr, cmdpos); - cmdpos = rosh_parse_sp_1(filestr, cmdstr, cmdpos); + tpos = rosh_parse_sp_1(filestr, cmdstr, cmdpos); /* If there are no real arguments, substitute PWD */ - if (strlen(filestr) == 0) + if (strlen(filestr) == 0) { strcpy(filestr, pwdstr); + cmdpos = tpos; + } else { /* Parse for command line options */ + while (strlen(filestr) > 0) { + numargs += rosh_ls_parse_opt(filestr, optstr); + tpos = rosh_parse_sp_1(filestr, cmdstr, tpos); + } + if (numargs == 0) { + strcpy(filestr, pwdstr); + cmdpos = tpos; + } else { + cmdpos = rosh_parse_sp_1(filestr, cmdstr, cmdpos); + } + } +#ifdef DO_DEBUG + if (!strchr(optstr, 'l')) + strcat(optstr, "l"); +#endif /* DO_DEBUG */ + rosh_ls_arg_opt(optstr, optarr); + ROSH_DEBUG("\tfopt: '%s'\n", optstr); while (strlen(filestr) > 0) { - rosh_dir_arg(filestr, pwdstr); - cmdpos = rosh_parse_sp_1(filestr, cmdstr, cmdpos); + if (rosh_ls_parse_opt(filestr, NULL)) { + rosh_ls_arg(filestr, pwdstr, optarr); + argpos++; + } + if (argpos < numargs) + cmdpos = rosh_parse_sp_1(filestr, cmdstr, cmdpos); + else + break; } -} /* rosh_dir */ +} /* rosh_ls */ -/* List Directory; Calls rosh_dir() for now. +/* Simple directory listing; calls rosh_ls() * cmdstr command string to process * pwdstr Present Working Directory string */ -void rosh_ls(const char *cmdstr, const char *pwdstr) +void rosh_dir(const char *cmdstr, const char *pwdstr) { - printf(" ls implemented as dir (for now)\n"); - rosh_dir(cmdstr, pwdstr); -} /* rosh_ls */ + ROSH_DEBUG(" dir implemented as ls\n"); + rosh_ls(cmdstr, pwdstr); +} /* rosh_dir */ /* Page through a buffer string * buf Buffer to page through */ void rosh_more_buf(char *buf, int buflen, int rows, int cols) { - char *bufp, *bufeol; /* Pointer to current and next end-of-line - position in buffer */ + char *bufp, *bufeol, *bufeol2; /* Pointer to current and next + end-of-line position in buffer */ int bufpos, bufcnt; /* current position, count characters */ char scrbuf[ROSH_SBUF_SZ]; int inc; @@ -506,45 +765,36 @@ void rosh_more_buf(char *buf, int buflen, int rows, int cols) bufp = buf + bufpos; bufeol = bufp; numln = rows - 1; -printf("--(%d)\n", buflen); -// printf("--termIOS CONSTS: "); -// printf("ISIG=%08X ", ISIG); -// printf("ICANON=%08X ", ICANON); -// printf("ECHO=%08X ", ECHO); -// printf("=%08X", ); -// printf("\n"); + ROSH_DEBUG("--(%d)\n", buflen); while (bufpos < buflen) { - for (i=0; i<numln; i++){ - bufeol = strchr(bufeol, '\n'); - if (bufeol == NULL) { + for (i = 0; i < numln; i++) { + bufeol2 = strchr(bufeol, '\n'); + if (bufeol2 == NULL) { bufeol = buf + buflen; i = numln; } else { - bufeol++; + i += ((bufeol2 - bufeol)/cols); + bufeol = bufeol2 + 1; } -// printf("--readln\n"); } bufcnt = bufeol - bufp; -printf("--(%d/%d @%d)\n", bufcnt, buflen, bufpos); + printf("--(%d/%d @%d)\n", bufcnt, buflen, bufpos); memcpy(scrbuf, bufp, bufcnt); scrbuf[bufcnt] = 0; printf("%s", scrbuf); bufp = bufeol; bufpos += bufcnt; - if (bufpos == buflen) break; + if (bufpos == buflen) + break; inc = rosh_getkey(); numln = 1; - switch (inc){ + switch (inc) { case KEY_CTRL('c'): case 'q': case 'Q': bufpos = buflen; break; case ' ': numln = rows - 1; -// default: } } -/*tcgetattr(0, &tio); -rosh_print_tc(&tio); -printf("\n--END\n");*/ } /* rosh_more_buf */ /* Page through a single file using the open file stream @@ -622,6 +872,7 @@ void rosh_more(const char *cmdstr, const char *pwdstr) close(fd); } else { rosh_error(errno, "more", filestr); + errno = 0; } cmdpos = rosh_parse_sp_1(filestr, cmdstr, cmdpos); } @@ -649,7 +900,7 @@ void rosh_pwd(const char *cmdstr, const char *pwdstr) int istr; ROSH_DEBUG("CMD: '%s'\npwd: '%s'\n", cmdstr, pwdstr); printf("%s\n", pwdstr); - istr = htonl(*(int*)pwdstr); + istr = htonl(*(int *)pwdstr); ROSH_DEBUG(" --%08X\n", istr); } /* rosh_pwd */ @@ -708,32 +959,32 @@ char rosh_command(const char *cmdstr, char *pwdstr, const char *ipwdstr) case 'd': case 'D': rosh_cd(cmdstr, pwdstr, ipwdstr); break; case 'f': case 'F': - rosh_cfg(cmdstr, pwdstr); break; - default: rosh_help(1); + rosh_cfg(); break; + default: rosh_help(1, NULL); } break; case 'd': case 'D': /* run 'dir' */ rosh_dir(cmdstr, pwdstr); break; - case 'h': case 'H': case '?': rosh_help(2); + case 'h': case 'H': case '?': rosh_help(2, cmdstr); break; case 'l': case 'L': /* run 'ls' 'less' */ switch (cmdstr[1]) { - case 0: case 's': case 'S': + case 0: case ' ': case 's': case 'S': rosh_ls(cmdstr, pwdstr); break; case 'e': case 'E': rosh_less(cmdstr, pwdstr); break; - default: rosh_help(1); + default: rosh_help(1, NULL); } break; case 'm': case 'M': switch (cmdstr[1]) { case 'a': case 'A': - rosh_help(2); + rosh_help(2, cmdstr); break; case 'o': case 'O': rosh_more(cmdstr, pwdstr); break; - default: rosh_help(1); + default: rosh_help(1, NULL); } break; case 'p': case 'P': /* run 'pwd' */ @@ -743,7 +994,7 @@ char rosh_command(const char *cmdstr, char *pwdstr, const char *ipwdstr) case 'v': case 'V': rosh_version(); break; case 0: case '\n': break; - default : rosh_help(1); + default : rosh_help(1, NULL); } /* switch(cmdstr[0]) */ return do_exit; } /* rosh_command */ @@ -758,8 +1009,7 @@ int rosh_prompt(const char *icmdstr) int rv; char cmdstr[ROSH_CMD_SZ]; char pwdstr[ROSH_PATH_SZ + 1], ipwdstr[ROSH_PATH_SZ + 1]; -/* int numchar; -*/ char do_exit; + char do_exit; char *c; rv = 0; @@ -771,6 +1021,7 @@ int rosh_prompt(const char *icmdstr) do_exit = rosh_command(icmdstr, pwdstr, ipwdstr); while (!(do_exit)) { console_ansi_std(); + /* Extra preceeding newline */ printf("\nrosh: "); /* Read a line from console */ fgets(cmdstr, ROSH_CMD_SZ, stdin); @@ -796,7 +1047,6 @@ int main(int argc, char *argv[]) /* Initialization */ rv = 0; console_ansi_std(); -// console_ansi_raw(); if (argc != 1) { rv = rosh_argcat(cmdstr, argc, argv, 1); } else { diff --git a/com32/rosh/rosh.h b/com32/rosh/rosh.h index d7296e1..ee89714 100644 --- a/com32/rosh/rosh.h +++ b/com32/rosh/rosh.h @@ -1,6 +1,6 @@ /* ----------------------------------------------------------------------- * * - * Copyright 2008 Gene Cumm - All Rights Reserved + * Copyright 2008-2009 Gene Cumm - All Rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -18,6 +18,7 @@ /* * History + * b034 Improve debug functions to simpler code * b021 Move much PreProcessing stuff to rosh.h * b018 Create rosh_debug() macro * b012 Version of rosh.c at time of creating this file. @@ -41,22 +42,18 @@ #include <getkey.h> #include <consoles.h> -/* A GNUC extension to void out unused functions are used */ -/* Plus, there seem to be other references for SYSLINUX to __GNUC__ */ -#ifndef __GNUC__ -#error SYSLINUX (I believe) requires __GNUC__ -#endif /* __GNUC__ */ - #ifdef DO_DEBUG -#define ROSH_DEBUG(f, ...) printf (f, ## __VA_ARGS__) -#ifdef DO_DEBUG2 -#define ROSH_DEBUG2(f, ...) printf (f, ## __VA_ARGS__) -#else /* DO_DEBUG2 */ -#define ROSH_DEBUG2(f, ...) ((void)0) -#endif /* DO_DEBUG2 */ +# define ROSH_DEBUG printf +/* define ROSH_DEBUG(f, ...) printf (f, ## __VA_ARGS__) */ +# ifdef DO_DEBUG2 +# define ROSH_DEBUG2 printf +# else /* DO_DEBUG2 */ + /* This forces a format argument into the function call */ +# define ROSH_DEBUG2(f, ...) ((void)0) +# endif /* DO_DEBUG2 */ #else /* DO_DEBUG */ -#define ROSH_DEBUG(f, ...) ((void)0) -#define ROSH_DEBUG2(f, ...) ((void)0) +# define ROSH_DEBUG(f, ...) ((void)0) +# define ROSH_DEBUG2(f, ...) ((void)0) #endif /* DO_DEBUG */ #ifdef __COM32__ @@ -65,6 +62,7 @@ #include <syslinux/config.h> /* Has info on the SYSLINUX variant */ #include <syslinux/boot.h> /* syslinux_run_command() */ #define ROSH_COM32(f, ...) printf (f, ## __VA_ARGS__) +#define ROSH_FREE_DIRENT(de) free(de) #else #include <termios.h> #define ROSH_IS_COM32 0 @@ -78,16 +76,16 @@ static inline int getscreensize(int fd, int *rows, int *cols) int rv; *rows = 0; *cols = 0; - if (rows) { - str = getenv("LINES"); - if (str) { - *rows = atoi(str); + if (fd == 1) { + if (rows) { + str = getenv("LINES"); + if (str) + *rows = atoi(str); } - } - if (cols) { - str = getenv("COLUMNS"); - if (str) { - *cols = atoi(str); + if (cols) { + str = getenv("COLUMNS"); + if (str) + *cols = atoi(str); } } if (!rows || !cols) @@ -99,6 +97,7 @@ static inline int getscreensize(int fd, int *rows, int *cols) return rv; } #define ROSH_COM32(f, ...) ((void)0) +#define ROSH_FREE_DIRENT(de) ((void)0) #define syslinux_run_command(f) ((void)0) #endif /* __COM32__ */ @@ -129,20 +128,33 @@ static inline int getscreensize(int fd, int *rows, int *cols) #define ROSH_PATH_SZ 255 #endif /* NAME_MAX */ +#define ROSH_OPT_SZ 8 + +const char rosh_cd_norun_str[] +" -- cd (Change Directory) not implemented for use with run and exit.\n"; + +const char rosh_help_ls_str[] +"ls List contents of current directory\n\ + -l Long format\n\ + -i Inode; print Inode of file\n\ + -F Classify; Add a 1-character suffix to classify files"; + const char rosh_help_str1[] "Commands: ? cat cd cfg dir exit help less ls man more pwd run quit ver"; const char rosh_help_str2[] -"Commands: (some 1-letter abreviations also allowed)\n\ - h HELP\n ALSO ? help man\n\ +"Commands: (short generally non-ambiguous abreviations are also allowed)\n\ + h HELP\n ALSO ? help man\n ALSO help <command>\n\ cat Concatenate file to console\n cat <file>\n\ cd Change to directory <dir>\n cd <dir>\n\ less Page a file with rewind\n\ ls List contents of current directory\n ls <dir>\n\ - ALSO dir\n\ + ALSO l dir\n\ more Page a file\n\ pwd display Present Working Directory\n\ run Run a program/kernel with options\n\ exit Exit to previous environment\n ALSO quit"; +const char rosh_help_str_adv[] = "No additional help available for '%s'"; + #endif /* Not ROSH_H */