/* ----------------------------------------------------------------------- * * * 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; }