1002 lines
21 KiB
C
1002 lines
21 KiB
C
/* Copyright (C) 2005 Thomas Petazzoni, David Decotigny
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License
|
|
as published by the Free Software Foundation; either version 2
|
|
of the License, or (at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
|
USA.
|
|
*/
|
|
|
|
#include <crt.h>
|
|
#include <libc.h>
|
|
#include <stdarg.h>
|
|
#include <string.h>
|
|
#include <debug.h>
|
|
#include <drivers/devices.h>
|
|
|
|
#include "fstest_utils.h"
|
|
|
|
/**
|
|
* @file shell.c
|
|
*
|
|
* Small shell.
|
|
*/
|
|
|
|
static int shell_uname (int argc, char *argv[])
|
|
{
|
|
printf ("SOS article 10\n");
|
|
return 0;
|
|
}
|
|
|
|
static void shell_ls_internal(int detailed, int recursive, int reclevel)
|
|
{
|
|
char tab[256], *c;
|
|
int i;
|
|
struct dirent * dirent;
|
|
DIR * here;
|
|
|
|
here = opendir(".");
|
|
if (! here)
|
|
return;
|
|
|
|
/* Build initial tabulation */
|
|
if (recursive)
|
|
{
|
|
for (c = tab, i = 0 ; (i < reclevel) && (i < sizeof(tab)/2) ; i++)
|
|
{
|
|
*c++ = ' ';
|
|
*c++ = ' ';
|
|
}
|
|
*c++ = '\0';
|
|
}
|
|
else
|
|
*tab = '\0';
|
|
|
|
while ((dirent = readdir(here)) != NULL)
|
|
{
|
|
char entrychar;
|
|
char * entrysuffix;
|
|
|
|
switch(dirent->type)
|
|
{
|
|
case S_IFREG: entrychar='-'; entrysuffix=""; break;
|
|
case S_IFDIR: entrychar='d'; entrysuffix="/"; break;
|
|
case S_IFLNK: entrychar='l'; entrysuffix="@"; break;
|
|
case S_IFCHR: entrychar='c'; entrysuffix=NULL; break;
|
|
case S_IFBLK: entrychar='b'; entrysuffix=NULL; break;
|
|
default: entrychar='?'; entrysuffix="?!?"; break;
|
|
}
|
|
|
|
if (detailed)
|
|
{
|
|
struct stat stat;
|
|
char target_name[SOS_FS_DIRENT_NAME_MAXLEN];
|
|
char majorminor[24];
|
|
|
|
if (lstat(dirent->name, & stat))
|
|
continue;
|
|
|
|
*target_name = '\0';
|
|
if (stat.st_type == S_IFLNK)
|
|
{
|
|
int fd = open(dirent->name, O_RDONLY | O_NOFOLLOW);
|
|
if (fd >= 0)
|
|
{
|
|
int len = read(fd, target_name, sizeof(target_name) - 1);
|
|
if (len < 0)
|
|
*target_name='\0';
|
|
else
|
|
target_name[len] = '\0';
|
|
close(fd);
|
|
}
|
|
}
|
|
else if ( (stat.st_type == S_IFCHR) || (stat.st_type == S_IFBLK) )
|
|
{
|
|
snprintf(majorminor, sizeof(majorminor), " %d,%d",
|
|
stat.st_rdev_major, stat.st_rdev_minor);
|
|
entrysuffix = majorminor;
|
|
}
|
|
|
|
printf("%s%c%c%c%c %lld %s%s%s%s (location=0x%llx)\n",
|
|
tab, entrychar,
|
|
(stat.st_access_rights&S_IRUSR)?'r':'-',
|
|
(stat.st_access_rights&S_IWUSR)?'w':'-',
|
|
(stat.st_access_rights&S_IXUSR)?'x':'-',
|
|
stat.st_size,
|
|
dirent->name,
|
|
entrysuffix,
|
|
(stat.st_type==S_IFLNK)?" -> ":"",
|
|
target_name,
|
|
stat.st_storage_location);
|
|
}
|
|
else
|
|
printf("%s%s%s\n",
|
|
tab, dirent->name, entrysuffix);
|
|
|
|
/* Next iteration */
|
|
if (recursive)
|
|
{
|
|
int fd_here = dirfd(here);
|
|
if (chdir(dirent->name))
|
|
continue;
|
|
shell_ls_internal(detailed, recursive, reclevel+1);
|
|
if(fchdir(fd_here))
|
|
{
|
|
closedir(here);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
closedir(here);
|
|
}
|
|
|
|
static void shell_ls(const char * path, int detailed, int recursive)
|
|
{
|
|
int fd_here = open(".", O_RDONLY | O_DIRECTORY);
|
|
if (fd_here < 0)
|
|
return;
|
|
|
|
if (chdir(path))
|
|
{
|
|
close(fd_here);
|
|
return;
|
|
}
|
|
|
|
shell_ls_internal(detailed, recursive, 1);
|
|
|
|
fchdir(fd_here);
|
|
close(fd_here);
|
|
}
|
|
|
|
static int shell_chdir(int argc, char *argv[])
|
|
{
|
|
int ret;
|
|
|
|
ret = chdir(argv[1]);
|
|
|
|
if (ret < 0)
|
|
printf("Cannot chdir '%s': %d\n", argv[1], ret);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int shell_touch (int argc, char *argv[])
|
|
{
|
|
return creat (argv[1], S_IRUSR | S_IWUSR);
|
|
}
|
|
|
|
static int shell_mkdir (int argc, char *argv[])
|
|
{
|
|
int retval;
|
|
|
|
retval = mkdir (argv[1], S_IRUSR | S_IWUSR | S_IXUSR);
|
|
|
|
if (retval != 0)
|
|
printf("Cannot mkdir %s (%d)\n", argv[1], retval);
|
|
return retval;
|
|
}
|
|
|
|
static int shell_rmdir (int argc, char *argv[])
|
|
{
|
|
int ret;
|
|
|
|
ret = rmdir (argv[1]);
|
|
|
|
if (ret < 0)
|
|
printf("Cannot rmdir '%s': %d\n", argv[1], ret);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int shell_cat (int argc, char *argv[])
|
|
{
|
|
int fd;
|
|
char buf[4096];
|
|
int len;
|
|
|
|
fd = open (argv[1], O_RDONLY);
|
|
if (fd < 0) {
|
|
printf ("Cannot open '%s'\n", argv[1]);
|
|
return -1;
|
|
}
|
|
|
|
while (1)
|
|
{
|
|
len = read (fd, buf, sizeof(buf)-1);
|
|
if (len <= 0)
|
|
break;
|
|
buf[len] = '\0';
|
|
|
|
printf ("%s", buf);
|
|
}
|
|
|
|
close (fd);
|
|
return 0;
|
|
}
|
|
|
|
static int shell_edit (int argc, char *argv[])
|
|
{
|
|
int fd;
|
|
char buf[16];
|
|
int len;
|
|
|
|
fd = open (argv[1], O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
|
|
if (fd < 0) {
|
|
printf ("Cannot create '%s': %d\n", argv[1], fd);
|
|
return -1;
|
|
}
|
|
|
|
/* Activate echo and activate again canonical mode */
|
|
ioctl (0, SOS_IOCTL_TTY_SETPARAM, SOS_IOCTLPARAM_TTY_ECHO);
|
|
ioctl (0, SOS_IOCTL_TTY_SETPARAM, SOS_IOCTLPARAM_TTY_CANON);
|
|
|
|
while (1)
|
|
{
|
|
len = read (0, buf, sizeof(buf));
|
|
if (len <= 1)
|
|
break;
|
|
|
|
bochs_printf ("Writing %d bytes\n", len);
|
|
len = write (fd, buf, len);
|
|
if (len <= 0) {
|
|
printf ("Cannot write to '%s': %d\n", argv[1], len);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Desactivate echo and remove canonical mode */
|
|
ioctl (0, SOS_IOCTL_TTY_RESETPARAM, SOS_IOCTLPARAM_TTY_ECHO);
|
|
ioctl (0, SOS_IOCTL_TTY_RESETPARAM, SOS_IOCTLPARAM_TTY_CANON);
|
|
|
|
close (fd);
|
|
return 0;
|
|
}
|
|
|
|
static int shell_hexdump (int argc, char *argv[])
|
|
{
|
|
int fd;
|
|
char buf[16];
|
|
int count = 0;
|
|
int len;
|
|
|
|
fd = open (argv[1], O_RDONLY);
|
|
if (fd < 0) {
|
|
printf ("Cannot open '%s': %d\n", argv[1], fd);
|
|
return -1;
|
|
}
|
|
|
|
while (1)
|
|
{
|
|
int i;
|
|
|
|
len = read (fd, buf, sizeof(buf));
|
|
if (len <= 0)
|
|
break;
|
|
|
|
if (count < 0x10)
|
|
printf ("00%x ", count);
|
|
else if (count < 0x100)
|
|
printf ("0%x ", count);
|
|
else if (count < 0x1000)
|
|
printf ("%x ", count);
|
|
|
|
for (i = 0; i < len; i++)
|
|
{
|
|
if (buf[i] < 0x10)
|
|
printf ("0%x ", buf[i]);
|
|
else
|
|
printf ("%x ", buf[i]);
|
|
}
|
|
|
|
printf ("\n");
|
|
|
|
count += len;
|
|
}
|
|
|
|
close (fd);
|
|
return 0;
|
|
}
|
|
|
|
static int shell_test (int argc, char *argv[])
|
|
{
|
|
int i;
|
|
for (i = 0; i < argc; i++)
|
|
{
|
|
printf ("argv[%d] = %s\n", i, argv[i]);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int shell_spawn (int argc, char *argv[])
|
|
{
|
|
int retval;
|
|
if (argc < 2)
|
|
{
|
|
printf("Usage: spawn prog_name\n");
|
|
return -1;
|
|
}
|
|
retval = fork();
|
|
if (retval > 0)
|
|
return 0; /* father returns */
|
|
if (retval < 0)
|
|
{
|
|
printf("Could not fork (%d)\n", retval);
|
|
return -1;
|
|
}
|
|
printf("Created new process %d\n", getpid());
|
|
retval = execv(argv[1], & argv[1]);
|
|
printf("Could not exec %s: error %d\n", argv[1], retval);
|
|
exit(0);
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int shell_rm (int argc, char *argv[])
|
|
{
|
|
int i;
|
|
|
|
for (i = 1; i < argc; i++)
|
|
{
|
|
int ret;
|
|
|
|
ret = unlink (argv[i]);
|
|
if (ret < 0)
|
|
printf ("Cannot remove '%s', %d\n", argv[i], ret);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int shell_dd (int argc, char *argv[])
|
|
{
|
|
char *infile = NULL;
|
|
char *outfile = NULL;
|
|
long bs = 1;
|
|
long count = -1;
|
|
int i;
|
|
int infd, outfd;
|
|
char *buffer;
|
|
int ret;
|
|
|
|
for (i = 1; i < argc; i++)
|
|
{
|
|
if (strncmp (argv[i], "if=", 3) == 0)
|
|
infile = argv[i] + 3;
|
|
else if (strncmp (argv[i], "of=", 3) == 0)
|
|
outfile = argv[i] + 3;
|
|
else if (strncmp (argv[i], "bs=", 3) == 0)
|
|
{
|
|
char *tmp = argv[i] + 3;
|
|
char *multiplier_char;
|
|
int multiplier = 1;
|
|
int j;
|
|
|
|
multiplier_char = & tmp[strlen(tmp)-1];
|
|
if (*multiplier_char == 'k' ||
|
|
*multiplier_char == 'K')
|
|
{
|
|
multiplier = 1024;
|
|
*multiplier_char = '\0';
|
|
}
|
|
else if (*multiplier_char == 'm' ||
|
|
*multiplier_char == 'M')
|
|
{
|
|
multiplier = 1024 * 1024;
|
|
*multiplier_char = '\0';
|
|
}
|
|
|
|
for (j = 0; j < strlen(tmp); j++)
|
|
if (! isdigit(tmp[j]))
|
|
{
|
|
printf ("Syntax error in block size\n");
|
|
return -1;
|
|
}
|
|
|
|
bs = atol(tmp) * multiplier;
|
|
}
|
|
else if (strncmp (argv[i], "count=", 6) == 0)
|
|
{
|
|
char *tmp = argv[i] + 6;
|
|
int j;
|
|
|
|
for (j = 0; j < strlen(tmp); j++)
|
|
if (! isdigit(tmp[j]))
|
|
{
|
|
printf ("Syntax error in block count\n");
|
|
return -1;
|
|
}
|
|
|
|
count = atol(tmp);
|
|
}
|
|
else
|
|
{
|
|
printf ("Syntax error\n");
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
infd = open(infile, O_RDONLY);
|
|
if (infd < 0)
|
|
{
|
|
printf ("Cannot open '%s', %d\n", infile, infd);
|
|
return infd;
|
|
}
|
|
|
|
outfd = open(outfile, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
|
|
if (outfd < 0)
|
|
{
|
|
printf ("Cannot open '%s', %d\n", outfile, outfd);
|
|
return outfd;
|
|
}
|
|
|
|
buffer = malloc (bs);
|
|
if (! buffer)
|
|
return -1;
|
|
|
|
for (i = 0; (count < 0) || (i < count) ; i++)
|
|
{
|
|
int len;
|
|
|
|
ret = read (infd, buffer, bs);
|
|
if (ret < 0)
|
|
{
|
|
printf ("Input error from '%s' at %d\n", infile, i);
|
|
return -1;
|
|
}
|
|
if (ret == 0)
|
|
break;
|
|
|
|
len = ret;
|
|
|
|
ret = write (outfd, buffer, len);
|
|
if (ret != len)
|
|
{
|
|
printf ("Output error to '%s' at %d (%d)\n", outfile, i, ret);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int shell_partdump (int argc, char *argv[])
|
|
{
|
|
/**
|
|
* This structure defines the structure of a partition entry
|
|
* (determined by the PC architecture)
|
|
*/
|
|
struct partition_entry
|
|
{
|
|
unsigned char active;
|
|
unsigned char start_dl;
|
|
unsigned short start_cylinder;
|
|
unsigned char type;
|
|
unsigned char end_dl;
|
|
unsigned short end_cylinder;
|
|
unsigned long lba;
|
|
unsigned long size;
|
|
};
|
|
|
|
/**
|
|
* Offset of the partition table inside the 512-byte sector.
|
|
*/
|
|
#define PART_TABLE_OFFSET 446
|
|
|
|
/**
|
|
* The most common partition types. For a complete list, you can for
|
|
* example refer to
|
|
* http://www.win.tue.nl/~aeb/partitions/partition_types-1.html
|
|
*/
|
|
#define PART_TYPE_EXTENDED 0x5
|
|
#define PART_TYPE_FAT16_1 0xe
|
|
#define PART_TYPE_FAT16_2 0x6
|
|
#define PART_TYPE_FAT32_1 0xb
|
|
#define PART_TYPE_FAT32_2 0xc
|
|
#define PART_TYPE_LINUX_SWAP 0x82
|
|
#define PART_TYPE_LINUX 0x83
|
|
|
|
/**
|
|
* Converts a partition type to a string
|
|
*/
|
|
const char *
|
|
sos_part_type_str (unsigned int type)
|
|
{
|
|
switch (type)
|
|
{
|
|
case PART_TYPE_EXTENDED:
|
|
return "Extended";
|
|
case PART_TYPE_FAT16_1:
|
|
case PART_TYPE_FAT16_2:
|
|
return "FAT16";
|
|
case PART_TYPE_FAT32_1:
|
|
case PART_TYPE_FAT32_2:
|
|
return "FAT32";
|
|
case PART_TYPE_LINUX_SWAP:
|
|
return "Linux Swap";
|
|
case PART_TYPE_LINUX:
|
|
return "Linux";
|
|
default:
|
|
return "Unknown";
|
|
}
|
|
}
|
|
|
|
int fd;
|
|
/* We assume the block size is 512 bytes. The clean way would be to
|
|
have a BLKGETSIZE ioctl() on block devices */
|
|
#define BLKSIZE 512
|
|
char buffer[BLKSIZE];
|
|
int ret;
|
|
struct partition_entry *part_entry;
|
|
int partnum;
|
|
unsigned int extstart = 0, extsup = 0;
|
|
|
|
if (argc != 2)
|
|
{
|
|
printf ("Usage: partdump /dev/device\n");
|
|
return -1;
|
|
}
|
|
|
|
fd = open (argv[1], O_RDONLY);
|
|
if (fd < 0)
|
|
{
|
|
printf ("Cannot open '%s', %d\n", argv[1], fd);
|
|
return -1;
|
|
}
|
|
|
|
ret = read (fd, buffer, sizeof(buffer));
|
|
if (ret != sizeof(buffer))
|
|
{
|
|
printf ("Read error in '%s', %d\n", argv[1], fd);
|
|
return -1;
|
|
}
|
|
|
|
part_entry = (struct partition_entry *) (buffer + PART_TABLE_OFFSET);
|
|
|
|
printf ("Partitions in %s:\n", argv[1]);
|
|
|
|
/* Handle primary partitions */
|
|
for (partnum = 0; partnum < 4; partnum++)
|
|
{
|
|
if (part_entry [partnum].size == 0)
|
|
continue;
|
|
|
|
if (part_entry [partnum].type == PART_TYPE_EXTENDED)
|
|
{
|
|
if (extstart != 0)
|
|
printf ("Warning: two extended partitions detected\n");
|
|
extstart = part_entry [partnum].lba;
|
|
continue;
|
|
}
|
|
|
|
/* When size is >= 1 Mb, display size in Mb, otherwise display
|
|
size in Kb */
|
|
if (part_entry[partnum].size * BLKSIZE >= (1024*1024))
|
|
printf (" - %s%d (primary, %lu Mb, %s)\n", argv[1], partnum+1,
|
|
(part_entry[partnum].size * BLKSIZE >> 20),
|
|
sos_part_type_str(part_entry[partnum].type));
|
|
else
|
|
printf (" - %s%d (primary, %lu Kb, %s)\n", argv[1], partnum+1,
|
|
(part_entry[partnum].size * BLKSIZE >> 10),
|
|
sos_part_type_str(part_entry[partnum].type));
|
|
}
|
|
|
|
while (extstart != 0)
|
|
{
|
|
ret = lseek (fd, (extstart + extsup) * BLKSIZE, SEEK_SET);
|
|
if (ret != (extstart + extsup) * BLKSIZE)
|
|
{
|
|
printf ("Cannot seek at position %d in '%s', %d\n",
|
|
(extstart + extsup) * BLKSIZE, argv[1], ret);
|
|
return -1;
|
|
}
|
|
|
|
ret = read (fd, buffer, BLKSIZE);
|
|
if (ret != BLKSIZE)
|
|
{
|
|
printf ("Read error in '%s', %d\n", argv[1], ret);
|
|
break;
|
|
}
|
|
|
|
/* When size is >= 1 Mb, display size in Mb, otherwise display
|
|
size in Kb */
|
|
if (part_entry[0].size * BLKSIZE >= (1024*1024))
|
|
printf (" - %s%d (logical volume, %lu Mb, %s)\n", argv[1], partnum+1,
|
|
(part_entry[0].size * BLKSIZE >> 20),
|
|
sos_part_type_str(part_entry[0].type));
|
|
else
|
|
printf (" - %s%d (logical volume, %lu Kb, %s)\n", argv[1], partnum+1,
|
|
(part_entry[0].size * BLKSIZE >> 10),
|
|
sos_part_type_str(part_entry[0].type));
|
|
|
|
extsup = part_entry[1].lba;
|
|
partnum ++;
|
|
if (extsup == 0)
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int shell_mount (int argc, char *argv[])
|
|
{
|
|
/*char * end = NULL;*/
|
|
int retval = 0;
|
|
int flags = 0;
|
|
|
|
if (strncmp(argv[1], "-t", 2)) {
|
|
/*flags = strtol(argv[1], &end, 10);*/
|
|
if (argc == 8) {
|
|
retval = mount(argv[4], argv[5], argv[3], flags, argv[7]);
|
|
} else {
|
|
if (argc == 6) {
|
|
retval = mount(argv[4], argv[5], argv[3], flags, NULL);
|
|
} else {
|
|
printf("mount [FLAGS] -t TYPE DEVICE MOUNT_DIR [-o ARGS]\n");
|
|
}
|
|
}
|
|
} else {
|
|
if (argc == 7) {
|
|
retval = mount(argv[3], argv[4], argv[2], 0, argv[6]);
|
|
} else {
|
|
if (argc == 5) {
|
|
retval = mount(argv[3], argv[4], argv[2], 0, NULL);
|
|
} else {
|
|
printf("mount [FLAGS] -t TYPE DEVICE MOUNT_DIR [-o ARGS]\n");
|
|
}
|
|
}
|
|
}
|
|
|
|
if (retval != 0)
|
|
printf("Cannot mount %s (%d)\n", argv[2], retval);
|
|
return retval;
|
|
}
|
|
|
|
static int shell_umount (int argc, char *argv[])
|
|
{
|
|
int retval = 0;
|
|
|
|
if (argc == 2)
|
|
retval = umount(argv[1]);
|
|
else
|
|
printf("umount DIR\n");
|
|
|
|
if (retval != 0)
|
|
printf("Cannot umount %s (%d)\n", argv[1], retval);
|
|
return retval;
|
|
}
|
|
|
|
static int shell_mmap (int argc, char *argv[])
|
|
{
|
|
/*
|
|
* test mmap
|
|
*/
|
|
int fd, ret;
|
|
|
|
/* Common use: shared file suppressed as soon as possible */
|
|
fd = open("mmap.txt", O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
|
|
|
|
if (fork() == 0)
|
|
{
|
|
char *shrd;
|
|
shrd = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 4096);
|
|
if (shrd == NULL)
|
|
bochs_printf("shrd children error\n");
|
|
|
|
nanosleep(1, 0);
|
|
strzcpy(shrd, "Hello1 from the child (shared mapping) !", 4096);
|
|
exit(0);
|
|
}
|
|
else
|
|
{
|
|
char *shrd;
|
|
shrd = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 4096);
|
|
if (shrd == NULL)
|
|
bochs_printf("shrd father error\n");
|
|
|
|
strzcpy(shrd, "Garbage garbage garbage", 256);
|
|
nanosleep(2, 0);
|
|
bochs_printf("Father woken up\n");
|
|
bochs_printf("Read string from child: '%s'\n", shrd);
|
|
if (strcmp(shrd, "Hello1 from the child (shared mapping) !") == 0)
|
|
bochs_printf("TEST1 OK\n");
|
|
munmap(shrd, 8192);
|
|
}
|
|
ret = close(fd);
|
|
if (ret == 0)
|
|
bochs_printf("close OK\n");
|
|
ret = unlink("mmap.txt");
|
|
if (ret == 0)
|
|
bochs_printf("delete mmap.txt OK\n");
|
|
|
|
shell_ls_internal(1, 0, 1);
|
|
|
|
/* Common use: shared file suppressed as soon as possible */
|
|
fd = open("mmap.txt", O_RDWR | O_CREAT,
|
|
S_IRUSR | S_IWUSR);
|
|
ret = unlink("mmap.txt");
|
|
if (ret == 0)
|
|
bochs_printf("delete mmap.txt OK 2\n");
|
|
if (fork() == 0)
|
|
{
|
|
char *shrd;
|
|
shrd = mmap(NULL, 4096, PROT_READ | PROT_WRITE,
|
|
MAP_SHARED, fd, 4096);
|
|
if (shrd == NULL)
|
|
bochs_printf("shrd children error\n");
|
|
|
|
nanosleep(1, 0);
|
|
strzcpy(shrd, "Hello2 from the child (shared mapping) !", 4096);
|
|
exit(0);
|
|
}
|
|
else
|
|
{
|
|
char *shrd;
|
|
shrd = mmap(NULL, 4096, PROT_READ | PROT_WRITE,
|
|
MAP_SHARED, fd, 4096);
|
|
if (shrd == NULL)
|
|
bochs_printf("shrd father error\n");
|
|
|
|
strzcpy(shrd, "Garbage garbage garbage", 256);
|
|
nanosleep(2, 0);
|
|
bochs_printf("Father woken up\n");
|
|
bochs_printf("Read string from child: '%s'\n", shrd);
|
|
if (strcmp(shrd, "Hello2 from the child (shared mapping) !") == 0)
|
|
bochs_printf("Test 2 OK\n");
|
|
/*msync(shrd, 4096, MAP_SHARED);*/
|
|
munmap(shrd, 8192);
|
|
}
|
|
ret = close(fd);
|
|
if (ret == 0)
|
|
bochs_printf("close OK\n");
|
|
|
|
shell_ls_internal(1, 0, 1);
|
|
|
|
/* Basic use */
|
|
ret = creat("mmap.txt", S_IRUSR | S_IWUSR);
|
|
if (ret == 0)
|
|
bochs_printf("creat OK\n");
|
|
if (fork() == 0)
|
|
{
|
|
char *shrd;
|
|
fd = open("mmap.txt", O_RDWR | O_CREAT,
|
|
S_IRUSR | S_IWUSR);
|
|
|
|
shrd = mmap(NULL, 4096, PROT_READ | PROT_WRITE,
|
|
MAP_SHARED, fd, 4096);
|
|
if (shrd == NULL)
|
|
bochs_printf("shrd children error\n");
|
|
nanosleep(1, 0);
|
|
strzcpy(shrd, "Hello3 from the child (shared mapping) !", 4096);
|
|
exit(0);
|
|
}
|
|
else
|
|
{
|
|
char *shrd;
|
|
fd = open("mmap.txt", O_RDWR | O_CREAT,
|
|
S_IRUSR | S_IWUSR);
|
|
|
|
shrd = mmap(NULL, 4096, PROT_READ | PROT_WRITE,
|
|
MAP_SHARED, fd, 4096);
|
|
if (shrd == NULL)
|
|
bochs_printf("shrd father error\n");
|
|
|
|
strzcpy(shrd, "Garbage garbage garbage", 256);
|
|
nanosleep(2, 0);
|
|
bochs_printf("Father woken up\n");
|
|
bochs_printf("Read string from child: '%s'\n", shrd);
|
|
if (strcmp(shrd, "Hello3 from the child (shared mapping) !") == 0)
|
|
bochs_printf("TEST3 OK\n");
|
|
|
|
munmap(shrd, 8192);
|
|
ret = close(fd);
|
|
if (ret == 0)
|
|
bochs_printf("close OK\n");
|
|
}
|
|
shell_ls_internal(1, 0, 1);
|
|
|
|
return 0;
|
|
}
|
|
|
|
void command_exec (char * cmd)
|
|
{
|
|
char *c;
|
|
int argc = 1, i;
|
|
char **argv;
|
|
|
|
for (c = cmd; *c != '\0'; c++)
|
|
{
|
|
if (*c == ' ')
|
|
{
|
|
/* Skip all spaces */
|
|
while (*c && *c == ' ')
|
|
c++;
|
|
|
|
/* Reached the end of the command line ? */
|
|
if (! *c)
|
|
break;
|
|
|
|
argc++;
|
|
}
|
|
}
|
|
|
|
argv = malloc ((argc+1) * sizeof(char*));
|
|
argv[argc] = NULL; /* To be compatible with execv(e) */
|
|
if (argv == NULL)
|
|
return;
|
|
|
|
for (i = 0, c = cmd; i < argc; i++)
|
|
{
|
|
argv[i] = c;
|
|
while (*c != ' ' && *c != '\0')
|
|
c++;
|
|
*c = '\0';
|
|
c++;
|
|
/* Skip spaces */
|
|
while (*c && *c == ' ')
|
|
c++;
|
|
}
|
|
|
|
if (! strcmp (argv[0], "uname"))
|
|
shell_uname(argc, argv);
|
|
|
|
else if (! strcmp (argv[0], "ls"))
|
|
{
|
|
if (argv[1])
|
|
shell_ls (argv[1], 1, 0);
|
|
else
|
|
shell_ls (".", 1, 0);
|
|
}
|
|
|
|
else if (! strcmp (argv[0], "cd"))
|
|
{
|
|
shell_chdir(argc, argv);
|
|
}
|
|
|
|
else if (! strcmp (argv[0], "touch"))
|
|
{
|
|
shell_touch (argc, argv);
|
|
}
|
|
|
|
else if (! strcmp (argv[0], "mkdir"))
|
|
{
|
|
shell_mkdir (argc, argv);
|
|
}
|
|
|
|
else if (! strcmp (argv[0], "rmdir"))
|
|
{
|
|
shell_rmdir (argc, argv);
|
|
}
|
|
|
|
else if (! strcmp (argv[0], "cat"))
|
|
{
|
|
shell_cat (argc, argv);
|
|
}
|
|
|
|
else if (! strcmp (argv[0], "edit"))
|
|
{
|
|
shell_edit (argc, argv);
|
|
}
|
|
|
|
else if (! strcmp (argv[0], "hexdump"))
|
|
{
|
|
shell_hexdump (argc, argv);
|
|
}
|
|
else if (! strcmp (argv[0], "test"))
|
|
{
|
|
shell_test (argc, argv);
|
|
}
|
|
else if (! strcmp (argv[0], "spawn"))
|
|
{
|
|
shell_spawn (argc, argv);
|
|
}
|
|
else if (! strcmp (argv[0], "dd"))
|
|
{
|
|
shell_dd (argc, argv);
|
|
}
|
|
else if (! strcmp (argv[0], "rm"))
|
|
{
|
|
shell_rm (argc, argv);
|
|
}
|
|
else if (! strcmp (argv[0], "partdump"))
|
|
{
|
|
shell_partdump (argc, argv);
|
|
}
|
|
else if (! strcmp (argv[0], "mount"))
|
|
{
|
|
shell_mount (argc, argv);
|
|
}
|
|
else if (! strcmp (argv[0], "umount"))
|
|
{
|
|
shell_umount (argc, argv);
|
|
}
|
|
else if (! strcmp (argv[0], "mmap"))
|
|
{
|
|
shell_mmap (argc, argv);
|
|
}
|
|
else if (! strcmp(argv[0], "getenv"))
|
|
{
|
|
if (argc > 1)
|
|
printf("%s\n", getenv(argv[1]));
|
|
else
|
|
printf("Variable name missing\n");
|
|
}
|
|
else if (! strcmp(argv[0], "setenv"))
|
|
{
|
|
if (argc > 2)
|
|
printf("retval=%d\n",
|
|
setenv(argv[1], argv[2], TRUE));
|
|
else
|
|
printf("Variable name/value missing\n");
|
|
}
|
|
else if (! strcmp(argv[0], "unsetenv"))
|
|
{
|
|
if (argc > 1)
|
|
unsetenv(argv[1]);
|
|
else
|
|
printf("Variable name missing\n");
|
|
}
|
|
else
|
|
printf ("Command not found\n");
|
|
|
|
free (argv);
|
|
}
|
|
|
|
int main(void)
|
|
{
|
|
char buffer[256];
|
|
int i;
|
|
char chr;
|
|
|
|
ioctl (0, SOS_IOCTL_TTY_RESETPARAM, SOS_IOCTLPARAM_TTY_CANON);
|
|
|
|
while (1)
|
|
{
|
|
memset (buffer, 0, sizeof(buffer));
|
|
i = 0;
|
|
printf ("$ ");
|
|
|
|
while (1)
|
|
{
|
|
read (0, & chr, 1);
|
|
if (chr == '\n')
|
|
{
|
|
buffer[i] = '\0';
|
|
printf ("\n");
|
|
if (i != 0)
|
|
command_exec (buffer);
|
|
break;
|
|
}
|
|
else if (chr == '\b')
|
|
{
|
|
if (i > 0)
|
|
{
|
|
i--;
|
|
printf ("\b");
|
|
}
|
|
}
|
|
|
|
else if (i < 256)
|
|
{
|
|
buffer[i++] = chr;
|
|
printf ("%c", chr);
|
|
}
|
|
else
|
|
printf ("%c", chr);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|