Run Nindent on com32/rosh/rosh.c
[people/sha0/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'    %8d %8d\n", d->dd_name, d->dd_fd,
432                        d->dd_sect);
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_mode) {
439                     case 16:
440                         ty = 'D';
441                         break;
442                     case 32:
443                         ty = 'F';
444                         break;
445                     default:
446                         ty = '*';
447                     }
448                     printf("@%8d:%8d:%4d ", (int)de->d_ino, (int)de->d_size,
449                            de->d_mode);
450 #endif /* DO_DEBUG */
451 //                                      printf("%s\n", de->d_name);
452                     printf("'%s'\n", de->d_name);
453 #ifdef DO_DEBUG
454 // inchar = fgetc(stdin);
455 // fgets(instr, ROSH_CMD_SZ, stdin);
456 #endif /* DO_DEBUG */
457                     free(de);
458                     de = readdir(d);
459 // if(filepos>15){      de = NULL;      printf("Force Break\n");}
460                 }
461                 printf("Dir.dd_fd: '%8d'\n", d->dd_fd);
462                 closedir(d);
463             } else {
464                 rosh_error(0, "dir:NULL", filestr);
465             }
466         } else {
467             rosh_error(errno, "dir_c32", filestr);
468         }
469 #else
470         rosh_error(errno, "dir", filestr);
471 #endif /* __COM32__ */
472     }
473 }                               /* rosh_dir_arg */
474
475 /* Simple directory listing based on cmdstr and pwdstr
476  *      cmdstr  command string to process
477  *      pwdstr  Present Working Directory string
478  */
479 void rosh_dir(const char *cmdstr, const char *pwdstr)
480 {
481     char filestr[ROSH_PATH_SZ + 1];
482     int cmdpos;                 /* Position within cmdstr */
483
484     ROSH_DEBUG("CMD: '%s'\npwd: '%s'\n", cmdstr, pwdstr);
485     /* Initialization */
486     filestr[0] = 0;
487     cmdpos = 0;
488     /* skip the first word */
489     cmdpos = rosh_parse_sp_1(filestr, cmdstr, cmdpos);
490     cmdpos = rosh_parse_sp_1(filestr, cmdstr, cmdpos);
491     /* If there are no real arguments, substitute PWD */
492     if (strlen(filestr) == 0)
493         strcpy(filestr, pwdstr);
494     while (strlen(filestr) > 0) {
495         rosh_dir_arg(filestr, pwdstr);
496         cmdpos = rosh_parse_sp_1(filestr, cmdstr, cmdpos);
497     }
498 }                               /* rosh_dir */
499
500 /* List Directory; Calls rosh_dir() for now.
501  *      cmdstr  command string to process
502  *      pwdstr  Present Working Directory string
503  */
504 void rosh_ls(const char *cmdstr, const char *pwdstr)
505 {
506     printf("  ls implemented as dir (for now)\n");
507     rosh_dir(cmdstr, pwdstr);
508 }                               /* rosh_ls */
509
510 /* Page through a buffer string
511  *      buf     Buffer to page through
512  */
513 void rosh_more_buf(char *buf, int buflen, int rows, int cols)
514 {
515     char *bufp, *bufeol;        /* Pointer to current and next end-of-line
516                                    position in buffer */
517     int bufpos, bufcnt;         /* current position, count characters */
518     char scrbuf[ROSH_SBUF_SZ];
519     int inc;
520     int i, numln;               /* Index, Number of lines */
521
522     bufpos = 0;
523     bufp = buf + bufpos;
524     bufeol = bufp;
525     numln = rows - 1;
526     printf("--(%d)\n", buflen);
527 // printf("--termIOS CONSTS: ");
528 // printf("ISIG=%08X ", ISIG);
529 // printf("ICANON=%08X ", ICANON);
530 // printf("ECHO=%08X ", ECHO);
531 // printf("=%08X", );
532 // printf("\n");
533     while (bufpos < buflen) {
534         for (i = 0; i < numln; i++) {
535             bufeol = strchr(bufeol, '\n');
536             if (bufeol == NULL) {
537                 bufeol = buf + buflen;
538                 i = numln;
539             } else {
540                 bufeol++;
541             }
542 // printf("--readln\n");
543         }
544         bufcnt = bufeol - bufp;
545         printf("--(%d/%d @%d)\n", bufcnt, buflen, bufpos);
546         memcpy(scrbuf, bufp, bufcnt);
547         scrbuf[bufcnt] = 0;
548         printf("%s", scrbuf);
549         bufp = bufeol;
550         bufpos += bufcnt;
551         if (bufpos == buflen)
552             break;
553         inc = rosh_getkey();
554         numln = 1;
555         switch (inc) {
556         case KEY_CTRL('c'):
557         case 'q':
558         case 'Q':
559             bufpos = buflen;
560             break;
561         case ' ':
562             numln = rows - 1;
563 //              default:
564         }
565     }
566 /*tcgetattr(0, &tio);
567 rosh_print_tc(&tio);
568 printf("\n--END\n");*/
569 }                               /* rosh_more_buf */
570
571 /* Page through a single file using the open file stream
572  *      fd      File Descriptor
573  */
574 void rosh_more_fd(int fd, int rows, int cols)
575 {
576     struct stat fdstat;
577     int status;
578     char *buf;
579     int bufpos;
580     int numrd;
581     FILE *f;
582
583     status = fstat(fd, &fdstat);
584     if (S_ISREG(fdstat.st_mode)) {
585         buf = malloc((int)fdstat.st_size);
586         if (buf != NULL) {
587             f = fdopen(fd, "r");
588             bufpos = 0;
589             numrd = fread(buf, 1, (int)fdstat.st_size, f);
590             while (numrd > 0) {
591                 bufpos += numrd;
592                 numrd = fread(buf + bufpos, 1,
593                               ((int)fdstat.st_size - bufpos), f);
594             }
595             fclose(f);
596             rosh_more_buf(buf, bufpos, rows, cols);
597         }
598     } else {
599     }
600
601 }                               /* rosh_more_fd */
602
603 /* Page through a file like the more command
604  *      cmdstr  command string to process
605  *      pwdstr  Present Working Directory string
606  *      ipwdstr Initial PWD
607  */
608 void rosh_more(const char *cmdstr, const char *pwdstr)
609         /*, const char *ipwdstr) */
610 {
611     int fd;
612     char filestr[ROSH_PATH_SZ + 1];
613     int cmdpos;
614     int rows, cols;
615
616     ROSH_DEBUG("CMD: '%s'\npwd: '%s'\n", cmdstr, pwdstr);
617     /* Initialization */
618     filestr[0] = 0;
619     cmdpos = 0;
620     if (getscreensize(1, &rows, &cols)) {
621         ROSH_DEBUG("getscreensize() fail; fall back\n");
622         ROSH_DEBUG("\tROWS='%d'\tCOLS='%d'\n", rows, cols);
623         /* If either fail, go under normal size, just in case */
624         if (!rows)
625             rows = 20;
626         if (!cols)
627             cols = 75;
628     }
629     ROSH_DEBUG("\tROWS='%d'\tCOLS='%d'\n", rows, cols);
630
631     /* skip the first word */
632     cmdpos = rosh_parse_sp_1(filestr, cmdstr, cmdpos);
633     cmdpos = rosh_parse_sp_1(filestr, cmdstr, cmdpos);
634     if (strlen(filestr) > 0) {
635         /* There is no need to mess up the console if we don't have a
636            file */
637         rosh_console_raw();
638         while (strlen(filestr) > 0) {
639             printf("--File = '%s'\n", filestr);
640             fd = open(filestr, O_RDONLY);
641             if (fd != -1) {
642                 rosh_more_fd(fd, rows, cols);
643                 close(fd);
644             } else {
645                 rosh_error(errno, "more", filestr);
646             }
647             cmdpos = rosh_parse_sp_1(filestr, cmdstr, cmdpos);
648         }
649         rosh_console_std();
650     }
651 }                               /* rosh_more */
652
653 /* Page a file with rewind
654  *      cmdstr  command string to process
655  *      pwdstr  Present Working Directory string
656  *      ipwdstr Initial PWD
657  */
658 void rosh_less(const char *cmdstr, const char *pwdstr)
659 {
660     printf("  less implemented as more (for now)\n");
661     rosh_more(cmdstr, pwdstr);
662 }                               /* rosh_less */
663
664 /* Show PWD
665  *      cmdstr  command string to process
666  *      pwdstr  Present Working Directory string
667  */
668 void rosh_pwd(const char *cmdstr, const char *pwdstr)
669 {
670     int istr;
671     ROSH_DEBUG("CMD: '%s'\npwd: '%s'\n", cmdstr, pwdstr);
672     printf("%s\n", pwdstr);
673     istr = htonl(*(int *)pwdstr);
674     ROSH_DEBUG("  --%08X\n", istr);
675 }                               /* rosh_pwd */
676
677 /* Run a boot string, calling syslinux_run_command
678  *      cmdstr  command string to process
679  *      pwdstr  Present Working Directory string
680  *      ipwdstr Initial PWD
681  */
682 void rosh_run(const char *cmdstr, const char *pwdstr, const char *ipwdstr)
683 {
684     int cmdpos;
685     char *cmdptr;
686     char istr[ROSH_CMD_SZ];     /* input command string */
687
688     cmdpos = 0;
689     ROSH_DEBUG("CMD: '%s'\npwd: '%s'\n", cmdstr, pwdstr);
690     /* skip the first word */
691     cmdpos = rosh_search_sp(cmdstr, cmdpos);
692     /* skip spaces */
693     cmdpos = rosh_search_nonsp(cmdstr, cmdpos);
694     cmdptr = (char *)(cmdstr + cmdpos);
695     printf("--run: '%s'\n", cmdptr);
696     /* //HERE--Reparse if pwdstr != ipwdstr; seems a little daunting as
697        detecting params vs filenames is difficult/impossible */
698     if (strcmp(pwdstr, ipwdstr) != 0) {
699         /* For now, just prompt for verification */
700         printf("  from directory '%s'? (y/N):", pwdstr);
701         fgets(istr, ROSH_CMD_SZ, stdin);
702         if ((istr[0] != 'y') && (istr[0] != 'Y')) {
703             printf("Aborting run\n");
704             return;
705         }
706         printf("Run anyways\n");
707     }
708     syslinux_run_command(cmdptr);
709 }                               /* rosh_run */
710
711 /* Process a single command string and call handling function
712  *      cmdstr  command string to process
713  *      pwdstr  Present Working Directory string
714  *      ipwdstr Initial Present Working Directory string
715  *      returns Whether to exit prompt
716  */
717 char rosh_command(const char *cmdstr, char *pwdstr, const char *ipwdstr)
718 {
719     char do_exit;
720     do_exit = false;
721     ROSH_DEBUG("--cmd:'%s'\n", cmdstr);
722     switch (cmdstr[0]) {
723     case 'e':
724     case 'E':
725     case 'q':
726     case 'Q':
727         do_exit = true;
728         break;
729     case 'c':
730     case 'C':                   /* run 'cd' 'cat' 'cfg' */
731         switch (cmdstr[1]) {
732         case 'a':
733         case 'A':
734             rosh_cat(cmdstr, pwdstr);
735             break;
736         case 'd':
737         case 'D':
738             rosh_cd(cmdstr, pwdstr, ipwdstr);
739             break;
740         case 'f':
741         case 'F':
742             rosh_cfg(cmdstr, pwdstr);
743             break;
744         default:
745             rosh_help(1);
746         }
747         break;
748     case 'd':
749     case 'D':                   /* run 'dir' */
750         rosh_dir(cmdstr, pwdstr);
751         break;
752     case 'h':
753     case 'H':
754     case '?':
755         rosh_help(2);
756         break;
757     case 'l':
758     case 'L':                   /* run 'ls' 'less' */
759         switch (cmdstr[1]) {
760         case 0:
761         case 's':
762         case 'S':
763             rosh_ls(cmdstr, pwdstr);
764             break;
765         case 'e':
766         case 'E':
767             rosh_less(cmdstr, pwdstr);
768             break;
769         default:
770             rosh_help(1);
771         }
772         break;
773     case 'm':
774     case 'M':
775         switch (cmdstr[1]) {
776         case 'a':
777         case 'A':
778             rosh_help(2);
779             break;
780         case 'o':
781         case 'O':
782             rosh_more(cmdstr, pwdstr);
783             break;
784         default:
785             rosh_help(1);
786         }
787         break;
788     case 'p':
789     case 'P':                   /* run 'pwd' */
790         rosh_pwd(cmdstr, pwdstr);
791         break;
792     case 'r':
793     case 'R':                   /* run 'run' */
794         rosh_run(cmdstr, pwdstr, ipwdstr);
795         break;
796     case 'v':
797     case 'V':
798         rosh_version();
799         break;
800     case 0:
801     case '\n':
802         break;
803     default:
804         rosh_help(1);
805     }                           /* switch(cmdstr[0]) */
806     return do_exit;
807 }                               /* rosh_command */
808
809 /* Process the prompt for commands as read from stdin and call rosh_command
810  * to process command line string
811  *      icmdstr Initial command line string
812  *      returns Exit status
813  */
814 int rosh_prompt(const char *icmdstr)
815 {
816     int rv;
817     char cmdstr[ROSH_CMD_SZ];
818     char pwdstr[ROSH_PATH_SZ + 1], ipwdstr[ROSH_PATH_SZ + 1];
819 /*      int numchar;
820 */ char do_exit;
821     char *c;
822
823     rv = 0;
824     do_exit = false;
825     strcpy(pwdstr, "/");
826     getcwd(pwdstr, ROSH_PATH_SZ + 1);
827     strcpy(ipwdstr, pwdstr);    /* Retain the original PWD */
828     if (icmdstr[0] != '\0')
829         do_exit = rosh_command(icmdstr, pwdstr, ipwdstr);
830     while (!(do_exit)) {
831         console_ansi_std();
832         printf("\nrosh: ");
833         /* Read a line from console */
834         fgets(cmdstr, ROSH_CMD_SZ, stdin);
835         /* remove newline from input string */
836         c = strchr(cmdstr, '\n');
837         *c = 0;
838         do_exit = rosh_command(cmdstr, pwdstr, ipwdstr);
839     }
840     if (strcmp(pwdstr, ipwdstr) != 0) {
841         /* Change directory to the original directory */
842         strcpy(cmdstr, "cd ");
843         strcpy(cmdstr + 3, ipwdstr);
844         rosh_cd(cmdstr, pwdstr, ipwdstr);
845     }
846     return rv;
847 }
848
849 int main(int argc, char *argv[])
850 {
851     int rv;
852     char cmdstr[ROSH_CMD_SZ];
853
854     /* Initialization */
855     rv = 0;
856     console_ansi_std();
857 //      console_ansi_raw();
858     if (argc != 1) {
859         rv = rosh_argcat(cmdstr, argc, argv, 1);
860     } else {
861         rosh_version();
862         cmdstr[0] = '\0';
863     }
864     rv = rosh_prompt(cmdstr);
865     printf("--Exiting '%s'\n", APP_NAME);
866     console_ansi_std();
867     return rv;
868 }