1 /* ----------------------------------------------------------------------- *
3 * Copyright 2008-2010 Gene Cumm - All Rights Reserved
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, Inc., 53 Temple Place Ste 330,
8 * Boston MA 02111-1307, USA; either version 2 of the License, or
9 * (at your option) any later version; incorporated herein by reference.
11 * ----------------------------------------------------------------------- */
16 * Read-Only shell; Simple shell system designed for SYSLINUX-derivitives.
17 * Provides minimal commands utilizing the console via stdout/stderr as the
18 * sole output devices. Designed to compile for Linux for testing/debugging.
23 * prompt: Allow left/right arrow, home/end and more?
24 * commands Break into argv/argc-like array
25 * rosh_cfg: allow -s <file> to change config
26 * rosh_ls(): sorted; then multiple columns
31 /* Uncomment the above line for debugging output; Comment to remove */
34 /* Uncomment the above line for super-debugging output; Must have regular
35 * debugging enabled; Comment to remove.
38 #include "../../version.h"
40 #define APP_LONGNAME "Read-Only Shell"
41 #define APP_NAME "rosh"
42 #define APP_AUTHOR "Gene Cumm"
43 #define APP_YEAR "2010"
44 #define APP_VER "beta-b085"
46 /* Print version information to stdout
48 void rosh_version(int vtype)
52 printf("%s v %s; (c) %s %s.\n\tFrom Syslinux %s, %s\n", APP_LONGNAME, APP_VER, APP_YEAR, APP_AUTHOR, VERSION_STR, DATE);
55 rosh_get_env_ver(env, 256);
56 printf("\tRunning on %s\n", env);
60 /* Print beta message and if DO_DEBUG/DO_DEBUG2 are active
65 ROSH_DEBUG("DO_DEBUG active\n");
66 ROSH_DEBUG2("DO_DEBUG2 active\n");
69 /* Search a string for first non-space (' ') character, starting at ipos
70 * istr input string to parse
71 * ipos input position to start at
73 int rosh_search_nonsp(const char *istr, const int ipos)
80 while (c && isspace(c))
85 /* Search a string for space (' '), returning the position of the next space
86 * or the '\0' at end of string
87 * istr input string to parse
88 * ipos input position to start at
90 int rosh_search_sp(const char *istr, const int ipos)
97 while (c && !(isspace(c)))
102 /* Parse a string for the first non-space string, returning the end position
104 * dest string to contain the first non-space string
105 * src string to parse
106 * ipos Position to start in src
108 int rosh_parse_sp_1(char *dest, const char *src, const int ipos)
110 int bpos, epos; /* beginning and ending position of source string
111 to copy to destination string */
115 /* //HERE-error condition checking */
116 bpos = rosh_search_nonsp(src, ipos);
117 epos = rosh_search_sp(src, bpos);
119 memcpy(dest, src + bpos, epos - bpos);
120 if (dest[epos - bpos] != 0)
121 dest[epos - bpos] = 0;
130 * parse_args1: Try 1 at parsing a string to an argc/argv pair. use free_args1 to free memory malloc'd
132 * Derived from com32/lib/sys/argv.c:__parse_argv()
133 * Copyright 2004-2009 H. Peter Anvin - All Rights Reserved
134 * Copyright 2009 Intel Corporation; author: H. Peter Anvin
136 int parse_args1(char ***iargv, const char *istr)
140 char *q, *r, *args, **arg;
141 int sp = 1; //, qt = 0; /* Was a space; inside a quote */
144 /* I could eliminate this if I knew a max length, like strncpy() */
145 int len = strlen(istr);
147 /* Scan 2: Copy, nullify and make argc */
148 if (!(args = malloc(len + 1)))
151 for (p = istr;; p++) {
168 q--; /* Point q to final null */
169 /* Scan 3: Build array of pointers */
170 if (!(*iargv = malloc((argc + 1) * sizeof(char *))))
173 arg[argc] = NULL; /* Nullify the last pointer */
176 for (r = args; r < q ; r++) {
189 /* Free argv created by parse_args1()
190 * argv Argument Values
192 void free_args1(char ***argv)
200 /* Convert a string to an argc/argv pair
201 * str String to parse
202 * argv Argument Values
203 * returns Argument Count
205 int rosh_str2argv(char ***argv, const char *str)
207 return parse_args1(argv, str);
210 /* Free an argv created by rosh_str2argv()
211 * argv Argument Values to free
213 void rosh_free_argv(char ***argv)
218 /* Print the contents of an argc/argv pair
219 * argc Argument Count
220 * argv Argument Values
222 void rosh_pr_argv(int argc, char *argv[])
225 for (i = 0; i < argc; i++) {
226 printf("%s%s", argv[i], (i < argc)? " " : "");
231 /* Print the contents of an argc/argv pair verbosely
232 * argc Argument Count
233 * argv Argument Values
235 void rosh_pr_argv_v(int argc, char *argv[])
238 for (i = 0; i < argc; i++) {
239 printf("%4d '%s'\n", i, argv[i]);
245 * cmdstr Command for which help is requested
247 void rosh_help(int type, const char *cmdstr)
251 if ((cmdstr == NULL) || (strcmp(cmdstr, "") == 0)) {
253 puts(rosh_help_str2);
257 puts(rosh_help_cd_str);
260 puts(rosh_help_ls_str);
263 printf(rosh_help_str_adv, cmdstr);
270 puts(rosh_help_str1);
274 /* Handle most/all errors
275 * ierrno Input Error number
276 * cmdstr Command being executed to cause error
277 * filestr File/parameter causing error
279 void rosh_error(const int ierrno, const char *cmdstr, const char *filestr)
281 printf("--ERROR: %s '%s': ", cmdstr, filestr);
288 /* SYSLinux-3.72 COM32 API returns this for a
289 directory or empty file */
290 ROSH_COM32(" (COM32) could be a directory or empty file\n");
296 puts("Bad File Descriptor");
299 puts("Access DENIED");
302 puts("not a directory");
303 ROSH_COM32(" (COM32) could be directory\n");
306 puts("IS a directory");
309 puts("not implemented");
312 printf("returns error; errno=%d\n", ierrno);
316 /* Concatenate command line arguments into one string
317 * cmdstr Output command string
318 * argc Argument Count
319 * argv Argument Values
320 * barg Beginning Argument
322 int rosh_argcat(char *cmdstr, const int argc, char *argv[], const int barg)
324 int i, arglen, curpos; /* index, argument length, current position
327 cmdstr[0] = '\0'; /* Nullify string just to be sure */
328 for (i = barg; i < argc; i++) {
329 arglen = strlen(argv[i]);
330 /* Theoretically, this should never be met in SYSLINUX */
331 if ((curpos + arglen) > (ROSH_CMD_SZ - 1))
332 arglen = (ROSH_CMD_SZ - 1) - curpos;
333 memcpy(cmdstr + curpos, argv[i], arglen);
335 if (curpos >= (ROSH_CMD_SZ - 1)) {
336 /* Hopefully, curpos should not be greater than
338 /* Still need a '\0' at the last character */
339 cmdstr[(ROSH_CMD_SZ - 1)] = 0;
340 break; /* Escape out of the for() loop;
341 We can no longer process anything more */
343 cmdstr[curpos] = ' ';
348 /* If there's a ' ' at the end, remove it. This is normal unless
349 the maximum length is met/exceeded. */
350 if (cmdstr[curpos - 1] == ' ')
351 cmdstr[--curpos] = 0;
356 * Prints a lot of the data in a struct termios
359 void rosh_print_tc(struct termios *tio)
361 printf(" -- termios: ");
362 printf(".c_iflag=%04X ", tio->c_iflag);
363 printf(".c_oflag=%04X ", tio->c_oflag);
364 printf(".c_cflag=%04X ", tio->c_cflag);
365 printf(".c_lflag=%04X ", tio->c_lflag);
366 printf(".c_cc[VTIME]='%d' ", tio->c_cc[VTIME]);
367 printf(".c_cc[VMIN]='%d'", tio->c_cc[VMIN]);
373 * Attempts to get a single key from the console
374 * returns key pressed
376 int rosh_getkey(void)
381 while (inc == KEY_NONE)
382 inc = get_key(stdin, 6000);
387 * Qualifies a filename relative to the working directory
388 * filestr Filename to qualify
389 * pwdstr working directory
390 * returns qualified file name string
392 void rosh_qualify_filestr(char *filestr, const char *ifilstr,
396 if ((filestr) && (pwdstr) && (ifilstr)) {
397 if (ifilstr[0] != SEP) {
398 strcpy(filestr, pwdstr);
399 filepos = strlen(pwdstr);
400 if (filestr[filepos - 1] != SEP)
401 filestr[filepos++] = SEP;
403 strcpy(filestr + filepos, ifilstr);
404 ROSH_DEBUG("--'%s'\n", filestr);
408 /* Concatenate multiple files to stdout
409 * argc Argument Count
410 * argv Argument Values
412 void rosh_cat(int argc, char *argv[])
415 char buf[ROSH_BUF_SZ];
418 for (i = 0; i < argc; i++) {
419 printf("--File = '%s'\n", argv[i]);
421 f = fopen(argv[i], "r");
423 numrd = fread(buf, 1, ROSH_BUF_SZ, f);
425 fwrite(buf, 1, numrd, stdout);
426 numrd = fread(buf, 1, ROSH_BUF_SZ, f);
430 rosh_error(errno, "cat", argv[i]);
436 /* Change PWD (Present Working Directory)
437 * argc Argument count
438 * argv Argument values
439 * ipwdstr Initial PWD
441 void rosh_cd(int argc, char *argv[], const char *ipwdstr)
445 char filestr[ROSH_PATH_SZ];
446 #endif /* DO_DEBUG */
447 ROSH_DEBUG("CMD: \n");
448 ROSH_DEBUG_ARGV_V(argc, argv);
455 rosh_help(2, argv[0]);
458 rosh_error(errno, "cd", argv[1]);
460 rosh_error(errno, "cd", ipwdstr);
464 if (getcwd(filestr, ROSH_PATH_SZ))
465 ROSH_DEBUG(" %s\n", filestr);
466 #endif /* DO_DEBUG */
470 /* Print the syslinux config file name
474 printf("CFG: '%s'\n", syslinux_config_file());
477 /* Echo a string back to the screen
478 * cmdstr command string to process
480 void rosh_echo(const char *cmdstr)
483 ROSH_DEBUG("CMD: '%s'\n", cmdstr);
484 bpos = rosh_search_nonsp(cmdstr, rosh_search_sp(cmdstr, 0));
486 ROSH_DEBUG(" bpos=%d\n", bpos);
487 printf("'%s'\n", cmdstr + bpos);
493 /* Process argc/argv to optarr
494 * argc Argument count
495 * argv Argument values
496 * optarr option array to populate
498 void rosh_ls_arg_opt(int argc, char *argv[], int *optarr)
506 rv = getopt(argc, argv, rosh_ls_opt_str);
522 } /* rosh_ls_arg_opt */
524 /* Retrieve the size of a file argument
525 * filestr directory name of directory entry
528 int rosh_ls_de_size(const char *filestr, struct dirent *de)
531 char filestr2[ROSH_PATH_SZ];
539 file2pos = strlen(filestr);
540 memcpy(filestr2, filestr, file2pos);
541 filestr2[file2pos] = '/';
543 strcpy(filestr2 + file2pos + 1, de->d_name);
544 fd2 = open(filestr2, O_RDONLY);
545 status = fstat(fd2, &fdstat);
547 de_size = (int)fdstat.st_size;
549 } /* rosh_ls_de_size */
551 /* Retrieve the size and mode of a file
552 * filestr directory name of directory entry
555 int rosh_ls_de_size_mode(struct dirent *de, mode_t * st_mode)
558 // char filestr2[ROSH_PATH_SZ];
568 file2pos = strlen(filestr);
569 memcpy(filestr2, filestr, file2pos);
570 filestr2[file2pos] = '/';
572 strcpy(filestr2 + file2pos + 1, de->d_name);*/
574 status = stat(de->d_name, &fdstat);
575 ROSH_DEBUG2("\t--stat()=%d\terr=%d\n", status, errno);
577 rosh_error(errno, "ls:szmd.stat", de->d_name);
580 de_size = (int)fdstat.st_size;
581 *st_mode = fdstat.st_mode;
583 } /* rosh_ls_de_size_mode */
585 /* Returns the Inode number if fdstat contains it
586 * fdstat struct to extract inode from if not COM32, for now
588 long rosh_ls_d_ino(struct stat *fdstat)
596 #else /* __COM32__ */
597 de_ino = fdstat->st_ino;
598 #endif /* __COM32__ */
602 /* Convert a d_type to a single char in human readable format
603 * d_type d_type to convert
604 * returns human readable single character; a space if other
606 char rosh_d_type2char_human(unsigned char d_type)
618 break; /* Char Dev */
621 break; /* Directory */
624 break; /* Block Dev */
627 break; /* Regular File */
630 break; /* Link, Symbolic */
636 break; /* UnionFS Whiteout */
641 } /* rosh_d_type2char_human */
643 /* Convert a d_type to a single char by ls's prefix standards for -l
644 * d_type d_type to convert
645 * returns ls style single character; a space if other
647 char rosh_d_type2char_lspre(unsigned char d_type)
676 } /* rosh_d_type2char_lspre */
678 /* Convert a d_type to a single char by ls's classify (-F) suffix standards
679 * d_type d_type to convert
680 * returns ls style single character; a space if other
682 char rosh_d_type2char_lssuf(unsigned char d_type)
702 } /* rosh_d_type2char_lssuf */
704 /* Converts data in the "other" place of st_mode to a ls-style string
705 * st_mode Mode in other to analyze
706 * st_mode_str string to hold converted string
708 void rosh_st_mode_am2str(mode_t st_mode, char *st_mode_str)
710 st_mode_str[0] = ((st_mode & S_IROTH) ? 'r' : '-');
711 st_mode_str[1] = ((st_mode & S_IWOTH) ? 'w' : '-');
712 st_mode_str[2] = ((st_mode & S_IXOTH) ? 'x' : '-');
715 /* Converts st_mode to an ls-style string
716 * st_mode mode to convert
717 * st_mode_str string to hold converted string
719 void rosh_st_mode2str(mode_t st_mode, char *st_mode_str)
721 st_mode_str[0] = rosh_d_type2char_lspre(IFTODT(st_mode));
722 rosh_st_mode_am2str((st_mode & S_IRWXU) >> 6, st_mode_str + 1);
723 rosh_st_mode_am2str((st_mode & S_IRWXG) >> 3, st_mode_str + 4);
724 rosh_st_mode_am2str(st_mode & S_IRWXO, st_mode_str + 7);
726 } /* rosh_st_mode2str */
728 /* Output a single entry
729 * filestr directory name to list
731 * optarr Array of options
733 void rosh_ls_arg_dir_de(struct dirent *de, const int *optarr)
737 char st_mode_str[11];
740 printf("%10d ", (int)de->d_ino);
741 if (optarr[0] > -1) {
742 de_size = rosh_ls_de_size_mode(de, &st_mode);
743 rosh_st_mode2str(st_mode, st_mode_str);
744 ROSH_DEBUG2("%04X ", st_mode);
745 printf("%s %10d ", st_mode_str, de_size);
748 printf("%s", de->d_name);
751 printf("%c", rosh_d_type2char_lssuf(de->d_type));
753 } /* rosh_ls_arg_dir_de */
755 /* Output listing of a regular directory
756 * filestr directory name to list
758 * optarr Array of options
759 NOTE:This is where I could use qsort
761 void rosh_ls_arg_dir(const char *filestr, DIR * d, const int *optarr)
768 while ((de = readdir(d))) {
770 rosh_ls_arg_dir_de(de, optarr);
773 rosh_error(errno, "ls:arg_dir", filestr);
775 } else { if (filepos == 0)
776 ROSH_DEBUG("0 files found");
778 } /* rosh_ls_arg_dir */
780 /* Simple directory listing for one argument (file/directory) based on
782 * ifilstr input filename/directory name to list
783 * pwdstr Present Working Directory string
784 * optarr Option Array
786 void rosh_ls_arg(const char *filestr, const int *optarr)
790 // char filestr[ROSH_PATH_SZ];
795 /* Initialization; make filestr based on leading character of ifilstr
797 // rosh_qualify_filestr(filestr, ifilstr, pwdstr);
800 ROSH_DEBUG("\topt[0]=%d\topt[1]=%d\topt[2]=%d\n", optarr[0], optarr[1],
803 /* Now, the real work */
805 status = stat(filestr, &fdstat);
807 if (S_ISDIR(fdstat.st_mode)) {
808 ROSH_DEBUG("PATH '%s' is a directory\n", filestr);
809 if ((d = opendir(filestr))) {
810 rosh_ls_arg_dir(filestr, d, optarr);
813 rosh_error(errno, "ls", filestr);
817 de.d_ino = rosh_ls_d_ino(&fdstat);
818 de.d_type = (IFTODT(fdstat.st_mode));
819 strcpy(de.d_name, filestr);
820 if (S_ISREG(fdstat.st_mode)) {
821 ROSH_DEBUG("PATH '%s' is a regular file\n", filestr);
823 ROSH_DEBUG("PATH '%s' is some other file\n", filestr);
825 rosh_ls_arg_dir_de(&de, optarr);
826 /* if (ifilstr[0] == SEP)
827 rosh_ls_arg_dir_de(NULL, &de, optarr);
829 rosh_ls_arg_dir_de(pwdstr, &de, optarr);*/
832 rosh_error(errno, "ls", filestr);
838 /* Parse options that may be present in the cmdstr
839 * filestr Possible option string to parse
840 * optstr Current options
841 * returns 1 if filestr does not begin with '-' else 0
843 int rosh_ls_parse_opt(const char *filestr, char *optstr)
846 if (filestr[0] == '-') {
849 strcat(optstr, filestr + 1);
853 ROSH_DEBUG("ParseOpt: '%s'\n\topt: '%s'\n\tret: %d\n", filestr, optstr,
856 } /* rosh_ls_parse_opt */
859 * argc Argument count
860 * argv Argument values
862 void rosh_ls(int argc, char *argv[])
867 rosh_ls_arg_opt(argc, argv, optarr);
870 #endif /* DO_DEBUG */
871 ROSH_DEBUG(" argc=%d; optind=%d\n", argc, optind);
873 rosh_ls_arg(".", optarr);
874 for (i = optind; i < argc; i++) {
875 rosh_ls_arg(argv[i], optarr);
879 /* Simple directory listing; calls rosh_ls()
880 * argc Argument count
881 * argv Argument values
883 void rosh_dir(int argc, char *argv[])
885 ROSH_DEBUG(" dir implemented as ls\n");
889 /* Page through a buffer string
890 * buf Buffer to page through
892 void rosh_more_buf(char *buf, int buflen, int rows, int cols, char *scrbuf)
894 char *bufp, *bufeol, *bufeol2; /* Pointer to current and next
895 end-of-line position in buffer */
896 int bufpos, bufcnt; /* current position, count characters */
898 int i, numln; /* Index, Number of lines */
899 int elpl; /* Extra lines per line read */
907 ROSH_DEBUG("--(%d)\n", buflen);
908 while (bufpos < buflen) {
909 for (i = 0; i < numln; i++) {
910 bufeol2 = strchr(bufeol, '\n');
911 if (bufeol2 == NULL) {
912 bufeol = buf + buflen;
915 elpl = ((bufeol2 - bufeol - 1) / cols);
919 ROSH_DEBUG2(" %d/%d ", elpl, i+1);
920 /* If this will not push too much, use it */
921 /* but if it's the first line, use it */
922 /* //HERE: We should probably snip the line off */
923 if ((i < numln) || (i == elpl))
924 bufeol = bufeol2 + 1;
928 bufcnt = bufeol - bufp;
929 printf("--(%d/%d @%d)\n", bufcnt, buflen, bufpos);
930 memcpy(scrbuf, bufp, bufcnt);
932 printf("%s", scrbuf);
935 if (bufpos == buflen)
949 } /* rosh_more_buf */
951 /* Page through a single file using the open file stream
954 void rosh_more_fd(int fd, int rows, int cols, char *scrbuf)
963 status = fstat(fd, &fdstat);
964 if (S_ISREG(fdstat.st_mode)) {
965 buf = malloc((int)fdstat.st_size);
969 numrd = fread(buf, 1, (int)fdstat.st_size, f);
972 numrd = fread(buf + bufpos, 1,
973 ((int)fdstat.st_size - bufpos), f);
976 rosh_more_buf(buf, bufpos, rows, cols, scrbuf);
983 /* Page through a file like the more command
984 * argc Argument Count
985 * argv Argument Values
987 void rosh_more(int argc, char *argv[])
990 /* char filestr[ROSH_PATH_SZ];
996 ROSH_DEBUG("CMD: '%s'\n", cmdstr);
997 ret = getscreensize(1, &rows, &cols);
999 ROSH_DEBUG("getscreensize() fail(%d); fall back\n", ret);
1000 ROSH_DEBUG("\tROWS='%d'\tCOLS='%d'\n", rows, cols);
1001 /* If either fail, go under normal size, just in case */
1007 ROSH_DEBUG("\tUSE ROWS='%d'\tCOLS='%d'\n", rows, cols);
1008 /* 32 bit align beginning of row and over allocate */
1009 scrbuf = malloc(rows * ((cols+3)&(INT_MAX - 3)));
1014 /* There is no need to mess up the console if we don't have a
1017 for (i = 0; i < argc; i++) {
1018 printf("--File = '%s'\n", argv[i]);
1020 fd = open(argv[i], O_RDONLY);
1022 rosh_more_fd(fd, rows, cols, scrbuf);
1025 rosh_error(errno, "more", argv[i]);
1034 /* Page a file with rewind
1035 * argc Argument Count
1036 * argv Argument Values
1038 void rosh_less(int argc, char *argv[])
1040 printf(" less implemented as more (for now)\n");
1041 rosh_more(argc, argv);
1048 char pwdstr[ROSH_PATH_SZ];
1050 if (getcwd(pwdstr, ROSH_PATH_SZ)) {
1051 printf("%s\n", pwdstr);
1053 rosh_error(errno, "pwd", "");
1058 /* Reboot; use warm reboot if one of certain options set
1059 * argc Argument count
1060 * argv Argument values
1062 void rosh_reboot(int argc, char *argv[])
1066 /* For now, just use the first */
1067 switch (argv[0][0]) {
1074 switch (argv[0][1]) {
1084 syslinux_reboot(rtype);
1087 /* Run a boot string, calling syslinux_run_command
1088 * argc Argument count
1089 * argv Argument values
1091 void rosh_run(int argc, char *argv[])
1093 char cmdstr[ROSH_CMD_SZ];
1096 len = rosh_argcat(cmdstr, argc, argv, 0);
1098 printf("--run: '%s'\n", cmdstr);
1099 syslinux_run_command(cmdstr);
1101 printf(APP_NAME ":run: No arguments\n");
1105 /* Process an argc/argv pair and call handling function
1106 * argc Argument count
1107 * argv Argument values
1108 * ipwdstr Initial Present Working Directory string
1109 * returns Whether to exit prompt
1111 char rosh_command(int argc, char *argv[], const char *ipwdstr)
1113 char do_exit = false;
1115 tlen = strlen(argv[0]);
1116 ROSH_DEBUG_ARGV_V(argc, argv);
1117 switch (argv[0][0]) {
1122 switch (argv[0][1]) {
1128 if ((strncasecmp("exit", argv[0], tlen) == 0) ||
1129 (strncasecmp("quit", argv[0], tlen) == 0))
1136 if (strncasecmp("echo", argv[0], tlen) == 0)
1137 rosh_pr_argv(argc - 1, &argv[1]);
1146 case 'C': /* run 'cd' 'cat' 'cfg' */
1147 switch (argv[0][1]) {
1150 if (strncasecmp("cat", argv[0], tlen) == 0)
1151 rosh_cat(argc - 1, &argv[1]);
1157 if (strncasecmp("cd", argv[0], tlen) == 0)
1158 rosh_cd(argc, argv, ipwdstr);
1164 if (strncasecmp("cfg", argv[0], tlen) == 0)
1174 case 'D': /* run 'dir' */
1175 if (strncasecmp("dir", argv[0], tlen) == 0)
1176 rosh_dir(argc - 1, &argv[1]);
1183 if ((strncasecmp("help", argv[0], tlen) == 0) || (tlen == 1))
1184 rosh_help(2, argv[1]);
1189 case 'L': /* run 'ls' 'less' */
1190 switch (argv[0][1]) {
1194 if (strncasecmp("ls", argv[0], tlen) == 0)
1195 rosh_ls(argc - 1, &argv[1]);
1201 if (strncasecmp("less", argv[0], tlen) == 0)
1202 rosh_less(argc - 1, &argv[1]);
1212 switch (argv[0][1]) {
1215 if (strncasecmp("man", argv[0], tlen) == 0)
1216 rosh_help(2, argv[1]);
1222 if (strncasecmp("more", argv[0], tlen) == 0)
1223 rosh_more(argc - 1, &argv[1]);
1232 case 'P': /* run 'pwd' */
1233 if (strncasecmp("pwd", argv[0], tlen) == 0)
1239 case 'R': /* run 'run' */
1240 switch (argv[0][1]) {
1244 if (strncasecmp("reboot", argv[0], tlen) == 0)
1245 rosh_reboot(argc - 1, &argv[1]);
1251 if (strncasecmp("run", argv[0], tlen) == 0)
1252 rosh_run(argc - 1, &argv[1]);
1260 if (strncasecmp("version", argv[0], tlen) == 0)
1270 } /* switch(argv[0][0]) */
1272 } /* rosh_command */
1274 /* Process the prompt for commands as read from stdin and call rosh_command
1275 * to process command line string
1276 * icmdstr Initial command line string
1277 * returns Exit status
1279 int rosh_prompt(int iargc, char *iargv[])
1282 char cmdstr[ROSH_CMD_SZ];
1283 char ipwdstr[ROSH_PATH_SZ];
1290 if (!getcwd(ipwdstr, ROSH_PATH_SZ))
1291 strcpy(ipwdstr, "./");
1293 do_exit = rosh_command(iargc - 1, &iargv[1], ipwdstr);
1294 while (!(do_exit)) {
1295 /* Extra preceeding newline */
1297 /* Read a line from console */
1298 if (fgets(cmdstr, ROSH_CMD_SZ, stdin)) {
1299 argc = rosh_str2argv(&argv, cmdstr);
1300 do_exit = rosh_command(argc, argv, ipwdstr);
1301 rosh_free_argv(&argv);
1309 int main(int argc, char *argv[])
1313 /* Initialization */
1320 rv = rosh_prompt(argc, argv);
1321 printf("--Exiting '" APP_NAME "'\n");