001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019 #include <crt.h>
020 #include <libc.h>
021 #include <stdarg.h>
022 #include <string.h>
023 #include <debug.h>
024 #include <drivers/devices.h>
025
026 #include "fstest_utils.h"
027
028
029
030
031
032
033
034 static int shell_uname (int argc, char *argv[])
035 {
036 printf ("SOS article 9.5\n");
037 return 0;
038 }
039
040 static void shell_ls_internal(int detailed, int recursive, int reclevel)
041 {
042 char tab[256], *c;
043 int i;
044 struct dirent * dirent;
045 DIR * here;
046
047 here = opendir(".");
048 if (! here)
049 return;
050
051
052 if (recursive)
053 {
054 for (c = tab, i = 0 ; (i < reclevel) && (i < sizeof(tab)/2) ; i++)
055 {
056 *c++ = ' ';
057 *c++ = ' ';
058 }
059 *c++ = '\0';
060 }
061 else
062 *tab = '\0';
063
064 while ((dirent = readdir(here)) != NULL)
065 {
066 char entrychar;
067 char * entrysuffix;
068
069 switch(dirent->type)
070 {
071 case S_IFREG: entrychar='-'; entrysuffix=""; break;
072 case S_IFDIR: entrychar='d'; entrysuffix="/"; break;
073 case S_IFLNK: entrychar='l'; entrysuffix="@"; break;
074 case S_IFCHR: entrychar='c'; entrysuffix=NULL; break;
075 case S_IFBLK: entrychar='b'; entrysuffix=NULL; break;
076 default: entrychar='?'; entrysuffix="?!?"; break;
077 }
078
079 if (detailed)
080 {
081 struct stat stat;
082 char target_name[SOS_FS_DIRENT_NAME_MAXLEN];
083 char majorminor[24];
084
085 if (lstat(dirent->name, & stat))
086 continue;
087
088 *target_name = '\0';
089 if (stat.st_type == S_IFLNK)
090 {
091 int fd = open(dirent->name, O_RDONLY | O_NOFOLLOW);
092 if (fd >= 0)
093 {
094 int len = read(fd, target_name, sizeof(target_name) - 1);
095 if (len < 0)
096 *target_name='\0';
097 else
098 target_name[len] = '\0';
099 close(fd);
100 }
101 }
102 else if ( (stat.st_type == S_IFCHR) || (stat.st_type == S_IFBLK) )
103 {
104 snprintf(majorminor, sizeof(majorminor), " %d,%d",
105 stat.st_rdev_major, stat.st_rdev_minor);
106 entrysuffix = majorminor;
107 }
108
109 printf("%s%c%c%c%c %lld %s%s%s%s (location=0x%llx)\n",
110 tab, entrychar,
111 (stat.st_access_rights&S_IRUSR)?'r':'-',
112 (stat.st_access_rights&S_IWUSR)?'w':'-',
113 (stat.st_access_rights&S_IXUSR)?'x':'-',
114 stat.st_size,
115 dirent->name,
116 entrysuffix,
117 (stat.st_type==S_IFLNK)?" -> ":"",
118 target_name,
119 stat.st_storage_location);
120 }
121 else
122 printf("%s%s%s\n",
123 tab, dirent->name, entrysuffix);
124
125
126 if (recursive)
127 {
128 int fd_here = dirfd(here);
129 if (chdir(dirent->name))
130 continue;
131 shell_ls_internal(detailed, recursive, reclevel+1);
132 if(fchdir(fd_here))
133 {
134 closedir(here);
135 return;
136 }
137 }
138 }
139 closedir(here);
140 }
141
142 static void shell_ls(const char * path, int detailed, int recursive)
143 {
144 int fd_here = open(".", O_RDONLY | O_DIRECTORY);
145 if (fd_here < 0)
146 return;
147
148 if (chdir(path))
149 {
150 close(fd_here);
151 return;
152 }
153
154 shell_ls_internal(detailed, recursive, 1);
155
156 fchdir(fd_here);
157 close(fd_here);
158 }
159
160 static int shell_touch (int argc, char *argv[])
161 {
162 return creat (argv[1], S_IRUSR | S_IWUSR);
163 }
164
165 static int shell_mkdir (int argc, char *argv[])
166 {
167 return mkdir (argv[1], S_IRUSR | S_IWUSR | S_IXUSR);
168 }
169
170 static int shell_cat (int argc, char *argv[])
171 {
172 int fd;
173 char buf[4096];
174 int len;
175
176 fd = open (argv[1], O_RDONLY);
177 if (fd < 0) {
178 printf ("Cannot open '%s'\n", argv[1]);
179 return -1;
180 }
181
182 while (1)
183 {
184 len = read (fd, buf, sizeof(buf)-1);
185 if (len <= 0)
186 break;
187 buf[len] = '\0';
188
189 printf ("%s", buf);
190 }
191
192 close (fd);
193 return 0;
194 }
195
196 static int shell_edit (int argc, char *argv[])
197 {
198 int fd;
199 char buf[16];
200 int len;
201
202 fd = open (argv[1], O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
203 if (fd < 0) {
204 printf ("Cannot create '%s': %d\n", argv[1], fd);
205 return -1;
206 }
207
208
209 ioctl (0, SOS_IOCTL_TTY_SETPARAM, SOS_IOCTLPARAM_TTY_ECHO);
210 ioctl (0, SOS_IOCTL_TTY_SETPARAM, SOS_IOCTLPARAM_TTY_CANON);
211
212 while (1)
213 {
214 len = read (0, buf, sizeof(buf));
215 if (len <= 1)
216 break;
217
218 bochs_printf ("Writing %d bytes\n", len);
219 len = write (fd, buf, len);
220 if (len <= 0) {
221 printf ("Cannot write to '%s': %d\n", argv[1], len);
222 break;
223 }
224 }
225
226
227 ioctl (0, SOS_IOCTL_TTY_RESETPARAM, SOS_IOCTLPARAM_TTY_ECHO);
228 ioctl (0, SOS_IOCTL_TTY_RESETPARAM, SOS_IOCTLPARAM_TTY_CANON);
229
230 close (fd);
231 return 0;
232 }
233
234 static int shell_hexdump (int argc, char *argv[])
235 {
236 int fd;
237 char buf[16];
238 int count = 0;
239 int len;
240
241 fd = open (argv[1], O_RDONLY);
242 if (fd < 0) {
243 printf ("Cannot open '%s': %d\n", argv[1], fd);
244 return -1;
245 }
246
247 while (1)
248 {
249 int i;
250
251 len = read (fd, buf, sizeof(buf));
252 if (len <= 0)
253 break;
254
255 if (count < 0x10)
256 printf ("00%x ", count);
257 else if (count < 0x100)
258 printf ("0%x ", count);
259 else if (count < 0x1000)
260 printf ("%x ", count);
261
262 for (i = 0; i < len; i++)
263 {
264 if (buf[i] < 0x10)
265 printf ("0%x ", buf[i]);
266 else
267 printf ("%x ", buf[i]);
268 }
269
270 printf ("\n");
271
272 count += len;
273 }
274
275 close (fd);
276 return 0;
277 }
278
279 static int shell_test (int argc, char *argv[])
280 {
281 int i;
282 for (i = 0; i < argc; i++)
283 {
284 printf ("argv[%d] = %s\n", i, argv[i]);
285 }
286 return 0;
287 }
288
289
290 static int shell_spawn (int argc, char *argv[])
291 {
292 int retval;
293 if (argc < 2)
294 {
295 printf("Usage: spawn prog_name\n");
296 return -1;
297 }
298 retval = fork();
299 if (retval > 0)
300 return 0;
301 if (retval < 0)
302 {
303 printf("Could not fork (%d)\n", retval);
304 return -1;
305 }
306 retval = exec(argv[1]);
307 printf("Could not exec %s: error %d\n", argv[1], retval);
308 return 0;
309 }
310
311
312 static int shell_rm (int argc, char *argv[])
313 {
314 int i;
315
316 for (i = 1; i < argc; i++)
317 {
318 int ret;
319
320 ret = unlink (argv[i]);
321 if (ret < 0)
322 printf ("Cannot remove '%s', %d\n", argv[i], ret);
323 }
324
325 return 0;
326 }
327
328
329 static int shell_dd (int argc, char *argv[])
330 {
331 char *infile = NULL;
332 char *outfile = NULL;
333 long bs = 1;
334 long count = -1;
335 int i;
336 int infd, outfd;
337 char *buffer;
338 int ret;
339
340 for (i = 1; i < argc; i++)
341 {
342 if (strncmp (argv[i], "if=", 3) == 0)
343 infile = argv[i] + 3;
344 else if (strncmp (argv[i], "of=", 3) == 0)
345 outfile = argv[i] + 3;
346 else if (strncmp (argv[i], "bs=", 3) == 0)
347 {
348 char *tmp = argv[i] + 3;
349 char *multiplier_char;
350 int multiplier = 1;
351 int j;
352
353 multiplier_char = & tmp[strlen(tmp)-1];
354 if (*multiplier_char == 'k' ||
355 *multiplier_char == 'K')
356 {
357 multiplier = 1024;
358 *multiplier_char = '\0';
359 }
360 else if (*multiplier_char == 'm' ||
361 *multiplier_char == 'M')
362 {
363 multiplier = 1024 * 1024;
364 *multiplier_char = '\0';
365 }
366
367 for (j = 0; j < strlen(tmp); j++)
368 if (! isdigit(tmp[j]))
369 {
370 printf ("Syntax error in block size\n");
371 return -1;
372 }
373
374 bs = atol(tmp) * multiplier;
375 }
376 else if (strncmp (argv[i], "count=", 6) == 0)
377 {
378 char *tmp = argv[i] + 6;
379 int j;
380
381 for (j = 0; j < strlen(tmp); j++)
382 if (! isdigit(tmp[j]))
383 {
384 printf ("Syntax error in block count\n");
385 return -1;
386 }
387
388 count = atol(tmp);
389 }
390 else
391 {
392 printf ("Syntax error\n");
393 return -1;
394 }
395 }
396
397 infd = open(infile, O_RDONLY);
398 if (infd < 0)
399 {
400 printf ("Cannot open '%s', %d\n", infile, infd);
401 return infd;
402 }
403
404 outfd = open(outfile, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
405 if (outfd < 0)
406 {
407 printf ("Cannot open '%s', %d\n", outfile, outfd);
408 return outfd;
409 }
410
411 buffer = malloc (bs);
412 if (! buffer)
413 return -1;
414
415 for (i = 0; (count < 0) || (i < count) ; i++)
416 {
417 int len;
418
419 ret = read (infd, buffer, bs);
420 if (ret < 0)
421 {
422 printf ("Input error from '%s' at %d\n", infile, i);
423 return -1;
424 }
425 if (ret == 0)
426 break;
427
428 len = ret;
429
430 ret = write (outfd, buffer, len);
431 if (ret != len)
432 {
433 printf ("Output error to '%s' at %d (%d)\n", outfile, i, ret);
434 return -1;
435 }
436 }
437
438 return 0;
439 }
440
441
442 static int shell_partdump (int argc, char *argv[])
443 {
444
445
446
447
448 struct partition_entry
449 {
450 unsigned char active;
451 unsigned char start_dl;
452 unsigned short start_cylinder;
453 unsigned char type;
454 unsigned char end_dl;
455 unsigned short end_cylinder;
456 unsigned long lba;
457 unsigned long size;
458 };
459
460
461
462
463 #define PART_TABLE_OFFSET 446
464
465
466
467
468
469
470 #define PART_TYPE_EXTENDED 0x5
471 #define PART_TYPE_FAT16_1 0xe
472 #define PART_TYPE_FAT16_2 0x6
473 #define PART_TYPE_FAT32_1 0xb
474 #define PART_TYPE_FAT32_2 0xc
475 #define PART_TYPE_LINUX_SWAP 0x82
476 #define PART_TYPE_LINUX 0x83
477
478
479
480
481 const char *
482 sos_part_type_str (unsigned int type)
483 {
484 switch (type)
485 {
486 case PART_TYPE_EXTENDED:
487 return "Extended";
488 case PART_TYPE_FAT16_1:
489 case PART_TYPE_FAT16_2:
490 return "FAT16";
491 case PART_TYPE_FAT32_1:
492 case PART_TYPE_FAT32_2:
493 return "FAT32";
494 case PART_TYPE_LINUX_SWAP:
495 return "Linux Swap";
496 case PART_TYPE_LINUX:
497 return "Linux";
498 default:
499 return "Unknown";
500 }
501 }
502
503 int fd;
504
505
506 #define BLKSIZE 512
507 char buffer[BLKSIZE];
508 int ret;
509 struct partition_entry *part_entry;
510 int partnum;
511 unsigned int extstart = 0, extsup = 0;
512
513 if (argc != 2)
514 {
515 printf ("Usage: partdump /dev/device\n");
516 return -1;
517 }
518
519 fd = open (argv[1], O_RDONLY);
520 if (fd < 0)
521 {
522 printf ("Cannot open '%s', %d\n", argv[1], fd);
523 return -1;
524 }
525
526 ret = read (fd, buffer, sizeof(buffer));
527 if (ret != sizeof(buffer))
528 {
529 printf ("Read error in '%s', %d\n", argv[1], fd);
530 return -1;
531 }
532
533 part_entry = (struct partition_entry *) (buffer + PART_TABLE_OFFSET);
534
535 printf ("Partitions in %s:\n", argv[1]);
536
537
538 for (partnum = 0; partnum < 4; partnum++)
539 {
540 if (part_entry [partnum].size == 0)
541 continue;
542
543 if (part_entry [partnum].type == PART_TYPE_EXTENDED)
544 {
545 if (extstart != 0)
546 printf ("Warning: two extended partitions detected\n");
547 extstart = part_entry [partnum].lba;
548 continue;
549 }
550
551
552
553 if (part_entry[partnum].size * BLKSIZE >= (1024*1024))
554 printf (" - %s%d (primary, %lu Mb, %s)\n", argv[1], partnum+1,
555 (part_entry[partnum].size * BLKSIZE >> 20),
556 sos_part_type_str(part_entry[partnum].type));
557 else
558 printf (" - %s%d (primary, %lu Kb, %s)\n", argv[1], partnum+1,
559 (part_entry[partnum].size * BLKSIZE >> 10),
560 sos_part_type_str(part_entry[partnum].type));
561 }
562
563 while (extstart != 0)
564 {
565 ret = lseek (fd, (extstart + extsup) * BLKSIZE, SEEK_SET);
566 if (ret != (extstart + extsup) * BLKSIZE)
567 {
568 printf ("Cannot seek at position %d in '%s', %d\n",
569 (extstart + extsup) * BLKSIZE, argv[1], ret);
570 return -1;
571 }
572
573 ret = read (fd, buffer, BLKSIZE);
574 if (ret != BLKSIZE)
575 {
576 printf ("Read error in '%s', %d\n", argv[1], ret);
577 break;
578 }
579
580
581
582 if (part_entry[0].size * BLKSIZE >= (1024*1024))
583 printf (" - %s%d (logical volume, %lu Mb, %s)\n", argv[1], partnum+1,
584 (part_entry[0].size * BLKSIZE >> 20),
585 sos_part_type_str(part_entry[0].type));
586 else
587 printf (" - %s%d (logical volume, %lu Kb, %s)\n", argv[1], partnum+1,
588 (part_entry[0].size * BLKSIZE >> 10),
589 sos_part_type_str(part_entry[0].type));
590
591 extsup = part_entry[1].lba;
592 partnum ++;
593 if (extsup == 0)
594 break;
595 }
596
597 return 0;
598 }
599
600
601 void command_exec (char * cmd)
602 {
603 char *c;
604 int argc = 1, i;
605 char **argv;
606
607 for (c = cmd; *c != '\0'; c++)
608 if (*c == ' ')
609 argc++;
610
611 argv = malloc (argc * sizeof(char*));
612 if (argv == NULL)
613 return;
614
615 for (i = 0, c = cmd; i < argc; i++)
616 {
617 argv[i] = c;
618 while (*c != ' ' && *c != '\0')
619 c++;
620 *c = '\0';
621 c++;
622 }
623
624 if (! strcmp (argv[0], "uname"))
625 shell_uname(argc, argv);
626
627 else if (! strcmp (argv[0], "ls"))
628 {
629 if (argv[1])
630 shell_ls (argv[1], 1, 0);
631 else
632 shell_ls (".", 1, 0);
633 }
634
635 else if (! strcmp (argv[0], "touch"))
636 {
637 shell_touch (argc, argv);
638 }
639
640 else if (! strcmp (argv[0], "mkdir"))
641 {
642 shell_mkdir (argc, argv);
643 }
644
645 else if (! strcmp (argv[0], "cat"))
646 {
647 shell_cat (argc, argv);
648 }
649
650 else if (! strcmp (argv[0], "edit"))
651 {
652 shell_edit (argc, argv);
653 }
654
655 else if (! strcmp (argv[0], "hexdump"))
656 {
657 shell_hexdump (argc, argv);
658 }
659 else if (! strcmp (argv[0], "test"))
660 {
661 shell_test (argc, argv);
662 }
663 else if (! strcmp (argv[0], "spawn"))
664 {
665 shell_spawn (argc, argv);
666 }
667 else if (! strcmp (argv[0], "dd"))
668 {
669 shell_dd (argc, argv);
670 }
671 else if (! strcmp (argv[0], "rm"))
672 {
673 shell_rm (argc, argv);
674 }
675 else if (! strcmp (argv[0], "partdump"))
676 {
677 shell_partdump (argc, argv);
678 }
679
680 else
681 printf ("Command not found\n");
682
683 free (argv);
684 }
685
686 int main(void)
687 {
688 char buffer[256];
689 int i;
690 char chr;
691
692 ioctl (0, SOS_IOCTL_TTY_RESETPARAM, SOS_IOCTLPARAM_TTY_CANON);
693
694 while (1)
695 {
696 memset (buffer, 0, sizeof(buffer));
697 i = 0;
698 printf ("$ ");
699
700 while (1)
701 {
702 read (0, & chr, 1);
703 if (chr == '\n')
704 {
705 buffer[i] = '\0';
706 printf ("\n");
707 if (i != 0)
708 command_exec (buffer);
709 break;
710 }
711 else if (chr == '\b')
712 {
713 if (i > 0)
714 {
715 i--;
716 printf ("\b");
717 }
718 }
719
720 else if (i < 256)
721 {
722 buffer[i++] = chr;
723 printf ("%c", chr);
724 }
725 else
726 printf ("%c", chr);
727 }
728 }
729
730 return 0;
731 }