diff options
Diffstat (limited to 'contrib/syslinux-4.02/com32/rosh/rosh.c')
-rw-r--r-- | contrib/syslinux-4.02/com32/rosh/rosh.c | 1178 |
1 files changed, 1178 insertions, 0 deletions
diff --git a/contrib/syslinux-4.02/com32/rosh/rosh.c b/contrib/syslinux-4.02/com32/rosh/rosh.c new file mode 100644 index 0000000..bf1176f --- /dev/null +++ b/contrib/syslinux-4.02/com32/rosh/rosh.c @@ -0,0 +1,1178 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2008-2010 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 + * the Free Software Foundation, Inc., 53 Temple Place Ste 330, + * Boston MA 02111-1307, USA; either version 2 of the License, or + * (at your option) any later version; incorporated herein by reference. + * + * ----------------------------------------------------------------------- */ + +/* + * rosh.c + * + * Read-Only shell; Simple shell system designed for SYSLINUX-derivitives. + * Provides minimal commands utilizing the console via stdout/stderr as the + * sole output devices. Designed to compile for Linux for testing/debugging. + */ + +/* + * ToDos: + * 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. + */ +#include "rosh.h" + +#define APP_LONGNAME "Read-Only Shell" +#define APP_NAME "rosh" +#define APP_AUTHOR "Gene Cumm" +#define APP_YEAR "2010" +#define APP_VER "beta-b062" + +void rosh_version(void) +{ + printf("%s v %s; (c) %s %s.\n", APP_LONGNAME, APP_VER, APP_YEAR, + APP_AUTHOR); +} + +void print_beta(void) +{ + puts(rosh_beta_str); + ROSH_DEBUG("DO_DEBUG active\n"); + ROSH_DEBUG2("DO_DEBUG2 active\n"); +} + +/* Search a string for first non-space (' ') character, starting at ipos + * istr input string to parse + * ipos input position to start at + */ +int rosh_search_nonsp(const char *istr, const int ipos) +{ + int curpos; + char c; + + curpos = ipos; + c = istr[curpos]; + while (c && isspace(c)) + c = istr[++curpos]; + return curpos; +} + +/* Search a string for space (' '), returning the position of the next space + * or the '\0' at end of string + * istr input string to parse + * ipos input position to start at + */ +int rosh_search_sp(const char *istr, const int ipos) +{ + int curpos; + char c; + + curpos = ipos; + c = istr[curpos]; + while (c && !(isspace(c))) + c = istr[++curpos]; + return curpos; +} + +/* Parse a string for the first non-space string, returning the end position + * from src + * dest string to contain the first non-space string + * src string to parse + * ipos Position to start in src + */ +int rosh_parse_sp_1(char *dest, const char *src, const int ipos) +{ + int bpos, epos; /* beginning and ending position of source string + to copy to destination string */ + + bpos = 0; + epos = 0; +/* //HERE-error condition checking */ + bpos = rosh_search_nonsp(src, ipos); + epos = rosh_search_sp(src, bpos); + if (epos > bpos) { + memcpy(dest, src + bpos, epos - bpos); + if (dest[epos - bpos] != 0) + dest[epos - bpos] = 0; + } else { + epos = strlen(src); + dest[0] = 0; + } + return epos; +} + +/* Display help + * type Help type + * cmdstr Command string + */ +void rosh_help(int type, const char *cmdstr) +{ + const 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 + * filestr File/parameter causing error + */ +void rosh_error(const int ierrno, const char *cmdstr, const char *filestr) +{ + printf("--ERROR: %s '%s': ", cmdstr, filestr); + switch (ierrno) { + case 0: + puts("NO ERROR"); + break; + 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 EIO: + puts("I/O Error"); + break; + 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 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 + * argc Argument Count + * argv Argument Values + * barg Beginning Argument + */ +int rosh_argcat(char *cmdstr, const int argc, char *argv[], const int barg) +{ + int i, arglen, curpos; /* index, argument length, current position + in cmdstr */ + curpos = 0; + cmdstr[0] = '\0'; /* Nullify string just to be sure */ + for (i = barg; i < argc; i++) { + arglen = strlen(argv[i]); + /* Theoretically, this should never be met in SYSLINUX */ + if ((curpos + arglen) > (ROSH_CMD_SZ - 1)) + arglen = (ROSH_CMD_SZ - 1) - curpos; + memcpy(cmdstr + curpos, argv[i], arglen); + curpos += arglen; + if (curpos >= (ROSH_CMD_SZ - 1)) { + /* Hopefully, curpos should not be greater than + (ROSH_CMD_SZ - 1) */ + /* Still need a '\0' at the last character */ + cmdstr[(ROSH_CMD_SZ - 1)] = 0; + break; /* Escape out of the for() loop; + We can no longer process anything more */ + } else { + cmdstr[curpos] = ' '; + curpos += 1; + cmdstr[curpos] = 0; + } + } + /* If there's a ' ' at the end, remove it. This is normal unless + the maximum length is met/exceeded. */ + if (cmdstr[curpos - 1] == ' ') + cmdstr[--curpos] = 0; + return curpos; +} /* rosh_argcat */ + +/* + * Prints a lot of the data in a struct termios + */ +/* +void rosh_print_tc(struct termios *tio) +{ + printf(" -- termios: "); + printf(".c_iflag=%04X ", tio->c_iflag); + printf(".c_oflag=%04X ", tio->c_oflag); + printf(".c_cflag=%04X ", tio->c_cflag); + printf(".c_lflag=%04X ", tio->c_lflag); + printf(".c_cc[VTIME]='%d' ", tio->c_cc[VTIME]); + printf(".c_cc[VMIN]='%d'", tio->c_cc[VMIN]); + printf("\n"); +} +*/ + +/* + * Attempts to get a single key from the console + * returns key pressed + */ +int rosh_getkey(void) +{ + int inc; + + inc = KEY_NONE; + while (inc == KEY_NONE) + inc = get_key(stdin, 6000); + return inc; +} /* rosh_getkey */ + +/* + * Qualifies a filename relative to the working directory + * filestr Filename to qualify + * pwdstr working directory + * returns qualified file name string + */ +void rosh_qualify_filestr(char *filestr, const char *ifilstr, + const char *pwdstr) +{ + int filepos = 0; + if ((filestr) && (pwdstr) && (ifilstr)) { + if (ifilstr[0] != SEP) { + strcpy(filestr, pwdstr); + filepos = strlen(pwdstr); + if (filestr[filepos - 1] != SEP) + filestr[filepos++] = SEP; + } + strcpy(filestr + filepos, ifilstr); + ROSH_DEBUG("--'%s'\n", filestr); + } +} + +/* Concatenate multiple files to stdout + * cmdstr command string to process + */ +void rosh_cat(const char *cmdstr) +{ + FILE *f; + char filestr[ROSH_PATH_SZ]; + char buf[ROSH_BUF_SZ]; + int numrd; + int cmdpos; + + ROSH_DEBUG("CMD: '%s'\n", cmdstr); + /* Initialization */ + filestr[0] = 0; + cmdpos = 0; + /* skip the first word */ + cmdpos = rosh_parse_sp_1(filestr, cmdstr, cmdpos); + cmdpos = rosh_parse_sp_1(filestr, cmdstr, cmdpos); + while (strlen(filestr) > 0) { + printf("--File = '%s'\n", filestr); + f = fopen(filestr, "r"); + if (f != NULL) { + numrd = fread(buf, 1, ROSH_BUF_SZ, f); + while (numrd > 0) { + fwrite(buf, 1, numrd, stdout); + numrd = fread(buf, 1, ROSH_BUF_SZ, f); + } + fclose(f); + } else { + rosh_error(errno, "cat", filestr); + errno = 0; + } + cmdpos = rosh_parse_sp_1(filestr, cmdstr, cmdpos); + } +} /* rosh_cat */ + +/* Change PWD (Present Working Directory) + * cmdstr command string to process + * ipwdstr Initial PWD + */ +void rosh_cd(const char *cmdstr, const char *ipwdstr) +{ + int rv; + char filestr[ROSH_PATH_SZ]; + int cmdpos; + ROSH_DEBUG("CMD: '%s'\n", cmdstr); + /* Initialization */ + filestr[0] = 0; + cmdpos = 0; + rv = 0; + /* skip the first word */ + cmdpos = rosh_parse_sp_1(filestr, cmdstr, cmdpos); + cmdpos = rosh_parse_sp_1(filestr, cmdstr, cmdpos); + if (strlen(filestr) != 0) + rv = chdir(filestr); + else + rv = chdir(ipwdstr); + if (rv != 0) { + rosh_error(errno, "cd", filestr); + errno = 0; + } else { +#ifdef DO_DEBUG + if (getcwd(filestr, ROSH_PATH_SZ)) + ROSH_DEBUG(" %s\n", filestr); +#endif /* DO_DEBUG */ + } +} /* rosh_cd */ + +/* Print the syslinux config file name + */ +void rosh_cfg(void) +{ + 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; + char filestr2[ROSH_PATH_SZ]; + 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; + 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(struct dirent *de, mode_t * st_mode) +{ + int de_size; +// char filestr2[ROSH_PATH_SZ]; +// 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(de->d_name, &fdstat); + ROSH_DEBUG2("\t--stat()=%d\terr=%d\n", status, errno); + if (errno) { + rosh_error(errno, "ls:szmd.stat", de->d_name); + errno = 0; + } + de_size = (int)fdstat.st_size; + *st_mode = fdstat.st_mode; + return de_size; +} /* rosh_ls_de_size_mode */ + +/* Returns the Inode number if fdstat contains it + * fdstat struct to extract inode from if not COM32, for now + */ +long rosh_ls_d_ino(struct stat *fdstat) +{ + long de_ino; +#ifdef __COM32__ + if (fdstat) + de_ino = -1; + else + de_ino = 0; +#else /* __COM32__ */ + de_ino = fdstat->st_ino; +#endif /* __COM32__ */ + return de_ino; +} + +/* 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 DT_UNKNOWN: + ret = 'U'; + break; /* Unknown */ + case DT_FIFO: + ret = 'F'; + break; /* FIFO */ + case DT_CHR: + ret = 'C'; + break; /* Char Dev */ + case DT_DIR: + ret = 'D'; + break; /* Directory */ + case DT_BLK: + ret = 'B'; + break; /* Block Dev */ + case DT_REG: + ret = 'R'; + break; /* Regular File */ + case DT_LNK: + ret = 'L'; + break; /* Link, Symbolic */ + case DT_SOCK: + ret = 'S'; + break; /* Socket */ + case DT_WHT: + ret = 'W'; + break; /* UnionFS Whiteout */ + default: + ret = ' '; + } + return ret; +} /* rosh_d_type2char_human */ + +/* Convert a d_type to a single char by ls's prefix standards for -l + * 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 DT_FIFO: + ret = 'p'; + break; + case DT_CHR: + ret = 'c'; + break; + case DT_DIR: + ret = 'd'; + break; + case DT_BLK: + ret = 'b'; + break; + case DT_REG: + ret = '-'; + break; + case DT_LNK: + ret = 'l'; + break; + case DT_SOCK: + ret = 's'; + break; + default: + ret = '?'; + } + return ret; +} /* rosh_d_type2char_lspre */ + +/* Convert a d_type to a single char by ls's classify (-F) 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 DT_FIFO: + ret = '|'; + break; + case DT_DIR: + ret = '/'; + break; + case DT_LNK: + ret = '@'; + break; + case DT_SOCK: + ret = '='; + break; + default: + ret = ' '; + } + return ret; +} /* rosh_d_type2char_lssuf */ + +/* 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(struct dirent *de, const int *optarr) +{ + int de_size; + mode_t st_mode; + char st_mode_str[11]; + st_mode = 0; + if (optarr[2] > -1) + printf("%10d ", (int)de->d_ino); + if (optarr[0] > -1) { + de_size = rosh_ls_de_size_mode(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; + while ((de = readdir(d))) { + filepos++; + rosh_ls_arg_dir_de(de, optarr); + } + if (errno) + rosh_error(errno, "ls:arg_dir", filestr); + else if (filepos == 0) + ROSH_DEBUG("0 files found"); +} /* 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_ls_arg(const char *filestr, const int *optarr) +{ + struct stat fdstat; + int status; +// char filestr[ROSH_PATH_SZ]; +// int filepos; + DIR *d; + struct dirent de; + + /* Initialization; make filestr based on leading character of ifilstr + and pwdstr */ +// rosh_qualify_filestr(filestr, ifilstr, pwdstr); + fdstat.st_mode = 0; + fdstat.st_size = 0; + ROSH_DEBUG("\topt[0]=%d\topt[1]=%d\topt[2]=%d\n", optarr[0], optarr[1], + optarr[2]); + + /* Now, the real work */ + errno = 0; + status = stat(filestr, &fdstat); + if (status == 0) { + if (S_ISDIR(fdstat.st_mode)) { + ROSH_DEBUG("PATH '%s' is a directory\n", filestr); + d = opendir(filestr); + rosh_ls_arg_dir(filestr, d, optarr); + closedir(d); + } else { + de.d_ino = rosh_ls_d_ino(&fdstat); + de.d_type = (IFTODT(fdstat.st_mode)); + strcpy(de.d_name, filestr); + if (S_ISREG(fdstat.st_mode)) { + ROSH_DEBUG("PATH '%s' is a regular file\n", filestr); + } else { + ROSH_DEBUG("PATH '%s' is some other file\n", filestr); + } + rosh_ls_arg_dir_de(&de, optarr); +/* 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, "ls", filestr); + errno = 0; + } + return; +} /* rosh_ls_arg */ + +/* 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_ls(const char *cmdstr) +{ + char filestr[ROSH_PATH_SZ]; + 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[3]; + + ROSH_DEBUG("CMD: '%s'\n", cmdstr); + /* 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); + tpos = rosh_parse_sp_1(filestr, cmdstr, cmdpos); + /* If there are no real arguments, substitute PWD */ + if (strlen(filestr) == 0) { + strcpy(filestr, "."); + 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, "."); + 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) { + if (rosh_ls_parse_opt(filestr, NULL)) { + rosh_ls_arg(filestr, optarr); + argpos++; + } + if (argpos < numargs) + cmdpos = rosh_parse_sp_1(filestr, cmdstr, cmdpos); + else + break; + } +} /* rosh_ls */ + +/* Simple directory listing; calls rosh_ls() + * cmdstr command string to process + * pwdstr Present Working Directory string + */ +void rosh_dir(const char *cmdstr) +{ + ROSH_DEBUG(" dir implemented as ls\n"); + rosh_ls(cmdstr); +} /* rosh_dir */ + +/* Page through a buffer string + * buf Buffer to page through + */ +//HERE: minor pagination issue; sometimes prints 1 less than rows +void rosh_more_buf(char *buf, int buflen, int rows, int cols) +{ + 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; + int i, numln; /* Index, Number of lines */ + + (void)cols; + + bufpos = 0; + bufp = buf + bufpos; + bufeol = bufp; + numln = rows - 1; + ROSH_DEBUG("--(%d)\n", buflen); + while (bufpos < buflen) { + for (i = 0; i < numln; i++) { + bufeol2 = strchr(bufeol, '\n'); + if (bufeol2 == NULL) { + bufeol = buf + buflen; + i = numln; + } else { + i += ((bufeol2 - bufeol) / cols); + bufeol = bufeol2 + 1; + } + } + bufcnt = bufeol - bufp; + 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; + inc = rosh_getkey(); + numln = 1; + switch (inc) { + case KEY_CTRL('c'): + case 'q': + case 'Q': + bufpos = buflen; + break; + case ' ': + numln = rows - 1; + } + } +} /* rosh_more_buf */ + +/* Page through a single file using the open file stream + * fd File Descriptor + */ +void rosh_more_fd(int fd, int rows, int cols) +{ + struct stat fdstat; + int status; + char *buf; + int bufpos; + int numrd; + FILE *f; + + status = fstat(fd, &fdstat); + if (S_ISREG(fdstat.st_mode)) { + buf = malloc((int)fdstat.st_size); + if (buf != NULL) { + f = fdopen(fd, "r"); + bufpos = 0; + numrd = fread(buf, 1, (int)fdstat.st_size, f); + while (numrd > 0) { + bufpos += numrd; + numrd = fread(buf + bufpos, 1, + ((int)fdstat.st_size - bufpos), f); + } + fclose(f); + rosh_more_buf(buf, bufpos, rows, cols); + } + } else { + } + +} /* rosh_more_fd */ + +/* Page through a file like the more command + * cmdstr command string to process + * ipwdstr Initial PWD + */ +void rosh_more(const char *cmdstr) +{ + int fd; + char filestr[ROSH_PATH_SZ]; + int cmdpos; + int rows, cols; + + ROSH_DEBUG("CMD: '%s'\n", cmdstr); + /* Initialization */ + filestr[0] = 0; + cmdpos = 0; + if (getscreensize(1, &rows, &cols)) { + ROSH_DEBUG("getscreensize() fail; fall back\n"); + ROSH_DEBUG("\tROWS='%d'\tCOLS='%d'\n", rows, cols); + /* If either fail, go under normal size, just in case */ + if (!rows) + rows = 20; + if (!cols) + cols = 75; + } + ROSH_DEBUG("\tUSE ROWS='%d'\tCOLS='%d'\n", rows, cols); + + /* skip the first word */ + cmdpos = rosh_parse_sp_1(filestr, cmdstr, cmdpos); + cmdpos = rosh_parse_sp_1(filestr, cmdstr, cmdpos); + if (strlen(filestr) > 0) { + /* There is no need to mess up the console if we don't have a + file */ + rosh_console_raw(); + while (strlen(filestr) > 0) { + printf("--File = '%s'\n", filestr); + fd = open(filestr, O_RDONLY); + if (fd != -1) { + rosh_more_fd(fd, rows, cols); + close(fd); + } else { + rosh_error(errno, "more", filestr); + errno = 0; + } + cmdpos = rosh_parse_sp_1(filestr, cmdstr, cmdpos); + } + rosh_console_std(); + } +} /* rosh_more */ + +/* Page a file with rewind + * cmdstr command string to process + * pwdstr Present Working Directory string + * ipwdstr Initial PWD + */ +void rosh_less(const char *cmdstr) +{ + printf(" less implemented as more (for now)\n"); + rosh_more(cmdstr); +} /* rosh_less */ + +/* Show PWD + * cmdstr command string to process + */ +void rosh_pwd(const char *cmdstr) +{ + int istr; + char pwdstr[ROSH_PATH_SZ]; + if (cmdstr) + istr = 0; + ROSH_DEBUG("CMD: '%s'\n", cmdstr); + errno = 0; + if (getcwd(pwdstr, ROSH_PATH_SZ)) { + printf("%s\n", pwdstr); + } else { + rosh_error(errno, "pwd", ""); + errno = 0; + } + istr = htonl(*(int *)pwdstr); + ROSH_DEBUG2(" --%08X\n", istr); +} /* rosh_pwd */ + +/* Reboot + */ +void rosh_reboot(void) +{ +// char cmdstr[ROSH_CMD_SZ]; +// printf + syslinux_reboot(0); +} /* rosh_reboot */ + +/* Run a boot string, calling syslinux_run_command + * cmdstr command string to process + */ +void rosh_run(const char *cmdstr) +{ + int cmdpos; + char *cmdptr; + + cmdpos = 0; + ROSH_DEBUG("CMD: '%s'\n", cmdstr); + /* skip the first word */ + cmdpos = rosh_search_sp(cmdstr, cmdpos); + /* skip spaces */ + cmdpos = rosh_search_nonsp(cmdstr, cmdpos); + cmdptr = (char *)(cmdstr + cmdpos); + printf("--run: '%s'\n", cmdptr); + syslinux_run_command(cmdptr); +} /* rosh_run */ + +/* Process a single command string and call handling function + * cmdstr command string to process + * ipwdstr Initial Present Working Directory string + * returns Whether to exit prompt + */ +char rosh_command(const char *cmdstr, const char *ipwdstr) +{ + char do_exit; + char tstr[ROSH_CMD_SZ]; + int tlen; + do_exit = false; + ROSH_DEBUG("--cmd:'%s'\n", cmdstr); + tlen = rosh_parse_sp_1(tstr, cmdstr, 0); + switch (cmdstr[0]) { + case 'e': + case 'E': + case 'q': + case 'Q': + if ((strncasecmp("exit", tstr, tlen) == 0) || + (strncasecmp("quit", tstr, tlen) == 0)) + do_exit = true; + else + rosh_help(1, NULL); + break; + case 'c': + case 'C': /* run 'cd' 'cat' 'cfg' */ + switch (cmdstr[1]) { + case 'a': + case 'A': + if (strncasecmp("cat", tstr, tlen) == 0) + rosh_cat(cmdstr); + else + rosh_help(1, NULL); + break; + case 'd': + case 'D': + if (strncasecmp("cd", tstr, tlen) == 0) + rosh_cd(cmdstr, ipwdstr); + else + rosh_help(1, NULL); + break; + case 'f': + case 'F': + if (strncasecmp("cfg", tstr, tlen) == 0) + rosh_cfg(); + else + rosh_help(1, NULL); + break; + default: + rosh_help(1, NULL); + } + break; + case 'd': + case 'D': /* run 'dir' */ + if (strncasecmp("dir", tstr, tlen) == 0) + rosh_dir(cmdstr); + else + rosh_help(1, NULL); + break; + case 'h': + case 'H': + case '?': + if ((strncasecmp("help", tstr, tlen) == 0) || (tlen == 1)) + rosh_help(2, cmdstr); + else + rosh_help(1, NULL); + break; + case 'l': + case 'L': /* run 'ls' 'less' */ + switch (cmdstr[1]) { + case 0: + case ' ': + case 's': + case 'S': + if (strncasecmp("ls", tstr, tlen) == 0) + rosh_ls(cmdstr); + else + rosh_help(1, NULL); + break; + case 'e': + case 'E': + if (strncasecmp("less", tstr, tlen) == 0) + rosh_less(cmdstr); + else + rosh_help(1, NULL); + break; + default: + rosh_help(1, NULL); + } + break; + case 'm': + case 'M': + switch (cmdstr[1]) { + case 'a': + case 'A': + if (strncasecmp("man", tstr, tlen) == 0) + rosh_help(2, cmdstr); + else + rosh_help(1, NULL); + break; + case 'o': + case 'O': + if (strncasecmp("more", tstr, tlen) == 0) + rosh_more(cmdstr); + else + rosh_help(1, NULL); + break; + default: + rosh_help(1, NULL); + } + break; + case 'p': + case 'P': /* run 'pwd' */ + if (strncasecmp("pwd", tstr, tlen) == 0) + rosh_pwd(cmdstr); + else + rosh_help(1, NULL); + break; + case 'r': + case 'R': /* run 'run' */ + switch (cmdstr[1]) { + case 0: + case ' ': + case 'e': + case 'E': + if (strncasecmp("reboot", tstr, tlen) == 0) + rosh_reboot(); + else + rosh_help(1, NULL); + break; + case 'u': + case 'U': + if (strncasecmp("run", tstr, tlen) == 0) + rosh_run(cmdstr); + else + rosh_help(1, NULL); + break; + } + break; + case 'v': + case 'V': + if (strncasecmp("version", tstr, tlen) == 0) + rosh_version(); + else + rosh_help(1, NULL); + break; + case 0: + case '\n': + break; + default: + rosh_help(1, NULL); + } /* switch(cmdstr[0]) */ + return do_exit; +} /* rosh_command */ + +/* Process the prompt for commands as read from stdin and call rosh_command + * to process command line string + * icmdstr Initial command line string + * returns Exit status + */ +int rosh_prompt(const char *icmdstr) +{ + int rv; + char cmdstr[ROSH_CMD_SZ]; + char ipwdstr[ROSH_PATH_SZ]; + char do_exit; + char *c; + + rv = 0; + do_exit = false; + if (!getcwd(ipwdstr, ROSH_PATH_SZ)) + strcpy(ipwdstr, "./"); + if (icmdstr[0] != '\0') + do_exit = rosh_command(icmdstr, ipwdstr); + while (!(do_exit)) { + /* Extra preceeding newline */ + printf("\nrosh: "); + /* Read a line from console */ + if (fgets(cmdstr, ROSH_CMD_SZ, stdin)) { + /* remove newline from input string */ + c = strchr(cmdstr, '\n'); + *c = 0; + do_exit = rosh_command(cmdstr, ipwdstr); + } else { + do_exit = false; + } + } + return rv; +} + +int main(int argc, char *argv[]) +{ + int rv; + char cmdstr[ROSH_CMD_SZ]; + + /* Initialization */ + rv = 0; + rosh_console_std(); + if (argc != 1) { + rv = rosh_argcat(cmdstr, argc, argv, 1); + } else { + rosh_version(); + print_beta(); + cmdstr[0] = '\0'; + } + rv = rosh_prompt(cmdstr); + printf("--Exiting '%s'\n", APP_NAME); + return rv; +} |