Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

vere: bring your own boot sequence #544

Merged
merged 7 commits into from
Mar 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions pkg/c3/motes.h
Original file line number Diff line number Diff line change
Expand Up @@ -937,6 +937,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')
Expand Down
90 changes: 72 additions & 18 deletions pkg/vere/king.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 213 char prop names
c3_c url_c[256];
snprintf(url_c, 255,
//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
Expand All @@ -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)
Expand Down Expand Up @@ -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
//
Expand Down Expand Up @@ -251,6 +298,7 @@ _king_curl_bytes(c3_c* url_c, c3_w* len_w, c3_y** hun_y, c3_t veb_t)
CURL *cul_u;
CURLcode res_i;
long cod_i;
c3_y try_y = 0;
uv_buf_t buf_u = uv_buf_init(c3_malloc(1), 0);

if ( !(cul_u = curl_easy_init()) ) {
Expand All @@ -263,29 +311,34 @@ _king_curl_bytes(c3_c* url_c, c3_w* len_w, c3_y** hun_y, c3_t veb_t)
curl_easy_setopt(cul_u, CURLOPT_WRITEFUNCTION, _king_curl_alloc);
curl_easy_setopt(cul_u, CURLOPT_WRITEDATA, (void*)&buf_u);

res_i = curl_easy_perform(cul_u);
curl_easy_getinfo(cul_u, CURLINFO_RESPONSE_CODE, &cod_i);
while ( 5 > try_y ) {
sleep(try_y++);
res_i = curl_easy_perform(cul_u);
curl_easy_getinfo(cul_u, CURLINFO_RESPONSE_CODE, &cod_i);

// XX retry?
//
if ( CURLE_OK != res_i ) {
if ( veb_t ) {
u3l_log("curl: failed %s: %s", url_c, curl_easy_strerror(res_i));
if ( CURLE_OK != res_i ) {
if ( veb_t ) {
u3l_log("curl: failed to fetch %s: %s",
url_c, curl_easy_strerror(res_i));
}
ret_i = -1;
}
ret_i = -1;
}
if ( 300 <= cod_i ) {
if ( veb_t ) {
u3l_log("curl: error %s: HTTP %ld", url_c, cod_i);
else if ( 300 <= cod_i ) {
if ( veb_t ) {
u3l_log("curl: error fetching %s: HTTP %ld", url_c, cod_i);
}
ret_i = -2;
}
else {
*len_w = buf_u.len;
*hun_y = (c3_y*)buf_u.base;
ret_i = 0;
break;
}
ret_i = -2;
}

curl_easy_cleanup(cul_u);

*len_w = buf_u.len;
*hun_y = (c3_y*)buf_u.base;

return ret_i;
}

Expand Down Expand Up @@ -376,6 +429,7 @@ u3_king_next(c3_c* pac_c, c3_c** out_c)
}

// skip printfs on failed requests (/next is usually not present)
//REVIEW new retry logic means this case will take longer. make retries optional?
//
if ( _king_curl_bytes(url_c, &len_w, &hun_y, 0) ) {
c3_free(url_c);
Expand Down
46 changes: 46 additions & 0 deletions pkg/vere/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,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;
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
Expand Down Expand Up @@ -274,6 +287,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 },
Expand All @@ -289,6 +306,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;
Expand Down Expand Up @@ -609,6 +630,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);
Expand All @@ -634,6 +656,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");
Expand All @@ -648,6 +682,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;
}

Expand Down Expand Up @@ -809,6 +852,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",
Expand Down
58 changes: 53 additions & 5 deletions pkg/vere/pier.c
Original file line number Diff line number Diff line change
Expand Up @@ -1821,7 +1821,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

Expand Down Expand Up @@ -1873,7 +1874,52 @@ _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
//
// +$ prop [%prop meta tier (list ovum)]
// +$ meta term
// +$ tier ?(%fore %hind) :: before or after userspace
//
{
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;
}

Expand All @@ -1884,15 +1930,16 @@ _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;
{
pir_u->sat_e = u3_psat_boot;
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);
}

Expand Down Expand Up @@ -1976,7 +2023,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;

Expand All @@ -1988,7 +2036,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
//
Expand Down
13 changes: 12 additions & 1 deletion pkg/vere/vere.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -309,6 +317,8 @@
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

c3_o beb; // --behn-allow-blocked
} u3_opts;

Expand Down Expand Up @@ -1429,7 +1439,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.
*/
Expand Down
Loading