c634a94085bb411f82b252c7ab2a5245d4e50e52
[profile/ivi/syslinux.git] / com32 / rosh / rosh.c
1 /* ----------------------------------------------------------------------- *
2  *
3  *   Copyright 2008 Gene Cumm - All Rights Reserved
4  *
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.
10  *
11  * ----------------------------------------------------------------------- */
12
13 /*
14  * rosh.c
15  *
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.
19  */
20
21 /*
22  * ToDos:
23  * Change functions to use pwdstr
24  * In rosh_run() Reparse cmdstr relative to pwdstr
25  */
26
27 // #define DO_DEBUG 1
28         /* Uncomment the above line for debugging output; Comment to remove */
29 // #define DO_DEBUG2 1
30         /* Uncomment the above line for super-debugging output; Must have regular debugging enabled; Comment to remove */
31
32 #include "rosh.h"
33
34 #define APP_LONGNAME    "Read-Only Shell"
35 #define APP_NAME        "rosh"
36 #define APP_AUTHOR      "Gene Cumm"
37 #define APP_YEAR        "2008"
38 #define APP_VER         "beta-b032"
39
40 void rosh_version()
41 {
42     printf("%s v %s; (c) %s %s.\n", APP_LONGNAME, APP_VER, APP_YEAR,
43            APP_AUTHOR);
44 }
45
46 void rosh_help(int type)
47 {
48     rosh_version();
49     switch (type) {
50     case 2:
51         puts(rosh_help_str2);
52         break;
53     case 1:
54     default:
55         puts(rosh_help_str1);
56     }
57 }
58
59 /* Determine if a character is whitespace
60  *      inc     input character
61  *      returns 0 if not whitespace
62  */
63 int rosh_issp(char inc)
64 {
65     int rv;
66     switch (inc) {
67     case ' ':
68     case '\t':
69         rv = 1;
70         break;
71     default:
72         rv = 0;
73     }
74     return rv;
75 }                               /* ros_issp */
76
77 /* Search a string for first non-space (' ') character, starting at ipos
78  *      istr    input string to parse
79  *      ipos    input position to start at
80  */
81 int rosh_search_nonsp(const char *istr, const int ipos)
82 {
83     int curpos;
84     char c;
85
86     curpos = ipos;
87     c = istr[curpos];
88     while (rosh_issp(c) && c != 0)
89         c = istr[++curpos];
90     return curpos;
91 }
92
93 /* Search a string for space (' '), returning the position of the next space
94  * or the '\0' at end of string
95  *      istr    input string to parse
96  *      ipos    input position to start at
97  */
98 int rosh_search_sp(const char *istr, const int ipos)
99 {
100     int curpos;
101     char c;
102
103     curpos = ipos;
104     c = istr[curpos];
105     while (!(rosh_issp(c)) && c != 0)
106         c = istr[++curpos];
107     return curpos;
108 }
109
110 /* Parse a string for the first non-space string, returning the end position
111  * from src
112  *      dest    string to contain the first non-space string
113  *      src     string to parse
114  *      ipos    Position to start in src
115  */
116 int rosh_parse_sp_1(char *dest, const char *src, const int ipos)
117 {
118     int bpos, epos;             /* beginning and ending position of source string
119                                    to copy to destination string */
120
121     bpos = 0;
122     epos = 0;
123 /* //HERE-error condition checking */
124     bpos = rosh_search_nonsp(src, ipos);
125     epos = rosh_search_sp(src, bpos);
126     if (epos > bpos) {
127         memcpy(dest, src + bpos, epos - bpos);
128         if (dest[epos - bpos] != 0)
129             dest[epos - bpos] = 0;
130     } else {
131         epos = strlen(src);
132         dest[0] = 0;
133     }
134     return epos;
135 }
136
137 /* Handle most/all errors
138  *      ierrno  Input Error number
139  *      cmdstr  Command being executed to cause error
140  *      filestr File/parameter causing error
141  */
142 void rosh_error(const int ierrno, const char *cmdstr, const char *filestr)
143 {
144     printf("--ERROR: %s '%s': ", cmdstr, filestr);
145     switch (ierrno) {
146     case EACCES:
147         printf("Access DENIED\n");
148         break;
149     case ENOENT:
150         printf("not found\n");
151         /* SYSLinux-3.72 COM32 API returns this for a
152            directory or empty file */
153         ROSH_COM32("  (COM32) could be a directory or empty file\n");
154         break;
155     case ENOTDIR:
156         printf("not a directory\n");
157         ROSH_COM32("  (COM32) could be directory\n");
158         break;
159     case ENOSYS:
160         printf("not implemented");
161         break;
162     default:
163         printf("returns error; errno=%d\n", ierrno);
164     }
165 }
166
167 /* Concatenate command line arguments into one string
168  *      cmdstr  Output command string
169  *      argc    Argument Count
170  *      argv    Argument Values
171  *      barg    Beginning Argument
172  */
173 int rosh_argcat(char *cmdstr, const int argc, char *argv[], const int barg)
174 {
175     int i, arglen, curpos;      /* index, argument length, current position
176                                    in cmdstr */
177     curpos = 0;
178     cmdstr[0] = '\0';           /* Nullify string just to be sure */
179     for (i = barg; i < argc; i++) {
180         arglen = strlen(argv[i]);
181         /* Theoretically, this should never be met in SYSLINUX */
182         if ((curpos + arglen) > (ROSH_CMD_SZ - 1))
183             arglen = (ROSH_CMD_SZ - 1) - curpos;
184         memcpy(cmdstr + curpos, argv[i], arglen);
185         curpos += arglen;
186         if (curpos >= (ROSH_CMD_SZ - 1)) {
187             /* Hopefully, curpos should not be greater than
188                (ROSH_CMD_SZ - 1) */
189             /* Still need a '\0' at the last character */
190             cmdstr[(ROSH_CMD_SZ - 1)] = 0;
191             break;              /* Escape out of the for() loop;
192                                    We can no longer process anything more */
193         } else {
194             cmdstr[curpos] = ' ';
195             curpos += 1;
196             cmdstr[curpos] = 0;
197         }
198     }
199     /* If there's a ' ' at the end, remove it.  This is normal unless
200        the maximum length is met/exceeded. */
201     if (cmdstr[curpos - 1] == ' ')
202         cmdstr[--curpos] = 0;
203     return curpos;
204 }                               /* rosh_argcat */
205
206 /*
207  * Prints a lot of the data in a struct termios
208  */
209 /*
210 void rosh_print_tc(struct termios *tio)
211 {
212         printf("  -- termios: ");
213         printf(".c_iflag=%04X ", tio->c_iflag);
214         printf(".c_oflag=%04X ", tio->c_oflag);
215         printf(".c_cflag=%04X ", tio->c_cflag);
216         printf(".c_lflag=%04X ", tio->c_lflag);
217         printf(".c_cc[VTIME]='%d' ", tio->c_cc[VTIME]);
218         printf(".c_cc[VMIN]='%d'", tio->c_cc[VMIN]);
219         printf("\n");
220 }
221 */
222
223 /*
224  * Switches console over to raw input mode.  Allows get_key to get just
225  * 1 key sequence (without delay or display)
226  */
227 void rosh_console_raw()
228 {
229 //      struct termios itio, ntio;
230 //      tcgetattr(0, &itio);
231 //      rosh_print_tc(&itio);
232 /*      ntio = itio;
233         ntio.c_lflag &= ~(ICANON|ECHO);
234         tcsetattr(0, TCSAFLUSH, &ntio);*/
235     console_ansi_raw();         /* Allows get_key to get just 1 key sequence
236                                    (w/o delay or display */
237 //      tcgetattr(0, &ntio);
238 //      rosh_print_tc(&ntio);
239 }
240
241 /*
242  * Switches back to standard getline mode.
243  */
244 void rosh_console_std()
245 {
246 //      struct termios itio, ntio;
247     console_ansi_std();
248 //      tcsetattr(0, TCSANOW, &itio);
249 }
250
251 /*
252  * Attempts to get a single key from the console
253  *      returns key pressed
254  */
255 int rosh_getkey()
256 {
257     int inc;
258
259     inc = KEY_NONE;
260 //      rosh_console_raw();
261     while (inc == KEY_NONE) {
262         inc = get_key(stdin, 6000);
263     }
264 //      rosh_console_std();
265     return inc;
266 }                               /* rosh_getkey */
267
268 /* Template for command functions
269  *      cmdstr  command string to process
270  *      pwdstr  Present Working Directory string
271  *      ipwdstr Initial PWD
272  */
273 void rosh_1(const char *cmdstr, const char *pwdstr, const char *ipwdstr)
274 {
275     ROSH_DEBUG("CMD: '%s'\npwd: '%s'\npwd: '%s'\n", cmdstr, pwdstr, ipwdstr);
276 }                               /* rosh_1 */
277
278 /* Concatenate multiple files to stdout
279  *      cmdstr  command string to process
280  *      pwdstr  Present Working Directory string
281  */
282 void rosh_cat(const char *cmdstr, const char *pwdstr)
283 {
284     FILE *f;
285     char filestr[ROSH_PATH_SZ + 1];
286     char buf[ROSH_BUF_SZ];
287     int numrd;
288     int cmdpos;
289
290     ROSH_DEBUG("CMD: '%s'\npwd: '%s'\n", cmdstr, pwdstr);
291     /* Initialization */
292     filestr[0] = 0;
293     cmdpos = 0;
294     /* skip the first word */
295     cmdpos = rosh_parse_sp_1(filestr, cmdstr, cmdpos);
296     cmdpos = rosh_parse_sp_1(filestr, cmdstr, cmdpos);
297     while (strlen(filestr) > 0) {
298         printf("--File = '%s'\n", filestr);
299         f = fopen(filestr, "r");
300         if (f != NULL) {
301             numrd = fread(buf, 1, ROSH_BUF_SZ, f);
302             while (numrd > 0) {
303                 fwrite(buf, 1, numrd, stdout);
304                 numrd = fread(buf, 1, ROSH_BUF_SZ, f);
305             }
306             fclose(f);
307         } else {
308             rosh_error(errno, "cat", filestr);
309         }
310         cmdpos = rosh_parse_sp_1(filestr, cmdstr, cmdpos);
311     }
312 }                               /* rosh_cat */
313
314 /* Change PWD (Present Working Directory)
315  *      cmdstr  command string to process
316  *      pwdstr  Present Working Directory string
317  *      ipwdstr Initial PWD
318  */
319 void rosh_cd(const char *cmdstr, char *pwdstr, const char *ipwdstr)
320 {
321     int rv;
322     char filestr[ROSH_PATH_SZ + 1];
323     int cmdpos;
324     ROSH_DEBUG("CMD: '%s'\npwd: '%s'\n", cmdstr, pwdstr);
325     /* Initialization */
326     filestr[0] = 0;
327     cmdpos = 0;
328     rv = 0;
329     /* skip the first word */
330     cmdpos = rosh_parse_sp_1(filestr, cmdstr, cmdpos);
331     cmdpos = rosh_parse_sp_1(filestr, cmdstr, cmdpos);
332     ROSH_COM32
333         (" -- cd (Change Directory) not implemented for use with run and exit.\n");
334     if (strlen(filestr) != 0)
335         rv = chdir(filestr);
336     else
337         rv = chdir(ipwdstr);
338     if (rv != 0) {
339         rosh_error(errno, "cd", filestr);
340     } else {
341         getcwd(pwdstr, ROSH_PATH_SZ + 1);
342         printf("  %s\n", pwdstr);
343     }
344 }                               /* rosh_cd */
345
346 /* Print the syslinux config file name
347  *      cmdstr  command string to process
348  *      pwdstr  Present Working Directory string
349  */
350 void rosh_cfg(const char *cmdstr, const char *pwdstr)
351 {
352     ROSH_DEBUG("CMD: '%s'\npwd: '%s'\n", cmdstr, pwdstr);
353     printf("CFG:     '%s'\n", syslinux_config_file());
354 }                               /* rosh_cfg */
355
356 /* Simple directory listing for one argument (file/directory) based on
357  * filestr and pwdstr
358  *      ifilstr input filename/directory name to list
359  *      pwdstr  Present Working Directory string
360  */
361 void rosh_dir_arg(const char *ifilstr, const char *pwdstr)
362 {
363     struct stat fdstat;
364     int status;
365     int fd;
366     char filestr[ROSH_PATH_SZ + 1];
367     int filepos;
368     DIR *d;
369     struct dirent *de;
370 #ifdef DO_DEBUG
371     char filestr2[ROSH_PATH_SZ + 1];
372     int fd2, file2pos;
373 #ifdef __COM32__
374 //      int inchar;
375     char ty;
376 #endif /* __COM32__ */
377 #endif /* DO_DEBUG */
378
379     /* Initialization; make filestr based on leading character of ifilstr
380        and pwdstr */
381     if (ifilstr[0] == SEP) {
382         strcpy(filestr, ifilstr);
383     } else {
384         strcpy(filestr, pwdstr);
385         filepos = strlen(pwdstr);
386         if (filestr[filepos - 1] != SEP)
387             filestr[filepos++] = SEP;
388         strcpy(filestr + filepos, ifilstr);
389         ROSH_DEBUG("--'%s'\n", filestr);
390     }
391     fd = open(filestr, O_RDONLY);
392     if (fd == -1) {
393         status = fstat(fd, &fdstat);
394         if (S_ISDIR(fdstat.st_mode)) {
395             ROSH_DEBUG("PATH '%s' is a directory\n", ifilstr);
396             d = fdopendir(fd);
397             de = readdir(d);
398             while (de != NULL) {
399 #ifdef DO_DEBUG
400                 filestr2[0] = 0;
401                 file2pos = strlen(filestr);
402                 memcpy(filestr2, filestr, file2pos);
403                 filestr2[file2pos] = '/';
404                 strcpy(filestr2 + file2pos + 1, de->d_name);
405                 fd2 = open(filestr2, O_RDONLY);
406                 status = fstat(fd2, &fdstat);
407                 printf("@%8d:%8d:", (int)de->d_ino, (int)fdstat.st_size);
408                 fd2 = close(fd2);
409 #endif /* DO_DEBUG */
410                 printf("%s\n", de->d_name);
411 #ifdef DO_DEBUG
412 // inchar = fgetc(stdin);
413 #endif /* DO_DEBUG */
414                 de = readdir(d);
415             }
416             closedir(d);
417         } else if (S_ISREG(fdstat.st_mode)) {
418             ROSH_DEBUG("PATH '%s' is a regular file\n", ifilstr);
419             printf("%8d:%s\n", (int)fdstat.st_size, ifilstr);
420         } else {
421             ROSH_DEBUG("PATH '%s' is some other file\n", ifilstr);
422             printf("        :%s\n", ifilstr);
423         }
424     } else {
425 #ifdef __COM32__
426         if (filestr[strlen(filestr) - 1] == SEP) {
427             /* Directory */
428             filepos = 0;
429             d = opendir(filestr);
430             if (d != NULL) {
431                 printf("DIR:'%s'    %08x %8d\n", d->dd_name, (int)d->dd_sect, 
432                        d->dd_offset);
433                 de = readdir(d);
434                 while (de != NULL) {
435                     filepos++;
436 #ifdef DO_DEBUG
437 // if (strlen(de->d_name) > 25) de->d_name[25] = 0;
438                     switch (de->d_type) {
439                     case 16:
440                         ty = 'D';
441                         break;
442                     case 32:
443                         ty = 'F';
444                         break;
445                     default:
446                         ty = '*';
447                     }
448 #endif /* DO_DEBUG */
449 //                                      printf("%s\n", de->d_name);
450                     printf("'%s'\n", de->d_name);
451 #ifdef DO_DEBUG
452 // inchar = fgetc(stdin);
453 // fgets(instr, ROSH_CMD_SZ, stdin);
454 #endif /* DO_DEBUG */
455                     free(de);
456                     de = readdir(d);
457 // if(filepos>15){      de = NULL;      printf("Force Break\n");}
458                 }
459                 closedir(d);
460             } else {
461                 rosh_error(0, "dir:NULL", filestr);
462             }
463         } else {
464             rosh_error(errno, "dir_c32", filestr);
465         }
466 #else
467         rosh_error(errno, "dir", filestr);
468 #endif /* __COM32__ */
469     }
470 }                               /* rosh_dir_arg */
471
472 /* Simple directory listing based on cmdstr and pwdstr
473  *      cmdstr  command string to process
474  *      pwdstr  Present Working Directory string
475  */
476 void rosh_dir(const char *cmdstr, const char *pwdstr)
477 {
478     char filestr[ROSH_PATH_SZ + 1];
479     int cmdpos;                 /* Position within cmdstr */
480
481     ROSH_DEBUG("CMD: '%s'\npwd: '%s'\n", cmdstr, pwdstr);
482     /* Initialization */
483     filestr[0] = 0;
484     cmdpos = 0;
485     /* skip the first word */
486     cmdpos = rosh_parse_sp_1(filestr, cmdstr, cmdpos);
487     cmdpos = rosh_parse_sp_1(filestr, cmdstr, cmdpos);
488     /* If there are no real arguments, substitute PWD */
489     if (strlen(filestr) == 0)
490         strcpy(filestr, pwdstr);
491     while (strlen(filestr) > 0) {
492         rosh_dir_arg(filestr, pwdstr);
493         cmdpos = rosh_parse_sp_1(filestr, cmdstr, cmdpos);
494     }
495 }                               /* rosh_dir */
496
497 /* List Directory; Calls rosh_dir() for now.
498  *      cmdstr  command string to process
499  *      pwdstr  Present Working Directory string
500  */
501 void rosh_ls(const char *cmdstr, const char *pwdstr)
502 {
503     printf("  ls implemented as dir (for now)\n");
504     rosh_dir(cmdstr, pwdstr);
505 }                               /* rosh_ls */
506
507 /* Page through a buffer string
508  *      buf     Buffer to page through
509  */
510 void rosh_more_buf(char *buf, int buflen, int rows, int cols)
511 {
512     char *bufp, *bufeol;        /* Pointer to current and next end-of-line
513                                    position in buffer */
514     int bufpos, bufcnt;         /* current position, count characters */
515     char scrbuf[ROSH_SBUF_SZ];
516     int inc;
517     int i, numln;               /* Index, Number of lines */
518
519     bufpos = 0;
520     bufp = buf + bufpos;
521     bufeol = bufp;
522     numln = rows - 1;
523     printf("--(%d)\n", buflen);
524 // printf("--termIOS CONSTS: ");
525 // printf("ISIG=%08X ", ISIG);
526 // printf("ICANON=%08X ", ICANON);
527 // printf("ECHO=%08X ", ECHO);
528 // printf("=%08X", );
529 // printf("\n");
530     while (bufpos < buflen) {
531         for (i = 0; i < numln; i++) {
532             bufeol = strchr(bufeol, '\n');
533             if (bufeol == NULL) {
534                 bufeol = buf + buflen;
535                 i = numln;
536             } else {
537                 bufeol++;
538             }
539 // printf("--readln\n");
540         }
541         bufcnt = bufeol - bufp;
542         printf("--(%d/%d @%d)\n", bufcnt, buflen, bufpos);
543         memcpy(scrbuf, bufp, bufcnt);
544         scrbuf[bufcnt] = 0;
545         printf("%s", scrbuf);
546         bufp = bufeol;
547         bufpos += bufcnt;
548         if (bufpos == buflen)
549             break;
550         inc = rosh_getkey();
551         numln = 1;
552         switch (inc) {
553         case KEY_CTRL('c'):
554         case 'q':
555         case 'Q':
556             bufpos = buflen;
557             break;
558         case ' ':
559             numln = rows - 1;
560 //              default:
561         }
562     }
563 /*tcgetattr(0, &tio);
564 rosh_print_tc(&tio);
565 printf("\n--END\n");*/
566 }                               /* rosh_more_buf */
567
568 /* Page through a single file using the open file stream
569  *      fd      File Descriptor
570  */
571 void rosh_more_fd(int fd, int rows, int cols)
572 {
573     struct stat fdstat;
574     int status;
575     char *buf;
576     int bufpos;
577     int numrd;
578     FILE *f;
579
580     status = fstat(fd, &fdstat);
581     if (S_ISREG(fdstat.st_mode)) {
582         buf = malloc((int)fdstat.st_size);
583         if (buf != NULL) {
584             f = fdopen(fd, "r");
585             bufpos = 0;
586             numrd = fread(buf, 1, (int)fdstat.st_size, f);
587             while (numrd > 0) {
588                 bufpos += numrd;
589                 numrd = fread(buf + bufpos, 1,
590                               ((int)fdstat.st_size - bufpos), f);
591             }
592             fclose(f);
593             rosh_more_buf(buf, bufpos, rows, cols);
594         }
595     } else {
596     }
597
598 }                               /* rosh_more_fd */
599
600 /* Page through a file like the more command
601  *      cmdstr  command string to process
602  *      pwdstr  Present Working Directory string
603  *      ipwdstr Initial PWD
604  */
605 void rosh_more(const char *cmdstr, const char *pwdstr)
606         /*, const char *ipwdstr) */
607 {
608     int fd;
609     char filestr[ROSH_PATH_SZ + 1];
610     int cmdpos;
611     int rows, cols;
612
613     ROSH_DEBUG("CMD: '%s'\npwd: '%s'\n", cmdstr, pwdstr);
614     /* Initialization */
615     filestr[0] = 0;
616     cmdpos = 0;
617     if (getscreensize(1, &rows, &cols)) {
618         ROSH_DEBUG("getscreensize() fail; fall back\n");
619         ROSH_DEBUG("\tROWS='%d'\tCOLS='%d'\n", rows, cols);
620         /* If either fail, go under normal size, just in case */
621         if (!rows)
622             rows = 20;
623         if (!cols)
624             cols = 75;
625     }
626     ROSH_DEBUG("\tROWS='%d'\tCOLS='%d'\n", rows, cols);
627
628     /* skip the first word */
629     cmdpos = rosh_parse_sp_1(filestr, cmdstr, cmdpos);
630     cmdpos = rosh_parse_sp_1(filestr, cmdstr, cmdpos);
631     if (strlen(filestr) > 0) {
632         /* There is no need to mess up the console if we don't have a
633            file */
634         rosh_console_raw();
635         while (strlen(filestr) > 0) {
636             printf("--File = '%s'\n", filestr);
637             fd = open(filestr, O_RDONLY);
638             if (fd != -1) {
639                 rosh_more_fd(fd, rows, cols);
640                 close(fd);
641             } else {
642                 rosh_error(errno, "more", filestr);
643             }
644             cmdpos = rosh_parse_sp_1(filestr, cmdstr, cmdpos);
645         }
646         rosh_console_std();
647     }
648 }                               /* rosh_more */
649
650 /* Page a file with rewind
651  *      cmdstr  command string to process
652  *      pwdstr  Present Working Directory string
653  *      ipwdstr Initial PWD
654  */
655 void rosh_less(const char *cmdstr, const char *pwdstr)
656 {
657     printf("  less implemented as more (for now)\n");
658     rosh_more(cmdstr, pwdstr);
659 }                               /* rosh_less */
660
661 /* Show PWD
662  *      cmdstr  command string to process
663  *      pwdstr  Present Working Directory string
664  */
665 void rosh_pwd(const char *cmdstr, const char *pwdstr)
666 {
667     int istr;
668     ROSH_DEBUG("CMD: '%s'\npwd: '%s'\n", cmdstr, pwdstr);
669     printf("%s\n", pwdstr);
670     istr = htonl(*(int *)pwdstr);
671     ROSH_DEBUG("  --%08X\n", istr);
672 }                               /* rosh_pwd */
673
674 /* Run a boot string, calling syslinux_run_command
675  *      cmdstr  command string to process
676  *      pwdstr  Present Working Directory string
677  *      ipwdstr Initial PWD
678  */
679 void rosh_run(const char *cmdstr, const char *pwdstr, const char *ipwdstr)
680 {
681     int cmdpos;
682     char *cmdptr;
683     char istr[ROSH_CMD_SZ];     /* input command string */
684
685     cmdpos = 0;
686     ROSH_DEBUG("CMD: '%s'\npwd: '%s'\n", cmdstr, pwdstr);
687     /* skip the first word */
688     cmdpos = rosh_search_sp(cmdstr, cmdpos);
689     /* skip spaces */
690     cmdpos = rosh_search_nonsp(cmdstr, cmdpos);
691     cmdptr = (char *)(cmdstr + cmdpos);
692     printf("--run: '%s'\n", cmdptr);
693     /* //HERE--Reparse if pwdstr != ipwdstr; seems a little daunting as
694        detecting params vs filenames is difficult/impossible */
695     if (strcmp(pwdstr, ipwdstr) != 0) {
696         /* For now, just prompt for verification */
697         printf("  from directory '%s'? (y/N):", pwdstr);
698         fgets(istr, ROSH_CMD_SZ, stdin);
699         if ((istr[0] != 'y') && (istr[0] != 'Y')) {
700             printf("Aborting run\n");
701             return;
702         }
703         printf("Run anyways\n");
704     }
705     syslinux_run_command(cmdptr);
706 }                               /* rosh_run */
707
708 /* Process a single command string and call handling function
709  *      cmdstr  command string to process
710  *      pwdstr  Present Working Directory string
711  *      ipwdstr Initial Present Working Directory string
712  *      returns Whether to exit prompt
713  */
714 char rosh_command(const char *cmdstr, char *pwdstr, const char *ipwdstr)
715 {
716     char do_exit;
717     do_exit = false;
718     ROSH_DEBUG("--cmd:'%s'\n", cmdstr);
719     switch (cmdstr[0]) {
720     case 'e':
721     case 'E':
722     case 'q':
723     case 'Q':
724         do_exit = true;
725         break;
726     case 'c':
727     case 'C':                   /* run 'cd' 'cat' 'cfg' */
728         switch (cmdstr[1]) {
729         case 'a':
730         case 'A':
731             rosh_cat(cmdstr, pwdstr);
732             break;
733         case 'd':
734         case 'D':
735             rosh_cd(cmdstr, pwdstr, ipwdstr);
736             break;
737         case 'f':
738         case 'F':
739             rosh_cfg(cmdstr, pwdstr);
740             break;
741         default:
742             rosh_help(1);
743         }
744         break;
745     case 'd':
746     case 'D':                   /* run 'dir' */
747         rosh_dir(cmdstr, pwdstr);
748         break;
749     case 'h':
750     case 'H':
751     case '?':
752         rosh_help(2);
753         break;
754     case 'l':
755     case 'L':                   /* run 'ls' 'less' */
756         switch (cmdstr[1]) {
757         case 0:
758         case 's':
759         case 'S':
760             rosh_ls(cmdstr, pwdstr);
761             break;
762         case 'e':
763         case 'E':
764             rosh_less(cmdstr, pwdstr);
765             break;
766         default:
767             rosh_help(1);
768         }
769         break;
770     case 'm':
771     case 'M':
772         switch (cmdstr[1]) {
773         case 'a':
774         case 'A':
775             rosh_help(2);
776             break;
777         case 'o':
778         case 'O':
779             rosh_more(cmdstr, pwdstr);
780             break;
781         default:
782             rosh_help(1);
783         }
784         break;
785     case 'p':
786     case 'P':                   /* run 'pwd' */
787         rosh_pwd(cmdstr, pwdstr);
788         break;
789     case 'r':
790     case 'R':                   /* run 'run' */
791         rosh_run(cmdstr, pwdstr, ipwdstr);
792         break;
793     case 'v':
794     case 'V':
795         rosh_version();
796         break;
797     case 0:
798     case '\n':
799         break;
800     default:
801         rosh_help(1);
802     }                           /* switch(cmdstr[0]) */
803     return do_exit;
804 }                               /* rosh_command */
805
806 /* Process the prompt for commands as read from stdin and call rosh_command
807  * to process command line string
808  *      icmdstr Initial command line string
809  *      returns Exit status
810  */
811 int rosh_prompt(const char *icmdstr)
812 {
813     int rv;
814     char cmdstr[ROSH_CMD_SZ];
815     char pwdstr[ROSH_PATH_SZ + 1], ipwdstr[ROSH_PATH_SZ + 1];
816 /*      int numchar;
817 */ char do_exit;
818     char *c;
819
820     rv = 0;
821     do_exit = false;
822     strcpy(pwdstr, "/");
823     getcwd(pwdstr, ROSH_PATH_SZ + 1);
824     strcpy(ipwdstr, pwdstr);    /* Retain the original PWD */
825     if (icmdstr[0] != '\0')
826         do_exit = rosh_command(icmdstr, pwdstr, ipwdstr);
827     while (!(do_exit)) {
828         console_ansi_std();
829         printf("\nrosh: ");
830         /* Read a line from console */
831         fgets(cmdstr, ROSH_CMD_SZ, stdin);
832         /* remove newline from input string */
833         c = strchr(cmdstr, '\n');
834         *c = 0;
835         do_exit = rosh_command(cmdstr, pwdstr, ipwdstr);
836     }
837     if (strcmp(pwdstr, ipwdstr) != 0) {
838         /* Change directory to the original directory */
839         strcpy(cmdstr, "cd ");
840         strcpy(cmdstr + 3, ipwdstr);
841         rosh_cd(cmdstr, pwdstr, ipwdstr);
842     }
843     return rv;
844 }
845
846 int main(int argc, char *argv[])
847 {
848     int rv;
849     char cmdstr[ROSH_CMD_SZ];
850
851     /* Initialization */
852     rv = 0;
853     console_ansi_std();
854 //      console_ansi_raw();
855     if (argc != 1) {
856         rv = rosh_argcat(cmdstr, argc, argv, 1);
857     } else {
858         rosh_version();
859         cmdstr[0] = '\0';
860     }
861     rv = rosh_prompt(cmdstr);
862     printf("--Exiting '%s'\n", APP_NAME);
863     console_ansi_std();
864     return rv;
865 }