SimpleOS

LXR

Navigation



Site hébergé par : enix

The LXR Cross Referencer for SOS

source navigation ]
diff markup ]
identifier search ]
general search ]
 
 
Article:1 ] [ 2 ] [ 3 ] [ 4 ] [ 5 ] [ 6 ] [ 6.5 ] [ 7 ] [ 7.5 ] [ 8 ] [ 9 ] [ 9.5 ]

001 /* Copyright (C) 2005 Thomas Petazzoni, David Decotigny
002 
003    This program is free software; you can redistribute it and/or
004    modify it under the terms of the GNU General Public License
005    as published by the Free Software Foundation; either version 2
006    of the License, or (at your option) any later version.
007    
008    This program is distributed in the hope that it will be useful,
009    but WITHOUT ANY WARRANTY; without even the implied warranty of
010    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
011    GNU General Public License for more details.
012    
013    You should have received a copy of the GNU General Public License
014    along with this program; if not, write to the Free Software
015    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
016    USA. 
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  * @file shell.c
030  *
031  * Small shell.
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   /* Build initial tabulation */
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       /* Next iteration */
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   /* Activate echo and activate again canonical mode */
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   /* Desactivate echo and remove canonical mode */
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; /* father returns */
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    * This structure defines the structure of a partition entry
446    * (determined by the PC architecture)
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    * Offset of the partition table inside the 512-byte sector.
462    */
463 #define PART_TABLE_OFFSET 446
464 
465   /**
466    * The most common partition types. For a complete list, you can for
467    * example refer to
468    * http://www.win.tue.nl/~aeb/partitions/partition_types-1.html
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    * Converts a partition type to a string
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   /* We assume the block size is 512 bytes. The clean way would be to
505      have a BLKGETSIZE ioctl() on block devices */
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   /* Handle primary partitions */
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       /* When size is >= 1 Mb, display size in Mb, otherwise display
552          size in Kb */
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       /* When size is >= 1 Mb, display size in Mb, otherwise display
581          size in Kb */
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 }

source navigation ] diff markup ] identifier search ] general search ]