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