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 <term/client/client_blocking.h>
31 #include <trace/trace.h>
32 #include <trace_definitions/trace_defs.h>
35 #include <vfs/vfs_path.h>
36 #include <if/pixels_defs.h>
38 #include <if/octopus_defs.h>
39 #include <octopus/getset.h> // for oct_read TODO
40 #include <octopus/trigger.h> // for NOP_TRIGGER
41 #include <octopus/init.h> // oct_init
43 #include <linenoise/linenoise.h>
48 #define BOOTSCRIPT_NAME "/init.fish"
50 #define ENTRIES(array) (sizeof(array) / sizeof(array[0]))
52 extern char **environ;
53 static struct cmd *find_command(const char *name);
54 static int makeargs(char *cmdline, char *argv[]);
56 typedef int (*Command)(int argc, char *argv[]);
58 static int spawnpixels(int argc, char *argv[]);
68 static struct capref inheritcn_cap;
70 static int help(int argc, char *argv[]);
72 static int execute_program(coreid_t coreid, int argc, char *argv[],
73 struct capref *ret_domain_cap)
78 // if the name contains a directory separator, assume it is relative to PWD
80 if (strchr(argv[0], VFS_PATH_SEP) != NULL) {
81 prog = vfs_path_mkabsolute(cwd, argv[0]);
84 err = vfs_open(prog, &vh);
85 if (err_is_fail(err)) {
86 printf("%s: file not found: %s\n", prog, err_getstring(err));
93 assert(ret_domain_cap != NULL);
96 err = spawn_program_with_caps(coreid, prog, argv, NULL, inheritcn_cap,
97 NULL_CAP, SPAWN_FLAGS_NEW_DOMAIN, ret_domain_cap);
99 if (prog != argv[0]) {
103 if (err_is_fail(err)) {
104 printf("%s: error spawning: %s\n", argv[0], err_getstring(err));
105 DEBUG_ERR(err, "Spawning Error\n");
112 static int quit(int argc, char *argv[])
115 assert(!"exit() returned");
119 static int print_cspace(int argc, char *argv[])
125 static int dump_caps(int argc, char *argv[]) {
128 domainid_t domain = strtol(argv[1], NULL, 10);
129 err = spawn_dump_capabilities_compat(domain);
131 dispatcher_handle_t handle = curdispatcher();
132 struct capref dcb = get_dispatcher_generic(handle)->dcb_cap;
133 err = invoke_dispatcher_dump_capabilities(dcb);
135 if (err_is_fail(err)) {
136 printf("%s: error dumping capabilities: %s\n", argv[0], err_getstring(err));
137 DEBUG_ERR(err, "Error\n");
145 static int setenvcmd(int argc, char *argv[])
148 printf("Usage: %s [name=value]...\n", argv[0]);
152 for (int i=1; i < argc; i++) {
153 char *sep = strchr(argv[i], '=');
156 *sep = '\0'; // XXX: modify arg inplace
159 int r = setenv(argv[i], value, 1);
161 fprintf(stderr, "Error: setenv(%s, %s) failed\n", argv[i], value);
169 static int printenv(int argc, char *argv[])
172 for (int i=0; environ[i] != NULL; i++) {
173 printf("%s\n", environ[i]);
176 for (int i = 1; i < argc; i++) {
177 char *val = getenv(argv[i]);
187 static bool pixels_started = false;
188 static bool pixels_inited = false;
189 static int pixels_connected = 0;
190 #define NUM_PIXELS 16
191 static struct pixels_binding my_pixels_bindings[NUM_PIXELS];
195 static void pixels_ack(struct pixels_binding *cl)
200 static struct pixels_rx_vtbl pixels_vtbl = {
204 static void my_pixels_bind_cb(void *st, errval_t err, struct pixels_binding *b)
206 struct pixels_binding *pb = (struct pixels_binding *)st;
208 if (err_is_fail(err)) {
209 USER_PANIC_ERR(err, "bind failed");
212 pb->rx_vtbl = pixels_vtbl;
216 static void pixels_init(void)
218 // ensure pixels is up
219 if (!pixels_started) {
220 printf("Starting pixels...\n");
221 spawnpixels(0, NULL);
224 pixels_connected = 0;
226 for (int core = 0; core < NUM_PIXELS; core ++) {
231 sprintf(name, "pixels.%d", core);
233 /* Connect to the server */
234 err = nameservice_blocking_lookup(name, &serv_iref);
235 if (err_is_fail(err)) {
236 DEBUG_ERR(err, "failed to lookup server");
240 if (serv_iref == 0) {
241 DEBUG_ERR(err, "failed to get a valid iref back from lookup");
245 err = pixels_bind(serv_iref,
247 &my_pixels_bindings[core],
248 get_default_waitset(),
249 IDC_BIND_FLAGS_DEFAULT);
250 if (err_is_fail(err)) {
251 DEBUG_ERR(err, "bind request to pixels server failed immediately");
256 while (pixels_connected < NUM_PIXELS)
257 messages_wait_and_handle_next();
259 printf("connected to pixels server\n");
260 pixels_inited = true;
263 static const char *scroller = "Barrelfish posse in full effect!!! ";
265 static char c64map(char c) {
266 if ('A' <= c && c <= 'Z') {
268 } else if ('a' <= c && c <= 'z') {
270 } else if (c == ' ') {
272 } else if (c == '!') {
278 extern const char font[];
280 #define RENDER_WIDTH 48
281 #define PIXEL_WIDTH 100000
284 static int demo(int argc, char *argv[])
287 int pixwidth = PIXEL_WIDTH;
290 if (!pixels_inited) pixels_init();
293 pixwidth = atoi(argv[1]);
294 frames = atoi(argv[2]);
296 int width = 8 * strlen(scroller);
298 for (int x = 0; x < width - RENDER_WIDTH; x++) {
300 // Repeat each frame a few times to slow down scrolling!
301 for (int f = 0; f < frames; f++) {
302 trace_event(TRACE_SUBSYS_BENCH, TRACE_EVENT_BENCH_PCBENCH, 1);
303 for(int i = 0; i < RENDER_WIDTH; i++) {
305 int xpos = (x + i)%width;
306 char ascii = scroller[xpos >> 3];
307 char c64char = c64map(ascii);
311 for (core = 0 ;core < 8; core++) {
312 unsigned char bits = font[c64char*8 + (7-core)];
314 if (bits & (1<<(7-xsub)) ) {
316 my_pixels_bindings[core+2].tx_vtbl.display(&my_pixels_bindings[core+2], NOP_CONT, pixwidth);
321 uint64_t now = rdtsc();
324 messages_wait_and_handle_next();
326 while (rdtsc() - now < pixwidth) ;
329 trace_event(TRACE_SUBSYS_BENCH, TRACE_EVENT_BENCH_PCBENCH, 0);
335 static int oncore(int argc, char *argv[])
338 printf("Usage: %s <core id> <program> [args]\n", argv[0]);
342 int core = atoi(argv[1]);
347 struct capref domain_cap;
348 int ret = execute_program(core, argc, argv, &domain_cap);
350 // TODO: do something with domain_id
355 static int spawnpixels(int argc, char *argv[])
359 /* Spawn on all cores */
360 char *spawnargv[] = {"pixels", NULL};
361 err = spawn_program_on_all_cores(true, spawnargv[0], spawnargv, NULL,
362 SPAWN_FLAGS_DEFAULT, NULL, NULL);
363 if (err_is_fail(err)) {
364 USER_PANIC_ERR(err, "error spawning other core");
366 pixels_started = true;
372 static int ps(int argc, char *argv[])
378 err = spawn_get_domain_list(&domains, &len);
379 if (err_is_fail(err)) {
380 DEBUG_ERR(err, "spawn_get_domain_list");
384 printf("DOMAINID\tSTAT\tCOMMAND\n");
385 for(size_t i = 0; i < len; i++) {
386 struct spawn_ps_entry pse;
387 char *argbuf, status;
391 err = spawn_get_status(domains[i], &pse, &argbuf, &arglen, &reterr);
392 if (err_is_fail(err)) {
393 DEBUG_ERR(err, "spawn_get_status");
396 if(err_is_fail(reterr)) {
397 if(err_no(reterr) == SPAWN_ERR_DOMAIN_NOTFOUND) {
400 DEBUG_ERR(err, "status");
418 printf("%-8u\t%c\t", domains[i], status);
420 for(int p = 0; pos < arglen && p < MAX_CMDLINE_ARGS;) {
421 printf("%s ", &argbuf[pos]);
422 char *end = memchr(&argbuf[pos], '\0', arglen - pos);
424 pos = end - argbuf + 1;
435 static int skb(int argc, char *argv[])
437 static bool init = false;
440 printf("Usage: %s <program>\n", argv[0]);
445 skb_client_connect();
449 char *result = NULL, *str_err = NULL;
452 skb_evaluate(argv[1], &result, &str_err, &int_err);
454 if (int_err != 0 || (str_err != NULL && str_err[0] != '\0')) {
455 printf("SKB error returned: %"PRIu32" %s\n", int_err, str_err);
457 printf("SKB returned: %s\n", result);
466 static int mount(int argc, char *argv[])
469 printf("Usage: %s MOUNTPOINT URI\n", argv[0]);
473 char *path = vfs_path_mkabsolute(cwd, argv[1]);
474 errval_t err = vfs_mount(path, argv[2]);
476 if (err_is_fail(err)) {
477 DEBUG_ERR(err, "in vfs_mount %s %s", argv[1], argv[2]);
483 static int cat(int argc, char *argv[])
486 printf("Usage: %s [file...]\n", argv[0]);
494 int ret = EXIT_SUCCESS;
496 for (int i = 1; i < argc; i++) {
497 char *path = vfs_path_mkabsolute(cwd, argv[i]);
498 err = vfs_open(path, &vh);
500 if (err_is_fail(err)) {
501 printf("%s: file not found\n", argv[i]);
507 err = vfs_read(vh, buf, sizeof(buf), &size);
508 if (err_is_fail(err)) {
509 // XXX: Close any files that might be open
510 DEBUG_ERR(err, "error reading file");
514 fwrite(buf, 1, size, stdout);
518 if (err_is_fail(err)) {
519 DEBUG_ERR(err, "in vfs_close");
527 static int hd(int argc, char *argv[])
530 printf("Usage: %s [file...]\n", argv[0]);
538 int ret = EXIT_SUCCESS;
540 for (int i = 1; i < argc; i++) {
541 char *path = vfs_path_mkabsolute(cwd, argv[i]);
542 err = vfs_open(path, &vh);
544 if (err_is_fail(err)) {
545 printf("%s: file not found\n", argv[i]);
550 printf("Contents of %s\n", argv[i]);
553 err = vfs_read(vh, buf, sizeof(buf), &size);
554 if (err_is_fail(err)) {
555 // XXX: Close any files that might be open
556 DEBUG_ERR(err, "error reading file");
560 for (int j = k%LINE_SIZE; j < size; j++) {
561 if (j % LINE_SIZE == 0) {
562 printf("%08X: ", k+j);
564 printf("%02x%s", buf[j], (j+1)%LINE_SIZE == 0 ? "\n" : " ");
573 if (err_is_fail(err)) {
574 DEBUG_ERR(err, "in vfs_close");
581 static int cat2(int argc, char *argv[])
588 printf("Usage: %s [input-files...] output-file\n", argv[0]);
592 /* Open output file creating it if it does not exist */
593 path = vfs_path_mkabsolute(cwd, argv[argc - 1]);
594 vfs_handle_t output_vh;
595 err = vfs_create(path, &output_vh);
597 if (err_is_fail(err)) {
598 DEBUG_ERR(err, "error opening output file");
602 /* Open input files, read buffer and write to output file */
603 for (int i = 1; i < argc - 1; i++) {
606 vfs_handle_t input_vh;
607 path = vfs_path_mkabsolute(cwd, argv[i]);
608 err = vfs_open(path, &input_vh);
610 if (err_is_fail(err)) {
611 printf("%s: file not found\n", argv[i]);
617 err = vfs_read(input_vh, buf, sizeof(buf), &size);
618 if (err_is_fail(err)) {
619 // XXX: Close any files that might be open
620 DEBUG_ERR(err, "error reading file");
625 err = vfs_write(output_vh, buf, size, &output_size);
626 if (err_is_fail(err)) {
627 // XXX: Close any files that might be open
628 DEBUG_ERR(err, "error writing to output file");
631 if (output_size != size) {
632 printf("Wanted to write %zu but only wrote %zu, aborting\n",
634 // XXX: Close any files that might be open
639 err = vfs_close(input_vh);
640 if (err_is_fail(err)) {
641 DEBUG_ERR(err, "in vfs_close");
645 err = vfs_close(output_vh);
646 if (err_is_fail(err)) {
647 DEBUG_ERR(err, "in vfs_close");
652 static int cp(int argc, char *argv[])
655 printf("Usage: %s src dest\n", argv[0]);
659 static uint8_t buf[32768];
661 vfs_handle_t src = NULL, dst = NULL;
663 int ret = EXIT_SUCCESS;
665 char *path = vfs_path_mkabsolute(cwd, argv[1]);
666 err = vfs_open(path, &src);
668 if (err_is_fail(err)) {
669 printf("%s: %s\n", argv[1], err_getstring(err));
673 path = vfs_path_mkabsolute(cwd, argv[2]);
674 err = vfs_create(path, &dst);
676 if (err_is_fail(err)) {
677 printf("%s: %s\n", argv[2], err_getstring(err));
682 err = vfs_truncate(dst, 0);
683 if (err_is_fail(err)) {
684 printf("truncate %s: %s\n", argv[2], err_getstring(err));
690 err = vfs_read(src, buf, sizeof(buf), &rsize);
691 if (err_is_fail(err)) {
692 DEBUG_ERR(err, "error reading file");
698 while (wpos < rsize) {
699 err = vfs_write(dst, &buf[wpos], rsize - wpos, &wsize);
700 if (err_is_fail(err) || wsize == 0) {
701 DEBUG_ERR(err, "error writing file");
711 err = vfs_close(src);
712 if (err_is_fail(err)) {
713 DEBUG_ERR(err, "in vfs_close");
718 err = vfs_close(dst);
719 if (err_is_fail(err)) {
720 DEBUG_ERR(err, "in vfs_close");
727 static int dd(int argc, char *argv[])
733 vfs_handle_t source_vh = NULL;
734 vfs_handle_t target_vh = NULL;
736 size_t blocksize = 512;
743 size_t blocks_written = 0;
745 size_t total_bytes_read = 0;
746 size_t total_bytes_written = 0;
751 int ret = EXIT_SUCCESS;
753 for (int i = 1; i < argc; i++)
755 if (!strncmp(argv[i], "bs=", 3))
756 blocksize = atoi(argv[i] + 3);
758 else if (!strncmp(argv[i], "count=", 6))
759 count = atoi(argv[i] + 6);
761 else if (!strncmp(argv[i], "skip=", 5))
762 skip = atoi(argv[i] + 5);
764 else if (!strncmp(argv[i], "seek=", 5))
765 seek = atoi(argv[i] + 5);
767 else if (!strncmp(argv[i], "if=", 3))
768 source = (argv[i] + 3);
770 else if (!strncmp(argv[i], "of=", 3))
771 target = (argv[i] + 3);
772 else if (!strncmp(argv[i], "progress", 8))
776 size_t one_per_cent = (blocksize * count) / 100;
778 printf("from: %s to: %s bs=%zd count=%zd seek=%zd skip=%zd\n", source, target, blocksize, count, seek, skip);
782 char *path = vfs_path_mkabsolute(cwd, source);
783 err = vfs_open(path, &source_vh);
785 if (err_is_fail(err)) {
786 printf("%s: %s\n", source, err_getstring(err));
798 char *path = vfs_path_mkabsolute(cwd, target);
799 err = vfs_create(path, &target_vh);
801 if (err_is_fail(err)) {
802 // close source handle
803 if (source_vh != NULL)
804 vfs_close(source_vh);
805 printf("%s: %s\n", target, err_getstring(err));
815 uint8_t * buffer = malloc(blocksize);
817 #if defined(__x86_64__) || defined(__i386__)
819 err = sys_debug_get_tsc_per_ms(&tscperms);
820 assert(err_is_ok(err));
822 //printf("ticks per millisec: %" PRIu64 "\n", tscperms);
823 uint64_t start = rdtsc();
829 printf("failed to allocate buffer of size %zd\n", blocksize);
835 //printf("copying block\n");
836 size_t read_bytes = 0;
838 err = vfs_read(source_vh, buffer, blocksize, &rsize);
839 if (err_is_fail(err)) {
840 DEBUG_ERR(err, "error reading file");
845 total_bytes_read += rsize;
849 while (wpos < rsize) {
851 printf("was unable to write the whole chunk of size %zd. Now at pos: %zd of buffer\n", rsize, wpos);
853 err = vfs_write(target_vh, &buffer[wpos], rsize - wpos, &wsize);
854 if (err_is_fail(err) || wsize == 0) {
855 DEBUG_ERR(err, "error writing file");
860 total_bytes_written += wsize;
862 } while(read_bytes < blocksize);
866 if (progress && one_per_cent && total_bytes_written % one_per_cent == 0) {
870 //printf("block successfully copied. read: %zd. blocks written: %zd\n", rsize, blocks_written);
871 } while (rsize > 0 && !(count > 0 && blocks_written >= count));
873 if (progress) printf("\n");
879 if (source_vh != NULL) {
880 err = vfs_close(source_vh);
881 if (err_is_fail(err)) {
882 DEBUG_ERR(err, "in vfs_close");
886 if (target_vh != NULL) {
887 err = vfs_close(target_vh);
888 if (err_is_fail(err)) {
889 DEBUG_ERR(err, "in vfs_close");
893 #if defined(__x86_64__) || defined(__i386__)
894 uint64_t stop = rdtsc();
895 uint64_t elapsed_msecs = ((stop - start) / tscperms);
896 double elapsed_secs = (double)elapsed_msecs/1000.0;
898 printf("start: %" PRIu64 " stop: %" PRIu64 "\n", start, stop);
900 double kbps = ((double)total_bytes_written / 1024.0) / elapsed_secs;
902 printf("%zd bytes read. %zd bytes written. %f s, %f kB/s\n", total_bytes_read, total_bytes_written, elapsed_secs, kbps);
904 printf("%zd bytes read. %zd bytes written.\n", total_bytes_read, total_bytes_written);
910 static int touch(int argc, char *argv[])
913 printf("Usage: %s [file...]\n", argv[0]);
919 int ret = EXIT_SUCCESS;
921 for (int i = 1; i < argc; i++) {
922 char *path = vfs_path_mkabsolute(cwd, argv[i]);
923 err = vfs_create(path, &vh);
925 if (err_is_fail(err)) {
926 printf("%s: %s\n", argv[i], err_getstring(err));
927 DEBUG_ERR(err, "vfs_create failed");
933 if (err_is_fail(err)) {
934 DEBUG_ERR(err, "in vfs_close");
941 static char vfs_type_char(enum vfs_filetype type)
953 static int ls(int argc, char *argv[])
956 int ret = EXIT_SUCCESS;
958 // XXX: cheat and assume we have some extra space wherever argv lives
964 for (int i = 1; i < argc; i++) {
966 char *path = vfs_path_mkabsolute(cwd, argv[i]);
967 err = vfs_opendir(path, &vh);
969 if (err_is_fail(err)) {
970 DEBUG_ERR(err, "in vfs_opendir %s", argv[i]);
971 printf("%s: not found\n", argv[i]);
979 printf("%s:\n", argv[i]);
982 struct vfs_fileinfo info;
984 err = vfs_dir_read_next(vh, &name, &info);
985 if (err_is_ok(err)) {
986 printf("%8zu %c %s\n", info.size, vfs_type_char(info.type),
990 } while(err_is_ok(err));
992 err = vfs_closedir(vh);
993 if (err_is_fail(err)) {
994 DEBUG_ERR(err, "in vfs_closedir");
1001 static int mkdir(int argc, char *argv[])
1004 printf("Usage: %s dir\n", argv[0]);
1005 return EXIT_FAILURE;
1008 char *path = vfs_path_mkabsolute(cwd, argv[1]);
1009 errval_t err = vfs_mkdir(path);
1011 if (err_is_fail(err)) {
1012 printf("%s\n", err_getstring(err));
1013 return EXIT_FAILURE;
1015 return EXIT_SUCCESS;
1019 static int rmdir(int argc, char *argv[])
1022 printf("Usage: %s dir\n", argv[0]);
1023 return EXIT_FAILURE;
1026 char *path = vfs_path_mkabsolute(cwd, argv[1]);
1027 errval_t err = vfs_rmdir(path);
1029 if (err_is_fail(err)) {
1030 printf("%s\n", err_getstring(err));
1031 return EXIT_FAILURE;
1033 return EXIT_SUCCESS;
1037 static int rm(int argc, char *argv[])
1040 printf("Usage: %s file...\n", argv[0]);
1041 return EXIT_FAILURE;
1044 int ret = EXIT_SUCCESS;
1046 for (int i = 1; i < argc; i++) {
1047 char *path = vfs_path_mkabsolute(cwd, argv[i]);
1048 errval_t err = vfs_remove(path);
1050 if (err_is_fail(err)) {
1051 printf("%s: %s\n", argv[i], err_getstring(err));
1059 static int cd(int argc, char *argv[])
1064 printf("Usage: %s DIR\n", argv[0]);
1065 return EXIT_FAILURE;
1068 char *newcwd = vfs_path_mkabsolute(cwd, argv[1]);
1070 // ensure directory exists, by attempting to open it
1072 err = vfs_opendir(newcwd, &dh);
1073 if (err_is_fail(err)) {
1074 printf("cd to %s (-> %s) failed: %s\n",
1075 argv[1], newcwd, err_getstring(err));
1077 return EXIT_FAILURE;
1085 return EXIT_SUCCESS;
1088 static int pwd(int argc, char *argv[])
1090 printf("%s\n", cwd);
1091 return EXIT_SUCCESS;
1094 static int mnfs(int argc, char *argv[])
1096 char *args1[2] = { "mkdir", "/nfs" };
1098 char *args2[3] = { "mount", "/nfs", "nfs://10.110.4.4/local/nfs" };
1099 return mount(3, args2);
1102 /// Open file(s) with a list of commands and execute them
1103 static int src(int argc, char *argv[])
1106 printf("Usage: %s file...\n", argv[0]);
1109 int ret = EXIT_SUCCESS;
1110 for (int i = 1; i < argc; i++) {
1111 char *path = vfs_path_mkabsolute(cwd, argv[i]);
1112 FILE *f = fopen(path, "r");
1114 printf("File %s not found\n", path);
1118 printf("Executing file %s\n", path);
1120 // Read one line at a time, make args out of it and execute it
1122 char buf[1024] = "\0";
1123 char *p = fgets(buf, 1024, f);
1128 char *q = strrchr(p, '\n');
1130 char *cmdstr = strdup(p);
1132 int cmd_argc = makeargs(cmdstr, cmd_argv);
1133 if (cmd_argc == 0) {
1137 struct cmd *cmd = find_command(cmd_argv[0]);
1140 printf("running command: %s\n", p);
1141 int r = cmd->cmd(cmd_argc, cmd_argv);
1143 printf("running command %s failed errorcode %d\n", p, r);
1153 static int freecmd(int argc, char *argv[])
1155 struct mem_binding *mc = get_mem_client();
1158 genpaddr_t available, total;
1160 err = ram_available(&available, &total);
1161 if(err_is_fail(err)) {
1162 DEBUG_ERR(err, "available");
1163 return EXIT_FAILURE;
1166 printf("Free memory: %" PRIuGENPADDR " bytes\n", available);
1167 printf("Total memory: %" PRIuGENPADDR " bytes\n", total);
1169 return EXIT_SUCCESS;
1172 static int nproc(int argc, char* argv[]) {
1175 char** names = NULL;
1177 static char* spawnds = "r'spawn.[0-9]+' { iref: _ }";
1180 struct octopus_get_names_response__rx_args reply;
1181 struct octopus_binding *r = get_octopus_binding();
1182 err = r->rpc_tx_vtbl.get_names(r, spawnds, NOP_TRIGGER, reply.output,
1183 &reply.tid, &reply.error_code);
1184 if (err_is_fail(err) || err_is_fail(reply.error_code)) {
1185 DEBUG_ERR(err, "get_names failed");
1189 err = oct_parse_names(reply.output, &names, &count);
1190 if (err_is_fail(err)) {
1191 DEBUG_ERR(err, "parse_names failed.");
1196 oct_free_names(names, count);
1198 printf("%zx\n", count);
1199 return EXIT_SUCCESS;
1203 static struct cmd commands[] = {
1204 {"help", help, "Output usage information about given shell command"},
1205 {"print_cspace", print_cspace, "Debug print-out of my cspace"},
1206 {"quit", quit, "Quit the shell"},
1207 {"nproc", nproc, "Get amount of cores in system."},
1208 {"ps", ps, "List running processes"},
1209 {"demo", demo, "Run barrelfish demo"},
1210 {"pixels", spawnpixels, "Spawn pixels on all cores"},
1211 {"mnfs", mnfs, "Mount script for NFS on emmentaler"},
1212 {"oncore", oncore, "Start program on specified core"},
1213 {"reset", reset, "Reset machine"},
1214 {"poweroff", poweroff, "Power down machine"},
1215 {"skb", skb, "Send command to system knowledge base"},
1216 {"mount", mount, "Mount file system"},
1217 {"ls", ls, "List directory contents"},
1218 {"cd", cd, "Change working directory"},
1219 {"pwd", pwd, "Print current working directory"},
1220 {"touch", touch, "Create an empty file"},
1221 {"cat", cat, "Print the contents of file(s)"},
1222 {"hd", hd, "Print the contents of file(s) as hexdump"},
1223 {"cat2", cat2, "Print the contents of file(s) into another file"},
1224 {"dd", dd, "copy stuff"},
1225 {"cp", cp, "Copy files"},
1226 {"rm", rm, "Remove files"},
1227 {"mkdir", mkdir, "Create a new directory"},
1228 {"rmdir", rmdir, "Remove an existing directory"},
1229 {"setenv", setenvcmd, "Set environment variables"},
1230 {"src", src, "Execute the list of commands in a file"},
1231 {"printenv", printenv, "Display environment variables"},
1232 {"free", freecmd, "Display amount of free memory in the system"},
1233 {"dump_caps", dump_caps, "Display cspace debug information"},
1236 static struct cmd *find_command(const char *name)
1238 for(int i = 0; i < ENTRIES(commands); i++) {
1239 struct cmd *cmd = &commands[i];
1241 if(strcmp(name, cmd->name) == 0) {
1249 static int help(int argc, char *argv[])
1254 printf("available commands:\n");
1255 for (int i=0; i < ENTRIES(commands); i++) {
1256 printf("%-15s", commands[i].name);
1257 if (((i + 1) % 5) == 0) {
1262 return EXIT_SUCCESS;
1265 if ((cmd = find_command(argv[1])) != NULL) {
1266 printf("%s: %s\n", argv[1], cmd->usage);
1267 return EXIT_SUCCESS;
1269 printf("%s: %s: command not found\n", argv[0], argv[1]);
1270 return EXIT_FAILURE;
1274 static int makeargs(char *cmdline, char *argv[])
1277 bool inquote = false;
1292 for(argv[argc++] = p; *p != '\0'; p++) {
1295 *p = ' '; // mega-kludge!
1296 } else if (*p == ' ' && !inquote) {
1298 // Skip any redundant whitespace
1306 *p = ' '; // mega-kludge
1315 static uint8_t wait_domain_id(struct capref domainid)
1318 errval_t err = spawn_wait(domainid, &exitcode, false);
1319 if (err_is_fail(err)) {
1320 USER_PANIC_ERR(err, "spawn_wait");
1325 static void runbootscript(void)
1328 snprintf(cmdstr, 1024,"sh %s", BOOTSCRIPT_NAME);
1330 int cmd_argc = makeargs(cmdstr, cmd_argv);
1331 int ret = src(cmd_argc, cmd_argv);
1333 snprintf(cmdstr, 1024, "help");
1334 cmd_argc = makeargs(cmdstr, cmd_argv);
1335 help(cmd_argc, cmd_argv);
1340 int main(int argc, const char *argv[])
1343 bool is_bootscript = true;
1344 coreid_t my_core_id = disp_get_core_id();
1348 for (int i = 1; i < argc; i++) {
1349 if (strcmp(argv[i], "nobootscript") == 0) {
1350 is_bootscript = false;
1356 printf("fish v0.2 -- pleased to meet you!\n");
1358 // run canned pre-boot commands
1359 if (is_bootscript) {
1363 struct terminal_state *ts = get_terminal_state();
1364 term_client_blocking_config(&ts->client, TerminalConfig_CTRLC, false);
1365 linenoiseHistorySetMaxLen(1024);
1367 // Create inherit CNode to pass session cap to programs spawned from fish
1369 err = alloc_inheritcn_with_caps(&inheritcn_cap, NULL_CAP, cap_sessionid, NULL_CAP);
1370 if (err_is_fail(err)) {
1371 USER_PANIC_ERR(err, "Error allocating inherit CNode with session cap.");
1377 char *cmd_argv[64]; // Support a max of 64 cmd args
1380 input = linenoise("> ");
1381 if (input == NULL || input[0] == '\0') {
1385 linenoiseHistoryAdd(input); /* Add to the history. */
1386 linenoiseHistorySave("history.txt"); /* Save the history on disk. */
1387 cmd_argc = makeargs(input, cmd_argv);
1389 /* check for trailing '&' (== run in background) */
1392 size_t len = strlen(cmd_argv[cmd_argc - 1]);
1393 if (len > 0 && cmd_argv[cmd_argc - 1][len - 1] == '&') {
1395 // remove '&' character from args
1399 cmd_argv[cmd_argc - 1][len - 1] = '\0';
1404 if (cmd_argc == 0) {
1406 } else if ((cmd = find_command(cmd_argv[0])) != NULL) {
1407 exitcode = cmd->cmd(cmd_argc, cmd_argv);
1409 // Try loading a program off disk if VFS is initialized
1410 struct capref domain_cap;
1411 exitcode = execute_program(my_core_id, cmd_argc, cmd_argv, &domain_cap);
1413 // wait if it succeeds
1414 if (exitcode == 0 && wait) {
1415 exitcode = wait_domain_id(domain_cap);
1417 snprintf(exitstr, 128, "%u", exitcode);
1418 int r = setenv("EXITCODE", exitstr, 1);