summaryrefslogtreecommitdiffstats
path: root/contrib/syslinux-4.02/com32/rosh/rosh.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/syslinux-4.02/com32/rosh/rosh.c')
-rw-r--r--contrib/syslinux-4.02/com32/rosh/rosh.c1178
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;
+}