diff --git a/pkg/c3/motes.h b/pkg/c3/motes.h index 0000d5c593..4241c7f09d 100644 --- a/pkg/c3/motes.h +++ b/pkg/c3/motes.h @@ -936,6 +936,7 @@ # define c3__pril c3_s4('p','r','i','l') # define c3__pro c3_s3('p','r','o') # define c3__prod c3_s4('p','r','o','d') +# define c3__prop c3_s4('p','r','o','p') # define c3__prof c3_s4('p','r','o','f') # define c3__prox c3_s4('p','r','o','x') # define c3__psdg c3_s4('p','s','d','g') diff --git a/pkg/vere/king.c b/pkg/vere/king.c index 74ff7f782d..44979102b3 100644 --- a/pkg/vere/king.c +++ b/pkg/vere/king.c @@ -90,6 +90,8 @@ void _king_doom(u3_noun doom); void _king_fake(u3_noun ship, u3_noun pill, u3_noun path); void _king_pier(u3_noun pier); +static u3_noun _king_get_atom(c3_c* url_c); + /* _king_defy_fate(): invalid fate */ void @@ -158,6 +160,49 @@ _king_boot(u3_noun bul) u3z(bul); } +/* _king_prop(): events from prop arguments +*/ +u3_noun +_king_prop() +{ + u3_noun mor = u3_nul; + while ( 0 != u3_Host.ops_u.vex_u ) { + u3_even* vex_u = u3_Host.ops_u.vex_u; + switch ( vex_u->kin_i ) { + case 1: { // file + u3_atom jam = u3m_file(vex_u->loc_c); + mor = u3nc(u3ke_cue(jam), mor); + } break; + + case 2: { // url + u3l_log("boot: downloading prop %s", vex_u->loc_c); + u3_atom jam = _king_get_atom(vex_u->loc_c); + mor = u3nc(u3ke_cue(jam), mor); + } break; + + case 3: { // name + //NOTE this implementation limits us to max 38 char prop names + c3_c url_c[80]; + sprintf(url_c, + //TODO should maybe respect ops_u.url_c + "https://bootstrap.urbit.org/props/" URBIT_VERSION "/%s.jam", + vex_u->loc_c); + u3l_log("boot: downloading prop %s", url_c); + u3_atom jam = _king_get_atom(url_c); + mor = u3nc(u3ke_cue(jam), mor); + } break; + + default: { + u3l_log("invalid prop source %d", vex_u->kin_i); + exit(1); + } + } + + u3_Host.ops_u.vex_u = vex_u->pre_u; + } + return mor; +} + /* _king_fake(): boot with fake keys */ void @@ -166,7 +211,8 @@ _king_fake(u3_noun ship, u3_noun pill, u3_noun path) // XX link properly // u3_noun vent = u3nc(c3__fake, u3k(ship)); - u3K.pir_u = u3_pier_boot(sag_w, ship, vent, pill, path, u3_none); + u3K.pir_u = u3_pier_boot(sag_w, ship, vent, pill, path, + u3_none, _king_prop()); } /* _king_come(): mine a comet under star (unit) @@ -201,7 +247,8 @@ _king_dawn(u3_noun feed, u3_noun pill, u3_noun path) u3_noun vent = u3_dawn_vent(u3k(ship), u3k(feed)); // XX link properly // - u3K.pir_u = u3_pier_boot(sag_w, u3k(ship), vent, pill, path, feed); + u3K.pir_u = u3_pier_boot(sag_w, u3k(ship), vent, pill, path, + feed, _king_prop()); // disable ivory slog printfs // diff --git a/pkg/vere/main.c b/pkg/vere/main.c index 9a1680347c..9114cb4f74 100644 --- a/pkg/vere/main.c +++ b/pkg/vere/main.c @@ -215,6 +215,19 @@ _main_pier_run(c3_c* bin_c) return dir_c; } +/* _main_add_prop(): add a boot prop to u3_Host.ops_u.vex_u. +*/ +u3_even* +_main_add_prop(c3_i kin_i, c3_c* loc_c) +{ + u3_even* nex_u = c3_calloc(sizeof(*nex_u)); + nex_u->kin_i = kin_i; + nex_u->loc_c = loc_c; // XX _main_repath where appropriate? + nex_u->pre_u = u3_Host.ops_u.vex_u; + u3_Host.ops_u.vex_u = nex_u; + return nex_u; +} + /* _main_getopt(): extract option map from command line. */ static u3_noun @@ -269,6 +282,10 @@ _main_getopt(c3_i argc, c3_c** argv) { "scry-into", required_argument, NULL, 'Y' }, { "scry-format", required_argument, NULL, 'Z' }, // + { "prop-file", required_argument, NULL, 1 }, + { "prop-url", required_argument, NULL, 2 }, + { "prop-name", required_argument, NULL, 3 }, + // { "urth-loom", required_argument, NULL, 5 }, { "no-demand", no_argument, NULL, 6 }, { "swap", no_argument, NULL, 7 }, @@ -283,6 +300,10 @@ _main_getopt(c3_i argc, c3_c** argv) lop_u, &lid_i)) ) { switch ( ch_i ) { + case 1: case 2: case 3: { // prop-* + _main_add_prop(ch_i, strdup(optarg)); + break; + } case 5: { // urth-loom if (_main_readw_loom("urth-loom", &u3_Host.ops_u.lut_y)) { return c3n; @@ -591,6 +612,7 @@ _main_getopt(c3_i argc, c3_c** argv) if ( hyphen_c ) { *hyphen_c = '\0'; } + //TODO use brass pill from b.u.org/props/etc eventually c3_i res_i = asprintf(&u3_Host.ops_u.url_c, "https://bootstrap.urbit.org/urbit-v%s.pill", version_c); @@ -616,6 +638,18 @@ _main_getopt(c3_i argc, c3_c** argv) } } + if ( u3_Host.ops_u.vex_u != 0 ) { + struct stat s; + u3_even* vex_u = u3_Host.ops_u.vex_u; + while ( vex_u != 0 ) { + if ( vex_u->kin_i == 1 && stat(vex_u->loc_c, &s) != 0 ) { + fprintf(stderr, "events file %s not found\n", vex_u->loc_c); + return c3n; + } + vex_u = vex_u->pre_u; + } + } + struct sockaddr_in t; if ( u3_Host.ops_u.bin_c != 0 && inet_pton(AF_INET, u3_Host.ops_u.bin_c, &t.sin_addr) == 0 ) { fprintf(stderr, "-b invalid IP address\n"); @@ -630,6 +664,15 @@ _main_getopt(c3_i argc, c3_c** argv) } } + //TODO split up "default distribution" packages eventually + // // if we're not in lite mode, include the default props + // // + // if ( u3_Host.ops_u.lit == c3n ) { + // _main_add_prop(3, "landscape"); + // _main_add_prop(3, "webterm"); + // _main_add_prop(3, "groups"); + // } + return c3y; } @@ -790,6 +833,9 @@ u3_ve_usage(c3_i argc, c3_c** argv) " --no-dock Skip binary \"docking\" on boot\n", " --swap Use an explicit ephemeral (swap-like) file\n", " --swap-to FILE Specify ephemeral file location\n", + " --prop-file FILE Add a prop into the boot sequence\n" + " --prop-url URL Download a prop into the boot sequence\n", + " --prop-name NAME Download a prop from bootstrap.urbit.org\n", "\n", "Development Usage:\n", " To create a development ship, use a fakezod:\n", diff --git a/pkg/vere/pier.c b/pkg/vere/pier.c index bba434c4fd..b195291707 100644 --- a/pkg/vere/pier.c +++ b/pkg/vere/pier.c @@ -1820,7 +1820,8 @@ _pier_boot_make(u3_noun who, u3_noun wyr, u3_noun ven, u3_noun pil, - u3_weak fed) + u3_weak fed, + u3_noun mor) { u3_boot bot_u = _pier_pill_parse(pil); // transfer @@ -1872,7 +1873,48 @@ _pier_boot_make(u3_noun who, bot_u.use = u3nc(u3nc(wir, cad), bot_u.use); } + // prepend & append additional boot enhancements to the userspace sequence + // + { + u3_noun mos = mor; + u3_noun pre = u3_nul; + u3_noun aft = u3_nul; + while ( u3_nul != mos ) { + u3_noun mot = u3h(mos); + + switch ( u3h(mot) ) { + case c3__prop: { + u3_noun ter, met, ves; + + if ( c3n == u3r_trel(u3t(mot), &met, &ter, &ves) ) { + u3m_p("invalid prop", u3t(mot)); + break; + } + + if ( c3__fore == ter ) { + u3m_p("prop: fore", met); + pre = u3kb_weld(pre, u3k(ves)); + } + else if ( c3__hind == ter ) { + u3m_p("prop: hind", met); + aft = u3kb_weld(aft, u3k(ves)); + } + else { + u3m_p("unrecognized prop tier", ter); + } + } break; + + default: u3m_p("unrecognized boot sequence enhancement", u3h(mot)); + } + + mos = u3t(mos); + } + + bot_u.use = u3kb_weld(pre, u3kb_weld(bot_u.use, aft)); // transfer + } + u3z(fed); + u3z(mor); return bot_u; } @@ -1883,7 +1925,8 @@ _pier_boot_plan(u3_pier* pir_u, u3_noun who, u3_noun ven, u3_noun pil, - u3_weak fed) + u3_weak fed, + u3_noun mor) { u3_boot bot_u; { @@ -1891,7 +1934,7 @@ _pier_boot_plan(u3_pier* pir_u, pir_u->fak_o = ( c3__fake == u3h(ven) ) ? c3y : c3n; u3r_chubs(0, 2, pir_u->who_d, who); - bot_u = _pier_boot_make(who, _pier_wyrd_card(pir_u), ven, pil, fed); + bot_u = _pier_boot_make(who, _pier_wyrd_card(pir_u), ven, pil, fed, mor); pir_u->lif_w = u3qb_lent(bot_u.bot); } @@ -1967,7 +2010,8 @@ u3_pier_boot(c3_w wag_w, // config flags u3_noun ven, // boot event u3_noun pil, // type-of/path-to pill u3_noun pax, // path to pier - u3_weak fed) // extra private keys + u3_weak fed, // extra private keys + u3_noun mor) // extra boot sequence props { u3_pier* pir_u; @@ -1979,7 +2023,7 @@ u3_pier_boot(c3_w wag_w, // config flags // XX must be called from on_lord_live // - if ( c3n == _pier_boot_plan(pir_u, who, ven, pil, fed) ) { + if ( c3n == _pier_boot_plan(pir_u, who, ven, pil, fed, mor) ) { fprintf(stderr, "pier: boot plan fail\r\n"); // XX dispose // diff --git a/pkg/vere/vere.h b/pkg/vere/vere.h index b2b78b5e81..6361a1c3d2 100644 --- a/pkg/vere/vere.h +++ b/pkg/vere/vere.h @@ -258,6 +258,14 @@ struct _u3_auto* car_u; // driver hack } u3_utty; + /* u3_even: boot event specifier + */ + typedef struct _u3_even { + c3_i kin_i; + c3_c* loc_c; + struct _u3_even* pre_u; + } u3_even; + /* u3_opts: command line configuration. */ typedef struct _u3_opts { @@ -308,6 +316,7 @@ c3_o map; // --no-demand (reversed) c3_o eph; // --swap, use ephemeral file c3_o tos; // --toss, discard ephemeral + u3_even* vex_u; // --prop-*, boot enhancements } u3_opts; /* u3_host: entire host. @@ -1417,7 +1426,8 @@ u3_noun ven, // boot event u3_noun pil, // type-of/path-to pill u3_noun pax, // path to pier - u3_weak fed); // extra private keys + u3_weak fed, // extra private keys + u3_noun mor); // extra boot seq props /* u3_pier_stay(): restart the pier. */