Goto sanos source index
//
// msh.c
//
// Mini shell
//
// Copyright (C) 2002 Michael Ringgaard. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// 3. Neither the name of the project nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
// SUCH DAMAGE.
//
#include <os.h>
#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <glob.h>
#include <os/version.h>
#include <inifile.h>
#include <pwd.h>
#include <grp.h>
#define BUFSIZE 4096
int execute_script(char *cmdfile);
typedef int (*cmdproc_t)(int argc, char *argv[]);
struct command {
char *cmdname;
cmdproc_t proc;
char *help;
};
extern struct command cmdtab[];
static void display_buffer(FILE *f, char *buffer, int size) {
char *p;
char *q;
char *end;
p = buffer;
end = buffer + size;
while (p < end) {
q = p;
while (q < end && *q != '\n') q++;
if (p != q) fwrite(p, q - p, 1, f);
if (q < end) {
fwrite("\r\n", 2, 1, f);
q++;
}
p = q;
}
}
static int read_line(int f, char *buf) {
char c;
int rc;
int count;
count = 0;
while ((rc = read(f, &c, 1)) > 0) {
if (c == '\r') continue;
if (c == '\n') {
*buf++ = 0;
return count;
}
*buf++ = c;
count++;
}
*buf = 0;
return rc;
}
static int httpget(char *server, char *path, char *filename) {
struct hostent *hp;
struct sockaddr_in sin;
int s;
int rc;
int n;
int count;
int f;
char *buf;
hp = gethostbyname(server);
if (!hp) return -errno;
s = socket(AF_INET, SOCK_STREAM, 0);
if (s < 0) return s;
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
memcpy(&sin.sin_addr, hp->h_addr_list[0], hp->h_length);
sin.sin_port = htons(80);
rc = connect(s, (struct sockaddr *) &sin, sizeof(sin));
if (rc < 0) {
close(s);
return rc;
}
buf = malloc(8 * 1024);
if (!buf) return -ENOMEM;
sprintf(buf, "GET %s HTTP/1.0\r\nHost: %s\r\n\r\n", path, server);
rc = send(s, buf, strlen(buf), 0);
if (rc < 0) {
close(s);
return rc;
}
while ((rc = read_line(s, buf)) > 0) {
//printf("hdr %s\n", buf);
}
if (rc < 0) return rc;
f = open(filename, O_CREAT | O_TRUNC | O_BINARY, S_IREAD | S_IWRITE);
if (f < 0) {
close(s);
free(buf);
return f;
}
count = 0;
while ((n = recv(s, buf, 8 * 1024, 0)) > 0) {
write(f, buf, n);
count += n;
//printf("len %d\n", n);
}
if (rc < 0) {
close(s);
close(f);
free(buf);
return n;
}
close(s);
close(f);
free(buf);
return count;
}
int cmd_beep(int argc, char *argv[]) {
return ioctl(1, IOCTL_BEEP, NULL, 0);
}
int cmd_break(int argc, char *argv[]) {
dbgbreak();
return 0;
}
int cmd_cat(int argc, char *argv[]) {
int count;
int fd;
char *filename;
char buffer[BUFSIZE];
if (argc != 2) {
printf("usage: cat <filename>\n");
return -EINVAL;
}
filename = argv[1];
if ((fd = open(filename, O_BINARY)) < 0) {
printf("%s: %s\n", filename, strerror(fd));
return fd;
}
while ((count = read(fd, buffer, sizeof buffer)) > 0) {
fwrite(buffer, 1, count, stdout);
}
close(fd);
return 0;
}
int cmd_chdir(int argc, char *argv[]) {
char *path;
if (argc != 2) {
printf("usage: chdir <path>\n");
return -EINVAL;
}
path = argv[1];
if (chdir(path) < 0) {
printf("%s: %s\n", path, strerror(errno));
return -1;
}
return 0;
}
int cmd_chmod(int argc, char *argv[]) {
int mode;
char *path;
char *p;
if (argc != 3) {
printf("usage: chmod <mode> <path>\n");
return -EINVAL;
}
path = argv[2];
mode = 0;
p = argv[1];
while (*p) {
if (*p < '0' || *p > '7') {
printf("Illegal mode\n");
return -EINVAL;
}
mode = (mode << 3) + (*p++ - '0');
}
if (chmod(path, mode) < 0) perror(path);
return 0;
}
int cmd_chown(int argc, char *argv[]) {
struct passwd *pwd = NULL;
struct group *grp = NULL;
char *path;
char *p;
if (argc != 3) {
printf("usage: chown <owner>:<group> <path>\n");
return -EINVAL;
}
path = argv[2];
p = strchr(argv[1], ':');
if (p) {
*p++ = 0;
pwd = getpwnam(argv[1]);
grp = getgrnam(p);
if (!pwd && !grp) {
printf("Unknown user/group\n");
return -EINVAL;
}
} else {
pwd = getpwnam(argv[1]);
if (!pwd) {
printf("Unknown user\n");
return -EINVAL;
}
}
if (chown(path, pwd ? pwd->pw_uid : -1, grp ? grp->gr_gid : -1) < 0) perror(path);
return 0;
}
int cmd_cls(int argc, char *argv[]) {
printf("\f");
return 0;
}
int cmd_cp(int argc, char *argv[]) {
char *data;
int count;
int fd1;
int fd2;
char *srcfn;
char *dstfn;
struct stat st;
if (argc != 3) {
printf("usage: cp <source file> <dest file>\n");
return -EINVAL;
}
srcfn = argv[1];
dstfn = argv[2];
if ((fd1 = open(srcfn, O_BINARY)) < 0) {
printf("%s: %s\n", srcfn, strerror(errno));
return -1;
}
fstat(fd1, &st);
if ((fd2 = open(dstfn, O_CREAT | O_TRUNC | O_BINARY, st.st_mode)) < 0) {
close(fd1);
printf("%s: %s\n", dstfn, strerror(errno));
return -1;
}
data = malloc(64 * 1024);
while ((count = read(fd1, data, 64 * 1024)) > 0) {
if (write(fd2, data, count) != count) {
printf("%s: error writing data (%s)\n", dstfn, strerror(errno));
break;
}
}
free(data);
if (count < 0) {
printf("%s: %s\n", srcfn, strerror(errno));
close(fd1);
close(fd2);
return -1;
}
close(fd1);
close(fd2);
return 0;
}
int cmd_ln(int argc, char *argv[]) {
char *target;
char *linkname;
if (argc != 3) {
printf("usage: ln <target> <link name>\n");
return -EINVAL;
}
target = argv[1];
linkname = argv[2];
if (link(target, linkname) < 0) {
perror(target);
return -1;
}
return 0;
}
int cmd_crypt(int argc, char *argv[]) {
char *pw;
char *salt;
char saltc[3];
if (argc != 2 && argc != 3) {
printf("usage: crypt <pw> [<salt>]\n");
return -EINVAL;
}
pw = argv[1];
if (argc == 3) {
salt = argv[2];
} else {
int i;
salt = saltc;
for (i = 0; i < 2; i++) {
saltc[i] = (char) (random() & 077) + '.';
if (saltc[i] > '9') saltc[i] += 7;
if (saltc[i] > 'Z') saltc[i] += 6;
}
saltc[2] = 0;
}
printf("%s\n", crypt(pw, salt));
return 0;
}
int cmd_date(int argc, char *argv[]) {
time_t t;
struct tm tm;
t = time(NULL);
gmtime_r(&t, &tm);
if (argc > 1) {
char buffer[256];
strftime(buffer, 256, argv[1], &tm);
printf("%s\n", buffer);
} else {
printf("Time is %04d/%02d/%02d %02d:%02d:%02d\n", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
}
return 0;
}
int cmd_debug(int argc, char *argv[]) {
struct peb *peb = gettib()->peb;
if (argc > 1) {
if (strcmp(argv[1], "on") == 0) {
peb->debug = 1;
} else if (strcmp(argv[1], "off") == 0) {
peb->debug = 0;
} else {
printf("usage: debug [on|off]\n");
return -EINVAL;
}
}
printf("debug %s\n", peb->debug ? "on" : "off");
return 0;
}
int cmd_df(int argc, char *argv[]) {
int count;
int rc;
int n;
struct statfs *buf;
struct statfs *b;
count = getfsstat(NULL, 0);
if (count < 0) {
printf("df: %s\n", strerror(errno));
return -1;
}
buf = (struct statfs *) malloc(count * sizeof(struct statfs));
rc = getfsstat(buf, count * sizeof(struct statfs));
if (rc < 0) {
printf("df: %s\n", strerror(errno));
return -1;
}
printf("type mounted on mounted from cache total used avail files\n");
printf("------ ---------- -------------------- ------ -------- -------- -------- -----\n");
for (n = 0; n < count; n++) {
b = buf + n;
printf("%-7s%-11s%-20s", b->fstype, b->mntto, b->mntfrom);
if (b->blocks != -1) {
printf("%6dK", b->cachesize / 1024);
if (b->blocks * (b->bsize / 512) / 2 > 10000) {
printf("%8dM", b->blocks * (b->bsize / 512) / 2000);
} else {
printf("%8dK", b->blocks * (b->bsize / 512) / 2);
}
if ((b->blocks - b->bfree) * (b->bsize / 512) / 2 > 10000) {
printf("%8dM", (b->blocks - b->bfree) * (b->bsize / 512) / 2000);
} else {
printf("%8dK", (b->blocks - b->bfree) * (b->bsize / 512) / 2);
}
if (b->bfree * (b->bsize / 512) / 2 > 10000) {
printf("%8dM", b->bfree * (b->bsize / 512) / 2000);
} else {
printf("%8dK", b->bfree * (b->bsize / 512) / 2);
}
if (b->files != -1 && b->ffree != -1) printf(" %d/%d", b->files - b->ffree, b->files);
}
printf("\n");
}
free(buf);
return 0;
}
int cmd_exec(int argc, char *argv[]) {
char *filename;
if (argc != 2) {
printf("usage: dump <file>\n");
return -EINVAL;
}
filename = argv[1];
return execute_script(filename);
}
int cmd_dump(int argc, char *argv[]) {
char *filename;
int fd;
unsigned char buf[16];
int pos;
int count;
int line;
int i;
int ch;
if (argc != 2) {
printf("usage: dump <file>\n");
return -EINVAL;
}
filename = argv[1];
if ((fd = open(filename, O_BINARY)) < 0) {
printf("%s: %s\n", filename, strerror(errno));
return -EINVAL;
}
line = 0;
pos = 0;
while ((count = read(fd, buf, 16)) > 0) {
printf("%08X ", pos);
for (i = 0; i < count; i++) printf("%02X ", buf[i]);
for (i = count; i < 16; i++) printf(" ");
for (i = 0; i < count; i++) printf("%c", buf[i] < 0x20 ? '.' : buf[i]);
printf("\n");
if (line == 23) {
fflush(stdout);
ch = getchar();
if (ch == 'x') {
close(fd);
return 0;
}
line = 0;
} else {
line++;
}
pos += count;
}
close(fd);
return 0;
}
int cmd_grabcon(int argc, char *argv[]) {
dup2(fdin, 0);
dup2(fdout, 1);
dup2(fderr, 2);
return 0;
}
int cmd_id(int argc, char *argv[]) {
gid_t groups[NGROUPS_MAX];
int ngroups;
struct passwd *pwd = getpwuid(getuid());
struct group *grp = getgrgid(getgid());
if (!pwd || !grp) {
perror("id");
return -1;
}
printf("uid=%d(%s) gid=%d(%s)", pwd->pw_uid, pwd->pw_name, grp->gr_gid, grp->gr_name);
ngroups = getgroups(NGROUPS_MAX, groups);
if (ngroups > 0) {
int i;
printf(" groups");
for (i = 0; i < ngroups; i++) {
grp = getgrgid(groups[i]);
printf("%c%d(%s)", (i == 0 ? '=' : ','), groups[i], grp->gr_name);
}
}
printf("\n");
return 0;
return 0;
}
int cmd_ifconfig(int argc, char *argv[]) {
struct peb *peb = gettib()->peb;
int sock;
struct ifcfg iflist[16];
int n, i;
if (*peb->hostname) {
printf("Host Name ............... : %s\n", peb->hostname);
}
if (*peb->default_domain) {
printf("Domain Name ............. : %s\n", peb->default_domain);
}
if (peb->primary_dns.s_addr != INADDR_ANY) {
printf("Primary DNS Server ...... : %s\n", inet_ntoa(peb->primary_dns));
}
if (peb->secondary_dns.s_addr != INADDR_ANY) {
printf("Secondary DNS Server .... : %s\n", inet_ntoa(peb->secondary_dns));
}
if (peb->ntp_server1.s_addr != INADDR_ANY) {
printf("Primary NTP Server ...... : %s\n", inet_ntoa(peb->ntp_server1));
}
if (peb->ntp_server2.s_addr != INADDR_ANY) {
printf("Secondary NTP Server .... : %s\n", inet_ntoa(peb->ntp_server2));
}
sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock < 0) return -1;
n = ioctl(sock, SIOIFLIST, iflist, sizeof iflist);
if (n < 0) {
close(sock);
return -1;
}
for (i = 0; i < n / (int) sizeof(struct ifcfg); i++) {
struct sockaddr_in *addr = ((struct sockaddr_in *) &iflist[i].addr);
struct sockaddr_in *gw = ((struct sockaddr_in *) &iflist[i].gw);
struct sockaddr_in *mask = ((struct sockaddr_in *) &iflist[i].netmask);
struct sockaddr_in *bcast = ((struct sockaddr_in *) &iflist[i].broadcast);
unsigned char *hwaddr = (unsigned char *) iflist[i].hwaddr;
printf("\n");
printf("Network interface %s:\n", iflist[i].name);
printf(" IP Address ......... : %s\n", inet_ntoa(addr->sin_addr));
printf(" Subnet Mask ........ : %s\n", inet_ntoa(mask->sin_addr));
printf(" Default Gateway .... : %s\n", inet_ntoa(gw->sin_addr));
printf(" Broadcast Address .. : %s\n", inet_ntoa(bcast->sin_addr));
printf(" Physical Address ... : %02x:%02x:%02x:%02x:%02x:%02x\n",
hwaddr[0], hwaddr[1], hwaddr[2],
hwaddr[3], hwaddr[4], hwaddr[5]);
printf(" Flags .............. :");
if (iflist[i].flags & IFCFG_UP) printf(" UP");
if (iflist[i].flags & IFCFG_DHCP) printf(" DHCP");
if (iflist[i].flags & IFCFG_DEFAULT) printf(" DEFAULT");
if (iflist[i].flags & IFCFG_LOOPBACK) printf(" LOOPBACK");
printf("\n");
}
close(sock);
return 0;
}
int cmd_keyb(int argc, char *argv[]) {
char *keybname;
int keymap;
int rc;
if (argc != 2) {
printf("usage: keyb [us|uk|dk|fr]\n");
return -EINVAL;
}
keybname = argv[1];
if (strcmp(keybname, "us") == 0) {
keymap = 0;
} else if (strcmp(keybname, "dk") == 0) {
keymap = 1;
} else if (strcmp(keybname, "uk") == 0) {
keymap = 2;
} else if (strcmp(keybname, "fr") == 0) {
keymap = 3;
} else {
printf("keyb: unknown keymap '%s'\n", keybname);
return -EINVAL;
}
rc = ioctl(0, IOCTL_SET_KEYMAP, &keymap, sizeof(int));
return rc;
}
int cmd_heapstat(int argc, char *argv[]) {
struct mallinfo m;
m = mallinfo();
printf("Non-mmapped space allocated from system .. : %12d\n", m.arena);
printf("Number of free chunks .................... : %12d\n", m.ordblks);
printf("Number of fastbin blocks ................. : %12d\n", m.smblks);
printf("Number of mmapped regions ................ : %12d\n", m.hblks);
printf("Space in mmapped regions ................. : %12d\n", m.hblkhd);
printf("Maximum total allocated space ............ : %12d\n", m.usmblks);
printf("Space available in freed fastbin blocks .. : %12d\n", m.fsmblks);
printf("Total allocated space .................... : %12d\n", m.uordblks);
printf("Total free space ......................... : %12d\n", m.fordblks);
printf("Top-most, releasable space ............... : %12d\n", m.keepcost);
return 0;
}
int cmd_help(int argc, char *argv[]) {
struct command *command;
int lineno;
int ok;
int n;
lineno = 0;
for (command = cmdtab; command->cmdname; command++) {
ok = 1;
if (argc > 1) {
ok = 0;
for (n = 1; n < argc; n++) {
if (strstr(command->cmdname, argv[n]) ||
command->help && strstr(command->help, argv[n])) {
ok = 1;
break;
}
}
}
if (ok && command->help) {
printf("%-10.10s %s\n", command->cmdname, command->help);
if (++lineno == 24) {
fflush(stdout);
getchar();
lineno = 0;
}
}
}
return 0;
}
int cmd_httpget(int argc, char *argv[]) {
char *server;
char *path;
char *filename;
int rc;
clock_t t;
server = "localhost";
path = "/";
filename = "/dev/null";
if (argc == 1) {
printf("usage: httpget <server> [<url> [<filename>]]\n");
return -EINVAL;
}
if (argc >= 2) server = argv[1];
if (argc >= 3) path = argv[2];
if (argc >= 4) filename = argv[3];
t = clock();
rc = httpget(server, path, filename);
if (rc < 0) {
printf("Error %d '%s' retrieving %s from %s\n", errno, strerror(errno), path, server);
return -1;
}
t = clock() - t;
if (t == 0) t = 1;
printf("Received %d bytes in %d ms (%d KB/s)\n", rc, t, rc / t);
return 0;
}
int cmd_ps(int argc, char *argv[]) {
struct peb *peb = gettib()->peb;
struct process *proc = peb->firstproc;
printf(" id parent name hmod threads in out err command line\n");
printf("---- ------ ------------ -------- ------- --- --- --- -------------------------\n");
while (proc) {
printf("%4d %6d %-13s%08x%8d%4d%4d%4d %s\n", proc->id, proc->parent ? proc->parent->id : 0, proc->ident, proc->hmod, proc->threadcnt, proc->iob[0], proc->iob[1], proc->iob[2], proc->cmdline ? proc->cmdline : "");
proc = proc->nextproc;
}
return 0;
}
int cmd_kbd(int argc, char *argv[]) {
int escs;
int ch;
printf("(press esc three times to exit)\n");
escs = 0;
while (1) {
fflush(stdout);
ch = getchar();
if (ch == 0x1B) {
escs++;
} else {
escs = 0;
}
if (escs == 3) break;
printf("[0x%02X]", ch);
}
printf("\n");
return 0;
}
int cmd_kill(int argc, char *argv[]) {
int pid = getpid();
int signum = SIGINT;
int rc;
if (argc > 1) pid = atoi(argv[1]);
if (argc > 2) signum = atoi(argv[2]);
rc = kill(pid, signum);
if (rc < 0) perror("kill");
return 0;
}
int cmd_klog(int argc, char *argv[]) {
int enabled;
int klog;
int rc;
if (argc != 2) {
printf("usage: klog [on|off]\n");
return -EINVAL;
}
enabled = strcmp(argv[1], "on") == 0;
klog = open("/dev/klog", 0);
rc = ioctl(klog, IOCTL_KPRINT_ENABLED, &enabled, 4);
close(klog);
return rc;
}
int cmd_load(int argc, char *argv[]) {
char *pgm;
hmodule_t hmod;
if (argc != 2) {
printf("usage: load <module>\n");
return -EINVAL;
}
pgm = argv[1];
hmod = dlopen(pgm, 0);
if (hmod == NULL) {
printf("%s: unable to load module\n", pgm);
return -1;
}
return 0;
}
int cmd_loglevel(int argc, char *argv[]) {
int level;
int ll = 0;
if (argc != 2) {
printf("usage: logevel [<loglevel>]\n");
return -EINVAL;
}
level = atoi(argv[1]);
setlogmask((1 << (level + 1)) - 1);
return 0;
}
int cmd_ls(int argc, char *argv[]) {
char *dirname;
int verbose;
int i;
int dir;
struct direntry dirp;
struct stat buf;
struct tm tm;
char path[MAXPATH];
char *arg;
int col;
char perm[11];
struct passwd *pwd;
struct group *grp;
verbose = 0;
dirname = ".";
for (i = 1; i < argc; i++) {
arg = argv[i];
if (*arg == '-') {
while (*++arg) {
if (*arg == 'l') verbose = 1;
if (*arg == 'w') verbose = 2;
}
} else {
dirname = arg;
}
}
if ((dir = _opendir(dirname)) < 0) {
printf("%s: %s\n", dirname, strerror(errno));
return dir;
}
col = 0;
while (_readdir(dir, &dirp, 1) > 0) {
strcpy(path, dirname);
strcat(path, "/");
strcat(path, dirp.name);
if (stat(path, &buf) < 0) memset(&buf, 0, sizeof(struct stat));
if (verbose == 2) {
if (col == 4) col = 0;
if ((buf.st_mode & S_IFMT) == S_IFDIR) strcat(dirp.name, "/");
printf("%-20s", dirp.name);
col++;
} else {
strcpy(path, dirname);
strcat(path, "/");
strcat(path, dirp.name);
if (stat(path, &buf) < 0) memset(&buf, 0, sizeof(struct stat));
if (verbose) {
printf("%8d %4d %1d %2d ", (int) buf.st_size, buf.st_ino, buf.st_nlink, buf.st_dev);
gmtime_r(&buf.st_ctime, &tm);
printf("%02d/%02d/%04d %02d:%02d:%02d ", tm.tm_mday, tm.tm_mon + 1, tm.tm_year + 1900, tm.tm_hour, tm.tm_min, tm.tm_sec);
} else {
strcpy(perm, " ---------");
switch (buf.st_mode & S_IFMT) {
case S_IFREG: perm[0] = '-'; break;
case S_IFLNK: perm[0] = 'l'; break;
case S_IFDIR: perm[0] = 'd'; break;
case S_IFBLK: perm[0] = 'b'; break;
case S_IFCHR: perm[0] = 'c'; break;
case S_IFPKT: perm[0] = 'p'; break;
}
if (buf.st_mode & 0400) perm[1] = 'r';
if (buf.st_mode & 0200) perm[2] = 'w';
if (buf.st_mode & 0100) perm[3] = 'x';
if (buf.st_mode & 0040) perm[4] = 'r';
if (buf.st_mode & 0020) perm[5] = 'w';
if (buf.st_mode & 0010) perm[6] = 'x';
if (buf.st_mode & 0004) perm[7] = 'r';
if (buf.st_mode & 0002) perm[8] = 'w';
if (buf.st_mode & 0001) perm[9] = 'x';
printf("%s ", perm);
pwd = getpwuid(buf.st_uid);
grp = getgrgid(buf.st_gid);
printf("%-8s %-8s", pwd ? pwd->pw_name : "?", grp ? grp->gr_name : "?");
if ((buf.st_mode & S_IFMT) == S_IFDIR) {
printf(" ");
} else {
printf("%10d ", buf.st_size);
}
}
gmtime_r(&buf.st_mtime, &tm);
printf("%02d/%02d/%04d %02d:%02d:%02d ", tm.tm_mday, tm.tm_mon + 1, tm.tm_year + 1900, tm.tm_hour, tm.tm_min, tm.tm_sec);
printf("%s", dirp.name);
if ((buf.st_mode & S_IFMT) == S_IFDIR) printf("/", dirp.name);
printf("\n");
}
}
if (verbose == 2) printf("\n");
close(dir);
return 0;
}
int cmd_mkdir(int argc, char *argv[]) {
char *path;
int rc;
if (argc != 2) {
printf("usage: mkdir <path>\n");
return -EINVAL;
}
path = argv[1];
rc = mkdir(path, 0755);
if (rc < 0) {
printf("%s: %s\n", path, strerror(errno));
return -1;
}
return 0;
}
int cmd_mkfs(int argc, char *argv[]) {
char *devname;
char *type = "dfs";
char *opts = NULL;
int rc;
if (argc < 2) {
printf("usage: mkfs <device> [<type> [<options>]]\n");
return -EINVAL;
}
devname = argv[1];
if (argc > 2) type = argv[2];
if (argc > 3) opts = argv[3];
rc = mkfs(devname, type, opts);
if (rc < 0) {
printf("%s: %s\n", devname, strerror(errno));
return -1;
}
return 0;
}
int cmd_more(int argc, char *argv[]) {
char *filename;
int count;
int fd;
int line;
char *start;
char *end;
char ch;
char buffer[BUFSIZE];
if (argc != 2)
{
printf("usage: more <file>\n");
return -EINVAL;
}
filename = argv[1];
if ((fd = open(filename, O_BINARY)) < 0) {
printf("%s: %s\n", filename, strerror(errno));
return fd;
}
line = 0;
while ((count = read(fd, buffer, sizeof buffer)) > 0) {
start = end = buffer;
while (end < buffer + count) {
if (line == 24) {
display_buffer(stdout, start, end - start);
fflush(stdout);
ch = getchar();
if (ch == 'x') {
close(fd);
return 0;
}
start = end;
line = 0;
}
if (*end++ == '\n') line++;
}
display_buffer(stdout, start, end - start);
}
close(fd);
return 0;
}
int cmd_mount(int argc, char *argv[]) {
char *devname;
char *path;
char *type = "dfs";
char *opts = NULL;
int rc;
if (argc < 3) {
printf("usage: mount <device> <path> [<type> [<options>]]\n");
return -EINVAL;
}
devname = argv[1];
path = argv[2];
if (argc > 3) type = argv[3];
if (argc > 4) opts = argv[4];
rc = mount(type, path, devname, opts);
if (rc < 0) {
printf("%s: %s\n", devname, strerror(errno));
return -1;
}
return 0;
}
int cmd_mv(int argc, char *argv[]) {
char *oldname;
char *newname;
int rc;
if (argc != 3) {
printf("usage: mv <old name> <new name>\n");
return -EINVAL;
}
oldname = argv[1];
newname = argv[2];
rc = rename(oldname, newname);
if (rc < 0) {
printf("%s: %s\n", oldname, strerror(errno));
return -1;
}
return 0;
}
int cmd_nslookup(int argc, char *argv[]) {
char *name;
struct hostent *hp;
int i;
if (argc != 2) {
printf("usage: nslookup [<hostname>|<ipaddress>]\n");
return -EINVAL;
}
name = argv[1];
if (!*name) return 0;
if (*name >= '0' && *name <= '9') {
struct in_addr addr;
addr.s_addr = inet_addr(name);
if (addr.s_addr == INADDR_NONE) {
printf("%s: %s\n", name, strerror(errno));
return -1;
}
hp = gethostbyaddr((char *) &addr, sizeof(struct in_addr), AF_INET);
} else {
hp = gethostbyname(name);
}
if (!hp) {
printf("%s: %s\n", name, strerror(errno));
return -errno;
}
if (hp->h_addrtype != AF_INET) {
printf("unknown address type %d\n", hp->h_addrtype);
return 0;
}
if (hp->h_length != sizeof(struct in_addr)) {
printf("unknown address length %d\n", hp->h_length);
return 0;
}
printf("name: %s\n", hp->h_name);
for (i = 0; hp->h_aliases[i] != NULL; i++) printf("alias: %s\n", hp->h_aliases[i]);
for (i = 0; hp->h_addr_list[i] != NULL; i++) {
struct in_addr *addr = (struct in_addr *) (hp->h_addr_list[i]);
printf("address: %s\n", inet_ntoa(*addr));
}
return 0;
}
int cmd_play(int argc, char *argv[]) {
char *filename;
extern void play(char *song);
//play("AxelF:d=4, o=5, b=160:f#, 8a., 8f#, 16f#, 8a#, 8f#, 8e, f#, 8c.6, 8f#, 16f#, 8d6, 8c#6, 8a, 8f#, 8c#6, 8f#6, 16f#, 8e, 16e, 8c#, 8g#, f#.");
//play("dualingbanjos:d=4, o=5, b=200:8c#, 8d, e, c#, d, b4, c#, d#4, b4, p, 16c#6, 16p, 16d6, 16p, 8e6, 8p, 8c#6, 8p, 8d6, 8p, 8b, 8p, 8c#6, 8p, 8a, 8p, b, p, a4, a4, b4, c#, d#4, c#, b4, p, 8a, 8p, 8a, 8p, 8b, 8p, 8c#6, 8p, 8a, 8p, 8c#6, 8p, 8b");
//play("Entertainer:d=4, o=5, b=140:8d, 8d#, 8e, c6, 8e, c6, 8e, 2c.6, 8c6, 8d6, 8d#6, 8e6, 8c6, 8d6, e6, 8b, d6, 2c6, p, 8d, 8d#, 8e, c6, 8e, c6, 8e, 2c.6, 8p, 8a, 8g, 8f#, 8a, 8c6, e6, 8d6, 8c6, 8a, 2d6");
//play("Barbiegirl:d=4,o=5,b=125:8g#,8e,8g#,8c#6,a,p,8f#,8d#,8f#,8b,g#,8f#,8e,p,8e,8c#,f#,c#,p,8f#,8e,g#,f#");
//play("Muppets:d=4, o=5, b=250:c6, c6, a, b, 8a, b, g, p, c6, c6, a, 8b, 8a, 8p, g., p, e, e, g, f, 8e, f, 8c6, 8c, 8d, e, 8e, 8e, 8p, 8e, g, 2p, c6, c6, a, b, 8a, b, g, p, c6, c6, a, 8b, a, g., p, e, e, g, f, 8e, f, 8c6, 8c, 8d, e, 8e, d, 8d, c");
char buffer[4096];
FILE *f;
if (argc != 2) {
printf("usage: play <rttl file>\n");
return -EINVAL;
}
filename = argv[1];
f = fopen(filename, "r");
if (!f) {
printf("%s: %s\n", filename, strerror(errno));
return -1;
}
while (fgets(buffer, sizeof buffer, f)) {
printf("%s\n", buffer);
play(buffer);
}
fclose(f);
return 0;
}
int cmd_read(int argc, char *argv[]) {
char *filename;
int count;
int fd;
char *data;
clock_t start;
clock_t time;
int bytes;
if (argc != 2) {
printf("usage: read <file>\n");
return -EINVAL;
}
filename = argv[1];
if ((fd = open(filename, 0)) < 0) {
printf("%s: %s\n", filename, strerror(errno));
return fd;
}
data = malloc(64 * 1024);
bytes = 0;
start = clock();
while ((count = read(fd, data, 64 * 1024)) > 0) {
bytes += count;
}
time = clock() - start;
if (time == 0) time = 1;
printf("%s: read %dKB in %d ms, %dKB/s\n", filename, bytes / 1024, time, bytes / time);
free(data);
if (count < 0) printf("%s: %s\n", filename, strerror(errno));
close(fd);
return 0;
}
int cmd_reboot(int argc, char *argv[]) {
exitos(EXITOS_REBOOT);
return 0;
}
int cmd_rm(int argc, char *argv[]) {
char *filename;
int rc;
int i;
if (argc < 2) {
printf("usage: rm <file(s)>\n");
return -EINVAL;
}
for (i = 1; i < argc; i++) {
filename = argv[i];
rc = unlink(filename);
if (rc < 0) {
printf("%s: %s\n", filename, strerror(errno));
return -1;
}
}
return 0;
}
int cmd_rmdir(int argc, char *argv[]) {
char *path;
int rc;
if (argc != 2) {
printf("usage: rmdir <path>\n");
return -EINVAL;
}
path = argv[1];
rc = rmdir(path);
if (rc < 0) {
printf("%s: %s\n", path, strerror(errno));
return -1;
}
return 0;
}
int cmd_set(int argc, char *argv[]) {
char **env = environ;
int n;
if (argc <= 1) {
if (env) for (n = 0; env[n]; n++) printf("%s\n", env[n]);
} else {
for (n = 1; n < argc; n++) putenv(argv[n]);
}
return 0;
}
int cmd_sleep(int argc, char *argv[]) {
int ms;
if (argc != 2) {
printf("usage: sleep <millis>\n");
return -EINVAL;
}
ms = atoi(argv[1]);
msleep(ms);
return 0;
}
int cmd_sound(int argc, char *argv[]) {
int freq;
if (argc != 2) {
printf("usage: sound <freq> (0=silence)\n");
return -EINVAL;
}
freq = atoi(argv[1]);
return ioctl(1, IOCTL_SOUND, &freq, 4);
}
int cmd_shutdown(int argc, char *argv[]) {
exitos(EXITOS_POWEROFF);
return 0;
}
int cmd_sysinfo(int argc, char *argv[]) {
int rc;
struct cpuinfo cpu;
struct meminfo mem;
struct loadinfo load;
rc = sysinfo(SYSINFO_CPU, &cpu, sizeof(cpu));
if (rc < 0) return rc;
rc = sysinfo(SYSINFO_MEM, &mem, sizeof(mem));
if (rc < 0) return rc;
rc = sysinfo(SYSINFO_LOAD, &load, sizeof(load));
if (rc < 0) return rc;
printf("cpu vendor: %d family: %d model: %d stepping: %d mhz: %d feat: %08X pagesize: %d\n",
cpu.cpu_vendor, cpu.cpu_family, cpu.cpu_model, cpu.cpu_stepping, cpu.cpu_mhz, cpu.cpu_features, cpu.pagesize);
printf("mem phys total: %d K avail: %d K virt total: %d K avail: %d K pagesize: %d\n",
mem.physmem_total / 1024, mem.physmem_avail / 1024, mem.virtmem_total / 1024, mem.virtmem_avail / 1024, mem.pagesize);
printf("load uptime: %d s user: %d%% sys: %d%% intr: %d%% idle: %d%%\n",
load.uptime, load.load_user, load.load_system, load.load_intr, load.load_idle);
return 0;
}
int cmd_test(int argc, char *argv[]) {
int rc;
errno = 0;
rc = access(argv[1], F_OK);
printf("access(%s,F_OK)=%d %d %s\n", argv[1], rc, errno, strerror(errno));
rc = access(argv[1], R_OK);
printf("access(%s,R_OK)=%d %d %s\n", argv[1], rc, errno, strerror(errno));
rc = access(argv[1], W_OK);
printf("access(%s,W_OK)=%d %d %s\n", argv[1], rc, errno, strerror(errno));
rc = access(argv[1], X_OK);
printf("access(%s,X_OK)=%d %d %s\n", argv[1], rc, errno, strerror(errno));
return 0;
}
int cmd_glob(int argc, char *argv[]) {
glob_t globbuf;
int i;
int rc;
if (argc > 1) {
for (i = 1; i < argc; i++) {
rc = glob(argv[i], i > 1 ? GLOB_APPEND : 0, NULL, &globbuf);
if (rc < 0) printf("glob(%s) returned %d\n", argv[i], rc);
}
for (i = 0; i < (int) globbuf.gl_pathc; i++) {
printf("%s\n", globbuf.gl_pathv[i]);
}
globfree(&globbuf);
}
return 0;
}
int cmd_uname(int argc, char *argv[]) {
struct utsname buf;
if (uname(&buf) < 0) {
perror("uname");
return -1;
}
printf("%s %s %s %s %s\n", buf.sysname, buf.nodename, buf.release, buf.version, buf.machine);
return 0;
}
int cmd_umount(int argc, char *argv[]) {
char *path;
int rc;
if (argc != 2) {
printf("usage: umount <path>\n");
return -EINVAL;
}
path = argv[1];
rc = umount(path);
if (rc < 0) {
printf("%s: %s\n", path, strerror(errno));
return -1;
}
return 0;
}
int cmd_whoami(int argc, char *argv[]) {
struct passwd *pwd;
pwd = getpwuid(getuid());
if (pwd) {
printf("%s\n", pwd->pw_name);
} else {
printf("uid%d\n", getuid);
}
return 0;
}
int cmd_write(int argc, char *argv[]) {
char *filename;
int size;
int count;
int fd;
char *data;
clock_t start;
clock_t time;
int bytes;
if (argc != 3) {
printf("usage: write <file> <size (in kb)>\n");
return -EINVAL;
}
filename = argv[1];
size = atoi(argv[2]) * 1024;
if ((fd = open(filename, O_CREAT | O_BINARY, S_IREAD | S_IWRITE)) < 0) {
printf("%s: %s\n", filename, strerror(errno));
return -1;
}
data = malloc(64 * 1024);
bytes = 0;
start = clock();
while (bytes < size) {
if ((count = write(fd, data, 64 * 1024)) <= 0) {
printf("%s: error writing file\n", filename);
break;
}
bytes += count;
}
time = clock() - start;
if (time == 0) time = 1;
printf("%s: wrote %dKB in %d ms, %dKB/s\n", filename, bytes / 1024, time, bytes / time);
free(data);
close(fd);
return 0;
}
struct command cmdtab[] = {
{"?", cmd_help, "This help"},
{"beep", cmd_beep, "Play beep in speaker"},
{"break", cmd_break, "Debug breakpoint"},
{"bye", cmd_shutdown, "Shutdown computer and power off"},
{"cat", cmd_cat, "Display file"},
{"cd", cmd_chdir, "Change current directory"},
{"chdir", cmd_chdir, "Change current directory"},
{"chmod", cmd_chmod, "Change file permissions"},
{"chown", cmd_chown, "Change file owner"},
{"copy", cmd_cp, "Copy file"},
{"cls", cmd_cls, "Clear screen"},
{"cp", cmd_cp, "Copy file"},
{"crypt", cmd_crypt, "Encrypt password"},
{"date", cmd_date, "Display date"},
{"debug", cmd_debug, "Enable/disable debug mode"},
{"del", cmd_rm, "Delete file"},
{"df", cmd_df, "Display file system usage"},
{"dir", cmd_ls, "List directory"},
{"dump", cmd_dump, "Display file in hex format"},
{"exec", cmd_exec, "Execute shell script"},
{"exit", NULL, "Exit shell"},
{"glob", cmd_glob, "Expand filename arguments"},
{"grabcon", cmd_grabcon, "Grab the main console file descriptors"},
{"id", cmd_id, "Display real and effective user and group ids"},
{"ifconfig", cmd_ifconfig, "Display network interface configuration"},
{"ipconfig", cmd_ifconfig, "Display network interface configuration"},
{"keyb", cmd_keyb, "Change keyboard map"},
{"heapstat", cmd_heapstat, "Display heap statistics"},
{"help", cmd_help, "This help"},
{"httpget", cmd_httpget, "Retrieve file via http"},
{"jobs", cmd_ps, "Display process list"},
{"kbd", cmd_kbd, "Keyboard test"},
{"kill", cmd_kill, "Send signal"},
{"klog", cmd_klog, "Enable/disable kernel log messages"},
{"load", cmd_load, "Load module"},
{"loglevel", cmd_loglevel, "Set syslog tracing mask and level"},
{"lookup", cmd_nslookup, "Lookup hostname or IP address using DNS"},
{"ln", cmd_ln, "Create link to file or directory"},
{"ls", cmd_ls, "List directory"},
{"md", cmd_mkdir, "Make new directory"},
{"mkdir", cmd_mkdir, "Make new directory"},
{"mkfs", cmd_mkfs, "Format device for new file system"},
{"more", cmd_more, "Display file paginated"},
{"mount", cmd_mount, "Mount file system"},
{"move", cmd_mv, "Move file"},
{"mv", cmd_mv, "Move file"},
{"nslookup", cmd_nslookup, "Lookup hostname or IP address using DNS"},
{"play", cmd_play, "Play RTTTL file in speaker"},
{"ps", cmd_ps, "Display process list"},
{"read", cmd_read, "Read file from disk"},
{"reboot", cmd_reboot, "Reboot computer"},
{"rm", cmd_rm, "Delete file"},
{"rd", cmd_rmdir, "Remove directory"},
{"rmdir", cmd_rmdir, "Remove directory"},
{"set", cmd_set, "Set or display environment variables"},
{"sleep", cmd_sleep, "Sleep for a number of milliseconds"},
{"sound", cmd_sound, "Play sound in speaker"},
{"shutdown", cmd_shutdown, "Shutdown computer and power off"},
{"sysinfo", cmd_sysinfo, "Display system info"},
{"test", cmd_test, "Dummy command for misc. tests"},
{"type", cmd_cat, "Display file"},
{"uname", cmd_uname, "Print system information"},
{"umount", cmd_umount, "Unmount file system"},
{"whoami", cmd_whoami, "Display logged in user"},
{"write", cmd_write, "Write zero filled file to disk"},
{NULL, NULL, NULL}
};
static void exec_program(char *args) {
int rc;
rc = spawn(P_WAIT, NULL, args, NULL, NULL);
if (rc < 0) perror("error");
}
static void launch_program(char *args) {
int h;
h = spawn(P_NOWAIT, NULL, args, NULL, NULL);
if (h < 0) {
perror("error");
} else {
printf("[process %d started]\n", h);
close(h);
}
}
static int exec_builtin(int argc, char *argv[], int *found) {
struct command *command;
for (command = cmdtab; command->cmdname; command++) {
if (strcmp(argv[0], command->cmdname) == 0) break;
}
if (!command->cmdname) {
if (found) *found = 0;
return -ENOENT;
}
if (found) *found = 1;
if (!command->proc) return -ENOSYS;
return command->proc(argc, argv);
}
static int parse_args(char *args, char **argv) {
char *p;
int argc;
char *start;
char *end;
char *buf;
int delim;
p = args;
argc = 0;
while (*p) {
while (*p == ' ') p++;
if (!*p) break;
if (*p == '"' || *p == '\'') {
delim = *p++;
start = p;
while (*p && *p != delim) p++;
end = p;
if (*p == delim) p++;
} else {
start = p;
while (*p && *p != ' ') p++;
end = p;
}
if (argv) {
buf = (char *) malloc(end - start + 1);
if (!buf) break;
memcpy(buf, start, end - start);
buf[end - start] = 0;
argv[argc] = buf;
}
argc++;
}
return argc;
}
static void free_args(int argc, char **argv) {
int i;
for (i = 0; i < argc; ++i) free(argv[i]);
free(argv);
}
static int exec_command(char *cmdline) {
int argc;
char **argv;
int found;
int rc;
argc = parse_args(cmdline, NULL);
if (!argc) return 0;
argv = (char **) malloc(argc * sizeof(char *));
parse_args(cmdline, argv);
rc = exec_builtin(argc, argv, &found);
if (found) {
free_args(argc, argv);
return rc;
}
if (strcmp(argv[0], "start") == 0) {
char *args = cmdline;
while (*args != 0 && *args != ' ') args++;
while (*args == ' ') args++;
launch_program(args);
} else if (strcmp(argv[argc - 1], "&") == 0) {
char *buf = strdup(cmdline);
buf[strlen(buf) - 1] = 0;
launch_program(buf);
free(buf);
} else {
exec_program(cmdline);
}
free_args(argc, argv);
return 0;
}
void shell() {
char curdir[MAXPATH];
char cmdline[256];
char *prompt = get_property(osconfig(), "shell", "prompt", "msh %s$ ");
int rc;
while (1) {
printf(prompt, getcwd(curdir, sizeof curdir));
rc = readline(cmdline, sizeof cmdline);
if (rc < 0) {
if (errno != EINTR) break;
} else {
if (stricmp(cmdline, "exit") == 0) break;
fflush(stdout);
exec_command(cmdline);
}
}
}
int execute_script(char *cmdfile) {
FILE *f;
char cmdline[256];
int echo;
echo = get_numeric_property(osconfig(), "shell", "echo", 0);
f = fopen(cmdfile, "r");
if (!f) {
perror(cmdfile);
return -errno;
}
while (fgets(cmdline, sizeof cmdline, f)) {
if (*cmdline == ';' || *cmdline == '#') continue;
if (echo) fwrite(cmdline, strlen(cmdline), 1, stdout);
if (strchr(cmdline, '\r')) *strchr(cmdline, '\r') = 0;
if (strchr(cmdline, '\n')) *strchr(cmdline, '\n') = 0;
if (exec_command(cmdline) < 0) break;
}
fclose(f);
return 0;
}
int main(int argc, char *argv[]) {
if (gettib()->proc->term->type == TERM_VT100) setvbuf(stdout, NULL, 0, 8192);
if (argc > 1) {
char *cmdline = gettib()->proc->cmdline;
while (*cmdline != ' ') {
if (!*cmdline) return 0;
cmdline++;
}
while (*cmdline == ' ') cmdline++;
return exec_command(cmdline);
} else {
shell();
}
setbuf(stdout, NULL);
return 0;
}