summaryrefslogtreecommitdiff
path: root/user/shell.c
diff options
context:
space:
mode:
authorFreya Murphy <freya@freyacat.org>2025-04-21 16:45:28 -0400
committerFreya Murphy <freya@freyacat.org>2025-04-21 16:45:33 -0400
commitceb9471fed96f907e37a6ba031825c31167a8ff4 (patch)
treed98392e420b4541a6ba926ff4d8b3ebe85734580 /user/shell.c
parentupdate linker scripts (diff)
downloadcomus-ceb9471fed96f907e37a6ba031825c31167a8ff4.tar.gz
comus-ceb9471fed96f907e37a6ba031825c31167a8ff4.tar.bz2
comus-ceb9471fed96f907e37a6ba031825c31167a8ff4.zip
update userland to compile
Diffstat (limited to 'user/shell.c')
-rw-r--r--user/shell.c346
1 files changed, 0 insertions, 346 deletions
diff --git a/user/shell.c b/user/shell.c
deleted file mode 100644
index f8c13cd..0000000
--- a/user/shell.c
+++ /dev/null
@@ -1,346 +0,0 @@
-#include <common.h>
-
-// should we keep going?
-static bool_t time_to_stop = false;
-
-// number of spawned but uncollected children
-static int children = 0;
-
-/*
-** For the test programs in the baseline system, command-line arguments
-** follow these rules. The first two entries are as follows:
-**
-** argv[0] the name used to "invoke" this process
-** argv[1] the "character to print" (identifies the process)
-**
-** Most user programs have one or more additional arguments.
-**
-** See the comment at the beginning of each user-code source file for
-** information on the argument list that code expects.
-*/
-
-/*
-** "Spawn table" process entry. Similar to that in init.c,
-** except this one has no place to store the PID of the child.
-*/
-typedef struct proc_s {
- uint_t index; // process table index
- int8_t prio; // process priority
- char select[3]; // identifying character, NUL, extra
- char *args[N_ARGS]; // argument vector strings
-} proc_t;
-
-/*
-** Create a spawn table entry for a process with a string literal
-** as its argument buffer. We rely on the fact that the C standard
-** ensures our array of pointers will be filled out with NULLs
-*/
-#define PROCENT(e, p, s, ...) \
- { \
- e, p, s, \
- { \
- __VA_ARGS__, NULL \
- } \
- }
-
-// sentinel value for the end of the table - must be updated
-// if you have more than 90,210 user programs in the table
-#define TBLEND 90210
-
-/*
-** The spawn table contains entries for processes that are started
-** by the shell.
-*/
-static proc_t spawn_table[] = {
-
-// Users A-C each run ProgABC, which loops printing its character
-#if defined(SPAWN_A)
- PROCENT(ProgABC, PRIO_STD, "A", "userA", "A", "30"),
-#endif
-#if defined(SPAWN_B)
- PROCENT(ProgABC, PRIO_STD, "B", "userB", "B", "30"),
-#endif
-#if defined(SPAWN_C)
- PROCENT(ProgABC, PRIO_STD, "C", "userC", "C", "30"),
-#endif
-
-// Users D and E run ProgDE, which is like ProgABC but doesn't exit()
-#if defined(SPAWN_D)
- PROCENT(ProgDE, PRIO_STD, "D", "userD", "D", "20"),
-#endif
-#if defined(SPAWN_E)
- PROCENT(ProgDE, PRIO_STD, "E", "userE", "E", "20"),
-#endif
-
-// Users F and G run ProgFG, which sleeps between write() calls
-#if defined(SPAWN_F)
- PROCENT(ProgFG, PRIO_STD, "F", "userF", "F", "20"),
-#endif
-#if defined(SPAWN_G)
- PROCENT(ProgFG, PRIO_STD, "G", "userG", "G", "10"),
-#endif
-
-// User H tests reparenting of orphaned children
-#if defined(SPAWN_H)
- PROCENT(ProgH, PRIO_STD, "H", "userH", "H", "4"),
-#endif
-
-// User I spawns several children, kills one, and waits for all
-#if defined(SPAWN_I)
- PROCENT(ProgI, PRIO_STD, "I", "userI", "I"),
-#endif
-
-// User J tries to spawn 2 * N_PROCS children
-#if defined(SPAWN_J)
- PROCENT(ProgJ, PRIO_STD, "J", "userJ", "J"),
-#endif
-
-// Users K and L iterate spawning userX and sleeping
-#if defined(SPAWN_K)
- PROCENT(ProgKL, PRIO_STD, "K", "userK", "K", "8"),
-#endif
-#if defined(SPAWN_L)
- PROCENT(ProgKL, PRIO_STD, "L", "userL", "L", "5"),
-#endif
-
-// Users M and N spawn copies of userW and userZ via ProgMN
-#if defined(SPAWN_M)
- PROCENT(ProgMN, PRIO_STD, "M", "userM", "M", "5", "f"),
-#endif
-#if defined(SPAWN_N)
- PROCENT(ProgMN, PRIO_STD, "N", "userN", "N", "5", "t"),
-#endif
-
-// There is no user O
-
-// User P iterates, reporting system time and stats, and sleeping
-#if defined(SPAWN_P)
- PROCENT(ProgP, PRIO_STD, "P", "userP", "P", "3", "2"),
-#endif
-
-// User Q tries to execute a bad system call
-#if defined(SPAWN_Q)
- PROCENT(ProgQ, PRIO_STD, "Q", "userQ", "Q"),
-#endif
-
-// User R reports its PID, PPID, and sequence number; it
-// calls fork() but not exec(), with each child getting the
-// next sequence number, to a total of five copies
-#if defined(SPAWN_R)
- PROCENT(ProgR, PRIO_STD, "R", "userR", "R", "20", "1"),
-#endif
-
-// User S loops forever, sleeping 13 sec. on each iteration
-#if defined(SPAWN_S)
- PROCENT(ProgS, PRIO_STD, "S", "userS", "S", "13"),
-#endif
-
-// Users T-V run ProgTUV(); they spawn copies of userW
-// User T waits for any child
-// User U waits for each child by PID
-// User V kills each child
-#if defined(SPAWN_T)
- PROCENT(ProgTUV, PRIO_STD, "T", "userT", "T", "6", "w"),
-#endif
-#if defined(SPAWN_U)
- PROCENT(ProgTUV, PRIO_STD, "U", "userU", "U", "6", "W"),
-#endif
-#if defined(SPAWN_V)
- PROCENT(ProgTUV, PRIO_STD, "V", "userV", "V", "6", "k"),
-#endif
-
- // a dummy entry to use as a sentinel
- { TBLEND }
-
- // these processes are spawned by the ones above, and are never
- // spawned directly.
-
- // PROCENT( ProgW, PRIO_STD, "?", "userW", "W", "20", "3" ),
- // PROCENT( ProgX, PRIO_STD, "?", "userX", "X", "20" ),
- // PROCENT( ProgY, PRIO_STD, "?", "userY", "Y", "10" ),
- // PROCENT( ProgZ, PRIO_STD, "?", "userZ", "Z", "10" )
-};
-
-/*
-** usage function
-*/
-static void usage(void)
-{
- swrites("\nTests - run with '@x', where 'x' is one or more of:\n ");
- proc_t *p = spawn_table;
- while (p->index != TBLEND) {
- swritech(' ');
- swritech(p->select[0]);
- }
- swrites("\nOther commands: @* (all), @h (help), @x (exit)\n");
-}
-
-/*
-** run a program from the program table, or a builtin command
-*/
-static int run(char which)
-{
- char buf[128];
- register proc_t *p;
-
- if (which == 'h') {
- // builtin "help" command
- usage();
-
- } else if (which == 'x') {
- // builtin "exit" command
- time_to_stop = true;
-
- } else if (which == '*') {
- // torture test! run everything!
- for (p = spawn_table; p->index != TBLEND; ++p) {
- int status = spawn(p->index, p->args);
- if (status > 0) {
- ++children;
- }
- }
-
- } else {
- // must be a single test; find and run it
- for (p = spawn_table; p->index != TBLEND; ++p) {
- if (p->select[0] == which) {
- // found it!
- int status = spawn(p->index, p->args);
- if (status > 0) {
- ++children;
- }
- return status;
- }
- }
-
- // uh-oh, made it through the table without finding the program
- sprint(buf, "shell: unknown cmd '%c'\n", which);
- swrites(buf);
- usage();
- }
-
- return 0;
-}
-
-/**
-** edit - perform any command-line editing we need to do
-**
-** @param line Input line buffer
-** @param n Number of valid bytes in the buffer
-*/
-static int edit(char line[], int n)
-{
- char *ptr = line + n - 1; // last char in buffer
-
- // strip the EOLN sequence
- while (n > 0) {
- if (*ptr == '\n' || *ptr == '\r') {
- --n;
- } else {
- break;
- }
- }
-
- // add a trailing NUL byte
- if (n > 0) {
- line[n] = '\0';
- }
-
- return n;
-}
-
-/**
-** shell - extremely simple shell for spawning test programs
-**
-** Scheduled by _kshell() when the character 'u' is typed on
-** the console keyboard.
-*/
-USERMAIN(main)
-{
- // keep the compiler happy
- (void)argc;
- (void)argv;
-
- // report that we're up and running
- swrites("Shell is ready\n");
-
- // print a summary of the commands we'll accept
- usage();
-
- // loop forever
- while (!time_to_stop) {
- char line[128];
- char *ptr;
-
- // the shell reads one line from the keyboard, parses it,
- // and performs whatever command it requests.
-
- swrites("\n> ");
- int n = read(CHAN_SIO, line, sizeof(line));
-
- // shortest valid command is "@?", so must have 3+ chars here
- if (n < 3) {
- // ignore it
- continue;
- }
-
- // edit it as needed; new shortest command is 2+ chars
- if ((n = edit(line, n)) < 2) {
- continue;
- }
-
- // find the '@'
- int i = 0;
- for (ptr = line; i < n; ++i, ++ptr) {
- if (*ptr == '@') {
- break;
- }
- }
-
- // did we find an '@'?
- if (i < n) {
- // yes; process any commands that follow it
- ++ptr;
-
- for (; *ptr != '\0'; ++ptr) {
- char buf[128];
- int pid = run(*ptr);
-
- if (pid < 0) {
- // spawn() failed
- sprint(buf, "+++ Shell spawn %c failed, code %d\n", *ptr,
- pid);
- cwrites(buf);
- }
-
- // should we end it all?
- if (time_to_stop) {
- break;
- }
- } // for
-
- // now, wait for all the spawned children
- while (children > 0) {
- // wait for the child
- int32_t status;
- char buf[128];
- int whom = waitpid(0, &status);
-
- // figure out the result
- if (whom == E_NO_CHILDREN) {
- break;
- } else if (whom < 1) {
- sprint(buf, "shell: waitpid() returned %d\n", whom);
- } else {
- --children;
- sprint(buf, "shell: PID %d exit status %d\n", whom, status);
- }
- // report it
- swrites(buf);
- }
- } // if i < n
- } // while
-
- cwrites("!!! shell exited loop???\n");
- exit(1);
-}