diff options
-rw-r--r-- | com32/include/unistd.h | 4 | ||||
-rw-r--r-- | com32/rosh/rosh.c | 658 | ||||
-rw-r--r-- | com32/rosh/rosh.h | 18 | ||||
-rw-r--r-- | core/pxelinux.asm | 21 | ||||
-rw-r--r-- | sample/Makefile | 1 |
5 files changed, 448 insertions, 254 deletions
diff --git a/com32/include/unistd.h b/com32/include/unistd.h index fc514f10..9e13381a 100644 --- a/com32/include/unistd.h +++ b/com32/include/unistd.h @@ -28,6 +28,10 @@ __extern int chdir(const char *); __extern unsigned int sleep(unsigned int); __extern unsigned int msleep(unsigned int); +__extern int getopt(int, char *const *, const char *); +__extern char *optarg; +__extern int optind, opterr, optopt; + /* Standard file descriptor numbers. */ #define STDIN_FILENO 0 #define STDOUT_FILENO 1 diff --git a/com32/rosh/rosh.c b/com32/rosh/rosh.c index 9efa35ef..12e09995 100644 --- a/com32/rosh/rosh.c +++ b/com32/rosh/rosh.c @@ -20,7 +20,12 @@ /* * ToDos: - * rosh_ls(): sorted; then multiple columns + * prompt: Allow left/right arrow, home/end and more? + * commands Break into argv/argc-like array + * rosh_cfg: allow -s <file> to change config + * rosh_ls(): sorted; then multiple columns + * prompt: Possibly honor timeout on initial entry for usage as UI + * Also possibly honor totaltimeout */ /*#define DO_DEBUG 1 @@ -38,8 +43,10 @@ #define APP_NAME "rosh" #define APP_AUTHOR "Gene Cumm" #define APP_YEAR "2010" -#define APP_VER "beta-b068" +#define APP_VER "beta-b089" +/* Print version information to stdout + */ void rosh_version(int vtype) { char env[256]; @@ -52,6 +59,8 @@ void rosh_version(int vtype) } } +/* Print beta message and if DO_DEBUG/DO_DEBUG2 are active + */ void print_beta(void) { puts(rosh_beta_str); @@ -119,32 +128,156 @@ int rosh_parse_sp_1(char *dest, const char *src, const int ipos) return epos; } +/* + * parse_args1: Try 1 at parsing a string to an argc/argv pair. use free_args1 to free memory malloc'd + * + * Derived from com32/lib/sys/argv.c:__parse_argv() + * Copyright 2004-2009 H. Peter Anvin - All Rights Reserved + * Copyright 2009 Intel Corporation; author: H. Peter Anvin + */ +int parse_args1(char ***iargv, const char *istr) +{ + int argc = 0; + const char *p; + char *q, *r, *args, **arg; + int sp = 1; //, qt = 0; /* Was a space; inside a quote */ + + /* Scan 1: Length */ + /* I could eliminate this if I knew a max length, like strncpy() */ + int len = strlen(istr); + + /* Scan 2: Copy, nullify and make argc */ + if (!(args = malloc(len + 1))) + goto fail_args; + q = args; + for (p = istr;; p++) { + if (*p <= ' ') { + if (!sp) { + sp = 1; + *q++ = '\0'; + } + } else { + if (sp) { + argc++; + sp = 0; + } + *q++ = *p; + } + if (!*p) + break; + } + + q--; /* Point q to final null */ + /* Scan 3: Build array of pointers */ + if (!(*iargv = malloc((argc + 1) * sizeof(char *)))) + goto fail_args_ptr; + arg = *iargv; + arg[argc] = NULL; /* Nullify the last pointer */ + if (*args != '\0') + *arg++ = args; + for (r = args; r < q ; r++) { + if (*r == '\0') { + *arg++ = r + 1; + } + } + +fail_args: + return argc; +fail_args_ptr: + free(args); + return 0; +} + +/* Free argv created by parse_args1() + * argv Argument Values + */ +void free_args1(char ***argv) +{ + char *s; + s = **argv; + free(*argv); + free(s); +} + +/* Convert a string to an argc/argv pair + * str String to parse + * argv Argument Values + * returns Argument Count + */ +int rosh_str2argv(char ***argv, const char *str) +{ + return parse_args1(argv, str); +} + +/* Free an argv created by rosh_str2argv() + * argv Argument Values to free + */ +void rosh_free_argv(char ***argv) +{ + free_args1(argv); +} + +/* Print the contents of an argc/argv pair + * argc Argument Count + * argv Argument Values + */ +void rosh_pr_argv(int argc, char *argv[]) +{ + int i; + for (i = 0; i < argc; i++) { + printf("%s%s", argv[i], (i < argc)? " " : ""); + } + puts(""); +} + +/* Print the contents of an argc/argv pair verbosely + * argc Argument Count + * argv Argument Values + */ +void rosh_pr_argv_v(int argc, char *argv[]) +{ + int i; + for (i = 0; i < argc; i++) { + printf("%4d '%s'\n", i, argv[i]); + } +} + +/* Reset the getopt() environment + */ +void rosh_getopt_reset(void) +{ + optind = 0; + optopt = 0; +} + /* Display help * type Help type - * cmdstr Command string + * cmdstr Command for which help is requested */ 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)) { + if ((cmdstr == NULL) || (strcmp(cmdstr, "") == 0)) { rosh_version(0); puts(rosh_help_str2); } else { - switch (istr[0]) { + switch (cmdstr[0]) { + case 'c': + puts(rosh_help_cd_str); + break; case 'l': puts(rosh_help_ls_str); break; default: - printf(rosh_help_str_adv, istr); + printf(rosh_help_str_adv, cmdstr); } } break; case 1: default: + if (cmdstr) + printf("%s: %s: unknown command\n", APP_NAME, cmdstr); rosh_version(0); puts(rosh_help_str1); } @@ -194,11 +327,13 @@ void rosh_error(const int ierrno, const char *cmdstr, const char *filestr) /* Concatenate command line arguments into one string * cmdstr Output command string + * cmdlen Length of cmdstr * argc Argument Count * argv Argument Values * barg Beginning Argument */ -int rosh_argcat(char *cmdstr, const int argc, char *argv[], const int barg) +int rosh_argcat(char *cmdstr, const int cmdlen, const int argc, char *argv[], + const int barg) { int i, arglen, curpos; /* index, argument length, current position in cmdstr */ @@ -207,15 +342,15 @@ int rosh_argcat(char *cmdstr, const int argc, char *argv[], const int barg) 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; + if ((curpos + arglen) > (cmdlen - 1)) + arglen = (cmdlen - 1) - curpos; memcpy(cmdstr + curpos, argv[i], arglen); curpos += arglen; - if (curpos >= (ROSH_CMD_SZ - 1)) { + if (curpos >= (cmdlen - 1)) { /* Hopefully, curpos should not be greater than - (ROSH_CMD_SZ - 1) */ + (cmdlen - 1) */ /* Still need a '\0' at the last character */ - cmdstr[(ROSH_CMD_SZ - 1)] = 0; + cmdstr[(cmdlen - 1)] = 0; break; /* Escape out of the for() loop; We can no longer process anything more */ } else { @@ -285,26 +420,19 @@ void rosh_qualify_filestr(char *filestr, const char *ifilstr, } /* Concatenate multiple files to stdout - * cmdstr command string to process + * argc Argument Count + * argv Argument Values */ -void rosh_cat(const char *cmdstr) +void rosh_cat(int argc, char *argv[]) { FILE *f; - char filestr[ROSH_PATH_SZ]; char buf[ROSH_BUF_SZ]; - int numrd; - int cmdpos; + int i, numrd; - 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"); + for (i = 0; i < argc; i++) { + printf("--File = '%s'\n", argv[i]); + errno = 0; + f = fopen(argv[i], "r"); if (f != NULL) { numrd = fread(buf, 1, ROSH_BUF_SZ, f); while (numrd > 0) { @@ -313,36 +441,37 @@ void rosh_cat(const char *cmdstr) } fclose(f); } else { - rosh_error(errno, "cat", filestr); + rosh_error(errno, "cat", argv[i]); errno = 0; } - cmdpos = rosh_parse_sp_1(filestr, cmdstr, cmdpos); } } /* rosh_cat */ /* Change PWD (Present Working Directory) - * cmdstr command string to process + * argc Argument count + * argv Argument values * ipwdstr Initial PWD */ -void rosh_cd(const char *cmdstr, const char *ipwdstr) +void rosh_cd(int argc, char *argv[], const char *ipwdstr) { - int rv; + int rv = 0; +#ifdef DO_DEBUG 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 +#endif /* DO_DEBUG */ + ROSH_DEBUG("CMD: \n"); + ROSH_DEBUG_ARGV_V(argc, argv); + errno = 0; + if (argc == 2) + rv = chdir(argv[1]); + else if (argc == 1) rv = chdir(ipwdstr); + else + rosh_help(2, argv[0]); if (rv != 0) { - rosh_error(errno, "cd", filestr); + if (argc == 2) + rosh_error(errno, "cd", argv[1]); + else + rosh_error(errno, "cd", ipwdstr); errno = 0; } else { #ifdef DO_DEBUG @@ -359,31 +488,61 @@ 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 +/* Echo a string back to the screen + * cmdstr command string to process */ -void rosh_ls_arg_opt(const char *optstr, int *optarr) +void rosh_echo(const char *cmdstr) { - 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; + int bpos = 0; + ROSH_DEBUG("CMD: '%s'\n", cmdstr); + bpos = rosh_search_nonsp(cmdstr, rosh_search_sp(cmdstr, 0)); + if (bpos > 1) { + ROSH_DEBUG(" bpos=%d\n", bpos); + printf("'%s'\n", cmdstr + bpos); } else { - optarr[1] = -1; + puts(""); } - cpos = strchr(optstr, 'i'); - if (cpos) { - optarr[2] = cpos - optstr; - } else { - optarr[2] = -1; +} /* rosh_echo */ + +/* Process argc/argv to optarr + * argc Argument count + * argv Argument values + * optarr option array to populate + */ +void rosh_ls_arg_opt(int argc, char *argv[], int optarr[]) +{ + int rv = 0; + + optarr[0] = -1; + optarr[1] = -1; + optarr[2] = -1; + rosh_getopt_reset(); + while (rv != -1) { + ROSH_DEBUG2("getopt optind=%d rv=%d\n", optind, rv); + rv = getopt(argc, argv, rosh_ls_opt_str); + switch (rv) { + case 'l': + case 0: + optarr[0] = 1; + break; + case 'F': + case 1: + optarr[1] = 1; + break; + case 'i': + case 2: + optarr[2] = 1; + break; + case '?': + case -1: + default: + ROSH_DEBUG2("getopt optind=%d rv=%d\n", optind, rv); + break; + } } + ROSH_DEBUG2(" end getopt optind=%d rv=%d\n", optind, rv); + ROSH_DEBUG2("\tIn rosh_ls_arg_opt() opt[0]=%d\topt[1]=%d\topt[2]=%d\n", optarr[0], optarr[1], + optarr[2]); } /* rosh_ls_arg_opt */ /* Retrieve the size of a file argument @@ -435,6 +594,7 @@ int rosh_ls_de_size_mode(struct dirent *de, mode_t * st_mode) filestr2[file2pos] = '/'; } strcpy(filestr2 + file2pos + 1, de->d_name);*/ + errno = 0; status = stat(de->d_name, &fdstat); ROSH_DEBUG2("\t--stat()=%d\terr=%d\n", status, errno); if (errno) { @@ -628,14 +788,17 @@ void rosh_ls_arg_dir(const char *filestr, DIR * d, const int *optarr) int filepos; filepos = 0; + errno = 0; while ((de = readdir(d))) { filepos++; rosh_ls_arg_dir_de(de, optarr); } - if (errno) + if (errno) { rosh_error(errno, "ls:arg_dir", filestr); - else if (filepos == 0) + errno = 0; + } else { if (filepos == 0) ROSH_DEBUG("0 files found"); + } } /* rosh_ls_arg_dir */ /* Simple directory listing for one argument (file/directory) based on @@ -667,9 +830,13 @@ void rosh_ls_arg(const char *filestr, const int *optarr) 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); + if ((d = opendir(filestr))) { + rosh_ls_arg_dir(filestr, d, optarr); + closedir(d); + } else { + rosh_error(errno, "ls", filestr); + errno = 0; + } } else { de.d_ino = rosh_ls_d_ino(&fdstat); de.d_type = (IFTODT(fdstat.st_mode)); @@ -712,71 +879,37 @@ int rosh_ls_parse_opt(const char *filestr, char *optstr) return ret; } /* rosh_ls_parse_opt */ -/* List Directory based on cmdstr and pwdstr - * cmdstr command string to process - * pwdstr Present Working Directory string +/* List Directory + * argc Argument count + * argv Argument values */ -void rosh_ls(const char *cmdstr) +void rosh_ls(int argc, char *argv[]) { - 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]; + int i; - 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); - } - } + rosh_ls_arg_opt(argc, argv, optarr); + ROSH_DEBUG2("In ls()\n"); + ROSH_DEBUG2_ARGV_V(argc, argv); #ifdef DO_DEBUG - if (!strchr(optstr, 'l')) - strcat(optstr, "l"); + optarr[0] = 2; #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_DEBUG2(" argc=%d; optind=%d\n", argc, optind); + if (optind >= argc) + rosh_ls_arg(".", optarr); + for (i = optind; i < argc; i++) { + rosh_ls_arg(argv[i], optarr); } } /* rosh_ls */ /* Simple directory listing; calls rosh_ls() - * cmdstr command string to process - * pwdstr Present Working Directory string + * argc Argument count + * argv Argument values */ -void rosh_dir(const char *cmdstr) +void rosh_dir(int argc, char *argv[]) { ROSH_DEBUG(" dir implemented as ls\n"); - rosh_ls(cmdstr); + rosh_ls(argc, argv); } /* rosh_dir */ /* Page through a buffer string @@ -874,22 +1007,19 @@ void rosh_more_fd(int fd, int rows, int cols, char *scrbuf) } /* rosh_more_fd */ /* Page through a file like the more command - * cmdstr command string to process - * ipwdstr Initial PWD + * argc Argument Count + * argv Argument Values */ -void rosh_more(const char *cmdstr) +void rosh_more(int argc, char *argv[]) { - int fd; - char filestr[ROSH_PATH_SZ]; - int cmdpos; + int fd, i; +/* char filestr[ROSH_PATH_SZ]; + int cmdpos;*/ int rows, cols; char *scrbuf; int ret; - ROSH_DEBUG("CMD: '%s'\n", cmdstr); - /* Initialization */ - filestr[0] = 0; - cmdpos = 0; + ROSH_DEBUG_ARGV_V(argc, argv); ret = getscreensize(1, &rows, &cols); if (ret) { ROSH_DEBUG("getscreensize() fail(%d); fall back\n", ret); @@ -906,24 +1036,21 @@ void rosh_more(const char *cmdstr) if (!scrbuf) return; - /* skip the first word */ - cmdpos = rosh_parse_sp_1(filestr, cmdstr, cmdpos); - cmdpos = rosh_parse_sp_1(filestr, cmdstr, cmdpos); - if (strlen(filestr) > 0) { + if (argc) { /* 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); + for (i = 0; i < argc; i++) { + printf("--File = '%s'\n", argv[i]); + errno = 0; + fd = open(argv[i], O_RDONLY); if (fd != -1) { rosh_more_fd(fd, rows, cols, scrbuf); close(fd); } else { - rosh_error(errno, "more", filestr); + rosh_error(errno, "more", argv[i]); errno = 0; } - cmdpos = rosh_parse_sp_1(filestr, cmdstr, cmdpos); } rosh_console_std(); } @@ -931,26 +1058,20 @@ void rosh_more(const char *cmdstr) } /* rosh_more */ /* Page a file with rewind - * cmdstr command string to process - * pwdstr Present Working Directory string - * ipwdstr Initial PWD + * argc Argument Count + * argv Argument Values */ -void rosh_less(const char *cmdstr) +void rosh_less(int argc, char *argv[]) { printf(" less implemented as more (for now)\n"); - rosh_more(cmdstr); + rosh_more(argc, argv); } /* rosh_less */ /* Show PWD - * cmdstr command string to process */ -void rosh_pwd(const char *cmdstr) +void rosh_pwd(void) { - 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); @@ -958,190 +1079,223 @@ void rosh_pwd(const char *cmdstr) rosh_error(errno, "pwd", ""); errno = 0; } - istr = htonl(*(int *)pwdstr); - ROSH_DEBUG2(" --%08X\n", istr); } /* rosh_pwd */ -/* Reboot +/* Reboot; use warm reboot if one of certain options set + * argc Argument count + * argv Argument values */ -void rosh_reboot(void) +void rosh_reboot(int argc, char *argv[]) { -// char cmdstr[ROSH_CMD_SZ]; -// printf - syslinux_reboot(0); + int rtype = 0; + if (argc) { + /* For now, just use the first */ + switch (argv[0][0]) { + case '1': + case 's': + case 'w': + rtype = 1; + break; + case '-': + switch (argv[0][1]) { + case '1': + case 's': + case 'w': + rtype = 1; + break; + } + break; + } + } + syslinux_reboot(rtype); } /* rosh_reboot */ /* Run a boot string, calling syslinux_run_command - * cmdstr command string to process + * argc Argument count + * argv Argument values */ -void rosh_run(const char *cmdstr) +void rosh_run(int argc, char *argv[]) { - int cmdpos; - char *cmdptr; + char cmdstr[ROSH_CMD_SZ]; + int len; - 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); + len = rosh_argcat(cmdstr, ROSH_CMD_SZ, argc, argv, 0); + if (len) { + printf("--run: '%s'\n", cmdstr); + syslinux_run_command(cmdstr); + } else { + printf(APP_NAME ":run: No arguments\n"); + } } /* rosh_run */ -/* Process a single command string and call handling function - * cmdstr command string to process +/* Process an argc/argv pair and call handling function + * argc Argument count + * argv Argument values * ipwdstr Initial Present Working Directory string * returns Whether to exit prompt */ -char rosh_command(const char *cmdstr, const char *ipwdstr) +char rosh_command(int argc, char *argv[], const char *ipwdstr) { - char do_exit; - char tstr[ROSH_CMD_SZ]; + char do_exit = false; int tlen; - do_exit = false; - ROSH_DEBUG("--cmd:'%s'\n", cmdstr); - tlen = rosh_parse_sp_1(tstr, cmdstr, 0); - switch (cmdstr[0]) { + tlen = strlen(argv[0]); + ROSH_DEBUG_ARGV_V(argc, argv); + switch (argv[0][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); + switch (argv[0][1]) { + case 0: + case 'x': + case 'X': + case 'u': + case 'U': + if ((strncasecmp("exit", argv[0], tlen) == 0) || + (strncasecmp("quit", argv[0], tlen) == 0)) + do_exit = true; + else + rosh_help(1, argv[0]); + break; + case 'c': + case 'C': + if (strncasecmp("echo", argv[0], tlen) == 0) + rosh_pr_argv(argc - 1, &argv[1]); + else + rosh_help(1, argv[0]); + break; + default: + rosh_help(1, argv[0]); + } break; case 'c': case 'C': /* run 'cd' 'cat' 'cfg' */ - switch (cmdstr[1]) { + switch (argv[0][1]) { case 'a': case 'A': - if (strncasecmp("cat", tstr, tlen) == 0) - rosh_cat(cmdstr); + if (strncasecmp("cat", argv[0], tlen) == 0) + rosh_cat(argc - 1, &argv[1]); else - rosh_help(1, NULL); + rosh_help(1, argv[0]); break; case 'd': case 'D': - if (strncasecmp("cd", tstr, tlen) == 0) - rosh_cd(cmdstr, ipwdstr); + if (strncasecmp("cd", argv[0], tlen) == 0) + rosh_cd(argc, argv, ipwdstr); else - rosh_help(1, NULL); + rosh_help(1, argv[0]); break; case 'f': case 'F': - if (strncasecmp("cfg", tstr, tlen) == 0) + if (strncasecmp("cfg", argv[0], tlen) == 0) rosh_cfg(); else - rosh_help(1, NULL); + rosh_help(1, argv[0]); break; default: - rosh_help(1, NULL); + rosh_help(1, argv[0]); } break; case 'd': case 'D': /* run 'dir' */ - if (strncasecmp("dir", tstr, tlen) == 0) - rosh_dir(cmdstr); + if (strncasecmp("dir", argv[0], tlen) == 0) + rosh_dir(argc - 1, &argv[1]); else - rosh_help(1, NULL); + rosh_help(1, argv[0]); break; case 'h': case 'H': case '?': - if ((strncasecmp("help", tstr, tlen) == 0) || (tlen == 1)) - rosh_help(2, cmdstr); + if ((strncasecmp("help", argv[0], tlen) == 0) || (tlen == 1)) + rosh_help(2, argv[1]); else rosh_help(1, NULL); break; case 'l': case 'L': /* run 'ls' 'less' */ - switch (cmdstr[1]) { + switch (argv[0][1]) { case 0: - case ' ': case 's': case 'S': - if (strncasecmp("ls", tstr, tlen) == 0) - rosh_ls(cmdstr); + if (strncasecmp("ls", argv[0], tlen) == 0) + rosh_ls(argc, argv); else - rosh_help(1, NULL); + rosh_help(1, argv[0]); break; case 'e': case 'E': - if (strncasecmp("less", tstr, tlen) == 0) - rosh_less(cmdstr); + if (strncasecmp("less", argv[0], tlen) == 0) + rosh_less(argc - 1, &argv[1]); else - rosh_help(1, NULL); + rosh_help(1, argv[0]); break; default: - rosh_help(1, NULL); + rosh_help(1, argv[0]); } break; case 'm': case 'M': - switch (cmdstr[1]) { + switch (argv[0][1]) { case 'a': case 'A': - if (strncasecmp("man", tstr, tlen) == 0) - rosh_help(2, cmdstr); + if (strncasecmp("man", argv[0], tlen) == 0) + rosh_help(2, argv[1]); else - rosh_help(1, NULL); + rosh_help(1, argv[0]); break; case 'o': case 'O': - if (strncasecmp("more", tstr, tlen) == 0) - rosh_more(cmdstr); + if (strncasecmp("more", argv[0], tlen) == 0) + rosh_more(argc - 1, &argv[1]); else - rosh_help(1, NULL); + rosh_help(1, argv[0]); break; default: - rosh_help(1, NULL); + rosh_help(1, argv[0]); } break; case 'p': case 'P': /* run 'pwd' */ - if (strncasecmp("pwd", tstr, tlen) == 0) - rosh_pwd(cmdstr); + if (strncasecmp("pwd", argv[0], tlen) == 0) + rosh_pwd(); else - rosh_help(1, NULL); + rosh_help(1, argv[0]); break; case 'r': case 'R': /* run 'run' */ - switch (cmdstr[1]) { + switch (argv[0][1]) { case 0: - case ' ': case 'e': case 'E': - if (strncasecmp("reboot", tstr, tlen) == 0) - rosh_reboot(); + if (strncasecmp("reboot", argv[0], tlen) == 0) + rosh_reboot(argc - 1, &argv[1]); else - rosh_help(1, NULL); + rosh_help(1, argv[0]); break; case 'u': case 'U': - if (strncasecmp("run", tstr, tlen) == 0) - rosh_run(cmdstr); + if (strncasecmp("run", argv[0], tlen) == 0) + rosh_run(argc - 1, &argv[1]); else - rosh_help(1, NULL); + rosh_help(1, argv[0]); break; + default: + rosh_help(1, argv[0]); } break; case 'v': case 'V': - if (strncasecmp("version", tstr, tlen) == 0) + if (strncasecmp("version", argv[0], tlen) == 0) rosh_version(1); else - rosh_help(1, NULL); + rosh_help(1, argv[0]); break; case 0: case '\n': break; default: - rosh_help(1, NULL); - } /* switch(cmdstr[0]) */ + rosh_help(1, argv[0]); + } /* switch(argv[0][0]) */ return do_exit; } /* rosh_command */ @@ -1150,29 +1304,29 @@ char rosh_command(const char *cmdstr, const char *ipwdstr) * icmdstr Initial command line string * returns Exit status */ -int rosh_prompt(const char *icmdstr) +int rosh_prompt(int iargc, char *iargv[]) { int rv; char cmdstr[ROSH_CMD_SZ]; char ipwdstr[ROSH_PATH_SZ]; char do_exit; - char *c; + char **argv; + int argc; rv = 0; do_exit = false; if (!getcwd(ipwdstr, ROSH_PATH_SZ)) strcpy(ipwdstr, "./"); - if (icmdstr[0] != '\0') - do_exit = rosh_command(icmdstr, ipwdstr); + if (iargc > 1) + do_exit = rosh_command(iargc - 1, &iargv[1], 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); + argc = rosh_str2argv(&argv, cmdstr); + do_exit = rosh_command(argc, argv, ipwdstr); + rosh_free_argv(&argv); } else { do_exit = false; } @@ -1183,19 +1337,21 @@ int rosh_prompt(const char *icmdstr) 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 { + if (argc == 1) { rosh_version(0); print_beta(); - cmdstr[0] = '\0'; + } else { +#ifdef DO_DEBUG + char cmdstr[ROSH_CMD_SZ]; + rosh_argcat(cmdstr, ROSH_CMD_SZ, argc, argv, 1); + ROSH_DEBUG("arg='%s'\n", cmdstr); +#endif } - rv = rosh_prompt(cmdstr); - printf("--Exiting '%s'\n", APP_NAME); + rv = rosh_prompt(argc, argv); + printf("--Exiting '" APP_NAME "'\n"); return rv; } diff --git a/com32/rosh/rosh.h b/com32/rosh/rosh.h index b016e2f2..cabf556a 100644 --- a/com32/rosh/rosh.h +++ b/com32/rosh/rosh.h @@ -36,26 +36,32 @@ #include <sys/stat.h> /* fstat() */ #include <fcntl.h> /* open(); open mode macros */ #include <dirent.h> /* fdopendir() opendir() readdir() closedir() DIR */ -#include <unistd.h> /* getcwd() */ +#include <unistd.h> /* getcwd() getopt() */ #include <errno.h> /* errno; error macros */ #include <netinet/in.h> /* For htonl/ntohl/htons/ntohs */ #include <ctype.h> /* isspace() */ #include <getkey.h> #include <consoles.h> /* console_ansi_raw() console_ansi_std() */ +// #include <getopt.h> /* getopt_long() */ #ifdef DO_DEBUG # define ROSH_DEBUG printf +# define ROSH_DEBUG_ARGV_V rosh_pr_argv_v /* define ROSH_DEBUG(f, ...) printf (f, ## __VA_ARGS__) */ # ifdef DO_DEBUG2 # define ROSH_DEBUG2 printf +# define ROSH_DEBUG2_ARGV_V rosh_pr_argv_v # else /* DO_DEBUG2 */ /* This forces a format argument into the function call */ # define ROSH_DEBUG2(f, ...) ((void)0) +# define ROSH_DEBUG2_ARGV_V(argc, argv) ((void)0) # endif /* DO_DEBUG2 */ #else /* DO_DEBUG */ # define ROSH_DEBUG(f, ...) ((void)0) +# define ROSH_DEBUG_ARGV_V(argc, argv) ((void)0) # define ROSH_DEBUG2(f, ...) ((void)0) +# define ROSH_DEBUG2_ARGV_V(argc, argv) ((void)0) #endif /* DO_DEBUG */ #ifdef __COM32__ @@ -135,10 +141,10 @@ static inline int getscreensize(int fd, int *rows, int *cols) str = NULL; if (fd == 1) { ioctl(0, TIOCGWINSZ, &ws); -/* if (rows) + if (rows) *rows = ws.ws_row; if (cols) - *cols = ws.ws_col;*/ + *cols = ws.ws_col; if (rows && !*rows) { str = getenv("LINES"); if (str) @@ -235,6 +241,10 @@ const char rosh_beta_str[] = const char rosh_cd_norun_str[] = " -- cd (Change Directory) not implemented for use with run and exit.\n"; +const char rosh_help_cd_str[] = "cd Change directory\n\ + with no argument, return to original directory from entry to rosh\n\ + with one argument, change to that directory"; + const char rosh_help_ls_str[] = "ls List contents of current directory\n\ -l Long format\n\ -i Inode; print Inode of file\n\ @@ -259,4 +269,6 @@ const char rosh_help_str2[] = const char rosh_help_str_adv[] = "No additional help available for '%s'"; +const char rosh_ls_opt_str[] = "lFi"; + #endif /* Not ROSH_H */ diff --git a/core/pxelinux.asm b/core/pxelinux.asm index a46b3da5..e8818a6c 100644 --- a/core/pxelinux.asm +++ b/core/pxelinux.asm @@ -365,6 +365,16 @@ pxenv: pushfd pushad + ; We may be removing ourselves from memory + cmp bx,0073h ; PXENV_RESTART_TFTP + jz .disable_timer + cmp bx,00E5h ; gPXE PXENV_FILE_EXEC + jnz .store_stack + +.disable_timer: + call timer_cleanup + +.store_stack: mov [cs:PXEStack],sp mov [cs:PXEStack+2],ss lss sp,[cs:InitStack] @@ -391,6 +401,17 @@ pxenv: ; This clobbers the AX return, but we already saved it into ; the PXEStatus variable. popad + + ; If the call failed, it could return. + cmp bx,0073h + jz .enable_timer + cmp bx,00E5h + jnz .pop_flags + +.enable_timer: + call timer_init + +.pop_flags: popfd ; Restore flags (incl. IF, DF) ret diff --git a/sample/Makefile b/sample/Makefile index f1006ff9..d7f439ca 100644 --- a/sample/Makefile +++ b/sample/Makefile @@ -15,6 +15,7 @@ ## topdir = .. +include $(topdir)/MCONFIG.embedded PPMTOLSS16 = $(topdir)/utils/ppmtolss16 |