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-b072"
46 void rosh_version(int vtype)
50 printf("%s v %s; (c) %s %s.\n\tFrom Syslinux %s, %s\n", APP_LONGNAME, APP_VER, APP_YEAR, APP_AUTHOR, VERSION_STR, DATE);
53 rosh_get_env_ver(env, 256);
54 printf("\tRunning on %s\n", env);
61 ROSH_DEBUG("DO_DEBUG active\n");
62 ROSH_DEBUG2("DO_DEBUG2 active\n");
65 /* Search a string for first non-space (' ') character, starting at ipos
66 * istr input string to parse
67 * ipos input position to start at
69 int rosh_search_nonsp(const char *istr, const int ipos)
76 while (c && isspace(c))
81 /* Search a string for space (' '), returning the position of the next space
82 * or the '\0' at end of string
83 * istr input string to parse
84 * ipos input position to start at
86 int rosh_search_sp(const char *istr, const int ipos)
93 while (c && !(isspace(c)))
98 /* Parse a string for the first non-space string, returning the end position
100 * dest string to contain the first non-space string
101 * src string to parse
102 * ipos Position to start in src
104 int rosh_parse_sp_1(char *dest, const char *src, const int ipos)
106 int bpos, epos; /* beginning and ending position of source string
107 to copy to destination string */
111 /* //HERE-error condition checking */
112 bpos = rosh_search_nonsp(src, ipos);
113 epos = rosh_search_sp(src, bpos);
115 memcpy(dest, src + bpos, epos - bpos);
116 if (dest[epos - bpos] != 0)
117 dest[epos - bpos] = 0;
125 int __parse_argv(char ***argv, const char *str);
128 * parse_args1: Try 1 at parsing a string to an argc/argv pair. use free_args1 to free memory malloc'd
130 * Derived from com32/lib/sys/argv.c:__parse_argv()
131 * Copyright 2004-2009 H. Peter Anvin - All Rights Reserved
132 * Copyright 2009 Intel Corporation; author: H. Peter Anvin
134 int parse_args1(char ***iargv, const char *istr)
138 char *q, *r, *args, **arg;
139 int sp = 1; //, qt = 0; /* Was a space; inside a quote */
142 /* I could eliminate this if I knew a max length, like strncpy() */
143 int len = strlen(istr);
145 /* Scan 2: Copy, nullify and make argc */
146 if (!(args = malloc(len + 1)))
149 for (p = istr;; p++) {
166 q--; /* Point q to final null */
167 /* Scan 3: Build array of pointers */
168 if (!(*iargv = malloc((argc + 1) * sizeof(char *))))
171 arg[argc] = NULL; /* Nullify the last pointer */
174 for (r = args; r < q ; r++) {
187 void free_args1(char ***argv)
195 int rosh_str2argv(char ***argv, const char *str)
197 return parse_args1(argv, str);
200 void rosh_free_argv(char ***argv)
205 void rosh_pr_argv_v(int argc, char *argv[])
208 for (i = 0; i < argc; i++) {
209 printf("%4d '%s'\n", i, argv[i]);
215 * cmdstr Command string
217 void rosh_help(int type, const char *cmdstr)
223 istr += rosh_search_nonsp(cmdstr, rosh_search_sp(cmdstr, 0));
224 if ((cmdstr == NULL) || (strcmp(istr, "") == 0)) {
226 puts(rosh_help_str2);
230 puts(rosh_help_cd_str);
233 puts(rosh_help_ls_str);
236 printf(rosh_help_str_adv, istr);
243 puts(rosh_help_str1);
247 /* Handle most/all errors
248 * ierrno Input Error number
249 * cmdstr Command being executed to cause error
250 * filestr File/parameter causing error
252 void rosh_error(const int ierrno, const char *cmdstr, const char *filestr)
254 printf("--ERROR: %s '%s': ", cmdstr, filestr);
261 /* SYSLinux-3.72 COM32 API returns this for a
262 directory or empty file */
263 ROSH_COM32(" (COM32) could be a directory or empty file\n");
269 puts("Bad File Descriptor");
272 puts("Access DENIED");
275 puts("not a directory");
276 ROSH_COM32(" (COM32) could be directory\n");
279 puts("IS a directory");
282 puts("not implemented");
285 printf("returns error; errno=%d\n", ierrno);
289 /* Concatenate command line arguments into one string
290 * cmdstr Output command string
291 * argc Argument Count
292 * argv Argument Values
293 * barg Beginning Argument
295 int rosh_argcat(char *cmdstr, const int argc, char *argv[], const int barg)
297 int i, arglen, curpos; /* index, argument length, current position
300 cmdstr[0] = '\0'; /* Nullify string just to be sure */
301 for (i = barg; i < argc; i++) {
302 arglen = strlen(argv[i]);
303 /* Theoretically, this should never be met in SYSLINUX */
304 if ((curpos + arglen) > (ROSH_CMD_SZ - 1))
305 arglen = (ROSH_CMD_SZ - 1) - curpos;
306 memcpy(cmdstr + curpos, argv[i], arglen);
308 if (curpos >= (ROSH_CMD_SZ - 1)) {
309 /* Hopefully, curpos should not be greater than
311 /* Still need a '\0' at the last character */
312 cmdstr[(ROSH_CMD_SZ - 1)] = 0;
313 break; /* Escape out of the for() loop;
314 We can no longer process anything more */
316 cmdstr[curpos] = ' ';
321 /* If there's a ' ' at the end, remove it. This is normal unless
322 the maximum length is met/exceeded. */
323 if (cmdstr[curpos - 1] == ' ')
324 cmdstr[--curpos] = 0;
329 * Prints a lot of the data in a struct termios
332 void rosh_print_tc(struct termios *tio)
334 printf(" -- termios: ");
335 printf(".c_iflag=%04X ", tio->c_iflag);
336 printf(".c_oflag=%04X ", tio->c_oflag);
337 printf(".c_cflag=%04X ", tio->c_cflag);
338 printf(".c_lflag=%04X ", tio->c_lflag);
339 printf(".c_cc[VTIME]='%d' ", tio->c_cc[VTIME]);
340 printf(".c_cc[VMIN]='%d'", tio->c_cc[VMIN]);
346 * Attempts to get a single key from the console
347 * returns key pressed
349 int rosh_getkey(void)
354 while (inc == KEY_NONE)
355 inc = get_key(stdin, 6000);
360 * Qualifies a filename relative to the working directory
361 * filestr Filename to qualify
362 * pwdstr working directory
363 * returns qualified file name string
365 void rosh_qualify_filestr(char *filestr, const char *ifilstr,
369 if ((filestr) && (pwdstr) && (ifilstr)) {
370 if (ifilstr[0] != SEP) {
371 strcpy(filestr, pwdstr);
372 filepos = strlen(pwdstr);
373 if (filestr[filepos - 1] != SEP)
374 filestr[filepos++] = SEP;
376 strcpy(filestr + filepos, ifilstr);
377 ROSH_DEBUG("--'%s'\n", filestr);
381 /* Concatenate multiple files to stdout
382 * cmdstr command string to process
384 void rosh_cat(const char *cmdstr)
387 char filestr[ROSH_PATH_SZ];
388 char buf[ROSH_BUF_SZ];
392 ROSH_DEBUG("CMD: '%s'\n", cmdstr);
396 /* skip the first word */
397 cmdpos = rosh_parse_sp_1(filestr, cmdstr, cmdpos);
398 cmdpos = rosh_parse_sp_1(filestr, cmdstr, cmdpos);
399 while (strlen(filestr) > 0) {
400 printf("--File = '%s'\n", filestr);
401 f = fopen(filestr, "r");
403 numrd = fread(buf, 1, ROSH_BUF_SZ, f);
405 fwrite(buf, 1, numrd, stdout);
406 numrd = fread(buf, 1, ROSH_BUF_SZ, f);
410 rosh_error(errno, "cat", filestr);
413 cmdpos = rosh_parse_sp_1(filestr, cmdstr, cmdpos);
417 /* Change PWD (Present Working Directory)
418 * argc Argument count
419 * argv Argument values
420 * ipwdstr Initial PWD
422 void rosh_cd(int argc, char *argv[], const char *ipwdstr)
426 char filestr[ROSH_PATH_SZ];
427 #endif /* DO_DEBUG */
428 ROSH_DEBUG("CMD: \n");
429 ROSH_DEBUG_ARGV_V(argc, argv);
435 rosh_help(2, argv[0]);
438 rosh_error(errno, "cd", argv[1]);
440 rosh_error(errno, "cd", ipwdstr);
444 if (getcwd(filestr, ROSH_PATH_SZ))
445 ROSH_DEBUG(" %s\n", filestr);
446 #endif /* DO_DEBUG */
450 /* Print the syslinux config file name
454 printf("CFG: '%s'\n", syslinux_config_file());
457 /* Echo a string back to the screen
458 * cmdstr command string to process
460 void rosh_echo(const char *cmdstr)
463 ROSH_DEBUG("CMD: '%s'\n", cmdstr);
464 bpos = rosh_search_nonsp(cmdstr, rosh_search_sp(cmdstr, 0));
466 ROSH_DEBUG(" bpos=%d\n", bpos);
467 printf("'%s'\n", cmdstr + bpos);
473 /* Process optstr to optarr
474 * optstr option string to process
475 * optarr option array to populate
477 void rosh_ls_arg_opt(const char *optstr, int *optarr)
480 cpos = strchr(optstr, 'l');
482 optarr[0] = cpos - optstr;
486 cpos = strchr(optstr, 'F');
488 optarr[1] = cpos - optstr;
492 cpos = strchr(optstr, 'i');
494 optarr[2] = cpos - optstr;
498 } /* rosh_ls_arg_opt */
500 /* Retrieve the size of a file argument
501 * filestr directory name of directory entry
504 int rosh_ls_de_size(const char *filestr, struct dirent *de)
507 char filestr2[ROSH_PATH_SZ];
515 file2pos = strlen(filestr);
516 memcpy(filestr2, filestr, file2pos);
517 filestr2[file2pos] = '/';
519 strcpy(filestr2 + file2pos + 1, de->d_name);
520 fd2 = open(filestr2, O_RDONLY);
521 status = fstat(fd2, &fdstat);
523 de_size = (int)fdstat.st_size;
525 } /* rosh_ls_de_size */
527 /* Retrieve the size and mode of a file
528 * filestr directory name of directory entry
531 int rosh_ls_de_size_mode(struct dirent *de, mode_t * st_mode)
534 // char filestr2[ROSH_PATH_SZ];
544 file2pos = strlen(filestr);
545 memcpy(filestr2, filestr, file2pos);
546 filestr2[file2pos] = '/';
548 strcpy(filestr2 + file2pos + 1, de->d_name);*/
549 status = stat(de->d_name, &fdstat);
550 ROSH_DEBUG2("\t--stat()=%d\terr=%d\n", status, errno);
552 rosh_error(errno, "ls:szmd.stat", de->d_name);
555 de_size = (int)fdstat.st_size;
556 *st_mode = fdstat.st_mode;
558 } /* rosh_ls_de_size_mode */
560 /* Returns the Inode number if fdstat contains it
561 * fdstat struct to extract inode from if not COM32, for now
563 long rosh_ls_d_ino(struct stat *fdstat)
571 #else /* __COM32__ */
572 de_ino = fdstat->st_ino;
573 #endif /* __COM32__ */
577 /* Convert a d_type to a single char in human readable format
578 * d_type d_type to convert
579 * returns human readable single character; a space if other
581 char rosh_d_type2char_human(unsigned char d_type)
593 break; /* Char Dev */
596 break; /* Directory */
599 break; /* Block Dev */
602 break; /* Regular File */
605 break; /* Link, Symbolic */
611 break; /* UnionFS Whiteout */
616 } /* rosh_d_type2char_human */
618 /* Convert a d_type to a single char by ls's prefix standards for -l
619 * d_type d_type to convert
620 * returns ls style single character; a space if other
622 char rosh_d_type2char_lspre(unsigned char d_type)
651 } /* rosh_d_type2char_lspre */
653 /* Convert a d_type to a single char by ls's classify (-F) suffix standards
654 * d_type d_type to convert
655 * returns ls style single character; a space if other
657 char rosh_d_type2char_lssuf(unsigned char d_type)
677 } /* rosh_d_type2char_lssuf */
679 /* Converts data in the "other" place of st_mode to a ls-style string
680 * st_mode Mode in other to analyze
681 * st_mode_str string to hold converted string
683 void rosh_st_mode_am2str(mode_t st_mode, char *st_mode_str)
685 st_mode_str[0] = ((st_mode & S_IROTH) ? 'r' : '-');
686 st_mode_str[1] = ((st_mode & S_IWOTH) ? 'w' : '-');
687 st_mode_str[2] = ((st_mode & S_IXOTH) ? 'x' : '-');
690 /* Converts st_mode to an ls-style string
691 * st_mode mode to convert
692 * st_mode_str string to hold converted string
694 void rosh_st_mode2str(mode_t st_mode, char *st_mode_str)
696 st_mode_str[0] = rosh_d_type2char_lspre(IFTODT(st_mode));
697 rosh_st_mode_am2str((st_mode & S_IRWXU) >> 6, st_mode_str + 1);
698 rosh_st_mode_am2str((st_mode & S_IRWXG) >> 3, st_mode_str + 4);
699 rosh_st_mode_am2str(st_mode & S_IRWXO, st_mode_str + 7);
701 } /* rosh_st_mode2str */
703 /* Output a single entry
704 * filestr directory name to list
706 * optarr Array of options
708 void rosh_ls_arg_dir_de(struct dirent *de, const int *optarr)
712 char st_mode_str[11];
715 printf("%10d ", (int)de->d_ino);
716 if (optarr[0] > -1) {
717 de_size = rosh_ls_de_size_mode(de, &st_mode);
718 rosh_st_mode2str(st_mode, st_mode_str);
719 ROSH_DEBUG2("%04X ", st_mode);
720 printf("%s %10d ", st_mode_str, de_size);
723 printf("%s", de->d_name);
726 printf("%c", rosh_d_type2char_lssuf(de->d_type));
728 } /* rosh_ls_arg_dir_de */
730 /* Output listing of a regular directory
731 * filestr directory name to list
733 * optarr Array of options
734 NOTE:This is where I could use qsort
736 void rosh_ls_arg_dir(const char *filestr, DIR * d, const int *optarr)
742 while ((de = readdir(d))) {
744 rosh_ls_arg_dir_de(de, optarr);
747 rosh_error(errno, "ls:arg_dir", filestr);
748 else if (filepos == 0)
749 ROSH_DEBUG("0 files found");
750 } /* rosh_ls_arg_dir */
752 /* Simple directory listing for one argument (file/directory) based on
754 * ifilstr input filename/directory name to list
755 * pwdstr Present Working Directory string
756 * optarr Option Array
758 void rosh_ls_arg(const char *filestr, const int *optarr)
762 // char filestr[ROSH_PATH_SZ];
767 /* Initialization; make filestr based on leading character of ifilstr
769 // rosh_qualify_filestr(filestr, ifilstr, pwdstr);
772 ROSH_DEBUG("\topt[0]=%d\topt[1]=%d\topt[2]=%d\n", optarr[0], optarr[1],
775 /* Now, the real work */
777 status = stat(filestr, &fdstat);
779 if (S_ISDIR(fdstat.st_mode)) {
780 ROSH_DEBUG("PATH '%s' is a directory\n", filestr);
781 if (d = opendir(filestr)) {
782 rosh_ls_arg_dir(filestr, d, optarr);
785 rosh_error(errno, "ls", filestr);
789 de.d_ino = rosh_ls_d_ino(&fdstat);
790 de.d_type = (IFTODT(fdstat.st_mode));
791 strcpy(de.d_name, filestr);
792 if (S_ISREG(fdstat.st_mode)) {
793 ROSH_DEBUG("PATH '%s' is a regular file\n", filestr);
795 ROSH_DEBUG("PATH '%s' is some other file\n", filestr);
797 rosh_ls_arg_dir_de(&de, optarr);
798 /* if (ifilstr[0] == SEP)
799 rosh_ls_arg_dir_de(NULL, &de, optarr);
801 rosh_ls_arg_dir_de(pwdstr, &de, optarr);*/
804 rosh_error(errno, "ls", filestr);
810 /* Parse options that may be present in the cmdstr
811 * filestr Possible option string to parse
812 * optstr Current options
813 * returns 1 if filestr does not begin with '-' else 0
815 int rosh_ls_parse_opt(const char *filestr, char *optstr)
818 if (filestr[0] == '-') {
821 strcat(optstr, filestr + 1);
825 ROSH_DEBUG("ParseOpt: '%s'\n\topt: '%s'\n\tret: %d\n", filestr, optstr,
828 } /* rosh_ls_parse_opt */
830 /* List Directory based on cmdstr and pwdstr
831 * cmdstr command string to process
832 * pwdstr Present Working Directory string
834 void rosh_ls(const char *cmdstr)
836 char filestr[ROSH_PATH_SZ];
837 char optstr[ROSH_OPT_SZ]; /* Options string */
838 int cmdpos, tpos; /* Position within cmdstr, temp position */
839 int numargs; /* number of non-option arguments */
840 int argpos; /* number of non-option arguments processed */
843 ROSH_DEBUG("CMD: '%s'\n", cmdstr);
850 /* skip the first word */
851 cmdpos = rosh_parse_sp_1(filestr, cmdstr, cmdpos);
852 tpos = rosh_parse_sp_1(filestr, cmdstr, cmdpos);
853 /* If there are no real arguments, substitute PWD */
854 if (strlen(filestr) == 0) {
855 strcpy(filestr, ".");
857 } else { /* Parse for command line options */
858 while (strlen(filestr) > 0) {
859 numargs += rosh_ls_parse_opt(filestr, optstr);
860 tpos = rosh_parse_sp_1(filestr, cmdstr, tpos);
863 strcpy(filestr, ".");
866 cmdpos = rosh_parse_sp_1(filestr, cmdstr, cmdpos);
870 if (!strchr(optstr, 'l'))
872 #endif /* DO_DEBUG */
873 rosh_ls_arg_opt(optstr, optarr);
874 ROSH_DEBUG("\tfopt: '%s'\n", optstr);
875 while (strlen(filestr) > 0) {
876 if (rosh_ls_parse_opt(filestr, NULL)) {
877 rosh_ls_arg(filestr, optarr);
880 if (argpos < numargs)
881 cmdpos = rosh_parse_sp_1(filestr, cmdstr, cmdpos);
887 /* Simple directory listing; calls rosh_ls()
888 * cmdstr command string to process
889 * pwdstr Present Working Directory string
891 void rosh_dir(const char *cmdstr)
893 ROSH_DEBUG(" dir implemented as ls\n");
897 /* Page through a buffer string
898 * buf Buffer to page through
900 void rosh_more_buf(char *buf, int buflen, int rows, int cols, char *scrbuf)
902 char *bufp, *bufeol, *bufeol2; /* Pointer to current and next
903 end-of-line position in buffer */
904 int bufpos, bufcnt; /* current position, count characters */
906 int i, numln; /* Index, Number of lines */
907 int elpl; /* Extra lines per line read */
915 ROSH_DEBUG("--(%d)\n", buflen);
916 while (bufpos < buflen) {
917 for (i = 0; i < numln; i++) {
918 bufeol2 = strchr(bufeol, '\n');
919 if (bufeol2 == NULL) {
920 bufeol = buf + buflen;
923 elpl = ((bufeol2 - bufeol - 1) / cols);
927 ROSH_DEBUG2(" %d/%d ", elpl, i+1);
928 /* If this will not push too much, use it */
929 /* but if it's the first line, use it */
930 /* //HERE: We should probably snip the line off */
931 if ((i < numln) || (i == elpl))
932 bufeol = bufeol2 + 1;
936 bufcnt = bufeol - bufp;
937 printf("--(%d/%d @%d)\n", bufcnt, buflen, bufpos);
938 memcpy(scrbuf, bufp, bufcnt);
940 printf("%s", scrbuf);
943 if (bufpos == buflen)
957 } /* rosh_more_buf */
959 /* Page through a single file using the open file stream
962 void rosh_more_fd(int fd, int rows, int cols, char *scrbuf)
971 status = fstat(fd, &fdstat);
972 if (S_ISREG(fdstat.st_mode)) {
973 buf = malloc((int)fdstat.st_size);
977 numrd = fread(buf, 1, (int)fdstat.st_size, f);
980 numrd = fread(buf + bufpos, 1,
981 ((int)fdstat.st_size - bufpos), f);
984 rosh_more_buf(buf, bufpos, rows, cols, scrbuf);
991 /* Page through a file like the more command
992 * cmdstr command string to process
993 * ipwdstr Initial PWD
995 void rosh_more(const char *cmdstr)
998 char filestr[ROSH_PATH_SZ];
1004 ROSH_DEBUG("CMD: '%s'\n", cmdstr);
1005 /* Initialization */
1008 ret = getscreensize(1, &rows, &cols);
1010 ROSH_DEBUG("getscreensize() fail(%d); fall back\n", ret);
1011 ROSH_DEBUG("\tROWS='%d'\tCOLS='%d'\n", rows, cols);
1012 /* If either fail, go under normal size, just in case */
1018 ROSH_DEBUG("\tUSE ROWS='%d'\tCOLS='%d'\n", rows, cols);
1019 /* 32 bit align beginning of row and over allocate */
1020 scrbuf = malloc(rows * ((cols+3)&(INT_MAX - 3)));
1024 /* skip the first word */
1025 cmdpos = rosh_parse_sp_1(filestr, cmdstr, cmdpos);
1026 cmdpos = rosh_parse_sp_1(filestr, cmdstr, cmdpos);
1027 if (strlen(filestr) > 0) {
1028 /* There is no need to mess up the console if we don't have a
1031 while (strlen(filestr) > 0) {
1032 printf("--File = '%s'\n", filestr);
1033 fd = open(filestr, O_RDONLY);
1035 rosh_more_fd(fd, rows, cols, scrbuf);
1038 rosh_error(errno, "more", filestr);
1041 cmdpos = rosh_parse_sp_1(filestr, cmdstr, cmdpos);
1048 /* Page a file with rewind
1049 * cmdstr command string to process
1050 * pwdstr Present Working Directory string
1051 * ipwdstr Initial PWD
1053 void rosh_less(const char *cmdstr)
1055 printf(" less implemented as more (for now)\n");
1060 * cmdstr command string to process
1062 void rosh_pwd(const char *cmdstr)
1065 char pwdstr[ROSH_PATH_SZ];
1068 ROSH_DEBUG("CMD: '%s'\n", cmdstr);
1070 if (getcwd(pwdstr, ROSH_PATH_SZ)) {
1071 printf("%s\n", pwdstr);
1073 rosh_error(errno, "pwd", "");
1076 istr = htonl(*(int *)pwdstr);
1077 ROSH_DEBUG2(" --%08X\n", istr);
1082 void rosh_reboot(void)
1084 // char cmdstr[ROSH_CMD_SZ];
1089 /* Run a boot string, calling syslinux_run_command
1090 * cmdstr command string to process
1092 void rosh_run(const char *cmdstr)
1098 ROSH_DEBUG("CMD: '%s'\n", cmdstr);
1099 /* skip the first word */
1100 cmdpos = rosh_search_sp(cmdstr, cmdpos);
1102 cmdpos = rosh_search_nonsp(cmdstr, cmdpos);
1103 cmdptr = (char *)(cmdstr + cmdpos);
1104 printf("--run: '%s'\n", cmdptr);
1105 syslinux_run_command(cmdptr);
1108 /* Process an argc/argv pair and call handling function
1109 * argc Argument count
1110 * argv Argument values
1111 * ipwdstr Initial Present Working Directory string
1112 * returns Whether to exit prompt
1114 char rosh_command(int argc, char *argv[], const char *ipwdstr)
1116 char do_exit = false;
1118 char cmdstr[ROSH_CMD_SZ];
1119 // argc = rosh_str2argv(&argv, cmdstr);
1120 tlen = strlen(argv[0]);
1121 rosh_argcat(cmdstr, argc, argv, 0);
1122 ROSH_DEBUG("--cmd:'%s'\n", cmdstr);
1123 ROSH_DEBUG_ARGV_V(argc, argv);
1124 switch (argv[0][0]) {
1129 switch (argv[0][1]) {
1135 if ((strncasecmp("exit", argv[0], tlen) == 0) ||
1136 (strncasecmp("quit", argv[0], tlen) == 0))
1143 if (strncasecmp("echo", argv[0], tlen) == 0)
1153 case 'C': /* run 'cd' 'cat' 'cfg' */
1154 switch (argv[0][1]) {
1157 if (strncasecmp("cat", argv[0], tlen) == 0)
1164 if (strncasecmp("cd", argv[0], tlen) == 0)
1165 rosh_cd(argc, argv, ipwdstr);
1171 if (strncasecmp("cfg", argv[0], tlen) == 0)
1181 case 'D': /* run 'dir' */
1182 if (strncasecmp("dir", argv[0], tlen) == 0)
1190 if ((strncasecmp("help", argv[0], tlen) == 0) || (tlen == 1))
1191 rosh_help(2, cmdstr);
1196 case 'L': /* run 'ls' 'less' */
1197 switch (argv[0][1]) {
1202 if (strncasecmp("ls", argv[0], tlen) == 0)
1209 if (strncasecmp("less", argv[0], tlen) == 0)
1220 switch (argv[0][1]) {
1223 if (strncasecmp("man", argv[0], tlen) == 0)
1224 rosh_help(2, cmdstr);
1230 if (strncasecmp("more", argv[0], tlen) == 0)
1240 case 'P': /* run 'pwd' */
1241 if (strncasecmp("pwd", argv[0], tlen) == 0)
1247 case 'R': /* run 'run' */
1248 switch (argv[0][1]) {
1253 if (strncasecmp("reboot", argv[0], tlen) == 0)
1260 if (strncasecmp("run", argv[0], tlen) == 0)
1269 if (strncasecmp("version", argv[0], tlen) == 0)
1279 } /* switch(argv[0][0]) */
1281 } /* rosh_command */
1283 /* Process the prompt for commands as read from stdin and call rosh_command
1284 * to process command line string
1285 * icmdstr Initial command line string
1286 * returns Exit status
1288 int rosh_prompt(int iargc, char *iargv[])
1291 char cmdstr[ROSH_CMD_SZ];
1292 char ipwdstr[ROSH_PATH_SZ];
1299 if (!getcwd(ipwdstr, ROSH_PATH_SZ))
1300 strcpy(ipwdstr, "./");
1302 do_exit = rosh_command(iargc - 1, &iargv[1], ipwdstr);
1303 while (!(do_exit)) {
1304 /* Extra preceeding newline */
1306 /* Read a line from console */
1307 if (fgets(cmdstr, ROSH_CMD_SZ, stdin)) {
1308 argc = rosh_str2argv(&argv, cmdstr);
1309 do_exit = rosh_command(argc, argv, ipwdstr);
1310 rosh_free_argv(&argv);
1318 int main(int argc, char *argv[])
1322 /* Initialization */
1329 rv = rosh_prompt(argc, argv);
1330 printf("--Exiting '%s'\n", APP_NAME);