1 /* ----------------------------------------------------------------------- *
3 * Copyright 2008-2011 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
27 * prompt: Possibly honor timeout on initial entry for usage as UI
28 * Also possibly honor totaltimeout
33 /* Uncomment the above line for debugging output; Comment to remove */
36 /* Uncomment the above line for super-debugging output; Must have regular
37 * debugging enabled; Comment to remove.
40 #include "../../version.h"
42 #define APP_LONGNAME "Read-Only Shell"
43 #define APP_NAME "rosh"
44 #define APP_AUTHOR "Gene Cumm"
45 #define APP_YEAR "2010"
46 #define APP_VER "beta-b090"
48 /* Print version information to stdout
50 void rosh_version(int vtype)
54 printf("%s v %s; (c) %s %s.\n\tFrom Syslinux %s, %s\n", APP_LONGNAME, APP_VER, APP_YEAR, APP_AUTHOR, VERSION_STR, DATE);
57 rosh_get_env_ver(env, 256);
58 printf("\tRunning on %s\n", env);
62 /* Print beta message and if DO_DEBUG/DO_DEBUG2 are active
67 ROSH_DEBUG("DO_DEBUG active\n");
68 ROSH_DEBUG2("DO_DEBUG2 active\n");
71 /* Search a string for first non-space (' ') character, starting at ipos
72 * istr input string to parse
73 * ipos input position to start at
75 int rosh_search_nonsp(const char *istr, const int ipos)
82 while (c && isspace(c))
87 /* Search a string for space (' '), returning the position of the next space
88 * or the '\0' at end of string
89 * istr input string to parse
90 * ipos input position to start at
92 int rosh_search_sp(const char *istr, const int ipos)
99 while (c && !(isspace(c)))
104 /* Parse a string for the first non-space string, returning the end position
106 * dest string to contain the first non-space string
107 * src string to parse
108 * ipos Position to start in src
110 int rosh_parse_sp_1(char *dest, const char *src, const int ipos)
112 int bpos, epos; /* beginning and ending position of source string
113 to copy to destination string */
117 /* //HERE-error condition checking */
118 bpos = rosh_search_nonsp(src, ipos);
119 epos = rosh_search_sp(src, bpos);
121 memcpy(dest, src + bpos, epos - bpos);
122 if (dest[epos - bpos] != 0)
123 dest[epos - bpos] = 0;
132 * parse_args1: Try 1 at parsing a string to an argc/argv pair. use free_args1 to free memory malloc'd
134 * Derived from com32/lib/sys/argv.c:__parse_argv()
135 * Copyright 2004-2009 H. Peter Anvin - All Rights Reserved
136 * Copyright 2009 Intel Corporation; author: H. Peter Anvin
138 int parse_args1(char ***iargv, const char *istr)
142 char *q, *r, *args, **arg;
143 int sp = 1; //, qt = 0; /* Was a space; inside a quote */
146 /* I could eliminate this if I knew a max length, like strncpy() */
147 int len = strlen(istr);
149 /* Scan 2: Copy, nullify and make argc */
150 if (!(args = malloc(len + 1)))
153 for (p = istr;; p++) {
170 q--; /* Point q to final null */
171 /* Scan 3: Build array of pointers */
172 if (!(*iargv = malloc((argc + 1) * sizeof(char *))))
175 arg[argc] = NULL; /* Nullify the last pointer */
178 for (r = args; r < q ; r++) {
191 /* Free argv created by parse_args1()
192 * argv Argument Values
194 void free_args1(char ***argv)
202 /* Convert a string to an argc/argv pair
203 * str String to parse
204 * argv Argument Values
205 * returns Argument Count
207 int rosh_str2argv(char ***argv, const char *str)
209 return parse_args1(argv, str);
212 /* Free an argv created by rosh_str2argv()
213 * argv Argument Values to free
215 void rosh_free_argv(char ***argv)
220 /* Print the contents of an argc/argv pair
221 * argc Argument Count
222 * argv Argument Values
224 void rosh_pr_argv(int argc, char *argv[])
227 for (i = 0; i < argc; i++) {
228 printf("%s%s", argv[i], (i < argc)? " " : "");
233 /* Print the contents of an argc/argv pair verbosely
234 * argc Argument Count
235 * argv Argument Values
237 void rosh_pr_argv_v(int argc, char *argv[])
240 for (i = 0; i < argc; i++) {
241 printf("%4d '%s'\n", i, argv[i]);
245 /* Reset the getopt() environment
247 void rosh_getopt_reset(void)
255 * cmdstr Command for which help is requested
257 void rosh_help(int type, const char *cmdstr)
261 if ((cmdstr == NULL) || (strcmp(cmdstr, "") == 0)) {
263 puts(rosh_help_str2);
267 puts(rosh_help_cd_str);
270 puts(rosh_help_ls_str);
273 printf(rosh_help_str_adv, cmdstr);
280 printf("%s: %s: unknown command\n", APP_NAME, cmdstr);
282 puts(rosh_help_str1);
286 /* Handle most/all errors
287 * ierrno Input Error number
288 * cmdstr Command being executed to cause error
289 * filestr File/parameter causing error
291 void rosh_error(const int ierrno, const char *cmdstr, const char *filestr)
293 printf("--ERROR: %s '%s': ", cmdstr, filestr);
300 /* SYSLinux-3.72 COM32 API returns this for a
301 directory or empty file */
302 ROSH_COM32(" (COM32) could be a directory or empty file\n");
308 puts("Bad File Descriptor");
311 puts("Access DENIED");
314 puts("not a directory");
315 ROSH_COM32(" (COM32) could be directory\n");
318 puts("IS a directory");
321 puts("not implemented");
324 printf("returns error; errno=%d\n", ierrno);
328 /* Concatenate command line arguments into one string
329 * cmdstr Output command string
330 * cmdlen Length of cmdstr
331 * argc Argument Count
332 * argv Argument Values
333 * barg Beginning Argument
335 int rosh_argcat(char *cmdstr, const int cmdlen, const int argc, char *argv[],
338 int i, arglen, curpos; /* index, argument length, current position
341 cmdstr[0] = '\0'; /* Nullify string just to be sure */
342 for (i = barg; i < argc; i++) {
343 arglen = strlen(argv[i]);
344 /* Theoretically, this should never be met in SYSLINUX */
345 if ((curpos + arglen) > (cmdlen - 1))
346 arglen = (cmdlen - 1) - curpos;
347 memcpy(cmdstr + curpos, argv[i], arglen);
349 if (curpos >= (cmdlen - 1)) {
350 /* Hopefully, curpos should not be greater than
352 /* Still need a '\0' at the last character */
353 cmdstr[(cmdlen - 1)] = 0;
354 break; /* Escape out of the for() loop;
355 We can no longer process anything more */
357 cmdstr[curpos] = ' ';
362 /* If there's a ' ' at the end, remove it. This is normal unless
363 the maximum length is met/exceeded. */
364 if (cmdstr[curpos - 1] == ' ')
365 cmdstr[--curpos] = 0;
370 * Prints a lot of the data in a struct termios
373 void rosh_print_tc(struct termios *tio)
375 printf(" -- termios: ");
376 printf(".c_iflag=%04X ", tio->c_iflag);
377 printf(".c_oflag=%04X ", tio->c_oflag);
378 printf(".c_cflag=%04X ", tio->c_cflag);
379 printf(".c_lflag=%04X ", tio->c_lflag);
380 printf(".c_cc[VTIME]='%d' ", tio->c_cc[VTIME]);
381 printf(".c_cc[VMIN]='%d'", tio->c_cc[VMIN]);
387 * Attempts to get a single key from the console
388 * returns key pressed
390 int rosh_getkey(void)
395 while (inc == KEY_NONE)
396 inc = get_key(stdin, 6000);
401 * Qualifies a filename relative to the working directory
402 * filestr Filename to qualify
403 * pwdstr working directory
404 * returns qualified file name string
406 void rosh_qualify_filestr(char *filestr, const char *ifilstr,
410 if ((filestr) && (pwdstr) && (ifilstr)) {
411 if (ifilstr[0] != SEP) {
412 strcpy(filestr, pwdstr);
413 filepos = strlen(pwdstr);
414 if (filestr[filepos - 1] != SEP)
415 filestr[filepos++] = SEP;
417 strcpy(filestr + filepos, ifilstr);
418 ROSH_DEBUG("--'%s'\n", filestr);
422 /* Concatenate multiple files to stdout
423 * argc Argument Count
424 * argv Argument Values
426 void rosh_cat(int argc, char *argv[])
429 char buf[ROSH_BUF_SZ];
432 for (i = 0; i < argc; i++) {
433 printf("--File = '%s'\n", argv[i]);
435 f = fopen(argv[i], "r");
437 numrd = fread(buf, 1, ROSH_BUF_SZ, f);
439 fwrite(buf, 1, numrd, stdout);
440 numrd = fread(buf, 1, ROSH_BUF_SZ, f);
444 rosh_error(errno, "cat", argv[i]);
450 /* Change PWD (Present Working Directory)
451 * argc Argument count
452 * argv Argument values
453 * ipwdstr Initial PWD
455 void rosh_cd(int argc, char *argv[], const char *ipwdstr)
459 char filestr[ROSH_PATH_SZ];
460 #endif /* DO_DEBUG */
461 ROSH_DEBUG("CMD: \n");
462 ROSH_DEBUG_ARGV_V(argc, argv);
469 rosh_help(2, argv[0]);
472 rosh_error(errno, "cd", argv[1]);
474 rosh_error(errno, "cd", ipwdstr);
478 if (getcwd(filestr, ROSH_PATH_SZ))
479 ROSH_DEBUG(" %s\n", filestr);
480 #endif /* DO_DEBUG */
484 /* Print the syslinux config file name
488 printf("CFG: '%s'\n", syslinux_config_file());
491 /* Echo a string back to the screen
492 * cmdstr command string to process
494 void rosh_echo(const char *cmdstr)
497 ROSH_DEBUG("CMD: '%s'\n", cmdstr);
498 bpos = rosh_search_nonsp(cmdstr, rosh_search_sp(cmdstr, 0));
500 ROSH_DEBUG(" bpos=%d\n", bpos);
501 printf("'%s'\n", cmdstr + bpos);
507 /* Process argc/argv to optarr
508 * argc Argument count
509 * argv Argument values
510 * optarr option array to populate
512 void rosh_ls_arg_opt(int argc, char *argv[], int optarr[])
521 ROSH_DEBUG2("getopt optind=%d rv=%d\n", optind, rv);
522 rv = getopt(argc, argv, rosh_ls_opt_str);
539 ROSH_DEBUG2("getopt optind=%d rv=%d\n", optind, rv);
543 ROSH_DEBUG2(" end getopt optind=%d rv=%d\n", optind, rv);
544 ROSH_DEBUG2("\tIn rosh_ls_arg_opt() opt[0]=%d\topt[1]=%d\topt[2]=%d\n", optarr[0], optarr[1],
546 } /* rosh_ls_arg_opt */
548 /* Retrieve the size of a file argument
549 * filestr directory name of directory entry
552 int rosh_ls_de_size(const char *filestr, struct dirent *de)
555 char filestr2[ROSH_PATH_SZ];
562 file2pos = strlen(filestr);
563 memcpy(filestr2, filestr, file2pos);
564 filestr2[file2pos] = '/';
566 strcpy(filestr2 + file2pos + 1, de->d_name);
567 fd2 = open(filestr2, O_RDONLY);
570 de_size = (int)fdstat.st_size;
572 } /* rosh_ls_de_size */
574 /* Retrieve the size and mode of a file
575 * filestr directory name of directory entry
578 int rosh_ls_de_size_mode(const char *filestr, struct dirent *de, mode_t * st_mode)
581 char filestr2[ROSH_PATH_SZ];
588 memset(&fdstat, 0, sizeof fdstat);
589 ROSH_DEBUG2("ls:dsm(%s, %s) ", filestr, de->d_name);
591 /* FIXME: prevent string overflow */
592 file2pos = strlen(filestr);
593 memcpy(filestr2, filestr, file2pos);
594 if (( filestr2[file2pos - 1] == SEP )) {
597 filestr2[file2pos] = SEP;
600 strcpy(filestr2 + file2pos + 1, de->d_name);
602 ROSH_DEBUG2("stat(%s) ", filestr2);
603 status = stat(filestr2, &fdstat);
605 ROSH_DEBUG2("\t--stat()=%d\terr=%d\n", status, errno);
607 rosh_error(errno, "ls:szmd.stat", de->d_name);
610 de_size = (int)fdstat.st_size;
611 *st_mode = fdstat.st_mode;
613 } /* rosh_ls_de_size_mode */
615 /* Returns the Inode number if fdstat contains it
616 * fdstat struct to extract inode from if not COM32, for now
618 long rosh_ls_d_ino(struct stat *fdstat)
626 #else /* __COM32__ */
627 de_ino = fdstat->st_ino;
628 #endif /* __COM32__ */
632 /* Convert a d_type to a single char in human readable format
633 * d_type d_type to convert
634 * returns human readable single character; a space if other
636 char rosh_d_type2char_human(unsigned char d_type)
648 break; /* Char Dev */
651 break; /* Directory */
654 break; /* Block Dev */
657 break; /* Regular File */
660 break; /* Link, Symbolic */
666 break; /* UnionFS Whiteout */
671 } /* rosh_d_type2char_human */
673 /* Convert a d_type to a single char by ls's prefix standards for -l
674 * d_type d_type to convert
675 * returns ls style single character; a space if other
677 char rosh_d_type2char_lspre(unsigned char d_type)
706 } /* rosh_d_type2char_lspre */
708 /* Convert a d_type to a single char by ls's classify (-F) suffix standards
709 * d_type d_type to convert
710 * returns ls style single character; a space if other
712 char rosh_d_type2char_lssuf(unsigned char d_type)
732 } /* rosh_d_type2char_lssuf */
734 /* Converts data in the "other" place of st_mode to a ls-style string
735 * st_mode Mode in other to analyze
736 * st_mode_str string to hold converted string
738 void rosh_st_mode_am2str(mode_t st_mode, char *st_mode_str)
740 st_mode_str[0] = ((st_mode & S_IROTH) ? 'r' : '-');
741 st_mode_str[1] = ((st_mode & S_IWOTH) ? 'w' : '-');
742 st_mode_str[2] = ((st_mode & S_IXOTH) ? 'x' : '-');
745 /* Converts st_mode to an ls-style string
746 * st_mode mode to convert
747 * st_mode_str string to hold converted string
749 void rosh_st_mode2str(mode_t st_mode, char *st_mode_str)
751 st_mode_str[0] = rosh_d_type2char_lspre(IFTODT(st_mode));
752 rosh_st_mode_am2str((st_mode & S_IRWXU) >> 6, st_mode_str + 1);
753 rosh_st_mode_am2str((st_mode & S_IRWXG) >> 3, st_mode_str + 4);
754 rosh_st_mode_am2str(st_mode & S_IRWXO, st_mode_str + 7);
756 } /* rosh_st_mode2str */
758 /* Output a single entry
759 * filestr directory name to list
761 * optarr Array of options
763 void rosh_ls_arg_dir_de(const char *filestr, struct dirent *de, const int *optarr)
767 char st_mode_str[11];
771 printf("%10d ", (int)(de->d_ino));
772 if (optarr[0] > -1) {
773 de_size = rosh_ls_de_size_mode(filestr, de, &st_mode);
774 rosh_st_mode2str(st_mode, st_mode_str);
775 ROSH_DEBUG2("%04X ", st_mode);
776 printf("%s %10d ", st_mode_str, de_size);
779 printf("%s", de->d_name);
782 printf("%c", rosh_d_type2char_lssuf(de->d_type));
784 } /* rosh_ls_arg_dir_de */
786 /* Output listing of a regular directory
787 * filestr directory name to list
789 * optarr Array of options
790 NOTE:This is where I could use qsort
792 void rosh_ls_arg_dir(const char *filestr, DIR * d, const int *optarr)
799 while ((de = readdir(d))) {
801 rosh_ls_arg_dir_de(filestr, de, optarr);
804 rosh_error(errno, "ls:arg_dir", filestr);
806 } else { if (filepos == 0)
807 ROSH_DEBUG("0 files found");
809 } /* rosh_ls_arg_dir */
811 /* Simple directory listing for one argument (file/directory) based on
813 * ifilstr input filename/directory name to list
814 * pwdstr Present Working Directory string
815 * optarr Option Array
817 void rosh_ls_arg(const char *filestr, const int *optarr)
821 // char filestr[ROSH_PATH_SZ];
826 /* Initialization; make filestr based on leading character of ifilstr
828 // rosh_qualify_filestr(filestr, ifilstr, pwdstr);
831 ROSH_DEBUG("\topt[0]=%d\topt[1]=%d\topt[2]=%d\n", optarr[0], optarr[1],
834 /* Now, the real work */
836 status = stat(filestr, &fdstat);
838 if (S_ISDIR(fdstat.st_mode)) {
839 ROSH_DEBUG("PATH '%s' is a directory\n", filestr);
840 if ((d = opendir(filestr))) {
841 rosh_ls_arg_dir(filestr, d, optarr);
844 rosh_error(errno, "ls", filestr);
848 de.d_ino = rosh_ls_d_ino(&fdstat);
849 de.d_type = (IFTODT(fdstat.st_mode));
850 strcpy(de.d_name, filestr);
851 if (S_ISREG(fdstat.st_mode)) {
852 ROSH_DEBUG("PATH '%s' is a regular file\n", filestr);
854 ROSH_DEBUG("PATH '%s' is some other file\n", filestr);
856 rosh_ls_arg_dir_de(NULL, &de, optarr);
857 /* if (ifilstr[0] == SEP)
858 rosh_ls_arg_dir_de(NULL, &de, optarr);
860 rosh_ls_arg_dir_de(pwdstr, &de, optarr);*/
863 rosh_error(errno, "ls", filestr);
869 /* Parse options that may be present in the cmdstr
870 * filestr Possible option string to parse
871 * optstr Current options
872 * returns 1 if filestr does not begin with '-' else 0
874 int rosh_ls_parse_opt(const char *filestr, char *optstr)
877 if (filestr[0] == '-') {
880 strcat(optstr, filestr + 1);
884 ROSH_DEBUG("ParseOpt: '%s'\n\topt: '%s'\n\tret: %d\n", filestr, optstr,
887 } /* rosh_ls_parse_opt */
890 * argc Argument count
891 * argv Argument values
893 void rosh_ls(int argc, char *argv[])
898 rosh_ls_arg_opt(argc, argv, optarr);
899 ROSH_DEBUG2("In ls()\n");
900 ROSH_DEBUG2_ARGV_V(argc, argv);
903 #endif /* DO_DEBUG */
904 ROSH_DEBUG2(" argc=%d; optind=%d\n", argc, optind);
906 rosh_ls_arg(".", optarr);
907 for (i = optind; i < argc; i++) {
908 rosh_ls_arg(argv[i], optarr);
912 /* Simple directory listing; calls rosh_ls()
913 * argc Argument count
914 * argv Argument values
916 void rosh_dir(int argc, char *argv[])
918 ROSH_DEBUG(" dir implemented as ls\n");
922 /* Page through a buffer string
923 * buf Buffer to page through
925 void rosh_more_buf(char *buf, int buflen, int rows, int cols, char *scrbuf)
927 char *bufp, *bufeol, *bufeol2; /* Pointer to current and next
928 end-of-line position in buffer */
929 int bufpos, bufcnt; /* current position, count characters */
931 int i, numln; /* Index, Number of lines */
932 int elpl; /* Extra lines per line read */
940 ROSH_DEBUG("--(%d)\n", buflen);
941 while (bufpos < buflen) {
942 for (i = 0; i < numln; i++) {
943 bufeol2 = strchr(bufeol, '\n');
944 if (bufeol2 == NULL) {
945 bufeol = buf + buflen;
948 elpl = ((bufeol2 - bufeol - 1) / cols);
952 ROSH_DEBUG2(" %d/%d ", elpl, i+1);
953 /* If this will not push too much, use it */
954 /* but if it's the first line, use it */
955 /* //HERE: We should probably snip the line off */
956 if ((i < numln) || (i == elpl))
957 bufeol = bufeol2 + 1;
961 bufcnt = bufeol - bufp;
962 printf("--(%d/%d @%d)\n", bufcnt, buflen, bufpos);
963 memcpy(scrbuf, bufp, bufcnt);
965 printf("%s", scrbuf);
968 if (bufpos == buflen)
982 } /* rosh_more_buf */
984 /* Page through a single file using the open file stream
987 void rosh_more_fd(int fd, int rows, int cols, char *scrbuf)
996 if (S_ISREG(fdstat.st_mode)) {
997 buf = malloc((int)fdstat.st_size);
1001 numrd = fread(buf, 1, (int)fdstat.st_size, f);
1004 numrd = fread(buf + bufpos, 1,
1005 ((int)fdstat.st_size - bufpos), f);
1008 rosh_more_buf(buf, bufpos, rows, cols, scrbuf);
1013 } /* rosh_more_fd */
1015 /* Page through a file like the more command
1016 * argc Argument Count
1017 * argv Argument Values
1019 void rosh_more(int argc, char *argv[])
1022 /* char filestr[ROSH_PATH_SZ];
1028 ROSH_DEBUG_ARGV_V(argc, argv);
1029 ret = getscreensize(1, &rows, &cols);
1031 ROSH_DEBUG("getscreensize() fail(%d); fall back\n", ret);
1032 ROSH_DEBUG("\tROWS='%d'\tCOLS='%d'\n", rows, cols);
1033 /* If either fail, go under normal size, just in case */
1039 ROSH_DEBUG("\tUSE ROWS='%d'\tCOLS='%d'\n", rows, cols);
1040 /* 32 bit align beginning of row and over allocate */
1041 scrbuf = malloc(rows * ((cols+3)&(INT_MAX - 3)));
1046 /* There is no need to mess up the console if we don't have a
1049 for (i = 0; i < argc; i++) {
1050 printf("--File = '%s'\n", argv[i]);
1052 fd = open(argv[i], O_RDONLY);
1054 rosh_more_fd(fd, rows, cols, scrbuf);
1057 rosh_error(errno, "more", argv[i]);
1066 /* Page a file with rewind
1067 * argc Argument Count
1068 * argv Argument Values
1070 void rosh_less(int argc, char *argv[])
1072 printf(" less implemented as more (for now)\n");
1073 rosh_more(argc, argv);
1080 char pwdstr[ROSH_PATH_SZ];
1082 if (getcwd(pwdstr, ROSH_PATH_SZ)) {
1083 printf("%s\n", pwdstr);
1085 rosh_error(errno, "pwd", "");
1090 /* Reboot; use warm reboot if one of certain options set
1091 * argc Argument count
1092 * argv Argument values
1094 void rosh_reboot(int argc, char *argv[])
1098 /* For now, just use the first */
1099 switch (argv[0][0]) {
1106 switch (argv[0][1]) {
1116 syslinux_reboot(rtype);
1119 /* Run a boot string, calling syslinux_run_command
1120 * argc Argument count
1121 * argv Argument values
1123 void rosh_run(int argc, char *argv[])
1125 char cmdstr[ROSH_CMD_SZ];
1128 len = rosh_argcat(cmdstr, ROSH_CMD_SZ, argc, argv, 0);
1130 printf("--run: '%s'\n", cmdstr);
1131 syslinux_run_command(cmdstr);
1133 printf(APP_NAME ":run: No arguments\n");
1137 /* Process an argc/argv pair and call handling function
1138 * argc Argument count
1139 * argv Argument values
1140 * ipwdstr Initial Present Working Directory string
1141 * returns Whether to exit prompt
1143 char rosh_command(int argc, char *argv[], const char *ipwdstr)
1145 char do_exit = false;
1147 tlen = strlen(argv[0]);
1148 ROSH_DEBUG_ARGV_V(argc, argv);
1149 switch (argv[0][0]) {
1154 switch (argv[0][1]) {
1160 if ((strncasecmp("exit", argv[0], tlen) == 0) ||
1161 (strncasecmp("quit", argv[0], tlen) == 0))
1164 rosh_help(1, argv[0]);
1168 if (strncasecmp("echo", argv[0], tlen) == 0)
1169 rosh_pr_argv(argc - 1, &argv[1]);
1171 rosh_help(1, argv[0]);
1174 rosh_help(1, argv[0]);
1178 case 'C': /* run 'cd' 'cat' 'cfg' */
1179 switch (argv[0][1]) {
1182 if (strncasecmp("cat", argv[0], tlen) == 0)
1183 rosh_cat(argc - 1, &argv[1]);
1185 rosh_help(1, argv[0]);
1189 if (strncasecmp("cd", argv[0], tlen) == 0)
1190 rosh_cd(argc, argv, ipwdstr);
1192 rosh_help(1, argv[0]);
1196 if (strncasecmp("cfg", argv[0], tlen) == 0)
1199 rosh_help(1, argv[0]);
1202 rosh_help(1, argv[0]);
1206 case 'D': /* run 'dir' */
1207 if (strncasecmp("dir", argv[0], tlen) == 0)
1208 rosh_dir(argc - 1, &argv[1]);
1210 rosh_help(1, argv[0]);
1215 if ((strncasecmp("help", argv[0], tlen) == 0) || (tlen == 1))
1216 rosh_help(2, argv[1]);
1221 case 'L': /* run 'ls' 'less' */
1222 switch (argv[0][1]) {
1226 if (strncasecmp("ls", argv[0], tlen) == 0)
1227 rosh_ls(argc, argv);
1229 rosh_help(1, argv[0]);
1233 if (strncasecmp("less", argv[0], tlen) == 0)
1234 rosh_less(argc - 1, &argv[1]);
1236 rosh_help(1, argv[0]);
1239 rosh_help(1, argv[0]);
1244 switch (argv[0][1]) {
1247 if (strncasecmp("man", argv[0], tlen) == 0)
1248 rosh_help(2, argv[1]);
1250 rosh_help(1, argv[0]);
1254 if (strncasecmp("more", argv[0], tlen) == 0)
1255 rosh_more(argc - 1, &argv[1]);
1257 rosh_help(1, argv[0]);
1260 rosh_help(1, argv[0]);
1264 case 'P': /* run 'pwd' */
1265 if (strncasecmp("pwd", argv[0], tlen) == 0)
1268 rosh_help(1, argv[0]);
1271 case 'R': /* run 'run' */
1272 switch (argv[0][1]) {
1276 if (strncasecmp("reboot", argv[0], tlen) == 0)
1277 rosh_reboot(argc - 1, &argv[1]);
1279 rosh_help(1, argv[0]);
1283 if (strncasecmp("run", argv[0], tlen) == 0)
1284 rosh_run(argc - 1, &argv[1]);
1286 rosh_help(1, argv[0]);
1289 rosh_help(1, argv[0]);
1294 if (strncasecmp("version", argv[0], tlen) == 0)
1297 rosh_help(1, argv[0]);
1303 rosh_help(1, argv[0]);
1304 } /* switch(argv[0][0]) */
1306 } /* rosh_command */
1308 /* Process the prompt for commands as read from stdin and call rosh_command
1309 * to process command line string
1310 * icmdstr Initial command line string
1311 * returns Exit status
1313 int rosh_prompt(int iargc, char *iargv[])
1316 char cmdstr[ROSH_CMD_SZ];
1317 char ipwdstr[ROSH_PATH_SZ];
1324 if (!getcwd(ipwdstr, ROSH_PATH_SZ))
1325 strcpy(ipwdstr, "./");
1327 do_exit = rosh_command(iargc - 1, &iargv[1], ipwdstr);
1328 while (!(do_exit)) {
1329 /* Extra preceeding newline */
1331 /* Read a line from console */
1332 if (fgets(cmdstr, ROSH_CMD_SZ, stdin)) {
1333 argc = rosh_str2argv(&argv, cmdstr);
1334 do_exit = rosh_command(argc, argv, ipwdstr);
1335 rosh_free_argv(&argv);
1343 int main(int argc, char *argv[])
1347 /* Initialization */
1355 char cmdstr[ROSH_CMD_SZ];
1356 rosh_argcat(cmdstr, ROSH_CMD_SZ, argc, argv, 1);
1357 ROSH_DEBUG("arg='%s'\n", cmdstr);
1360 rv = rosh_prompt(argc, argv);
1361 printf("--Exiting '" APP_NAME "'\n");