3 * \brief fish - Shell commands
7 * Copyright (c) 2007, 2008, 2009, 2010, 2011, 2012, ETH Zurich.
10 * This file is distributed under the terms in the attached LICENSE file.
11 * If you do not find this file, copies can be found by writing to:
12 * ETH Zurich D-INFK, CAB F.78, Universitaetstr. 6, CH-8092 Zurich,
13 * Attn: Systems Group.
22 #include <barrelfish/barrelfish.h>
23 #include <barrelfish/dispatch.h>
24 #include <barrelfish_kpi/init.h>
25 #include <barrelfish/debug.h>
26 #include <barrelfish/monitor_client.h>
27 #include <barrelfish/nameservice_client.h>
28 #include <barrelfish/spawn_client.h>
29 #include <barrelfish/terminal.h>
30 #include <trace/trace.h>
31 #include <trace_definitions/trace_defs.h>
34 #include <vfs/vfs_path.h>
35 #include <if/pixels_defs.h>
37 #include <if/octopus_rpcclient_defs.h>
38 #include <octopus/getset.h> // for oct_read TODO
39 #include <octopus/trigger.h> // for NOP_TRIGGER
40 #include <octopus/init.h> // oct_init
45 #define BOOTSCRIPT_NAME "/init.fish"
47 #define ENTRIES(array) (sizeof(array) / sizeof(array[0]))
49 extern char **environ;
50 static struct cmd *find_command(const char *name);
51 static int makeargs(char *cmdline, char *argv[]);
53 typedef int (*Command)(int argc, char *argv[]);
55 static int spawnpixels(int argc, char *argv[]);
65 static int help(int argc, char *argv[]);
67 static int execute_program(coreid_t coreid, int argc, char *argv[],
68 domainid_t *retdomainid)
73 // if the name contains a directory separator, assume it is relative to PWD
75 if (strchr(argv[0], VFS_PATH_SEP) != NULL) {
76 prog = vfs_path_mkabsolute(cwd, argv[0]);
79 err = vfs_open(prog, &vh);
80 if (err_is_fail(err)) {
81 printf("%s: file not found: %s\n", prog, err_getstring(err));
88 assert(retdomainid != NULL);
90 // inherit the session capability
91 struct capref inheritcn_cap;
92 err = alloc_inheritcn_with_caps(&inheritcn_cap, NULL_CAP, cap_sessionid, NULL_CAP);
93 if (err_is_fail(err)) {
94 USER_PANIC_ERR(err, "Error allocating inherit CNode with session cap.");
98 err = spawn_program_with_caps(coreid, prog, argv, NULL, inheritcn_cap,
99 NULL_CAP, SPAWN_FLAGS_NEW_DOMAIN, retdomainid);
101 if (prog != argv[0]) {
105 if (err_is_fail(err)) {
106 printf("%s: error spawning: %s\n", argv[0], err_getstring(err));
107 DEBUG_ERR(err, "Spawning Error\n");
114 static int quit(int argc, char *argv[])
117 assert(!"exit() returned");
121 static int print_cspace(int argc, char *argv[])
127 static int debug_print_caps(int argc, char *argv[]) {
128 monitor_debug_print_cababilities();
132 static int setenvcmd(int argc, char *argv[])
135 printf("Usage: %s [name=value]...\n", argv[0]);
139 for (int i=1; i < argc; i++) {
140 char *sep = strchr(argv[i], '=');
143 *sep = '\0'; // XXX: modify arg inplace
146 int r = setenv(argv[i], value, 1);
148 fprintf(stderr, "Error: setenv(%s, %s) failed\n", argv[i], value);
156 static int printenv(int argc, char *argv[])
159 for (int i=0; environ[i] != NULL; i++) {
160 printf("%s\n", environ[i]);
163 for (int i = 1; i < argc; i++) {
164 char *val = getenv(argv[i]);
174 static bool pixels_started = false;
175 static bool pixels_inited = false;
176 static int pixels_connected = 0;
177 #define NUM_PIXELS 16
178 static struct pixels_binding my_pixels_bindings[NUM_PIXELS];
182 static void pixels_ack(struct pixels_binding *cl)
187 static struct pixels_rx_vtbl pixels_vtbl = {
191 static void my_pixels_bind_cb(void *st, errval_t err, struct pixels_binding *b)
193 struct pixels_binding *pb = (struct pixels_binding *)st;
195 if (err_is_fail(err)) {
196 USER_PANIC_ERR(err, "bind failed");
199 pb->rx_vtbl = pixels_vtbl;
203 static void pixels_init(void)
205 // ensure pixels is up
206 if (!pixels_started) {
207 printf("Starting pixels...\n");
208 spawnpixels(0, NULL);
211 pixels_connected = 0;
213 for (int core = 0; core < NUM_PIXELS; core ++) {
218 sprintf(name, "pixels.%d", core);
220 /* Connect to the server */
221 err = nameservice_blocking_lookup(name, &serv_iref);
222 if (err_is_fail(err)) {
223 DEBUG_ERR(err, "failed to lookup server");
227 if (serv_iref == 0) {
228 DEBUG_ERR(err, "failed to get a valid iref back from lookup");
232 err = pixels_bind(serv_iref,
234 &my_pixels_bindings[core],
235 get_default_waitset(),
236 IDC_BIND_FLAGS_DEFAULT);
237 if (err_is_fail(err)) {
238 DEBUG_ERR(err, "bind request to pixels server failed immediately");
243 while (pixels_connected < NUM_PIXELS)
244 messages_wait_and_handle_next();
246 printf("connected to pixels server\n");
247 pixels_inited = true;
250 static const char *scroller = "Barrelfish posse in full effect!!! ";
252 static char c64map(char c) {
253 if ('A' <= c && c <= 'Z') {
255 } else if ('a' <= c && c <= 'z') {
257 } else if (c == ' ') {
259 } else if (c == '!') {
265 extern const char font[];
267 #define RENDER_WIDTH 48
268 #define PIXEL_WIDTH 100000
271 static int demo(int argc, char *argv[])
274 int pixwidth = PIXEL_WIDTH;
277 if (!pixels_inited) pixels_init();
280 pixwidth = atoi(argv[1]);
281 frames = atoi(argv[2]);
283 int width = 8 * strlen(scroller);
285 for (int x = 0; x < width - RENDER_WIDTH; x++) {
287 // Repeat each frame a few times to slow down scrolling!
288 for (int f = 0; f < frames; f++) {
289 trace_event(TRACE_SUBSYS_BENCH, TRACE_EVENT_BENCH_PCBENCH, 1);
290 for(int i = 0; i < RENDER_WIDTH; i++) {
292 int xpos = (x + i)%width;
293 char ascii = scroller[xpos >> 3];
294 char c64char = c64map(ascii);
298 for (core = 0 ;core < 8; core++) {
299 unsigned char bits = font[c64char*8 + (7-core)];
301 if (bits & (1<<(7-xsub)) ) {
303 my_pixels_bindings[core+2].tx_vtbl.display(&my_pixels_bindings[core+2], NOP_CONT, pixwidth);
308 uint64_t now = rdtsc();
311 messages_wait_and_handle_next();
313 while (rdtsc() - now < pixwidth) ;
316 trace_event(TRACE_SUBSYS_BENCH, TRACE_EVENT_BENCH_PCBENCH, 0);
322 static int oncore(int argc, char *argv[])
325 printf("Usage: %s <core id> <program> [args]\n", argv[0]);
329 int core = atoi(argv[1]);
334 domainid_t domain_id;
335 int ret = execute_program(core, argc, argv, &domain_id);
337 // TODO: do something with domain_id
342 static int spawnpixels(int argc, char *argv[])
346 /* Spawn on all cores */
347 char *spawnargv[] = {"pixels", NULL};
348 err = spawn_program_on_all_cores(true, spawnargv[0], spawnargv, NULL,
349 SPAWN_FLAGS_DEFAULT, NULL, NULL);
350 if (err_is_fail(err)) {
351 USER_PANIC_ERR(err, "error spawning other core");
353 pixels_started = true;
359 static int ps(int argc, char *argv[])
365 err = spawn_get_domain_list(&domains, &len);
366 if (err_is_fail(err)) {
367 DEBUG_ERR(err, "spawn_get_domain_list");
371 printf("DOMAINID\tSTAT\tCOMMAND\n");
372 for(size_t i = 0; i < len; i++) {
373 struct spawn_ps_entry pse;
374 char *argbuf, status;
378 err = spawn_get_status(domains[i], &pse, &argbuf, &arglen, &reterr);
379 if (err_is_fail(err)) {
380 DEBUG_ERR(err, "spawn_get_status");
383 if(err_is_fail(reterr)) {
384 if(err_no(reterr) == SPAWN_ERR_DOMAIN_NOTFOUND) {
387 DEBUG_ERR(err, "status");
405 printf("%-8u\t%c\t", domains[i], status);
407 for(int p = 0; pos < arglen && p < MAX_CMDLINE_ARGS;) {
408 printf("%s ", &argbuf[pos]);
409 char *end = memchr(&argbuf[pos], '\0', arglen - pos);
411 pos = end - argbuf + 1;
422 static int skb(int argc, char *argv[])
424 static bool init = false;
427 printf("Usage: %s <program>\n", argv[0]);
432 skb_client_connect();
436 char *result = NULL, *str_err = NULL;
439 skb_evaluate(argv[1], &result, &str_err, &int_err);
441 if (int_err != 0 || (str_err != NULL && str_err[0] != '\0')) {
442 printf("SKB error returned: %"PRIu32" %s\n", int_err, str_err);
444 printf("SKB returned: %s\n", result);
453 static int mount(int argc, char *argv[])
456 printf("Usage: %s MOUNTPOINT URI\n", argv[0]);
460 char *path = vfs_path_mkabsolute(cwd, argv[1]);
461 errval_t err = vfs_mount(path, argv[2]);
463 if (err_is_fail(err)) {
464 DEBUG_ERR(err, "in vfs_mount %s %s", argv[1], argv[2]);
470 static int cat(int argc, char *argv[])
473 printf("Usage: %s [file...]\n", argv[0]);
481 int ret = EXIT_SUCCESS;
483 for (int i = 1; i < argc; i++) {
484 char *path = vfs_path_mkabsolute(cwd, argv[i]);
485 err = vfs_open(path, &vh);
487 if (err_is_fail(err)) {
488 printf("%s: file not found\n", argv[i]);
494 err = vfs_read(vh, buf, sizeof(buf), &size);
495 if (err_is_fail(err)) {
496 // XXX: Close any files that might be open
497 DEBUG_ERR(err, "error reading file");
501 fwrite(buf, 1, size, stdout);
505 if (err_is_fail(err)) {
506 DEBUG_ERR(err, "in vfs_close");
514 static int hd(int argc, char *argv[])
517 printf("Usage: %s [file...]\n", argv[0]);
525 int ret = EXIT_SUCCESS;
527 for (int i = 1; i < argc; i++) {
528 char *path = vfs_path_mkabsolute(cwd, argv[i]);
529 err = vfs_open(path, &vh);
531 if (err_is_fail(err)) {
532 printf("%s: file not found\n", argv[i]);
537 printf("Contents of %s\n", argv[i]);
540 err = vfs_read(vh, buf, sizeof(buf), &size);
541 if (err_is_fail(err)) {
542 // XXX: Close any files that might be open
543 DEBUG_ERR(err, "error reading file");
547 for (int j = k%LINE_SIZE; j < size; j++) {
548 if (j % LINE_SIZE == 0) {
549 printf("%08X: ", k+j);
551 printf("%02x%s", buf[j], (j+1)%LINE_SIZE == 0 ? "\n" : " ");
560 if (err_is_fail(err)) {
561 DEBUG_ERR(err, "in vfs_close");
568 static int cat2(int argc, char *argv[])
575 printf("Usage: %s [input-files...] output-file\n", argv[0]);
579 /* Open output file creating it if it does not exist */
580 path = vfs_path_mkabsolute(cwd, argv[argc - 1]);
581 vfs_handle_t output_vh;
582 err = vfs_create(path, &output_vh);
584 if (err_is_fail(err)) {
585 DEBUG_ERR(err, "error opening output file");
589 /* Open input files, read buffer and write to output file */
590 for (int i = 1; i < argc - 1; i++) {
593 vfs_handle_t input_vh;
594 path = vfs_path_mkabsolute(cwd, argv[i]);
595 err = vfs_open(path, &input_vh);
597 if (err_is_fail(err)) {
598 printf("%s: file not found\n", argv[i]);
604 err = vfs_read(input_vh, buf, sizeof(buf), &size);
605 if (err_is_fail(err)) {
606 // XXX: Close any files that might be open
607 DEBUG_ERR(err, "error reading file");
612 err = vfs_write(output_vh, buf, size, &output_size);
613 if (err_is_fail(err)) {
614 // XXX: Close any files that might be open
615 DEBUG_ERR(err, "error writing to output file");
618 if (output_size != size) {
619 printf("Wanted to write %zu but only wrote %zu, aborting\n",
621 // XXX: Close any files that might be open
626 err = vfs_close(input_vh);
627 if (err_is_fail(err)) {
628 DEBUG_ERR(err, "in vfs_close");
632 err = vfs_close(output_vh);
633 if (err_is_fail(err)) {
634 DEBUG_ERR(err, "in vfs_close");
639 static int cp(int argc, char *argv[])
642 printf("Usage: %s src dest\n", argv[0]);
646 static uint8_t buf[32768];
648 vfs_handle_t src = NULL, dst = NULL;
650 int ret = EXIT_SUCCESS;
652 char *path = vfs_path_mkabsolute(cwd, argv[1]);
653 err = vfs_open(path, &src);
655 if (err_is_fail(err)) {
656 printf("%s: %s\n", argv[1], err_getstring(err));
660 path = vfs_path_mkabsolute(cwd, argv[2]);
661 err = vfs_create(path, &dst);
663 if (err_is_fail(err)) {
664 printf("%s: %s\n", argv[2], err_getstring(err));
669 err = vfs_truncate(dst, 0);
670 if (err_is_fail(err)) {
671 printf("truncate %s: %s\n", argv[2], err_getstring(err));
677 err = vfs_read(src, buf, sizeof(buf), &rsize);
678 if (err_is_fail(err)) {
679 DEBUG_ERR(err, "error reading file");
685 while (wpos < rsize) {
686 err = vfs_write(dst, &buf[wpos], rsize - wpos, &wsize);
687 if (err_is_fail(err) || wsize == 0) {
688 DEBUG_ERR(err, "error writing file");
698 err = vfs_close(src);
699 if (err_is_fail(err)) {
700 DEBUG_ERR(err, "in vfs_close");
705 err = vfs_close(dst);
706 if (err_is_fail(err)) {
707 DEBUG_ERR(err, "in vfs_close");
714 static int dd(int argc, char *argv[])
720 vfs_handle_t source_vh = NULL;
721 vfs_handle_t target_vh = NULL;
723 size_t blocksize = 512;
730 size_t blocks_written = 0;
732 size_t total_bytes_read = 0;
733 size_t total_bytes_written = 0;
738 int ret = EXIT_SUCCESS;
740 for (int i = 1; i < argc; i++)
742 if (!strncmp(argv[i], "bs=", 3))
743 blocksize = atoi(argv[i] + 3);
745 else if (!strncmp(argv[i], "count=", 6))
746 count = atoi(argv[i] + 6);
748 else if (!strncmp(argv[i], "skip=", 5))
749 skip = atoi(argv[i] + 5);
751 else if (!strncmp(argv[i], "seek=", 5))
752 seek = atoi(argv[i] + 5);
754 else if (!strncmp(argv[i], "if=", 3))
755 source = (argv[i] + 3);
757 else if (!strncmp(argv[i], "of=", 3))
758 target = (argv[i] + 3);
759 else if (!strncmp(argv[i], "progress", 8))
763 size_t one_per_cent = (blocksize * count) / 100;
765 printf("from: %s to: %s bs=%zd count=%zd seek=%zd skip=%zd\n", source, target, blocksize, count, seek, skip);
769 char *path = vfs_path_mkabsolute(cwd, source);
770 err = vfs_open(path, &source_vh);
772 if (err_is_fail(err)) {
773 printf("%s: %s\n", source, err_getstring(err));
785 char *path = vfs_path_mkabsolute(cwd, target);
786 err = vfs_create(path, &target_vh);
788 if (err_is_fail(err)) {
789 // close source handle
790 if (source_vh != NULL)
791 vfs_close(source_vh);
792 printf("%s: %s\n", target, err_getstring(err));
802 uint8_t * buffer = malloc(blocksize);
804 #if defined(__x86_64__) || defined(__i386__)
806 err = sys_debug_get_tsc_per_ms(&tscperms);
807 assert(err_is_ok(err));
809 //printf("ticks per millisec: %" PRIu64 "\n", tscperms);
810 uint64_t start = rdtsc();
816 printf("failed to allocate buffer of size %zd\n", blocksize);
822 //printf("copying block\n");
823 size_t read_bytes = 0;
825 err = vfs_read(source_vh, buffer, blocksize, &rsize);
826 if (err_is_fail(err)) {
827 DEBUG_ERR(err, "error reading file");
832 total_bytes_read += rsize;
836 while (wpos < rsize) {
838 printf("was unable to write the whole chunk of size %zd. Now at pos: %zd of buffer\n", rsize, wpos);
840 err = vfs_write(target_vh, &buffer[wpos], rsize - wpos, &wsize);
841 if (err_is_fail(err) || wsize == 0) {
842 DEBUG_ERR(err, "error writing file");
847 total_bytes_written += wsize;
849 } while(read_bytes < blocksize);
853 if (progress && one_per_cent && total_bytes_written % one_per_cent == 0) {
857 //printf("block successfully copied. read: %zd. blocks written: %zd\n", rsize, blocks_written);
858 } while (rsize > 0 && !(count > 0 && blocks_written >= count));
860 if (progress) printf("\n");
866 if (source_vh != NULL) {
867 err = vfs_close(source_vh);
868 if (err_is_fail(err)) {
869 DEBUG_ERR(err, "in vfs_close");
873 if (target_vh != NULL) {
874 err = vfs_close(target_vh);
875 if (err_is_fail(err)) {
876 DEBUG_ERR(err, "in vfs_close");
880 #if defined(__x86_64__) || defined(__i386__)
881 uint64_t stop = rdtsc();
882 uint64_t elapsed_msecs = ((stop - start) / tscperms);
883 double elapsed_secs = (double)elapsed_msecs/1000.0;
885 printf("start: %" PRIu64 " stop: %" PRIu64 "\n", start, stop);
887 double kbps = ((double)total_bytes_written / 1024.0) / elapsed_secs;
889 printf("%zd bytes read. %zd bytes written. %f s, %f kB/s\n", total_bytes_read, total_bytes_written, elapsed_secs, kbps);
891 printf("%zd bytes read. %zd bytes written.\n", total_bytes_read, total_bytes_written);
897 static int touch(int argc, char *argv[])
900 printf("Usage: %s [file...]\n", argv[0]);
906 int ret = EXIT_SUCCESS;
908 for (int i = 1; i < argc; i++) {
909 char *path = vfs_path_mkabsolute(cwd, argv[i]);
910 err = vfs_create(path, &vh);
912 if (err_is_fail(err)) {
913 printf("%s: %s\n", argv[i], err_getstring(err));
914 DEBUG_ERR(err, "vfs_create failed");
920 if (err_is_fail(err)) {
921 DEBUG_ERR(err, "in vfs_close");
928 static char vfs_type_char(enum vfs_filetype type)
940 static int ls(int argc, char *argv[])
943 int ret = EXIT_SUCCESS;
945 // XXX: cheat and assume we have some extra space wherever argv lives
951 for (int i = 1; i < argc; i++) {
953 char *path = vfs_path_mkabsolute(cwd, argv[i]);
954 err = vfs_opendir(path, &vh);
956 if (err_is_fail(err)) {
957 DEBUG_ERR(err, "in vfs_opendir %s", argv[i]);
958 printf("%s: not found\n", argv[i]);
966 printf("%s:\n", argv[i]);
969 struct vfs_fileinfo info;
971 err = vfs_dir_read_next(vh, &name, &info);
972 if (err_is_ok(err)) {
973 printf("%8zu %c %s\n", info.size, vfs_type_char(info.type),
977 } while(err_is_ok(err));
979 err = vfs_closedir(vh);
980 if (err_is_fail(err)) {
981 DEBUG_ERR(err, "in vfs_closedir");
988 static int mkdir(int argc, char *argv[])
991 printf("Usage: %s dir\n", argv[0]);
995 char *path = vfs_path_mkabsolute(cwd, argv[1]);
996 errval_t err = vfs_mkdir(path);
998 if (err_is_fail(err)) {
999 printf("%s\n", err_getstring(err));
1000 return EXIT_FAILURE;
1002 return EXIT_SUCCESS;
1006 static int rmdir(int argc, char *argv[])
1009 printf("Usage: %s dir\n", argv[0]);
1010 return EXIT_FAILURE;
1013 char *path = vfs_path_mkabsolute(cwd, argv[1]);
1014 errval_t err = vfs_rmdir(path);
1016 if (err_is_fail(err)) {
1017 printf("%s\n", err_getstring(err));
1018 return EXIT_FAILURE;
1020 return EXIT_SUCCESS;
1024 static int rm(int argc, char *argv[])
1027 printf("Usage: %s file...\n", argv[0]);
1028 return EXIT_FAILURE;
1031 int ret = EXIT_SUCCESS;
1033 for (int i = 1; i < argc; i++) {
1034 char *path = vfs_path_mkabsolute(cwd, argv[i]);
1035 errval_t err = vfs_remove(path);
1037 if (err_is_fail(err)) {
1038 printf("%s: %s\n", argv[i], err_getstring(err));
1046 static int cd(int argc, char *argv[])
1051 printf("Usage: %s DIR\n", argv[0]);
1052 return EXIT_FAILURE;
1055 char *newcwd = vfs_path_mkabsolute(cwd, argv[1]);
1057 // ensure directory exists, by attempting to open it
1059 err = vfs_opendir(newcwd, &dh);
1060 if (err_is_fail(err)) {
1061 printf("cd to %s (-> %s) failed: %s\n",
1062 argv[1], newcwd, err_getstring(err));
1064 return EXIT_FAILURE;
1072 return EXIT_SUCCESS;
1075 static int pwd(int argc, char *argv[])
1077 printf("%s\n", cwd);
1078 return EXIT_SUCCESS;
1081 static int mnfs(int argc, char *argv[])
1083 char *args1[2] = { "mkdir", "/nfs" };
1085 char *args2[3] = { "mount", "/nfs", "nfs://10.110.4.4/local/nfs" };
1086 return mount(3, args2);
1089 /// Open file(s) with a list of commands and execute them
1090 static int src(int argc, char *argv[])
1093 printf("Usage: %s file...\n", argv[0]);
1096 int ret = EXIT_SUCCESS;
1097 for (int i = 1; i < argc; i++) {
1098 char *path = vfs_path_mkabsolute(cwd, argv[i]);
1099 FILE *f = fopen(path, "r");
1101 printf("File %s not found\n", path);
1105 printf("Executing file %s\n", path);
1107 // Read one line at a time, make args out of it and execute it
1109 char buf[1024] = "\0";
1110 char *p = fgets(buf, 1024, f);
1115 char *q = strrchr(p, '\n');
1117 char *cmdstr = strdup(p);
1119 int cmd_argc = makeargs(cmdstr, cmd_argv);
1120 if (cmd_argc == 0) {
1124 struct cmd *cmd = find_command(cmd_argv[0]);
1127 printf("running command: %s\n", p);
1128 int r = cmd->cmd(cmd_argc, cmd_argv);
1130 printf("running command %s failed errorcode %d\n", p, r);
1140 static int freecmd(int argc, char *argv[])
1142 struct mem_rpc_client *mc = get_mem_client();
1145 genpaddr_t available, total;
1147 err = ram_available(&available, &total);
1148 if(err_is_fail(err)) {
1149 DEBUG_ERR(err, "available");
1150 return EXIT_FAILURE;
1153 printf("Free memory: %" PRIuGENPADDR " bytes\n", available);
1154 printf("Total memory: %" PRIuGENPADDR " bytes\n", total);
1156 return EXIT_SUCCESS;
1159 static int nproc(int argc, char* argv[]) {
1160 errval_t err, error_code;
1161 octopus_trigger_id_t tid;
1163 char** names = NULL;
1166 static char* spawnds = "r'spawn.[0-9]+' { iref: _ }";
1169 struct octopus_rpc_client *r = get_octopus_rpc_client();
1170 err = r->vtbl.get_names(r, spawnds, NOP_TRIGGER, &buffer, &tid, &error_code);
1171 if (err_is_fail(err) || err_is_fail(error_code)) {
1172 DEBUG_ERR(err, "get_names failed");
1176 err = oct_parse_names(buffer, &names, &count);
1177 if (err_is_fail(err)) {
1178 DEBUG_ERR(err, "parse_names failed.");
1184 oct_free_names(names, count);
1186 printf("%zx\n", count);
1187 return EXIT_SUCCESS;
1191 static struct cmd commands[] = {
1192 {"help", help, "Output usage information about given shell command"},
1193 {"print_cspace", print_cspace, "Debug print-out of my cspace"},
1194 {"quit", quit, "Quit the shell"},
1195 {"nproc", nproc, "Get amount of cores in system."},
1196 {"ps", ps, "List running processes"},
1197 {"demo", demo, "Run barrelfish demo"},
1198 {"pixels", spawnpixels, "Spawn pixels on all cores"},
1199 {"mnfs", mnfs, "Mount script for NFS on emmentaler"},
1200 {"oncore", oncore, "Start program on specified core"},
1201 {"reset", reset, "Reset machine"},
1202 {"poweroff", poweroff, "Power down machine"},
1203 {"skb", skb, "Send command to system knowledge base"},
1204 {"mount", mount, "Mount file system"},
1205 {"ls", ls, "List directory contents"},
1206 {"cd", cd, "Change working directory"},
1207 {"pwd", pwd, "Print current working directory"},
1208 {"touch", touch, "Create an empty file"},
1209 {"cat", cat, "Print the contents of file(s)"},
1210 {"hd", hd, "Print the contents of file(s) as hexdump"},
1211 {"cat2", cat2, "Print the contents of file(s) into another file"},
1212 {"dd", dd, "copy stuff"},
1213 {"cp", cp, "Copy files"},
1214 {"rm", rm, "Remove files"},
1215 {"mkdir", mkdir, "Create a new directory"},
1216 {"rmdir", rmdir, "Remove an existing directory"},
1217 {"setenv", setenvcmd, "Set environment variables"},
1218 {"src", src, "Execute the list of commands in a file"},
1219 {"printenv", printenv, "Display environment variables"},
1220 {"free", freecmd, "Display amount of free memory in the system"},
1221 {"debug_print_caps", debug_print_caps, "Display cspace debug information"},
1224 static void getline(char *input, size_t size)
1230 if (in == '\b' || in == 0x7f /* DEL */) {
1233 putchar('\b'); // FIXME: this kinda works on my terminal
1236 //fputs("\033[1X", stdout); // XXX: suitable for xterm
1238 } else if (in != '\n' && i < size - 1) {
1242 } while (in != '\n');
1249 static struct cmd *find_command(const char *name)
1251 for(int i = 0; i < ENTRIES(commands); i++) {
1252 struct cmd *cmd = &commands[i];
1254 if(strcmp(name, cmd->name) == 0) {
1262 static int help(int argc, char *argv[])
1267 printf("available commands:\n");
1268 for (int i=0; i < ENTRIES(commands); i++) {
1269 printf("%-15s", commands[i].name);
1270 if (((i + 1) % 5) == 0) {
1275 return EXIT_SUCCESS;
1278 if ((cmd = find_command(argv[1])) != NULL) {
1279 printf("%s: %s\n", argv[1], cmd->usage);
1280 return EXIT_SUCCESS;
1282 printf("%s: %s: command not found\n", argv[0], argv[1]);
1283 return EXIT_FAILURE;
1287 static int makeargs(char *cmdline, char *argv[])
1290 bool inquote = false;
1305 for(argv[argc++] = p; *p != '\0'; p++) {
1308 *p = ' '; // mega-kludge!
1309 } else if (*p == ' ' && !inquote) {
1311 // Skip any redundant whitespace
1319 *p = ' '; // mega-kludge
1328 static uint8_t wait_domain_id(domainid_t domainid)
1331 errval_t err = spawn_wait(domainid, &exitcode, false);
1332 if (err_is_fail(err)) {
1333 USER_PANIC_ERR(err, "spawn_wait");
1338 static void runbootscript(void)
1341 snprintf(cmdstr, 1024,"sh %s", BOOTSCRIPT_NAME);
1343 int cmd_argc = makeargs(cmdstr, cmd_argv);
1344 int ret = src(cmd_argc, cmd_argv);
1346 snprintf(cmdstr, 1024, "help");
1347 cmd_argc = makeargs(cmdstr, cmd_argv);
1348 help(cmd_argc, cmd_argv);
1353 int main(int argc, const char *argv[])
1355 char input[MAX_LINE];
1357 bool is_bootscript = true;
1358 coreid_t my_core_id = disp_get_core_id();
1362 for (int i = 1; i < argc; i++) {
1363 if (strcmp(argv[i], "nobootscript") == 0) {
1364 is_bootscript = false;
1370 printf("fish v0.2 -- pleased to meet you!\n");
1372 // run canned pre-boot commands
1373 if (is_bootscript) {
1379 char *cmd_argv[64]; // Support a max of 64 cmd args
1384 getline(input, MAX_LINE);
1385 cmd_argc = makeargs(input, cmd_argv);
1387 /* check for trailing '&' (== run in background) */
1390 size_t len = strlen(cmd_argv[cmd_argc - 1]);
1391 if (len > 0 && cmd_argv[cmd_argc - 1][len - 1] == '&') {
1393 // remove '&' character from args
1397 cmd_argv[cmd_argc - 1][len - 1] = '\0';
1402 if (cmd_argc == 0) {
1404 } else if ((cmd = find_command(cmd_argv[0])) != NULL) {
1405 exitcode = cmd->cmd(cmd_argc, cmd_argv);
1407 // Try loading a program off disk if VFS is initialized
1408 domainid_t domain_id;
1409 exitcode = execute_program(my_core_id, cmd_argc, cmd_argv, &domain_id);
1411 // wait if it succeeds
1412 if (exitcode == 0 && wait) {
1413 exitcode = wait_domain_id(domain_id);
1415 snprintf(exitstr, 128, "%u", exitcode);
1416 int r = setenv("EXITCODE", exitstr, 1);