(command.CommandList children: [ (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(test)} {(-z)} {(DQ ($ Id.VSub_DollarName '$BASH_VERSION'))}) terminator: (Token id:Id.Op_Semi val:';' span_id:113) ) ] action: [ (command.Simple words: [{(echo)} {(DQ ('Please run this script using bash, not sh or any other shell.'))}] redirects: [ (redir.Redir op: (Token id:Id.Redir_GreatAnd val:'>&' span_id:124) fd: -1 arg_word: {(2)} ) ] ) (command.ControlFlow token: (Token id:Id.ControlFlow_Exit val:exit span_id:128) arg_word: {(1)} ) ] spids: [104 115] ) ] ) (command.ShFunction name: _ body: (command.BraceGroup children: [ (C {(Id.KW_Set set)} {(-euo)} {(pipefail)}) (C {(declare)} {(-a)} {(ORIGINAL_ARGS)}) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:CURL_USER_AGENT) op: assign_op.Equal rhs: { (DQ (braced_var_sub token: (Token id:Id.VSub_Name val:CURL_USER_AGENT span_id:186) suffix_op: (suffix_op.Unary op_id: Id.VTest_ColonHyphen arg_word: {(sandstorm-install-script)} ) ) ) } spids: [183] ) ] ) (command.ShFunction name: error body: (command.BraceGroup children: [ (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {($ Id.VSub_Pound '$#')} {(Id.KW_Bang '!') (Id.Lit_Equals '=')} {(0)} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:215) ) ] action: [ (command.Simple words: [ {(echo)} {(-en)} {(SQ (Token id:Id.Lit_Chars val:'\\e[0;31m' span_id:225))} ] redirects: [ (redir.Redir op: (Token id:Id.Redir_GreatAnd val:'>&' span_id:228) fd: -1 arg_word: {(2)} ) ] ) (command.Pipeline children: [ (C {(echo)} {(DQ ($ Id.VSub_At '$@'))}) (command.Subshell command_list: (command.CommandList children: [ (command.AndOr ops: [Id.Op_DPipe] children: [(C {(fold)} {(-s)}) (C {(cat)})] ) ] ) redirects: [ (redir.Redir op: (Token id:Id.Redir_GreatAnd val:'>&' span_id:250) fd: -1 arg_word: {(2)} ) ] ) ] negated: F ) (command.Simple words: [ {(echo)} {(-en)} {(SQ (Token id:Id.Lit_Chars val:'\\e[0m' span_id:259))} ] redirects: [ (redir.Redir op: (Token id:Id.Redir_GreatAnd val:'>&' span_id:262) fd: -1 arg_word: {(2)} ) ] ) ] spids: [203 217] ) ] ) ] ) ) (command.ShFunction name: fail body: (command.BraceGroup children: [ (C {(local)} {(Id.Lit_VarLike 'error_code=') (DQ ($ Id.VSub_Number '$1'))}) (C {(shift)}) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} { (DQ (braced_var_sub token: (Token id: Id.VSub_Name val: SHOW_FAILURE_MSG span_id: 295 ) suffix_op: (suffix_op.Unary op_id: Id.VTest_ColonHyphen arg_word: {(yes)} ) ) ) } {(Id.Lit_Equals '=')} {(DQ (yes))} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:309) ) ] action: [ (command.Simple words: [{(echo)} {(DQ ('*** INSTALLATION FAILED ***'))}] redirects: [ (redir.Redir op: (Token id:Id.Redir_GreatAnd val:'>&' span_id:320) fd: -1 arg_word: {(2)} ) ] ) (C {(echo)} {(DQ )}) ] spids: [289 311] ) ] ) (C {(error)} {(DQ ($ Id.VSub_At '$@'))}) (command.Simple words: [{(echo)} {(DQ )}] redirects: [ (redir.Redir op: (Token id:Id.Redir_GreatAnd val:'>&' span_id:345) fd: -1 arg_word: {(2)} ) ] ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} { (DQ (braced_var_sub token: (Token id:Id.VSub_Name val:REPORT span_id:359) suffix_op: (suffix_op.Unary op_id: Id.VTest_ColonHyphen arg_word: {(yes)} ) ) ) } {(Id.Lit_Equals '=')} {(DQ (yes))} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:373) ) ] action: [ (command.If arms: [ (if_arm cond: [ (command.Sentence child: (command.Simple words: [ {(prompt-yesno)} { (DQ ( 'Hmm, installation failed. Would it be OK to send an anonymous error report to the sandstorm.io team so we know something is wrong?\n' ) ('It would only contain this error code: ') ($ Id.VSub_DollarName '$error_code') ) } {(DQ (yes))} ] more_env: [ (env_pair name: USE_DEFAULTS val: {(no)} spids: [380] ) ] ) terminator: (Token id:Id.Op_Semi val:';' span_id:395) ) ] action: [ (command.Simple words: [{(echo)} {(DQ ('Sending problem report...'))}] redirects: [ (redir.Redir op: (Token id:Id.Redir_GreatAnd val:'>&' span_id:406) fd: -1 arg_word: {(2)} ) ] ) (C {(local)} {(Id.Lit_VarLike 'BEARER_TOKEN=') (DQ (ZiV1jbwHBPfpIjF3LNFv9-glp53F7KcsvVvljgKxQAL)) } ) (C {(local)} {(Id.Lit_VarLike 'API_ENDPOINT=') (DQ ('https://api.oasis.sandstorm.io/api')) } ) (C {(local)} {(Id.Lit_VarLike 'HTTP_STATUS=') (command_sub left_token: (Token id: Id.Left_DollarParen val: '$(' span_id: 429 ) command_list: (command.CommandList children: [ (C {(dotdotdot_curl)} {(--silent)} {(--max-time)} {(20)} {(--data-binary)} { (DQ ('{') (word_part.EscapedLiteral token: (Token id: Id.Lit_EscapedChar val: '\\"' span_id: 450 ) ) (error_code) (word_part.EscapedLiteral token:(Token id:Id.Lit_EscapedChar val:'\\"' span_id:452)) (':') (word_part.EscapedLiteral token: (Token id: Id.Lit_EscapedChar val: '\\"' span_id: 454 ) ) ($ Id.VSub_DollarName '$error_code') (word_part.EscapedLiteral token: (Token id: Id.Lit_EscapedChar val: '\\"' span_id: 456 ) ) (',') (word_part.EscapedLiteral token:(Token id:Id.Lit_EscapedChar val:'\\"' span_id:458)) (user-agent) (word_part.EscapedLiteral token: (Token id: Id.Lit_EscapedChar val: '\\"' span_id: 460 ) ) (':') (word_part.EscapedLiteral token:(Token id:Id.Lit_EscapedChar val:'\\"' span_id:462)) ($ Id.VSub_DollarName '$CURL_USER_AGENT') (word_part.EscapedLiteral token:(Token id:Id.Lit_EscapedChar val:'\\"' span_id:464)) ('}') ) } {(-H)} {(DQ ('Authorization: Bearer ') ($ Id.VSub_DollarName '$BEARER_TOKEN'))} {(-X)} {(POST)} {(--output)} {(DQ (/dev/null))} {(-w)} {(SQ (Token id:Id.Lit_Chars val:'%{http_code}' span_id:496))} {(DQ ($ Id.VSub_DollarName '$API_ENDPOINT'))} ) ] ) ) } ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(DQ (200))} {(Id.Lit_Equals '=') (Id.Lit_Equals '=')} {(DQ ($ Id.VSub_DollarName '$HTTP_STATUS'))} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:524) ) ] action: [ (command.Simple words: [ {(echo)} { (DQ ( '... problem reported successfully. Your installation did not succeed.' ) ) } ] redirects: [ (redir.Redir op: (Token id: Id.Redir_GreatAnd val: '>&' span_id: 535 ) fd: -1 arg_word: {(2)} ) ] ) ] spids: [507 526] ) (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(DQ (000))} {(Id.Lit_Equals '=') (Id.Lit_Equals '=')} {(DQ ($ Id.VSub_DollarName '$HTTP_STATUS'))} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:556) ) ] action: [ (C {(error)} { (DQ ( 'Submitting error report failed. Maybe there is a connectivity problem.' ) ) } ) ] spids: [539 558] ) ] else_action: [ (C {(error)} { (DQ ( 'Submitting error report resulted in strange HTTP status: ' ) ($ Id.VSub_DollarName '$HTTP_STATUS') ) } ) ] ) ] spids: [378 397] ) ] else_action: [ (command.Simple words: [{(echo)} {(DQ ('Not sending report.'))}] redirects: [ (redir.Redir op: (Token id:Id.Redir_GreatAnd val:'>&' span_id:591) fd: -1 arg_word: {(2)} ) ] ) ] ) (C {(echo)} {(DQ )}) ] spids: [353 375] ) ] ) (command.Simple words: [ {(echo)} {(DQ ('You can report bugs at: http://github.com/sandstorm-io/sandstorm'))} ] redirects: [ (redir.Redir op: (Token id:Id.Redir_GreatAnd val:'>&' span_id:613) fd: -1 arg_word: {(2)} ) ] ) (command.ControlFlow token: (Token id:Id.ControlFlow_Exit val:exit span_id:617) arg_word: {(1)} ) ] ) ) (command.ShFunction name: retryable_curl body: (command.BraceGroup children: [ (C {(local)} {(Id.Lit_VarLike 'CURL_FAILED=') (DQ (no))}) (command.AndOr ops: [Id.Op_DPipe] children: [ (command.Simple words: [ {(curl)} {(-A)} {(DQ (${ Id.VSub_Name CURL_USER_AGENT))} {(-f)} {(DQ ($ Id.VSub_Number '$1'))} ] redirects: [ (redir.Redir op: (Token id:Id.Redir_Great val:'>' span_id:663) fd: -1 arg_word: {(DQ ($ Id.VSub_Number '$2'))} ) ] ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:CURL_FAILED) op: assign_op.Equal rhs: {(DQ (yes))} spids: [671] ) ] ) ] ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(DQ (yes))} {(Id.Lit_Equals '=')} {(DQ (${ Id.VSub_Name CURL_FAILED))} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:695) ) ] action: [ (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(prompt-yesno)} { (DQ ('Downloading ') ($ Id.VSub_Number '$1') (' failed. OK to retry?') ) } {(DQ (yes))} ) terminator: (Token id:Id.Op_Semi val:';' span_id:714) ) ] action: [ (command.Simple words: [{(echo)} {(DQ )}] redirects: [ (redir.Redir op: (Token id:Id.Redir_GreatAnd val:'>&' span_id:724) fd: -1 arg_word: {(2)} ) ] ) (command.Simple words: [ {(echo)} { (DQ ( 'Download failed. Waiting one second before retrying...' ) ) } ] redirects: [ (redir.Redir op: (Token id:Id.Redir_GreatAnd val:'>&' span_id:734) fd: -1 arg_word: {(2)} ) ] ) (C {(sleep)} {(1)}) (C {(retryable_curl)} {(DQ ($ Id.VSub_Number '$1'))} {(DQ ($ Id.VSub_Number '$2'))} ) ] spids: [700 716] ) ] ) ] spids: [677 697] ) ] ) ] ) ) (command.ShFunction name: dotdotdot_curl body: (command.BraceGroup children: [ (command.Simple words: [{(echo)} {(-n)} {(SQ (Token id:Id.Lit_Chars val:... span_id:828))}] redirects: [ (redir.Redir op: (Token id:Id.Redir_GreatAnd val:'>&' span_id:831) fd: -1 arg_word: {(2)} ) ] ) (C {(curl)} {(DQ ($ Id.VSub_At '$@'))}) (command.Simple words: [{(echo)} {(-ne)} {(SQ (Token id:Id.Lit_Chars val:'\\r' span_id:849))}] redirects: [ (redir.Redir op: (Token id:Id.Redir_GreatAnd val:'>&' span_id:852) fd: -1 arg_word: {(2)} ) ] ) ] ) ) (command.ShFunction name: is_port_bound body: (command.BraceGroup children: [ (C {(local)} {(Id.Lit_VarLike 'SCAN_HOST=') (DQ ($ Id.VSub_Number '$1'))}) (C {(local)} {(Id.Lit_VarLike 'SCAN_PORT=') (DQ ($ Id.VSub_Number '$2'))}) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(DQ (${ Id.VSub_Name DEV_TCP_USABLE))} {(Id.Lit_Equals '=')} {(DQ (unchecked))} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:900) ) ] action: [ (command.Simple words: [ {(fail)} {(DQ (E_DEV_TCP_UNCHECKED))} { (DQ ( 'Programmer error. The author of install.sh used an uninitialized variable.' ) ) } ] more_env: [(env_pair name:REPORT val:{(no)} spids:[905])] ) ] spids: [882 902] ) ] ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(DQ (${ Id.VSub_Name DEV_TCP_USABLE))} {(Id.Lit_Equals '=')} {(DQ (yes))} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:949) ) ] action: [ (command.If arms: [ (if_arm cond: [ (command.Sentence child: (command.Simple words: [ {(timeout)} {(1)} {(bash)} {(-c)} { (DQ (': < /dev/tcp/') (${ Id.VSub_Name SCAN_HOST) (/) (${ Id.VSub_Name SCAN_PORT) ) } ] redirects: [ (redir.Redir op: (Token id:Id.Redir_Great val:'2>' span_id:975) fd: 2 arg_word: {(/dev/null)} ) ] ) terminator: (Token id:Id.Op_Semi val:';' span_id:977) ) ] action: [ (command.ControlFlow token: (Token id:Id.ControlFlow_Return val:return span_id:982) arg_word: {(0)} ) ] spids: [954 979] ) ] else_action: [ (command.ControlFlow token: (Token id:Id.ControlFlow_Return val:return span_id:990) arg_word: {(1)} ) ] ) ] spids: [931 951] ) ] ) (C {(local)} {(Id.Lit_VarLike 'DEBIAN_STYLE_INDICATED_BOUND=') (DQ (no))}) (command.AndOr ops: [Id.Op_DAmp] children: [ (command.Simple words: [ {(${ Id.VSub_Name NC_PATH)} {(-z)} {(DQ ($ Id.VSub_DollarName '$SCAN_HOST'))} {(DQ ($ Id.VSub_DollarName '$SCAN_PORT'))} ] redirects: [ (redir.Redir op: (Token id:Id.Redir_Great val:'>' span_id:1092) fd: -1 arg_word: {(/dev/null)} ) (redir.Redir op: (Token id:Id.Redir_Great val:'2>' span_id:1095) fd: 2 arg_word: {(/dev/null)} ) ] ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:DEBIAN_STYLE_INDICATED_BOUND) op: assign_op.Equal rhs: {(yes)} spids: [1100] ) ] ) ] ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(DQ ($ Id.VSub_DollarName '$DEBIAN_STYLE_INDICATED_BOUND'))} {(Id.Lit_Equals '=') (Id.Lit_Equals '=')} {(DQ (yes))} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:1122) ) ] action: [ (command.ControlFlow token: (Token id:Id.ControlFlow_Return val:return span_id:1127) arg_word: {(0)} ) ] spids: [1105 1124] ) ] ) (C {(local)} {(Id.Lit_VarLike 'NMAP_STYLE_INDICATED_BOUND=') (DQ (no))}) (command.AndOr ops: [Id.Op_DAmp] children: [ (command.Simple words: [ {(${ Id.VSub_Name NC_PATH)} {(--wait)} {(1)} {(--recv-only)} {(--send-only)} {(DQ ($ Id.VSub_DollarName '$SCAN_HOST'))} {(DQ ($ Id.VSub_DollarName '$SCAN_PORT'))} ] redirects: [ (redir.Redir op: (Token id:Id.Redir_Great val:'>' span_id:1168) fd: -1 arg_word: {(/dev/null)} ) (redir.Redir op: (Token id:Id.Redir_Great val:'2>' span_id:1171) fd: 2 arg_word: {(/dev/null)} ) ] ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:NMAP_STYLE_INDICATED_BOUND) op: assign_op.Equal rhs: {(yes)} spids: [1178] ) ] ) ] ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(DQ ($ Id.VSub_DollarName '$NMAP_STYLE_INDICATED_BOUND'))} {(Id.Lit_Equals '=') (Id.Lit_Equals '=')} {(DQ (yes))} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:1200) ) ] action: [ (command.ControlFlow token: (Token id:Id.ControlFlow_Return val:return span_id:1205) arg_word: {(0)} ) ] spids: [1183 1202] ) ] ) (command.ControlFlow token: (Token id:Id.ControlFlow_Return val:return span_id:1222) arg_word: {(1)} ) ] ) ) (command.ShFunction name: writeConfig body: (command.BraceGroup children: [ (command.WhileUntil keyword: (Token id:Id.KW_While val:while span_id:1245) cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {($ Id.VSub_Pound '$#')} {(-gt)} {(0)} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:1256) ) ] body: (command.DoGroup children: [ (C {(eval)} {(echo)} { (DQ ($ Id.VSub_Number '$1') ('=') (word_part.EscapedLiteral token: (Token id:Id.Lit_EscapedChar val:'\\$' span_id:1268) ) ($ Id.VSub_Number '$1') ) } ) (C {(shift)}) ] ) ) ] ) ) (command.ShFunction name: prompt body: (command.BraceGroup children: [ (C {(local)} {(VALUE)}) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(DQ (yes))} {(Id.Lit_Equals '=')} {(DQ ($ Id.VSub_DollarName '$USE_DEFAULTS'))} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:1322) ) ] action: [ (C {(echo)} {(DQ ($ Id.VSub_Number '$2'))}) (command.ControlFlow token: (Token id:Id.ControlFlow_Return val:return span_id:1338) ) ] spids: [1306 1324] ) ] ) (command.Simple words: [{(echo)} {(-en)} {(SQ (Token id:Id.Lit_Chars val:'\\e[1m' span_id:1354))}] redirects: [ (redir.Redir op: (Token id:Id.Redir_GreatAnd val:'>&' span_id:1357) fd: -1 arg_word: {(3)} ) ] ) (command.Simple words: [ {(echo)} {(-n)} {(DQ ($ Id.VSub_Number '$1') (' [') ($ Id.VSub_Number '$2') (']'))} ] redirects: [ (redir.Redir op: (Token id:Id.Redir_GreatAnd val:'>&' span_id:1372) fd: -1 arg_word: {(3)} ) ] ) (command.Simple words: [{(echo)} {(-en)} {(SQ (Token id:Id.Lit_Chars val:'\\e[0m ' span_id:1381))}] redirects: [ (redir.Redir op: (Token id:Id.Redir_GreatAnd val:'>&' span_id:1384) fd: -1 arg_word: {(3)} ) ] ) (C {(read)} {(-u)} {(3)} {(VALUE)}) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(-z)} {(DQ ($ Id.VSub_DollarName '$VALUE'))} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:1408) ) ] action: [ (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:VALUE) op: assign_op.Equal rhs: {($ Id.VSub_Number '$2')} spids: [1413] ) ] ) ] spids: [1397 1410] ) ] ) (C {(echo)} {(DQ ($ Id.VSub_DollarName '$VALUE'))}) ] ) ) (command.ShFunction name: prompt-numeric body: (command.BraceGroup children: [ (C {(local)} {(Id.Lit_VarLike 'NUMERIC_REGEX=') (DQ ('^[0-9]+') (Id.Lit_Other '$'))}) (command.WhileUntil keyword: (Token id:Id.KW_While val:while span_id:1445) cond: [ (command.Sentence child: (C {(true)}) terminator: (Token id:Id.Op_Semi val:';' span_id:1448) ) ] body: (command.DoGroup children: [ (C {(local)} {(Id.Lit_VarLike 'VALUE=') (command_sub left_token: (Token id:Id.Left_DollarParen val:'$(' span_id:1456) command_list: (command.CommandList children: [(C {(prompt)} {(DQ ($ Id.VSub_At '$@'))})] ) ) } ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (command.Pipeline children: [ (command.DBracket expr: (bool_expr.Binary op_id: Id.BoolBinary_EqualTilde left: {(DQ ($ Id.VSub_DollarName '$VALUE'))} right: {($ Id.VSub_DollarName '$NUMERIC_REGEX')} ) ) ] negated: T ) terminator: (Token id:Id.Op_Semi val:';' span_id:1482) ) ] action: [ (command.Simple words: [ {(echo)} { (DQ ("You entered '") ($ Id.VSub_DollarName '$VALUE') ("'. Please enter a number.") ) } ] redirects: [ (redir.Redir op: (Token id:Id.Redir_GreatAnd val:'>&' span_id:1495) fd: -1 arg_word: {(3)} ) ] ) ] spids: [1466 1484] ) ] else_action: [ (C {(echo)} {(DQ ($ Id.VSub_DollarName '$VALUE'))}) (command.ControlFlow token: (Token id:Id.ControlFlow_Return val:return span_id:1509) ) ] ) ] ) ) ] ) ) (command.ShFunction name: prompt-yesno body: (command.BraceGroup children: [ (command.WhileUntil keyword: (Token id:Id.KW_While val:while span_id:1527) cond: [ (command.Sentence child: (C {(true)}) terminator: (Token id:Id.Op_Semi val:';' span_id:1530) ) ] body: (command.DoGroup children: [ (C {(local)} {(Id.Lit_VarLike 'VALUE=') (command_sub left_token: (Token id:Id.Left_DollarParen val:'$(' span_id:1538) command_list: (command.CommandList children: [(C {(prompt)} {(DQ ($ Id.VSub_At '$@'))})] ) ) } ) (command.Case to_match: {($ Id.VSub_DollarName '$VALUE')} arms: [ (case_arm pat_list: [{(y)} {(Y)} {(yes)} {(YES)} {(Yes)}] action: [ (command.ControlFlow token: (Token id:Id.ControlFlow_Return val:return span_id:1576) arg_word: {(0)} ) ] spids: [1555 1573 1581 -1] ) (case_arm pat_list: [{(n)} {(N)} {(no)} {(NO)} {(No)}] action: [ (command.ControlFlow token: (Token id:Id.ControlFlow_Return val:return span_id:1605) arg_word: {(1)} ) ] spids: [1584 1602 1610 -1] ) ] ) (C {(echo)} { (DQ ('*** Please answer ') (word_part.EscapedLiteral token: (Token id:Id.Lit_EscapedChar val:'\\"' span_id:1621) ) (yes) (word_part.EscapedLiteral token:(Token id:Id.Lit_EscapedChar val:'\\"' span_id:1623)) (' or ') (word_part.EscapedLiteral token: (Token id:Id.Lit_EscapedChar val:'\\"' span_id:1625) ) (no) (word_part.EscapedLiteral token:(Token id:Id.Lit_EscapedChar val:'\\"' span_id:1627)) (.) ) } ) ] ) ) ] ) ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:USE_DEFAULTS) op: assign_op.Equal rhs: {(DQ (no))} spids: [1644] ) ] ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:USE_EXTERNAL_INTERFACE) op: assign_op.Equal rhs: {(DQ (no))} spids: [1649] ) ] ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:USE_SANDCATS) op: assign_op.Equal rhs: {(DQ (no))} spids: [1654] ) ] ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:SANDCATS_SUCCESSFUL) op: assign_op.Equal rhs: {(DQ (no))} spids: [1659] ) ] ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:SANDCATS_HTTPS_SUCCESSFUL) op: assign_op.Equal rhs: {(DQ (no))} spids: [1664] ) ] ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:CURRENTLY_UID_ZERO) op: assign_op.Equal rhs: {(DQ (no))} spids: [1669] ) ] ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:PREFER_ROOT) op: assign_op.Equal rhs: {(DQ (yes))} spids: [1674] ) ] ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:SHOW_MESSAGE_ABOUT_NEEDING_PORTS_OPEN) op: assign_op.Equal rhs: {(DQ (no))} spids: [1679] ) ] ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:STARTED_SANDSTORM) op: assign_op.Equal rhs: {(DQ (no))} spids: [1684] ) ] ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:NC_PATH) op: assign_op.Equal rhs: { (DQ (braced_var_sub token: (Token id:Id.VSub_Name val:OVERRIDE_NC_PATH span_id:1699) suffix_op: (suffix_op.Unary op_id:Id.VTest_ColonHyphen arg_word:{(nc)}) ) ) } spids: [1696] ) ] ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:DEV_TCP_USABLE) op: assign_op.Equal rhs: {(DQ (unchecked))} spids: [1709] ) ] ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:DEFAULT_DIR_FOR_ROOT) op: assign_op.Equal rhs: { (DQ (braced_var_sub token: (Token id: Id.VSub_Name val: OVERRIDE_SANDSTORM_DEFAULT_DIR span_id: 1724 ) suffix_op: (suffix_op.Unary op_id: Id.VTest_ColonHyphen arg_word: {(Id.Lit_Slash /) (opt) (Id.Lit_Slash /) (sandstorm)} ) ) ) } spids: [1721] ) ] ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:DEFAULT_DIR_FOR_NON_ROOT) op: assign_op.Equal rhs: { (DQ (braced_var_sub token: (Token id: Id.VSub_Name val: OVERRIDE_SANDSTORM_DEFAULT_DIR span_id: 1736 ) suffix_op: (suffix_op.Unary op_id: Id.VTest_ColonHyphen arg_word: { (braced_var_sub token: (Token id:Id.VSub_Name val:HOME span_id:1739) suffix_op: (suffix_op.Unary op_id: Id.VTest_ColonHyphen arg_word: {(opt)} ) ) (Id.Lit_Slash /) (sandstorm) } ) ) ) } spids: [1733] ) ] ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:DEFAULT_SMTP_PORT) op: assign_op.Equal rhs: {(DQ (30025))} spids: [1748] ) ] ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:DEFAULT_UPDATE_CHANNEL) op: assign_op.Equal rhs: {(DQ (dev))} spids: [1753] ) ] ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:DEFAULT_SERVER_USER) op: assign_op.Equal rhs: { (DQ (braced_var_sub token: (Token id: Id.VSub_Name val: OVERRIDE_SANDSTORM_DEFAULT_SERVER_USER span_id: 1761 ) suffix_op: (suffix_op.Unary op_id: Id.VTest_ColonHyphen arg_word: {(sandstorm)} ) ) ) } spids: [1758] ) ] ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:SANDCATS_BASE_DOMAIN) op: assign_op.Equal rhs: { (DQ (braced_var_sub token: (Token id: Id.VSub_Name val: OVERRIDE_SANDCATS_BASE_DOMAIN span_id: 1770 ) suffix_op: (suffix_op.Unary op_id: Id.VTest_ColonHyphen arg_word: {(sandcats.io)} ) ) ) } spids: [1767] ) ] ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:ALLOW_DEV_ACCOUNTS) op: assign_op.Equal rhs: {(DQ (false))} spids: [1776] ) ] ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:SANDCATS_GETCERTIFICATE) op: assign_op.Equal rhs: { (DQ (braced_var_sub token: (Token id: Id.VSub_Name val: OVERRIDE_SANDCATS_GETCERTIFICATE span_id: 1784 ) suffix_op: (suffix_op.Unary op_id:Id.VTest_ColonHyphen arg_word:{(yes)}) ) ) } spids: [1781] ) ] ) (command.ShFunction name: usage body: (command.BraceGroup children: [ (command.Simple words: [ {(echo)} { (DQ ('usage: ') ($ Id.VSub_DollarName '$SCRIPT_NAME') (' [-d] [-e] [-p PORT_NUMBER] [-u] [<bundle>]') ) } ] redirects: [ (redir.Redir op: (Token id:Id.Redir_GreatAnd val:'>&' span_id:1810) fd: -1 arg_word: {(2)} ) ] ) (command.Simple words: [ {(echo)} { (DQ ( 'If <bundle> is provided, it must be the name of a Sandstorm bundle file,' ) ) } ] redirects: [ (redir.Redir op: (Token id:Id.Redir_GreatAnd val:'>&' span_id:1820) fd: -1 arg_word: {(2)} ) ] ) (command.Simple words: [ {(echo)} { (DQ ( "like 'sandstorm-123.tar.xz', which will be installed. Otherwise, the script" ) ) } ] redirects: [ (redir.Redir op: (Token id:Id.Redir_GreatAnd val:'>&' span_id:1830) fd: -1 arg_word: {(2)} ) ] ) (command.Simple words: [{(echo)} {(DQ ('downloads a bundle from the internet via HTTP.'))}] redirects: [ (redir.Redir op: (Token id:Id.Redir_GreatAnd val:'>&' span_id:1840) fd: -1 arg_word: {(2)} ) ] ) (command.Simple words: [{(echo)} {(SQ )}] redirects: [ (redir.Redir op: (Token id:Id.Redir_GreatAnd val:'>&' span_id:1849) fd: -1 arg_word: {(2)} ) ] ) (command.Simple words: [ {(echo)} { (SQ (Token id: Id.Lit_Chars val: 'If -d is specified, the auto-installs with defaults suitable for app development.' span_id: 1856 ) ) } ] redirects: [ (redir.Redir op: (Token id:Id.Redir_GreatAnd val:'>&' span_id:1859) fd: -1 arg_word: {(2)} ) ] ) (command.Simple words: [ {(echo)} { (SQ (Token id: Id.Lit_Chars val: 'If -e is specified, default to listening on an external interface, not merely loopback.' span_id: 1866 ) ) } ] redirects: [ (redir.Redir op: (Token id:Id.Redir_GreatAnd val:'>&' span_id:1869) fd: -1 arg_word: {(2)} ) ] ) (command.Simple words: [ {(echo)} { (SQ (Token id: Id.Lit_Chars val: 'If -i is specified, default to (i)nsecure mode where we do not request a HTTPS certificate.' span_id: 1876 ) ) } ] redirects: [ (redir.Redir op: (Token id:Id.Redir_GreatAnd val:'>&' span_id:1879) fd: -1 arg_word: {(2)} ) ] ) (C {(echo)} { (SQ (Token id: Id.Lit_Chars val: 'If -p is specified, use its argument (PORT_NUMBER) as the default port for HTTP. Otherwise, use 6080. Note that if the install script enables HTTPS via sandcats.io, it will use 443 instead!' span_id: 1886 ) ) } ) (command.Simple words: [ {(echo)} { (SQ (Token id: Id.Lit_Chars val: 'If -u is specified, default to avoiding root priviliges. Note that the dev tools only work if the server as root privileges.' span_id: 1893 ) ) } ] redirects: [ (redir.Redir op: (Token id:Id.Redir_GreatAnd val:'>&' span_id:1896) fd: -1 arg_word: {(2)} ) ] ) (command.ControlFlow token: (Token id:Id.ControlFlow_Exit val:exit span_id:1900) arg_word: {(1)} ) ] ) ) (command.ShFunction name: detect_current_uid body: (command.BraceGroup children: [ (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} { (command_sub left_token: (Token id: Id.Left_DollarParen val: '$(' span_id: 1918 ) command_list: (command.CommandList children: [(C {(id)} {(-u)})] ) ) } {(Id.Lit_Equals '=')} {(0)} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:1929) ) ] action: [ (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:CURRENTLY_UID_ZERO) op: assign_op.Equal rhs: {(DQ (yes))} spids: [1934] ) ] ) ] spids: [1914 1931] ) ] ) ] ) ) (command.ShFunction name: disable_smtp_port_25_if_port_unavailable body: (command.BraceGroup children: [ (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:PORT_25_AVAILABLE) op: assign_op.Equal rhs: {(DQ (no))} spids: [1952] ) ] ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(is_port_bound)} {(0.0.0.0)} {(25)}) terminator: (Token id:Id.Op_Semi val:';' span_id:1965) ) ] action: [ (command.ControlFlow token: (Token id:Id.ControlFlow_Return val:return span_id:1970) ) ] spids: [1958 1967] ) ] ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(is_port_bound)} {(127.0.0.1)} {(25)}) terminator: (Token id:Id.Op_Semi val:';' span_id:1983) ) ] action: [ (command.ControlFlow token: (Token id:Id.ControlFlow_Return val:return span_id:1988) ) ] spids: [1976 1985] ) ] ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:PORT_25_AVAILABLE) op: assign_op.Equal rhs: {(DQ (yes))} spids: [1994] ) ] ) ] ) ) (command.ShFunction name: disable_https_if_ports_unavailable body: (command.BraceGroup children: [ (C {(local)} {(Id.Lit_VarLike 'PORT_80_AVAILABLE=') (DQ (no))}) (command.AndOr ops: [Id.Op_DPipe] children: [ (C {(is_port_bound)} {(0.0.0.0)} {(80)}) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:PORT_80_AVAILABLE) op: assign_op.Equal rhs: {(DQ (yes))} spids: [2073] ) ] ) ] ) (C {(local)} {(Id.Lit_VarLike 'PORT_443_AVAILABLE=') (DQ (no))}) (command.AndOr ops: [Id.Op_DPipe] children: [ (C {(is_port_bound)} {(0.0.0.0)} {(443)}) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:PORT_443_AVAILABLE) op: assign_op.Equal rhs: {(DQ (yes))} spids: [2096] ) ] ) ] ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(DQ ($ Id.VSub_DollarName '$PORT_443_AVAILABLE'))} {(Id.Lit_Equals '=') (Id.Lit_Equals '=')} {(DQ (no))} {(-o)} {(DQ ($ Id.VSub_DollarName '$PORT_80_AVAILABLE'))} {(Id.Lit_Equals '=') (Id.Lit_Equals '=')} {(DQ (no))} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:2133) ) ] action: [ (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:SANDCATS_GETCERTIFICATE) op: assign_op.Equal rhs: {(DQ (no))} spids: [2138] ) ] ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:SHOW_MESSAGE_ABOUT_NEEDING_PORTS_OPEN) op: assign_op.Equal rhs: {(DQ (yes))} spids: [2144] ) ] ) ] spids: [2103 2135] ) ] ) ] ) ) (command.ShFunction name: handle_args body: (command.BraceGroup children: [ (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:SCRIPT_NAME) op: assign_op.Equal rhs: {($ Id.VSub_Number '$1')} spids: [2163] ) ] ) (C {(shift)}) (command.WhileUntil keyword: (Token id:Id.KW_While val:while span_id:2171) cond: [ (command.Sentence child: (C {(getopts)} {(DQ (':deiup:'))} {(opt)}) terminator: (Token id:Id.Op_Semi val:';' span_id:2180) ) ] body: (command.DoGroup children: [ (command.Case to_match: {($ Id.VSub_DollarName '$opt')} arms: [ (case_arm pat_list: [{(d)}] action: [ (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:USE_DEFAULTS) op: assign_op.Equal rhs: {(DQ (yes))} spids: [2196] ) ] ) ] spids: [2192 2193 2202 -1] ) (case_arm pat_list: [{(e)}] action: [ (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:USE_EXTERNAL_INTERFACE) op: assign_op.Equal rhs: {(DQ (yes))} spids: [2209] ) ] ) ] spids: [2205 2206 2215 -1] ) (case_arm pat_list: [{(i)}] action: [ (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:SANDCATS_GETCERTIFICATE) op: assign_op.Equal rhs: {(DQ (no))} spids: [2222] ) ] ) ] spids: [2218 2219 2228 -1] ) (case_arm pat_list: [{(u)}] action: [ (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:PREFER_ROOT) op: assign_op.Equal rhs: {(no)} spids: [2235] ) ] ) ] spids: [2231 2232 2239 -1] ) (case_arm pat_list: [{(p)}] action: [ (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:DEFAULT_PORT) op: assign_op.Equal rhs: {(DQ (${ Id.VSub_Name OPTARG))} spids: [2246] ) ] ) ] spids: [2242 2243 2254 -1] ) (case_arm pat_list: [{(Id.Lit_Star '*')}] action: [(C {(usage)})] spids: [2257 2258 2264 -1] ) ] ) ] ) ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:DEFAULT_PORT) op: assign_op.Equal rhs: { (DQ (braced_var_sub token: (Token id:Id.VSub_Name val:DEFAULT_PORT span_id:2281) suffix_op: (suffix_op.Unary op_id: Id.VTest_ColonHyphen arg_word: {(6080)} ) ) ) } spids: [2278] ) ] ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:ORIGINAL_ARGS) op: assign_op.Equal rhs: { (sh_array_literal left: (Token id:Id.Op_LParen val:'(' span_id:2298) words: [{(DQ ($ Id.VSub_At '$@'))}] ) } spids: [2297] ) ] ) (C {(shift)} { (DQ (word_part.ArithSub anode: (arith_expr.Binary op_id: Id.Arith_Minus left: (arith_expr.VarRef token: (Token id:Id.Lit_ArithVarLike val:OPTIND span_id:2314) ) right: (arith_expr.ArithWord w:{(Id.Lit_Digits 1)}) ) ) ) } ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (command.AndOr ops: [Id.Op_DAmp] children: [ (C {(Id.Lit_LBracket '[')} {($ Id.VSub_Pound '$#')} {(Id.Lit_Equals '=')} {(1)} {(Id.Lit_RBracket ']')} ) (command.DBracket expr: (bool_expr.LogicalNot child: (bool_expr.Binary op_id: Id.BoolBinary_EqualTilde left: {($ Id.VSub_Number '$1')} right: {(Id.Lit_Other '^') (-)} ) ) ) ] ) terminator: (Token id:Id.Op_Semi val:';' span_id:2351) ) ] action: [ (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:BUNDLE_FILE) op: assign_op.Equal rhs: {(DQ ($ Id.VSub_Number '$1'))} spids: [2356] ) ] ) ] spids: [2325 2353] ) (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {($ Id.VSub_Pound '$#')} {(Id.KW_Bang '!') (Id.Lit_Equals '=')} {(0)} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:2374) ) ] action: [(C {(usage)})] spids: [2362 2376] ) ] ) ] ) ) (command.ShFunction name: rerun_script_as_root body: (command.BraceGroup children: [ (C {(local)} {(Id.Lit_VarLike 'ENVVARS=') (command_sub left_token: (Token id:Id.Left_DollarParen val:'$(' span_id:2431) command_list: (command.CommandList children: [(C {(echo)} {($ Id.VSub_At '$@')})] ) ) } ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:ENVVARS) op: assign_op.Equal rhs: { (DQ ($ Id.VSub_DollarName '$ENVVARS') (' CURL_USER_AGENT=') ($ Id.VSub_DollarName '$CURL_USER_AGENT') ) } spids: [2447] ) ] ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} { (DQ (command_sub left_token: (Token id: Id.Left_DollarParen val: '$(' span_id: 2461 ) command_list: (command.CommandList children: [ (C {(basename)} {($ Id.VSub_DollarName '$SCRIPT_NAME')}) ] ) ) ) } {(Id.Lit_Equals '=') (Id.Lit_Equals '=')} {(bash)} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:2474) ) ] action: [ (C {(echo)} {(DQ ('Re-running script as root...'))}) (C {(exec)} {(sudo)} {(bash)} {(-euo)} {(pipefail)} {(-c)} { (DQ ('curl -fs -A ') ($ Id.VSub_DollarName '$CURL_USER_AGENT') (' https://install.sandstorm.io | ') ($ Id.VSub_DollarName '$ENVVARS') (' bash') ) } ) ] spids: [2456 2476] ) (if_arm cond: [ (command.Sentence child: (command.AndOr ops: [Id.Op_DAmp] children: [ (C {(Id.Lit_LBracket '[')} { (DQ (command_sub left_token: (Token id: Id.Left_DollarParen val: '$(' span_id: 2517 ) command_list: (command.CommandList children: [ (C {(basename)} {($ Id.VSub_DollarName '$SCRIPT_NAME')} ) ] ) ) ) } {(Id.Lit_Equals '=') (Id.Lit_Equals '=')} {(install.sh)} {(Id.Lit_RBracket ']')} ) (C {(Id.Lit_LBracket '[')} {(-e)} {(DQ ($ Id.VSub_Number '$0'))} {(Id.Lit_RBracket ']')} ) ] ) terminator: (Token id:Id.Op_Semi val:';' span_id:2542) ) ] action: [ (C {(echo)} {(DQ ('Re-running script as root...'))}) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} { (braced_var_sub token: (Token id: Id.VSub_Name val: ORIGINAL_ARGS span_id: 2564 ) prefix_op: (Id.VSub_Pound) bracket_op: (bracket_op.WholeArray op_id:Id.Lit_At) ) } {(Id.Lit_Equals '=')} {(0)} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:2575) ) ] action: [ (C {(exec)} {(sudo)} {($ Id.VSub_DollarName '$ENVVARS')} {(bash)} {(DQ ($ Id.VSub_DollarName '$SCRIPT_NAME'))} ) ] spids: [2558 2577] ) ] else_action: [ (C {(exec)} {(sudo)} {($ Id.VSub_DollarName '$ENVVARS')} {(bash)} {(DQ ($ Id.VSub_DollarName '$SCRIPT_NAME'))} { (DQ (braced_var_sub token: (Token id:Id.VSub_Name val:ORIGINAL_ARGS span_id:2610) bracket_op: (bracket_op.WholeArray op_id:Id.Lit_At) ) ) } ) ] ) ] spids: [2512 2544] ) ] ) (command.Simple words: [ {(fail)} {(DQ (E_CANT_SWITCH_TO_ROOT))} { (DQ ( 'ERROR: This script could not detect its own filename, so could not switch to root. ' ) ("Please download a copy and name it 'install.sh' and run that as root, perhaps using sudo. ") ('Try this command:\n') ('\n') ('curl https://install.sandstorm.io/ > install.sh && sudo bash install.sh') ) } ] more_env: [(env_pair name:REPORT val:{(no)} spids:[2629])] ) ] ) ) (command.ShFunction name: set_umask body: (command.BraceGroup children:[(C {(umask)} {(0022)})]) ) (command.ShFunction name: assert_on_terminal body: (command.BraceGroup children: [ (command.If arms: [ (if_arm cond: [ (command.Sentence child: (command.AndOr ops: [Id.Op_DAmp] children: [ (C {(Id.Lit_LBracket '[')} {(DQ (no))} {(Id.Lit_Equals '=')} {(DQ ($ Id.VSub_DollarName '$USE_DEFAULTS'))} {(Id.Lit_RBracket ']')} ) (C {(Id.Lit_LBracket '[')} {(Id.KW_Bang '!')} {(-t)} {(1)} {(Id.Lit_RBracket ']')} ) ] ) terminator: (Token id:Id.Op_Semi val:';' span_id:2703) ) ] action: [ (command.Simple words: [ {(fail)} {(DQ (E_NO_TTY))} {(DQ ('This script is interactive. Please run it on a terminal.'))} ] more_env: [(env_pair name:REPORT val:{(no)} spids:[2708])] ) ] spids: [2676 2705] ) ] ) (command.Simple words: [{(exec)}] redirects: [ (redir.Redir op: (Token id:Id.Redir_LessAnd val:'3<&' span_id:2752) fd: 3 arg_word: {(1)} ) ] ) ] ) ) (command.ShFunction name: assert_linux_x86_64 body: (command.BraceGroup children: [ (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} { (DQ (command_sub left_token: (Token id: Id.Left_DollarParen val: '$(' span_id: 2770 ) command_list: (command.CommandList children:[(C {(uname)})]) ) ) } {(Id.KW_Bang '!') (Id.Lit_Equals '=')} {(Linux)} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:2781) ) ] action: [ (C {(fail)} {(DQ (E_NON_LINUX))} { (DQ ( 'Sandstorm requires Linux. If you want to run Sandstorm on a Windows or\n' ) ('Mac system, you can use Vagrant or another virtualization tool. See our install documentation:\n') ('\n') ('- https://docs.sandstorm.io/en/latest/install/') ) } ) ] spids: [2765 2783] ) ] ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} { (DQ (command_sub left_token: (Token id: Id.Left_DollarParen val: '$(' span_id: 2809 ) command_list: (command.CommandList children: [(C {(uname)} {(-m)})] ) ) ) } {(Id.KW_Bang '!') (Id.Lit_Equals '=')} {(x86_64)} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:2822) ) ] action: [ (C {(fail)} {(DQ (E_NON_X86_64))} { (DQ ( 'Sorry, the Sandstorm server currently only runs on x86_64 machines.' ) ) } ) ] spids: [2804 2824] ) ] ) ] ) ) (command.ShFunction name: assert_usable_kernel body: (command.BraceGroup children: [ (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:KVERSION) op: assign_op.Equal rhs: { (sh_array_literal left: (Token id:Id.Op_LParen val:'(' span_id:2851) words: [ { (command_sub left_token: (Token id: Id.Left_DollarParen val: '$(' span_id: 2853 ) command_list: (command.CommandList children: [ (command.Pipeline children: [ (C {(uname)} {(-r)}) (C {(grep)} {(-o)} { (SQ (Token id: Id.Lit_Chars val: '^[0-9.]*' span_id: 2865 ) ) } ) (C {(tr)} {(.)} {(SQ (Token id:Id.Lit_Chars val:' ' span_id:2875))} ) ] negated: F ) ] ) ) } ] ) } spids: [2850] ) ] ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (command.DParen child: (arith_expr.Binary op_id: Id.Arith_DPipe left: (arith_expr.Binary op_id: Id.Arith_Less left: (arith_expr.Binary op_id: Id.Arith_LBracket left: (arith_expr.VarRef token: (Token id: Id.Lit_ArithVarLike val: KVERSION span_id: 2887 ) ) right: (arith_expr.ArithWord w:{(Id.Lit_Digits 0)}) ) right: (arith_expr.ArithWord w:{(Id.Lit_Digits 3)}) ) right: (arith_expr.Binary op_id: Id.Arith_DAmp left: (arith_expr.Binary op_id: Id.Arith_DEqual left: (arith_expr.Binary op_id: Id.Arith_LBracket left: (arith_expr.VarRef token: (Token id: Id.Lit_ArithVarLike val: KVERSION span_id: 2899 ) ) right: (arith_expr.ArithWord w:{(Id.Lit_Digits 0)}) ) right: (arith_expr.ArithWord w:{(Id.Lit_Digits 3)}) ) right: (arith_expr.Binary op_id: Id.Arith_Less left: (arith_expr.Binary op_id: Id.Arith_LBracket left: (arith_expr.VarRef token: (Token id: Id.Lit_ArithVarLike val: KVERSION span_id: 2910 ) ) right: (arith_expr.ArithWord w:{(Id.Lit_Digits 1)}) ) right: (arith_expr.ArithWord w:{(Id.Lit_Digits 10)}) ) ) ) ) terminator: (Token id:Id.Op_Semi val:';' span_id:2922) ) ] action: [ (C {(error)} { (DQ ('Detected Linux kernel version: ') (command_sub left_token: (Token id:Id.Left_DollarParen val:'$(' span_id:2931) command_list: (command.CommandList children: [(C {(uname)} {(-r)})] ) ) ) } ) (C {(fail)} {(DQ (E_KERNEL_OLDER_THAN_310))} { (DQ ( 'Sorry, your kernel is too old to run Sandstorm. We require kernel' ) ) } {(DQ ('version 3.10 or newer.'))} ) ] spids: [2883 2924] ) ] ) ] ) ) (command.ShFunction name: maybe_enable_userns_sysctl body: (command.BraceGroup children: [ (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(DQ ($ Id.VSub_DollarName '$USE_DEFAULTS'))} {(Id.KW_Bang '!') (Id.Lit_Equals '=')} {(DQ (yes))} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:2994) ) ] action: [ (command.ControlFlow token: (Token id:Id.ControlFlow_Return val:return span_id:3015) ) ] spids: [2977 2996] ) ] ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(DQ (no))} {(Id.Lit_Equals '=')} {(DQ ($ Id.VSub_DollarName '$CURRENTLY_UID_ZERO'))} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:3038) ) ] action: [ (command.ControlFlow token: (Token id:Id.ControlFlow_Return val:return span_id:3047) ) ] spids: [3022 3040] ) ] ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(Id.KW_Bang '!')} {(-e)} {(/proc/sys/kernel/unprivileged_userns_clone)} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:3065) ) ] action: [ (command.ControlFlow token: (Token id:Id.ControlFlow_Return val:return span_id:3074) ) ] spids: [3054 3067] ) ] ) (C {(local)} {(Id.Lit_VarLike 'OLD_VALUE=') (DQ (command_sub left_token: (Token id:Id.Left_DollarParen val:'$(' span_id:3085) command_list: (command.CommandList children: [ (command.Simple redirects: [ (redir.Redir op: (Token id:Id.Redir_Less val:'<' span_id:3086) fd: -1 arg_word: {(/proc/sys/kernel/unprivileged_userns_clone)} ) ] ) ] ) ) ) } ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(DQ ($ Id.VSub_DollarName '$OLD_VALUE'))} {(Id.Lit_Equals '=')} {(DQ (1))} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:3109) ) ] action: [ (command.ControlFlow token: (Token id:Id.ControlFlow_Return val:return span_id:3118) ) ] spids: [3094 3111] ) ] ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (command.Simple words: [ {(sysctl)} {(-wq)} {(kernel.unprivileged_userns_clone) (Id.Lit_Equals '=') (1)} ] redirects: [ (redir.Redir op: (Token id:Id.Redir_Great val:'2>' span_id:3139) fd: 2 arg_word: {(/dev/null)} ) ] ) terminator: (Token id:Id.Op_Semi val:';' span_id:3141) ) ] action: [ (C {(echo)} { (DQ ( 'NOTE: Enabled unprivileged user namespaces because you passed -d.' ) ) } ) ] spids: [3129 3143] ) ] else_action: [ (command.ControlFlow token: (Token id:Id.ControlFlow_Return val:return span_id:3160) ) ] ) (C {(local)} {(Id.Lit_VarLike 'SYSCTL_FILENAME=') (DQ (/etc/sysctl.conf))}) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(-d)} {(/etc/sysctl.d)} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:3193) ) ] action: [ (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:SYSCTL_FILENAME) op: assign_op.Equal rhs: {(DQ (/etc/sysctl.d/50-sandstorm.conf))} spids: [3198] ) ] ) ] spids: [3183 3195] ) ] ) (command.If arms: [ (if_arm cond: [ (command.Pipeline children: [ (command.Simple words: [{(cat)}] redirects: [ (redir.Redir op: (Token id:Id.Redir_DGreat val:'>>' span_id:3214) fd: -1 arg_word: {(DQ ($ Id.VSub_DollarName '$SYSCTL_FILENAME'))} ) (redir.HereDoc op: (Token id:Id.Redir_DLess val:'<<' span_id:3220) fd: -1 here_begin: {(__EOF__)} here_end_span_id: 3228 stdin_parts: [ ('\n') ( '# Enable non-root users to create sandboxes (needed by Sandstorm).\n' ) ('kernel.unprivileged_userns_clone = 1\n') ] ) ] ) ] negated: T ) ] action: [ (C {(echo)} { (DQ ( "NOTE: Never mind, not enabling userns because can't write /etc/sysctl.d." ) ) } ) (command.AndOr ops: [Id.Op_DPipe] children: [ (C {(sysctl)} {(-wq)} { (DQ ('kernel.unprivileged_userns_clone=') ($ Id.VSub_DollarName '$OLD_VALUE') ) } ) (C {(true)}) ] ) (command.ControlFlow token: (Token id:Id.ControlFlow_Return val:return span_id:3266) ) ] spids: [3208 3230] ) ] ) ] ) ) (command.ShFunction name: test_if_dev_tcp_works body: (command.BraceGroup children: [ (command.If arms: [ (if_arm cond: [ (command.Sentence child: (command.Pipeline children: [ (command.Subshell command_list: (command.CommandList children: [ (command.AndOr ops: [Id.Op_DPipe] children: [ (command.Simple words: [ {(timeout)} {(1)} {(bash)} {(-c)} { (SQ (Token id: Id.Lit_Chars val: ': < /dev/tcp/localhost/0' span_id: 3321 ) ) } ] redirects: [ (redir.Redir op: (Token id: Id.Redir_GreatAnd val: '2>&' span_id: 3324 ) fd: 2 arg_word: {(1)} ) ] ) (C {(true)}) ] ) ] ) ) (C {(grep)} {(-q)} {(SQ (Token id:Id.Lit_Chars val:'connect:' span_id:3339))} ) ] negated: F ) terminator: (Token id:Id.Op_Semi val:';' span_id:3342) ) ] action: [ (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:DEV_TCP_USABLE) op: assign_op.Equal rhs: {(DQ (yes))} spids: [3355] ) ] ) ] spids: [3309 3344] ) ] else_action: [ (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:DEV_TCP_USABLE) op: assign_op.Equal rhs: {(DQ (no))} spids: [3364] ) ] ) ] ) ] ) ) (command.ShFunction name: assert_dependencies body: (command.BraceGroup children: [ (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(-z)} { (DQ (braced_var_sub token: (Token id:Id.VSub_Name val:BUNDLE_FILE span_id:3390) suffix_op: (suffix_op.Unary op_id:Id.VTest_ColonHyphen arg_word:(word.Empty)) ) ) } {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:3396) ) ] action: [ (command.AndOr ops: [Id.Op_DPipe] children: [ (command.Simple words: [{(which)} {(curl)}] redirects: [ (redir.Redir op: (Token id:Id.Redir_Great val:'>' span_id:3405) fd: -1 arg_word: {(/dev/null)} ) ] ) (C {(fail)} {(DQ (E_CURL_MISSING))} { (DQ ( 'Please install curl(1). Sandstorm uses it to download updates.' ) ) } ) ] ) ] spids: [3382 3398] ) ] ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(DQ (${ Id.VSub_Name DEV_TCP_USABLE))} {(Id.Lit_Equals '=')} {(DQ (unchecked))} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:3451) ) ] action: [(C {(test_if_dev_tcp_works)})] spids: [3433 3453] ) ] ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(DQ (${ Id.VSub_Name DEV_TCP_USABLE))} {(Id.Lit_Equals '=')} {(DQ (no))} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:3480) ) ] action: [ (command.AndOr ops: [Id.Op_DPipe] children: [ (command.Simple words: [{(which)} {(nc)}] redirects: [ (redir.Redir op: (Token id:Id.Redir_Great val:'>' span_id:3489) fd: -1 arg_word: {(/dev/null)} ) ] ) (C {(fail)} {(DQ (E_NC_MISSING))} { (DQ ( "Please install nc(1). (Package may be called 'netcat-traditional' or 'netcat-openbsd'.)" ) ) } ) ] ) ] spids: [3462 3482] ) ] ) (command.AndOr ops: [Id.Op_DPipe] children: [ (command.Simple words: [{(which)} {(tar)}] redirects: [ (redir.Redir op: (Token id:Id.Redir_Great val:'>' span_id:3514) fd: -1 arg_word: {(/dev/null)} ) ] ) (C {(fail)} {(DQ (E_TAR_MISSING))} {(DQ ('Please install tar(1).'))}) ] ) (command.AndOr ops: [Id.Op_DPipe] children: [ (command.Simple words: [{(which)} {(xz)}] redirects: [ (redir.Redir op: (Token id:Id.Redir_Great val:'>' span_id:3535) fd: -1 arg_word: {(/dev/null)} ) ] ) (C {(fail)} {(DQ (E_XZ_MISSING))} {(DQ ("Please install xz(1). (Package may be called 'xz-utils'.)"))} ) ] ) ] ) ) (command.ShFunction name: assert_valid_bundle_file body: (command.BraceGroup children: [ (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(-n)} { (DQ (braced_var_sub token: (Token id:Id.VSub_Name val:BUNDLE_FILE span_id:3578) suffix_op: (suffix_op.Unary op_id:Id.VTest_ColonHyphen arg_word:(word.Empty)) ) ) } {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:3584) ) ] action: [ (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:BUNDLE_DIR) op: assign_op.Equal rhs: { (command_sub left_token: (Token id: Id.Left_DollarParen val: '$(' span_id: 3598 ) command_list: (command.CommandList children: [ (command.Pipeline children: [ (command.Subshell command_list: (command.CommandList children: [ (command.AndOr ops: [Id.Op_DPipe] children: [ (C {(tar)} {(Jtf)} { (DQ ($ Id.VSub_DollarName '$BUNDLE_FILE' ) ) } ) (C {(true)}) ] ) ] ) ) (C {(head)} {(-n)} {(1)}) ] negated: F ) ] ) ) } spids: [3597] ) ] ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (command.DBracket expr: (bool_expr.LogicalNot child: (bool_expr.Binary op_id: Id.BoolBinary_EqualTilde left: {(DQ ($ Id.VSub_DollarName '$BUNDLE_DIR'))} right: {(sandstorm-) (Id.Lit_Other '(') (Id.Lit_Other '[') (0-9) (Id.Lit_Other ']') (Id.Lit_Other '+') (Id.Lit_Other ')') (/) } ) ) ) terminator: (Token id:Id.Op_Semi val:';' span_id:3646) ) ] action: [ (C {(fail)} {(DQ (E_INVALID_BUNDLE))} { (DQ ($ Id.VSub_DollarName '$BUNDLE_FILE') (': Not a valid Sandstorm bundle') ) } ) ] spids: [3624 3648] ) ] ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:BUILD) op: assign_op.Equal rhs: { (braced_var_sub token: (Token id:Id.VSub_Name val:BASH_REMATCH span_id:3669) bracket_op: (bracket_op.ArrayIndex expr: (arith_expr.ArithWord w:{(Id.Lit_Digits 1)}) ) ) } spids: [3667] ) ] ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:BUNDLE_FILE) op: assign_op.Equal rhs: { (command_sub left_token: (Token id: Id.Left_DollarParen val: '$(' span_id: 3682 ) command_list: (command.CommandList children: [ (C {(readlink)} {(-f)} {(DQ ($ Id.VSub_DollarName '$BUNDLE_FILE'))} ) ] ) ) } spids: [3681] ) ] ) ] spids: [3570 3586] ) ] ) ] ) ) (command.ShFunction name: detect_init_system body: (command.BraceGroup children: [ (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:INIT_SYSTEM) op: assign_op.Equal rhs: {(DQ (unknown))} spids: [3709] ) ] ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(grep)} {(-q)} {(systemd)} {(/proc/1/comm)}) terminator: (Token id:Id.Op_Semi val:';' span_id:3729) ) ] action: [ (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:INIT_SYSTEM) op: assign_op.Equal rhs: {(DQ (systemd))} spids: [3734] ) ] ) (command.ControlFlow token: (Token id:Id.ControlFlow_Return val:return span_id:3740) ) ] spids: [3720 3731] ) ] ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(-e)} {(/etc/init.d)} {(Id.Lit_RBracket ']')}) terminator: (Token id:Id.Op_Semi val:';' span_id:3764) ) ] action: [ (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:INIT_SYSTEM) op: assign_op.Equal rhs: {(DQ (sysvinit))} spids: [3769] ) ] ) (command.ControlFlow token: (Token id:Id.ControlFlow_Return val:return span_id:3775) ) ] spids: [3755 3766] ) ] ) ] ) ) (command.ShFunction name: choose_install_mode body: (command.BraceGroup children: [ (C {(echo)} {(-n)} { (SQ (Token id: Id.Lit_Chars val: 'Sandstorm makes it easy to run web apps on your own server. ' span_id: 3804 ) ) } ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(DQ (yes))} {(Id.Lit_Equals '=')} {(DQ ($ Id.VSub_DollarName '$USE_DEFAULTS'))} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:3825) ) ] action: [ (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:CHOSEN_INSTALL_MODE) op: assign_op.Equal rhs: { (DQ (braced_var_sub token: (Token id: Id.VSub_Name val: CHOSEN_INSTALL_MODE span_id: 3833 ) suffix_op: (suffix_op.Unary op_id: Id.VTest_ColonHyphen arg_word: {(2)} ) ) ) } spids: [3830] ) ] ) ] spids: [3809 3827] ) ] ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(DQ (no))} {(Id.Lit_Equals '=')} { (DQ (braced_var_sub token: (Token id:Id.VSub_Name val:PREFER_ROOT span_id:3859) suffix_op: (suffix_op.Unary op_id:Id.VTest_ColonHyphen arg_word:(word.Empty)) ) ) } {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:3866) ) ] action: [ (C {(echo)} {(DQ )}) (C {(echo)} { (DQ ( 'NOTE: Showing you all options, including development options, but omitting ' ) ) } ) (C {(echo)} { (DQ ( ' init script automation, because you chose to install without using root.' ) ) } ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:CHOSEN_INSTALL_MODE) op: assign_op.Equal rhs: { (DQ (braced_var_sub token: (Token id: Id.VSub_Name val: CHOSEN_INSTALL_MODE span_id: 3894 ) suffix_op: (suffix_op.Unary op_id: Id.VTest_ColonHyphen arg_word: {(2)} ) ) ) } spids: [3891] ) ] ) ] spids: [3847 3868] ) ] ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(-z)} { (DQ (braced_var_sub token: (Token id: Id.VSub_Name val: CHOSEN_INSTALL_MODE span_id: 3916 ) suffix_op: (suffix_op.Unary op_id:Id.VTest_ColonHyphen arg_word:(word.Empty)) ) ) } {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:3922) ) ] action: [ (C {(echo)} {(DQ ('You can have:'))}) (C {(echo)} {(DQ )}) (C {(echo)} { (DQ ( '1. A typical install, to use Sandstorm (press enter to accept this default)' ) ) } ) (C {(echo)} { (DQ ( '2. A development server, for working on Sandstorm itself or localhost-based app development' ) ) } ) (C {(echo)} {(DQ )}) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:CHOSEN_INSTALL_MODE) op: assign_op.Equal rhs: { (command_sub left_token: (Token id: Id.Left_DollarParen val: '$(' span_id: 3961 ) command_list: (command.CommandList children: [ (C {(prompt-numeric)} { (DQ ( 'How are you going to use this Sandstorm install?' ) ) } {(DQ (1))} ) ] ) ) } spids: [3960] ) ] ) ] spids: [3908 3924] ) ] ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(DQ (1))} {(Id.Lit_Equals '=')} {(DQ ($ Id.VSub_DollarName '$CHOSEN_INSTALL_MODE'))} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:3994) ) ] action: [(C {(assert_full_server_dependencies)}) (C {(full_server_install)})] spids: [3978 3996] ) ] else_action: [(C {(dev_server_install)})] ) ] ) ) (command.ShFunction name: assert_full_server_dependencies body: (command.BraceGroup children: [ (command.AndOr ops: [Id.Op_DPipe] children: [ (command.Simple words: [{(which)} {(openssl)}] redirects: [ (redir.Redir op: (Token id:Id.Redir_Great val:'>' span_id:4039) fd: -1 arg_word: {(/dev/null)} ) ] ) (C {(fail)} {(DQ (E_OPENSSL_MISSING))} { (DQ ( 'Please install openssl(1). Sandstorm uses it for the Sandcats.io dynamic DNS service.' ) ) } ) ] ) ] ) ) (command.ShFunction name: dev_server_install body: (command.BraceGroup children: [ (command.If arms: [ (if_arm cond: [ (command.Sentence child: (command.AndOr ops: [Id.Op_DAmp] children: [ (C {(Id.Lit_LBracket '[')} {(DQ (yes))} {(Id.Lit_Equals '=')} {(DQ ($ Id.VSub_DollarName '$PREFER_ROOT'))} {(Id.Lit_RBracket ']')} ) (C {(Id.Lit_LBracket '[')} {(DQ (no))} {(Id.Lit_Equals '=')} {(DQ ($ Id.VSub_DollarName '$CURRENTLY_UID_ZERO'))} {(Id.Lit_RBracket ']')} ) ] ) terminator: (Token id:Id.Op_Semi val:';' span_id:4137) ) ] action: [ (C {(echo)} { (DQ ( 'If you want app developer mode for a Sandstorm install, you need root' ) ) } ) (C {(echo)} {(DQ ('due to limitations in the Linux kernel.'))}) (C {(echo)} {(DQ )}) (C {(echo)} {(DQ ('To set up Sandstorm, we will use sudo to switch to root, then'))} ) (C {(echo)} {(DQ ('provide further information before doing the install.'))}) (C {(echo)} {(DQ ("Sandstorm's database and web interface won't run as root."))} ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(DQ (yes))} {(Id.Lit_Equals '=')} {(DQ ($ Id.VSub_DollarName '$USE_DEFAULTS'))} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:4213) ) ] action: [ (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:ACCEPTED_SUDO_FOR_DEV_SERVER) op: assign_op.Equal rhs: {(DQ (no))} spids: [4218] ) ] ) ] spids: [4197 4215] ) ] else_action: [ (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(prompt-yesno)} {(DQ ('OK to continue?'))} {(DQ (yes))}) terminator: (Token id:Id.Op_Semi val:';' span_id:4239) ) ] action: [ (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name: ACCEPTED_SUDO_FOR_DEV_SERVER ) op: assign_op.Equal rhs: {(DQ (yes))} spids: [4244] ) ] ) ] spids: [4227 4241] ) ] else_action: [ (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:ACCEPTED_SUDO_FOR_DEV_SERVER) op: assign_op.Equal rhs: {(DQ (no))} spids: [4253] ) ] ) ] ) ] ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(DQ (yes))} {(Id.Lit_Equals '=')} { (DQ ($ Id.VSub_DollarName '$ACCEPTED_SUDO_FOR_DEV_SERVER') ) } {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:4282) ) ] action: [ (C {(rerun_script_as_root)} {(Id.Lit_VarLike 'CHOSEN_INSTALL_MODE=') (2)} ) ] spids: [4266 4284] ) ] else_action: [ (command.Simple words: [ {(fail)} {(DQ (E_NEED_ROOT))} { (DQ ('\n') ( 'One development feature does require root. To install anyway, run:\n' ) ('\n') ('install.sh -u\n') ('\n') ( "to install without using root access. In that case, Sandstorm will operate OK but package tracing ('spk dev') will not work." ) ) } ] more_env: [ (env_pair name: SHOW_FAILURE_MSG val: {(no)} spids: [4300] ) (env_pair name: REPORT val: {(no)} spids: [4303] ) ] ) ] ) ] spids: [4105 4139] ) ] ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (command.AndOr ops: [Id.Op_DAmp] children: [ (C {(Id.Lit_LBracket '[')} {(DQ (yes))} {(Id.KW_Bang '!') (Id.Lit_Equals '=')} {(DQ ($ Id.VSub_DollarName '$USE_DEFAULTS'))} {(Id.Lit_RBracket ']')} ) (C {(Id.Lit_LBracket '[')} {(DQ (yes))} {(Id.Lit_Equals '=')} {(DQ ($ Id.VSub_DollarName '$PREFER_ROOT'))} {(Id.Lit_RBracket ']')} ) ] ) terminator: (Token id:Id.Op_Semi val:';' span_id:4382) ) ] action: [ (C {(echo)} {(DQ ("We're going to:"))}) (C {(echo)} {(DQ )}) (C {(echo)} { (DQ ('* Install Sandstorm in ') (${ Id.VSub_Name DEFAULT_DIR_FOR_ROOT) (.) ) } ) (C {(echo)} { (DQ ( '* Automatically keep Sandstorm up-to-date (with signed updates).' ) ) } ) (C {(echo)} { (DQ ('* Create a service user (') ($ Id.VSub_DollarName '$DEFAULT_SERVER_USER') (") that owns Sandstorm's files.") ) } ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(-n)} { (DQ (braced_var_sub token: (Token id: Id.VSub_Name val: SUDO_USER span_id: 4435 ) suffix_op: (suffix_op.Unary op_id: Id.VTest_ColonHyphen arg_word: (word.Empty) ) ) ) } {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:4441) ) ] action: [ (C {(echo)} { (DQ ('* Add you (') ($ Id.VSub_DollarName '$SUDO_USER') (') to the ') ($ Id.VSub_DollarName '$DEFAULT_SERVER_USER') (' group so you can read/write app data.') ) } ) ] spids: [4427 4443] ) ] ) (C {(echo)} { (DQ ( '* Expose the service only on localhost aka local.sandstorm.io, not the public Internet.' ) ) } ) (C {(echo)} {(DQ ("* Enable 'dev accounts', for easy developer login."))}) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(DQ (unknown))} {(Id.Lit_Equals '=') (Id.Lit_Equals '=')} {(DQ ($ Id.VSub_DollarName '$INIT_SYSTEM'))} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:4490) ) ] action: [ (C {(echo)} { (DQ ( '*** WARNING: Could not detect how to run Sandstorm at startup on your system. ***' ) ) } ) ] spids: [4474 4492] ) ] else_action: [ (C {(echo)} { (DQ ('* Configure Sandstorm to start on system boot (with ') ($ Id.VSub_DollarName '$INIT_SYSTEM') (').') ) } ) ] ) (C {(echo)} { (DQ ('* Listen for inbound email on port ') (${ Id.VSub_Name DEFAULT_SMTP_PORT) (.) ) } ) (C {(echo)} {(DQ )}) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(prompt-yesno)} { (DQ ( "Press enter to accept defaults. Type 'no' to customize." ) ) } {(DQ (yes))} ) terminator: (Token id:Id.Op_Semi val:';' span_id:4547) ) ] action: [ (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:USE_DEFAULTS) op: assign_op.Equal rhs: {(DQ (yes))} spids: [4552] ) ] ) ] spids: [4535 4549] ) ] else_action: [ (C {(echo)} {(DQ )}) (C {(echo)} {(DQ ('OK. We will prompt you with every question.'))}) (C {(echo)} {(DQ )}) ] ) ] spids: [4349 4384] ) ] ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(DQ (yes))} {(Id.Lit_Equals '=')} {(DQ ($ Id.VSub_DollarName '$USE_DEFAULTS'))} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:4604) ) ] action: [ (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:UPDATE_CHANNEL) op: assign_op.Equal rhs: {(DQ ($ Id.VSub_DollarName '$DEFAULT_UPDATE_CHANNEL'))} spids: [4613] ) ] ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:USE_EXTERNAL_INTERFACE) op: assign_op.Equal rhs: { (DQ (braced_var_sub token: (Token id: Id.VSub_Name val: USE_EXTERNAL_INTERFACE span_id: 4627 ) suffix_op: (suffix_op.Unary op_id: Id.VTest_ColonHyphen arg_word: {(no)} ) ) ) } spids: [4624] ) ] ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:SS_HOSTNAME) op: assign_op.Equal rhs: { (DQ (braced_var_sub token: (Token id:Id.VSub_Name val:SS_HOSTNAME span_id:4650) suffix_op: (suffix_op.Unary op_id: Id.VTest_ColonHyphen arg_word: {(local.sandstorm.io)} ) ) ) } spids: [4647] ) ] ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:SMTP_LISTEN_PORT) op: assign_op.Equal rhs: {(DQ (${ Id.VSub_Name DEFAULT_SMTP_PORT))} spids: [4662] ) ] ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:START_AT_BOOT) op: assign_op.Equal rhs: {(DQ (yes))} spids: [4675] ) ] ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:USE_SANDCATS) op: assign_op.Equal rhs: {(DQ (no))} spids: [4686] ) ] ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:PORT) op: assign_op.Equal rhs: {(DQ (${ Id.VSub_Name DEFAULT_PORT))} spids: [4697] ) ] ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:ALLOW_DEV_ACCOUNTS) op: assign_op.Equal rhs: {(DQ (yes))} spids: [4719] ) ] ) ] spids: [4588 4606] ) ] ) ] ) ) (command.ShFunction name: full_server_install body: (command.BraceGroup children: [ (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(DQ (yes))} {(Id.KW_Bang '!') (Id.Lit_Equals '=')} {(DQ (${ Id.VSub_Name PREFER_ROOT))} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:4802) ) ] action: [ (command.Simple words: [ {(fail)} {(DQ (E_AUTO_NEEDS_SUDO))} { (DQ ( 'The automatic setup process requires sudo. Try again with option 2, development server, to customize.' ) ) } ] more_env: [(env_pair name:REPORT val:{(no)} spids:[4807])] ) ] spids: [4783 4804] ) ] ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(DQ (yes))} {(Id.Lit_Equals '=')} {(DQ ($ Id.VSub_DollarName '$USE_DEFAULTS'))} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:4841) ) ] action: [ (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(-z)} { (DQ (braced_var_sub token: (Token id: Id.VSub_Name val: DESIRED_SANDCATS_NAME span_id: 4854 ) suffix_op: (suffix_op.Unary op_id:Id.VTest_Hyphen arg_word:(word.Empty)) ) ) } {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:4861) ) ] action: [ (C {(local)} {(Id.Lit_VarLike 'MSG=') (DQ ( 'For now, USE_DEFAULTS for full server installs requires a DESIRED_SANDCATS_NAME variable.' ) ) } ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:MSG) op: assign_op.Equal rhs: { (DQ ($ Id.VSub_DollarName '$MSG') ( ' If you need support for non-sandcats full-server unattended installs, please file a bug.' ) ) } spids: [4874] ) ] ) (C {(fail)} {(DQ (E_USE_DEFAULTS_NEEDS_DESIRED_SANDCATS_NAME))} {(DQ ($ Id.VSub_DollarName '$MSG'))} ) ] spids: [4846 4863] ) ] else_action: [ (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(-z)} { (DQ (braced_var_sub token: (Token id: Id.VSub_Name val: SANDCATS_DOMAIN_RESERVATION_TOKEN span_id: 4903 ) suffix_op: (suffix_op.Unary op_id: Id.VTest_ColonHyphen arg_word: (word.Empty) ) ) ) } {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:4910) ) ] action: [ (C {(local)} {(Id.Lit_VarLike 'MSG=') (DQ ( 'When operating in USE_DEFAULTS mode, if you want a sandcats.io domain,' ) ) } ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:MSG) op: assign_op.Equal rhs: { (DQ ($ Id.VSub_DollarName '$MSG') ( ' you must pre-reserve it before running this script. Specify it via the' ) ) } spids: [4923] ) ] ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:MSG) op: assign_op.Equal rhs: { (DQ ($ Id.VSub_DollarName '$MSG') ( ' SANDCATS_DOMAIN_RESERVATION_TOKEN environment variable.' ) ) } spids: [4930] ) ] ) (C {(fail)} {(DQ (E_USE_DEFAULTS_NEEDS_DESIRED_SANDCATS_NAME))} {(DQ ($ Id.VSub_DollarName '$MSG'))} ) ] spids: [4895 4912] ) ] ) ] ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:ACCEPTED_FULL_SERVER_INSTALL) op: assign_op.Equal rhs: {(DQ (yes))} spids: [4959] ) ] ) ] spids: [4825 4843] ) ] ) (C {(disable_smtp_port_25_if_port_unavailable)}) (C {(local)} {(Id.Lit_VarLike 'PLANNED_SMTP_PORT=') (DQ (30025))}) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(DQ (yes))} {(Id.Lit_Equals '=')} {(DQ ($ Id.VSub_DollarName '$PORT_25_AVAILABLE'))} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:5000) ) ] action: [ (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:PLANNED_SMTP_PORT) op: assign_op.Equal rhs: {(DQ (25))} spids: [5005] ) ] ) ] spids: [4984 5002] ) ] ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(DQ (yes))} {(Id.KW_Bang '!') (Id.Lit_Equals '=')} { (DQ (braced_var_sub token: (Token id: Id.VSub_Name val: ACCEPTED_FULL_SERVER_INSTALL span_id: 5028 ) suffix_op: (suffix_op.Unary op_id:Id.VTest_ColonHyphen arg_word:(word.Empty)) ) ) } {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:5034) ) ] action: [ (C {(disable_https_if_ports_unavailable)}) (C {(echo)} {(DQ ("We're going to:"))}) (C {(echo)} {(DQ )}) (C {(echo)} { (DQ ('* Install Sandstorm in ') ($ Id.VSub_DollarName '$DEFAULT_DIR_FOR_ROOT') ) } ) (C {(echo)} {(DQ ('* Automatically keep Sandstorm up-to-date'))}) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(DQ (yes))} {(Id.Lit_Equals '=') (Id.Lit_Equals '=')} {(DQ ($ Id.VSub_DollarName '$SANDCATS_GETCERTIFICATE'))} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:5092) ) ] action: [ (C {(echo)} { (DQ ( '* Configure auto-renewing HTTPS if you use a subdomain of sandcats.io' ) ) } ) ] spids: [5075 5094] ) ] ) (C {(echo)} { (DQ ('* Create a service user (') ($ Id.VSub_DollarName '$DEFAULT_SERVER_USER') (") that owns Sandstorm's files") ) } ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(DQ (unknown))} {(Id.Lit_Equals '=') (Id.Lit_Equals '=')} {(DQ ($ Id.VSub_DollarName '$INIT_SYSTEM'))} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:5132) ) ] action: [ (C {(echo)} { (DQ ( '*** WARNING: Could not detect how to run Sandstorm at startup on your system. ***' ) ) } ) ] spids: [5116 5134] ) ] else_action: [ (C {(echo)} { (DQ ('* Configure Sandstorm to start on system boot (with ') ($ Id.VSub_DollarName '$INIT_SYSTEM') (')') ) } ) ] ) (C {(echo)} { (DQ ('* Listen for inbound email on port ') (${ Id.VSub_Name PLANNED_SMTP_PORT) (.) ) } ) (C {(echo)} {(DQ )}) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(DQ (yes))} {(Id.KW_Bang '!') (Id.Lit_Equals '=')} {(DQ ($ Id.VSub_DollarName '$CURRENTLY_UID_ZERO'))} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:5197) ) ] action: [ (C {(echo)} {(DQ ('To set up Sandstorm, we will need to use sudo.'))} ) ] spids: [5181 5199] ) ] else_action: [ (C {(echo)} {(DQ ("Rest assured that Sandstorm itself won't run as root."))} ) ] ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(prompt-yesno)} {(DQ ('OK to continue?'))} {(DQ (yes))}) terminator: (Token id:Id.Op_Semi val:';' span_id:5234) ) ] action: [ (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:ACCEPTED_FULL_SERVER_INSTALL) op: assign_op.Equal rhs: {(yes)} spids: [5239] ) ] ) ] spids: [5223 5236] ) ] else_action: [ (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:ACCEPTED_FULL_SERVER_INSTALL) op: assign_op.Equal rhs: {(no)} spids: [5246] ) ] ) ] ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(DQ (yes))} {(Id.Lit_Equals '=')} { (DQ ($ Id.VSub_DollarName '$SHOW_MESSAGE_ABOUT_NEEDING_PORTS_OPEN' ) ) } {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:5270) ) ] action: [ (C {(echo)} {(DQ )}) (C {(echo)} { (DQ ( 'NOTE: It looks like your system already has some other web server installed' ) ) } ) (C {(echo)} { (DQ ( ' (port 80 and/or 443 are taken), so Sandstorm cannot act as your main' ) ) } ) (C {(echo)} {(DQ (' web server.'))}) (C {(echo)} {(DQ )}) (C {(echo)} { (DQ (' This script can set up Sandstorm to run on port ') ($ Id.VSub_DollarName '$DEFAULT_PORT') (' instead,') ) } ) (C {(echo)} { (DQ ( " without HTTPS. This makes sense if you're OK with typing the port number" ) ) } ) (C {(echo)} { (DQ ( " into your browser whenever you access Sandstorm and you don't need" ) ) } ) (C {(echo)} { (DQ ( ' security. This also makes sense if you are going to set up a reverse proxy;' ) ) } ) (C {(echo)} { (DQ ( ' if so, see https://docs.sandstorm.io/en/latest/administering/reverse-proxy/' ) ) } ) (C {(echo)} {(DQ )}) (C {(echo)} { (DQ ( ' If you want, you can quit this script with Ctrl-C now, and go uninstall' ) ) } ) (C {(echo)} { (DQ ( ' your other web server, and then run this script again. It is also OK to' ) ) } ) (C {(echo)} {(DQ (' proceed if you want.'))}) (C {(echo)} {(DQ )}) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (command.Pipeline children: [ (C {(prompt-yesno)} { (DQ ( 'OK to skip automatic HTTPS setup & bind to port ' ) ($ Id.VSub_DollarName '$DEFAULT_PORT') (' instead?') ) } {(DQ (yes))} ) ] negated: T ) terminator: (Token id:Id.Op_Semi val:';' span_id:5394) ) ] action: [ (C {(fail)} {(DQ (E_USER_REFUSED_DEFAULT_PORT))} { (DQ ( 'Exiting now. You can re-run the installer whenever you are ready.' ) ) } ) ] spids: [5378 5396] ) ] ) ] spids: [5254 5272] ) ] ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(DQ (yes))} {(Id.KW_Bang '!') (Id.Lit_Equals '=')} {(DQ ($ Id.VSub_DollarName '$CURRENTLY_UID_ZERO'))} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:5458) ) ] action: [ (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(DQ (yes))} {(Id.Lit_Equals '=')} {(DQ ($ Id.VSub_DollarName '$ACCEPTED_FULL_SERVER_INSTALL'))} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:5479) ) ] action: [ (C {(rerun_script_as_root)} {(Id.Lit_VarLike 'CHOSEN_INSTALL_MODE=') (1)} {(Id.Lit_VarLike 'ACCEPTED_FULL_SERVER_INSTALL=') (yes)} {(Id.Lit_VarLike 'OVERRIDE_SANDCATS_BASE_DOMAIN=') (DQ (braced_var_sub token: (Token id: Id.VSub_Name val: OVERRIDE_SANDCATS_BASE_DOMAIN span_id: 5499 ) suffix_op: (suffix_op.Unary op_id: Id.VTest_ColonHyphen arg_word: (word.Empty) ) ) ) } {(Id.Lit_VarLike 'OVERRIDE_SANDCATS_API_BASE=') (DQ (braced_var_sub token: (Token id: Id.VSub_Name val: OVERRIDE_SANDCATS_API_BASE span_id: 5509 ) suffix_op: (suffix_op.Unary op_id: Id.VTest_ColonHyphen arg_word: (word.Empty) ) ) ) } {(Id.Lit_VarLike 'OVERRIDE_SANDCATS_GETCERTIFICATE=') (DQ (${ Id.VSub_Name SANDCATS_GETCERTIFICATE))} {(Id.Lit_VarLike 'OVERRIDE_NC_PATH=') (DQ (braced_var_sub token: (Token id: Id.VSub_Name val: OVERRIDE_NC_PATH span_id: 5528 ) suffix_op: (suffix_op.Unary op_id: Id.VTest_ColonHyphen arg_word: (word.Empty) ) ) ) } {(Id.Lit_VarLike 'OVERRIDE_SANDCATS_CURL_PARAMS=') (DQ (braced_var_sub token: (Token id: Id.VSub_Name val: OVERRIDE_SANDCATS_CURL_PARAMS span_id: 5538 ) suffix_op: (suffix_op.Unary op_id: Id.VTest_ColonHyphen arg_word: (word.Empty) ) ) ) } ) ] spids: [5463 5481] ) ] ) (C {(echo)} {(DQ )}) (C {(echo)} {(DQ ('The automatic setup script needs root in order to:'))} ) (C {(echo)} {(DQ ('* Create a separate user to run Sandstorm as, and'))} ) (C {(echo)} {(DQ ('* Set up Sandstorm to start on system boot.'))}) (C {(fail)} {(DQ (E_DECLINED_AUTO_SETUP_DETAILS))} { (DQ ( 'For a customized install, please re-run install.sh, and choose option (2) ' ) ) } {(DQ ('to do a development install.'))} ) ] spids: [5441 5460] ) ] ) ] spids: [5015 5036] ) ] ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(DQ (yes))} {(Id.Lit_Equals '=')} {(DQ (${ Id.VSub_Name ACCEPTED_FULL_SERVER_INSTALL))} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:5623) ) ] action: [ (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:UPDATE_CHANNEL) op: assign_op.Equal rhs: {(DQ ($ Id.VSub_DollarName '$DEFAULT_UPDATE_CHANNEL'))} spids: [5628] ) ] ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:DIR) op: assign_op.Equal rhs: {(DQ ($ Id.VSub_DollarName '$DEFAULT_DIR_FOR_ROOT'))} spids: [5634] ) ] ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:USE_EXTERNAL_INTERFACE) op: assign_op.Equal rhs: {(DQ (yes))} spids: [5640] ) ] ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:USE_SANDCATS) op: assign_op.Equal rhs: {(DQ (yes))} spids: [5646] ) ] ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:START_AT_BOOT) op: assign_op.Equal rhs: {(DQ (yes))} spids: [5652] ) ] ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:DESIRED_SERVER_USER) op: assign_op.Equal rhs: {(DQ ($ Id.VSub_DollarName '$DEFAULT_SERVER_USER'))} spids: [5658] ) ] ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:PORT) op: assign_op.Equal rhs: {(DQ (${ Id.VSub_Name DEFAULT_PORT))} spids: [5664] ) ] ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:MONGO_PORT) op: assign_op.Equal rhs: {(DQ (6081))} spids: [5672] ) ] ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:SMTP_LISTEN_PORT) op: assign_op.Equal rhs: {(DQ (${ Id.VSub_Name PLANNED_SMTP_PORT))} spids: [5678] ) ] ) ] spids: [5606 5625] ) ] else_action: [ (command.Simple words: [ {(fail)} {(DQ (E_USER_WANTS_CUSTOM_SETTINGS))} { (DQ ( 'If you prefer a more manual setup experience, try installing in development mode.' ) ) } ] more_env: [(env_pair name:REPORT val:{(no)} spids:[5689])] ) ] ) ] ) ) (command.ShFunction name: sandcats_configure body: (command.BraceGroup children: [ (C {(echo)} {(-n)} {(DQ ('As a Sandstorm user, you are invited to use a free Internet hostname '))} ) (C {(echo)} {(DQ ('as a subdomain of sandcats.io,'))}) (C {(echo)} {(DQ ('a service operated by the Sandstorm development team.'))}) (C {(sandcats_generate_keys)}) (C {(echo)} {(DQ )}) (C {(echo)} { (DQ ( 'Sandcats.io protects your privacy and is subject to terms of use. By using it,' ) ) } ) (C {(echo)} {(DQ ('you agree to the terms of service & privacy policy available here:'))} ) (C {(echo)} {(DQ ('https://sandcats.io/terms https://sandcats.io/privacy'))}) (C {(echo)} {(DQ )}) (C {(sandcats_register_name)}) (C {(sandcats_configure_https)}) ] ) ) (command.ShFunction name: configure_hostnames body: (command.BraceGroup children: [ (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(DQ (yes))} {(Id.Lit_Equals '=')} {(DQ ($ Id.VSub_DollarName '$USE_SANDCATS'))} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:5849) ) ] action: [(C {(sandcats_configure)})] spids: [5833 5851] ) ] ) (C {(choose_port)}) (C {(choose_mongo_port)}) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(DQ (yes))} {(Id.Lit_Equals '=')} {(DQ ($ Id.VSub_DollarName '$USE_EXTERNAL_INTERFACE'))} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:5915) ) ] action: [ (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:BIND_IP) op: assign_op.Equal rhs: {(0.0.0.0)} spids: [5920] ) ] ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:SS_HOSTNAME) op: assign_op.Equal rhs: { (DQ (braced_var_sub token: (Token id:Id.VSub_Name val:SS_HOSTNAME span_id:5927) suffix_op: (suffix_op.Unary op_id: Id.VTest_ColonHyphen arg_word: { (command_sub left_token: (Token id: Id.Left_DollarParen val: '$(' span_id: 5929 ) command_list: (command.CommandList children: [ (command.AndOr ops: [Id.Op_DPipe] children: [ (command.Simple words: [{(hostname)} {(-f)}] redirects: [ (redir.Redir op: (Token id: Id.Redir_Great val: '2>' span_id: 5934 ) fd: 2 arg_word: {(/dev/null)} ) ] ) (C {(hostname)}) ] ) ] ) ) } ) ) ) } spids: [5924] ) ] ) ] spids: [5900 5917] ) ] else_action: [ (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:BIND_IP) op: assign_op.Equal rhs: {(127.0.0.1)} spids: [5948] ) ] ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:SS_HOSTNAME) op: assign_op.Equal rhs: {(local.sandstorm.io)} spids: [5952] ) ] ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(DQ (yes))} {(Id.KW_Bang '!') (Id.Lit_Equals '=')} {(DQ ($ Id.VSub_DollarName '$USE_DEFAULTS'))} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:5973) ) ] action: [ (C {(echo)} { (DQ ( 'Note: local.sandstorm.io maps to 127.0.0.1, i.e. your local machine.' ) ) } ) (C {(echo)} { (DQ ( 'For reasons that will become clear in the next step, you should use this' ) ) } ) (C {(echo)} {(DQ ("instead of 'localhost'."))}) ] spids: [5956 5975] ) ] ) ] ) (C {(local)} {(Id.Lit_VarLike 'PORT_SUFFIX=') (DQ )}) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(DQ ($ Id.VSub_DollarName '$PORT'))} {(Id.Lit_Equals '=')} {(DQ (80))} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:6041) ) ] action: [ (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:PORT_SUFFIX) op: assign_op.Equal rhs: {(DQ )} spids: [6046] ) ] ) ] spids: [6025 6043] ) ] else_action: [ (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:PORT_SUFFIX) op: assign_op.Equal rhs: {(DQ (':') (${ Id.VSub_Name PORT))} spids: [6054] ) ] ) ] ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:DEFAULT_BASE_URL) op: assign_op.Equal rhs: { (DQ ('http://') (${ Id.VSub_Name SS_HOSTNAME) (${ Id.VSub_Name PORT_SUFFIX) ) } spids: [6067] ) ] ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(DQ ($ Id.VSub_DollarName '$SANDCATS_HTTPS_SUCCESSFUL'))} {(Id.Lit_Equals '=')} {(DQ (yes))} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:6099) ) ] action: [ (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:DEFAULT_BASE_URL) op: assign_op.Equal rhs: {(DQ ('https://') ($ Id.VSub_DollarName '$SS_HOSTNAME'))} spids: [6104] ) ] ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:HTTPS_PORT) op: assign_op.Equal rhs: {(443)} spids: [6111] ) ] ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:PORT) op: assign_op.Equal rhs: {(80)} spids: [6115] ) ] ) ] spids: [6084 6101] ) ] ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(DQ (yes))} {(Id.Lit_Equals '=')} {(DQ ($ Id.VSub_DollarName '$SANDCATS_SUCCESSFUL'))} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:6139) ) ] action: [ (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:BASE_URL) op: assign_op.Equal rhs: {(DQ ($ Id.VSub_DollarName '$DEFAULT_BASE_URL'))} spids: [6152] ) ] ) ] spids: [6123 6141] ) ] else_action: [ (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:BASE_URL) op: assign_op.Equal rhs: { (command_sub left_token: (Token id:Id.Left_DollarParen val:'$(' span_id:6162) command_list: (command.CommandList children: [ (C {(prompt)} {(DQ ('URL users will enter in browser:'))} {(DQ ($ Id.VSub_DollarName '$DEFAULT_BASE_URL'))} ) ] ) ) } spids: [6161] ) ] ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (command.Pipeline children: [ (command.DBracket expr: (bool_expr.Binary op_id: Id.BoolBinary_EqualTilde left: {(DQ ($ Id.VSub_DollarName '$BASE_URL'))} right: {(Id.Lit_Other '^') (http) (Id.Lit_Other '(') (s) (Id.Lit_Other '?') (Id.Lit_Other ')') (Id.Lit_Other ':') (//) } ) ) ] negated: T ) terminator: (Token id:Id.Op_Semi val:';' span_id:6198) ) ] action: [ (C {(local)} {(Id.Lit_VarLike 'PROPOSED_BASE_URL=') (DQ ('http://') (${ Id.VSub_Name BASE_URL)) } ) (command.Simple words: [ {(echo)} { (DQ ('** You entered ') (${ Id.VSub_Name BASE_URL) (', which needs http:// at the front. I can use:') ) } ] redirects: [ (redir.Redir op: (Token id:Id.Redir_GreatAnd val:'>&' span_id:6224) fd: -1 arg_word: {(2)} ) ] ) (command.Simple words: [ {(echo)} {(DQ (' ') (${ Id.VSub_Name PROPOSED_BASE_URL))} ] redirects: [ (redir.Redir op: (Token id:Id.Redir_GreatAnd val:'>&' span_id:6237) fd: -1 arg_word: {(2)} ) ] ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(prompt-yesno)} {(DQ ('Is this OK?'))} {(yes)}) terminator: (Token id:Id.Op_Semi val:';' span_id:6250) ) ] action: [ (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:BASE_URL) op: assign_op.Equal rhs: {(DQ (${ Id.VSub_Name PROPOSED_BASE_URL))} spids: [6255] ) ] ) ] spids: [6241 6252] ) ] else_action: [(C {(configure_hostnames)})] ) ] spids: [6175 6200] ) ] ) ] ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (command.DBracket expr: (bool_expr.Binary op_id: Id.BoolBinary_EqualTilde left: {(DQ ($ Id.VSub_DollarName '$BASE_URL'))} right: {(Id.Lit_Other '^') (http) (Id.Lit_Other ':') (//localhost) (Id.Lit_Other '(') (Id.Lit_Other '|') (Id.Lit_Other ':') (Id.Lit_Other '[') (0-9) (Id.Lit_Other ']') (Id.Lit_Other '*') (Id.Lit_Other ')') (Id.Lit_Other '(') (/) (Id.Lit_Other .) (Id.Lit_Other '*') (Id.Lit_Other ')') (Id.Lit_Other '?') (Id.Lit_Other '$') } ) ) terminator: (Token id:Id.Op_Semi val:';' span_id:6318) ) ] action: [ (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:DEFAULT_WILDCARD) op: assign_op.Equal rhs: {(Id.Lit_Star '*') (.local.sandstorm.io) (braced_var_sub token: (Token id:Id.VSub_Name val:BASH_REMATCH span_id:6327) bracket_op: (bracket_op.ArrayIndex expr: (arith_expr.ArithWord w:{(Id.Lit_Digits 1)}) ) ) } spids: [6323] ) ] ) ] spids: [6287 6320] ) (if_arm cond: [ (command.Sentence child: (command.DBracket expr: (bool_expr.Binary op_id: Id.BoolBinary_EqualTilde left: {(DQ ($ Id.VSub_DollarName '$BASE_URL'))} right: {(Id.Lit_Other '^') (Id.Lit_Other '[') (Id.Lit_Other '^') (Id.Lit_Other ':') (/) (Id.Lit_Other ']') (Id.Lit_Other '*') (Id.Lit_Other ':') (//) (Id.Lit_Other '(') (Id.Lit_Other '[') (Id.Lit_Other '^') (/) (Id.Lit_Other ']') (Id.Lit_Other '*') (Id.Lit_Other ')') (/) (Id.Lit_Other '?') (Id.Lit_Other '$') } ) ) terminator: (Token id:Id.Op_Semi val:';' span_id:6365) ) ] action: [ (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:DEFAULT_WILDCARD) op: assign_op.Equal rhs: { (DQ (braced_var_sub token: (Token id: Id.VSub_Name val: DEFAULT_WILDCARD span_id: 6373 ) suffix_op: (suffix_op.Unary op_id: Id.VTest_ColonHyphen arg_word: {('*.') (braced_var_sub token: (Token id: Id.VSub_Name val: BASH_REMATCH span_id: 6377 ) bracket_op: (bracket_op.ArrayIndex expr: (arith_expr.ArithWord w: {(Id.Lit_Digits 1)} ) ) ) } ) ) ) } spids: [6370] ) ] ) ] spids: [6334 6367] ) ] else_action: [ (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:DEFAULT_WILDCARD) op: assign_op.Equal rhs: (word.Empty) spids: [6389] ) ] ) ] ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(DQ (yes))} {(Id.Lit_Equals '=')} {(DQ ($ Id.VSub_DollarName '$SANDCATS_SUCCESSFUL'))} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:6420) ) ] action: [ (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:WILDCARD_HOST) op: assign_op.Equal rhs: {(DQ ($ Id.VSub_DollarName '$DEFAULT_WILDCARD'))} spids: [6425] ) ] ) ] spids: [6404 6422] ) ] else_action: [ (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(DQ (yes))} {(Id.KW_Bang '!') (Id.Lit_Equals '=')} {(DQ ($ Id.VSub_DollarName '$USE_DEFAULTS'))} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:6451) ) ] action: [ (C {(echo)} { (DQ ( 'Sandstorm requires you to set up a wildcard DNS entry pointing at the server.' ) ) } ) (C {(echo)} { (DQ ( 'This allows Sandstorm to allocate new hosts on-the-fly for sandboxing purposes.' ) ) } ) (C {(echo)} { (DQ ( "Please enter a DNS hostname containing a '*' which maps to your server. For " ) ) } ) (C {(echo)} { (DQ ( 'example, if you have mapped *.foo.example.com to your server, you could enter' ) ) } ) (C {(echo)} { (DQ (word_part.EscapedLiteral token: (Token id:Id.Lit_EscapedChar val:'\\"' span_id:6487) ) ('*.foo.example.com') (word_part.EscapedLiteral token: (Token id:Id.Lit_EscapedChar val:'\\"' span_id:6489) ) ('. You can also specify that hosts should have a special') ) } ) (C {(echo)} { (DQ ('prefix, like ') (word_part.EscapedLiteral token: (Token id:Id.Lit_EscapedChar val:'\\"' span_id:6498) ) ('ss-*.foo.example.com') (word_part.EscapedLiteral token: (Token id:Id.Lit_EscapedChar val:'\\"' span_id:6500) ) (". Note that if your server's main page") ) } ) (C {(echo)} { (DQ ( 'is served over SSL, the wildcard address must support SSL as well, which' ) ) } ) (C {(echo)} { (DQ ( 'implies that you must have a wildcard certificate. For local-machine servers,' ) ) } ) (C {(echo)} { (DQ ( 'we have mapped *.local.sandstorm.io to 127.0.0.1 for your convenience, so you' ) ) } ) (C {(echo)} { (DQ ('can use ') (word_part.EscapedLiteral token: (Token id:Id.Lit_EscapedChar val:'\\"' span_id:6530) ) ('*.local.sandstorm.io') (word_part.EscapedLiteral token: (Token id:Id.Lit_EscapedChar val:'\\"' span_id:6532) ) (' here. If you are serving off a non-standard') ) } ) (C {(echo)} {(DQ ('port, you must include it here as well.'))}) ] spids: [6434 6453] ) ] ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:WILDCARD_HOST) op: assign_op.Equal rhs: { (command_sub left_token: (Token id:Id.Left_DollarParen val:'$(' span_id:6548) command_list: (command.CommandList children: [ (C {(prompt)} {(DQ ('Wildcard host:'))} {(DQ ($ Id.VSub_DollarName '$DEFAULT_WILDCARD'))} ) ] ) ) } spids: [6547] ) ] ) (command.WhileUntil keyword: (Token id:Id.KW_While val:while span_id:6562) cond: [ (command.Sentence child: (command.Pipeline children: [ (command.DBracket expr: (bool_expr.Binary op_id: Id.BoolBinary_EqualTilde left: {(DQ ($ Id.VSub_DollarName '$WILDCARD_HOST'))} right: {(Id.Lit_Other '^') (Id.Lit_Other '[') (Id.Lit_Other '^') (Id.Lit_Other '*') (Id.Lit_Other ']') (Id.Lit_Other '*') (Id.Lit_Other '[') (Id.Lit_Other '*') (Id.Lit_Other ']') (Id.Lit_Other '[') (Id.Lit_Other '^') (Id.Lit_Other '*') (Id.Lit_Other ']') (Id.Lit_Other '*') (Id.Lit_Other '$') } ) ) ] negated: T ) terminator: (Token id:Id.Op_Semi val:';' span_id:6591) ) ] body: (command.DoGroup children: [ (C {(error)} { (DQ ( 'Invalid wildcard host. It must contain exactly one asterisk.' ) ) } ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:WILDCARD_HOST) op: assign_op.Equal rhs: { (command_sub left_token: (Token id: Id.Left_DollarParen val: '$(' span_id: 6604 ) command_list: (command.CommandList children: [ (C {(prompt)} {(DQ ('Wildcard host:'))} {(DQ ($ Id.VSub_DollarName '$DEFAULT_WILDCARD'))} ) ] ) ) } spids: [6603] ) ] ) ] ) ) ] ) ] ) ) (command.ShFunction name: choose_install_dir body: (command.BraceGroup children: [ (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(-z)} { (DQ (braced_var_sub token: (Token id:Id.VSub_Name val:DIR span_id:6640) suffix_op: (suffix_op.Unary op_id:Id.VTest_ColonHyphen arg_word:(word.Empty)) ) ) } {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:6647) ) ] action: [ (C {(local)} {(Id.Lit_VarLike 'DEFAULT_DIR=') (DQ ($ Id.VSub_DollarName '$DEFAULT_DIR_FOR_ROOT')) } ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(DQ (yes))} {(Id.KW_Bang '!') (Id.Lit_Equals '=')} {(DQ ($ Id.VSub_DollarName '$CURRENTLY_UID_ZERO'))} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:6677) ) ] action: [ (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:DEFAULT_DIR) op: assign_op.Equal rhs: {(DQ ($ Id.VSub_DollarName '$DEFAULT_DIR_FOR_NON_ROOT'))} spids: [6682] ) ] ) ] spids: [6660 6679] ) ] ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:DIR) op: assign_op.Equal rhs: { (command_sub left_token: (Token id: Id.Left_DollarParen val: '$(' span_id: 6693 ) command_list: (command.CommandList children: [ (C {(prompt)} {(DQ ('Where would you like to put Sandstorm?'))} {(DQ ($ Id.VSub_DollarName '$DEFAULT_DIR'))} ) ] ) ) } spids: [6692] ) ] ) ] spids: [6632 6649] ) ] ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (command.AndOr ops: [Id.Op_DPipe Id.Op_DPipe] children: [ (C {(Id.Lit_LBracket '[')} {(-e)} {(DQ ($ Id.VSub_DollarName '$DIR') (/sandstorm.conf))} {(Id.Lit_RBracket ']')} ) (C {(Id.Lit_LBracket '[')} {(-e)} {(DQ ($ Id.VSub_DollarName '$DIR') (/var))} {(Id.Lit_RBracket ']')} ) (C {(Id.Lit_LBracket '[')} {(-e)} {(DQ ($ Id.VSub_DollarName '$DIR') (/sandstorm))} {(Id.Lit_RBracket ']')} ) ] ) terminator: (Token id:Id.Op_Semi val:';' span_id:6765) ) ] action: [ (C {(error)} {(DQ )}) (C {(error)} { (DQ ('This script is trying to install to ') (${ Id.VSub_Name DIR) (.)) } ) (C {(error)} {(DQ )}) (C {(error)} { (DQ ('You seem to already have a ') (${ Id.VSub_Name DIR) ( ' directory with a Sandstorm installation inside. You should either:' ) ) } ) (C {(error)} {(DQ )}) (C {(error)} { (DQ ( '1. Reconfigure that Sandstorm install using its configuration file -- ' ) (${ Id.VSub_Name DIR) ('/sandstorm.conf -- or the admin interface. See docs at:') ) } ) (C {(error)} {(DQ ('https://docs.sandstorm.io/en/latest/administering/'))}) (C {(error)} {(DQ )}) (C {(error)} { (DQ ( '2. Uninstall Sandstorm before attempting to perform a new install. Even if you created a sandcats.io hostname, it is safe to uninstall so long as you do not need the data in your Sandstorm install. When you re-install Sandstorm, you can follow a process to use the old hostname with the new install. See uninstall docs at:' ) ) } ) (C {(error)} {(DQ ('https://docs.sandstorm.io/en/latest/install/#uninstall'))} ) (C {(error)} {(DQ )}) (C {(error)} { (DQ ( '3. Use a different target directory for the new Sandstorm install. Try running install.sh with the -d option.' ) ) } ) (C {(error)} {(DQ )}) (C {(error)} { (DQ ( '4. Retain your data, but restore your Sandstorm code and configuration to a fresh copy. To do that, keep a backup of ' ) (${ Id.VSub_Name DIR) ( '/var and then do a fresh install; stop the Sandstorm service, and restore your backup of ' ) (${ Id.VSub_Name DIR) ('/var. You may need to adjust permissions after doing that.') ) } ) (command.Simple words: [ {(fail)} {(DQ (E_DIR_ALREADY_EXISTS))} { (DQ ( 'Please try one of the above. Contact https://groups.google.com/d/forum/sandstorm-dev for further help.' ) ) } ] more_env: [(env_pair name:REPORT val:{(no)} spids:[6886])] ) ] spids: [6726 6767] ) ] ) (C {(mkdir)} {(-p)} {(DQ ($ Id.VSub_DollarName '$DIR'))}) (C {(cd)} {(DQ ($ Id.VSub_DollarName '$DIR'))}) ] ) ) (command.ShFunction name: choose_smtp_port body: (command.BraceGroup children: [ (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(Id.KW_Bang '!')} {(-z)} { (DQ (braced_var_sub token: (Token id: Id.VSub_Name val: SMTP_LISTEN_PORT span_id: 6943 ) suffix_op: (suffix_op.Unary op_id:Id.VTest_ColonHyphen arg_word:(word.Empty)) ) ) } {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:6950) ) ] action: [ (command.ControlFlow token: (Token id:Id.ControlFlow_Return val:return span_id:6955) ) ] spids: [6933 6952] ) ] ) (C {(local)} {(Id.Lit_VarLike 'REQUESTED_SMTP_PORT=') (command_sub left_token: (Token id:Id.Left_DollarParen val:'$(' span_id:6965) command_list: (command.CommandList children: [ (C {(prompt-numeric)} { (DQ ( 'Sandstorm grains can receive email. What port should Sandstorm listen on, for inbound SMTP?' ) ) } {(DQ (${ Id.VSub_Name DEFAULT_SMTP_PORT))} ) ] ) ) } ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(-z)} {(DQ (${ Id.VSub_Name REQUESTED_SMTP_PORT))} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:6994) ) ] action: [(C {(choose_smtp_port)})] spids: [6980 6996] ) ] else_action: [ (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:SMTP_LISTEN_PORT) op: assign_op.Equal rhs: {(DQ (${ Id.VSub_Name REQUESTED_SMTP_PORT))} spids: [7005] ) ] ) ] ) ] ) ) (command.ShFunction name: load_existing_settings body: (command.BraceGroup children: [ (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(Id.KW_Bang '!')} {(-e)} {(sandstorm.conf)} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:7044) ) ] action: [ (command.ControlFlow token: (Token id:Id.ControlFlow_Return val:return span_id:7049) ) ] spids: [7033 7046] ) ] ) (C {(echo)} {(DQ ('Found existing sandstorm.conf. Using it.'))}) (C {(.)} {(sandstorm.conf)}) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} { (DQ (braced_var_sub token: (Token id:Id.VSub_Name val:SERVER_USER span_id:7074) suffix_op: (suffix_op.Unary op_id: Id.VTest_ColonPlus arg_word: {(set)} ) ) ) } {(Id.KW_Bang '!') (Id.Lit_Equals '=')} {(Id.KW_Set set)} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:7086) ) ] action: [ (C {(fail)} {(DQ (E_CONF_DOES_NOT_SET_SERVER_USER))} { (DQ ( 'Existing config does not set SERVER_USER. Please fix or delete it.' ) ) } ) ] spids: [7068 7088] ) ] ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} { (DQ (braced_var_sub token: (Token id: Id.VSub_Name val: UPDATE_CHANNEL span_id: 7128 ) suffix_op: (suffix_op.Unary op_id: Id.VTest_ColonHyphen arg_word: {(none)} ) ) ) } {(Id.KW_Bang '!') (Id.Lit_Equals '=')} {(none)} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:7140) ) ] action: [ (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:DEFAULT_UPDATE_CHANNEL) op: assign_op.Equal rhs: {($ Id.VSub_DollarName '$UPDATE_CHANNEL')} spids: [7145] ) ] ) ] spids: [7122 7142] ) ] ) ] ) ) (command.ShFunction name: choose_server_user_if_needed body: (command.BraceGroup children: [ (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(-e)} {(sandstorm.conf)} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:7187) ) ] action: [ (command.ControlFlow token: (Token id:Id.ControlFlow_Return val:return span_id:7192) ) ] spids: [7177 7189] ) ] ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(DQ (yes))} {(Id.KW_Bang '!') (Id.Lit_Equals '=')} {(DQ ($ Id.VSub_DollarName '$CURRENTLY_UID_ZERO'))} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:7223) ) ] action: [ (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:SERVER_USER) op: assign_op.Equal rhs: { (command_sub left_token: (Token id: Id.Left_DollarParen val: '$(' span_id: 7229 ) command_list: (command.CommandList children: [(C {(id)} {(-un)})] ) ) } spids: [7228] ) ] ) (command.ControlFlow token: (Token id:Id.ControlFlow_Return val:return span_id:7236) ) ] spids: [7207 7225] ) ] ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(Id.KW_Bang '!')} {(-z)} { (DQ (braced_var_sub token: (Token id: Id.VSub_Name val: DESIRED_SERVER_USER span_id: 7261 ) suffix_op: (suffix_op.Unary op_id:Id.VTest_ColonHyphen arg_word:(word.Empty)) ) ) } {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:7268) ) ] action: [ (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:SERVER_USER) op: assign_op.Equal rhs: {(DQ ($ Id.VSub_DollarName '$DESIRED_SERVER_USER'))} spids: [7273] ) ] ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:CREATE_SERVER_USER) op: assign_op.Equal rhs: {(DQ (yes))} spids: [7279] ) ] ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:ADD_SUDO_USER_TO_SERVER_GROUP) op: assign_op.Equal rhs: {(DQ (no))} spids: [7285] ) ] ) (command.ControlFlow token: (Token id:Id.ControlFlow_Return val:return span_id:7291) ) ] spids: [7251 7270] ) ] ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:SERVER_USER) op: assign_op.Equal rhs: { (command_sub left_token: (Token id:Id.Left_DollarParen val:'$(' span_id:7303) command_list: (command.CommandList children: [ (C {(prompt)} {(DQ ('Local user account to run server under:'))} {(sandstorm)} ) ] ) ) } spids: [7302] ) ] ) (command.WhileUntil keyword: (Token id:Id.KW_While val:while span_id:7315) cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(DQ ($ Id.VSub_DollarName '$SERVER_USER'))} {(Id.Lit_Equals '=')} {(root)} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:7328) ) ] body: (command.DoGroup children: [ (C {(echo)} {(DQ ('Sandstorm cannot run as root!'))}) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:SERVER_USER) op: assign_op.Equal rhs: { (command_sub left_token: (Token id: Id.Left_DollarParen val: '$(' span_id: 7341 ) command_list: (command.CommandList children: [ (C {(prompt)} {(DQ ('Local user account to run server under:'))} {(sandstorm)} ) ] ) ) } spids: [7340] ) ] ) ] ) ) ] ) ) (command.ShFunction name: create_server_user_if_needed body: (command.BraceGroup children: [ (command.If arms: [ (if_arm cond: [ (command.Sentence child: (command.Simple words: [{(id)} {(DQ ($ Id.VSub_DollarName '$SERVER_USER'))}] redirects: [ (redir.Redir op: (Token id:Id.Redir_Great val:'>' span_id:7376) fd: -1 arg_word: {(/dev/null)} ) (redir.Redir op: (Token id:Id.Redir_GreatAnd val:'2>&' span_id:7380) fd: 2 arg_word: {(1)} ) ] ) terminator: (Token id:Id.Op_Semi val:';' span_id:7382) ) ] action: [ (command.ControlFlow token: (Token id:Id.ControlFlow_Return val:return span_id:7387) ) ] spids: [7368 7384] ) ] ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(DQ (yes))} {(Id.KW_Bang '!') (Id.Lit_Equals '=')} { (DQ (braced_var_sub token: (Token id: Id.VSub_Name val: CREATE_SERVER_USER span_id: 7415 ) suffix_op: (suffix_op.Unary op_id:Id.VTest_ColonHyphen arg_word:(word.Empty)) ) ) } {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:7422) ) ] action: [ (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(prompt-yesno)} { (DQ ("User account '") ($ Id.VSub_DollarName '$SERVER_USER') ("' doesn't exist. Create it?") ) } {(yes)} ) terminator: (Token id:Id.Op_Semi val:';' span_id:7439) ) ] action: [ (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:CREATE_SERVER_USER) op: assign_op.Equal rhs: {(yes)} spids: [7444] ) ] ) ] spids: [7427 7441] ) ] ) ] spids: [7402 7424] ) ] ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(DQ (yes))} {(Id.KW_Bang '!') (Id.Lit_Equals '=')} { (DQ (braced_var_sub token: (Token id: Id.VSub_Name val: CREATE_SERVER_USER span_id: 7472 ) suffix_op: (suffix_op.Unary op_id:Id.VTest_ColonHyphen arg_word:(word.Empty)) ) ) } {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:7479) ) ] action: [ (command.ControlFlow token: (Token id:Id.ControlFlow_Return val:return span_id:7484) ) ] spids: [7459 7481] ) ] ) (C {(useradd)} {(--system)} {(--user-group)} {(DQ ($ Id.VSub_DollarName '$SERVER_USER'))} ) (C {(echo)} { (DQ ("Note: Sandstorm's storage will only be accessible to the group '") ($ Id.VSub_DollarName '$SERVER_USER') ("'.") ) } ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(DQ (no))} {(Id.Lit_Equals '=')} { (DQ (braced_var_sub token: (Token id: Id.VSub_Name val: ADD_SUDO_USER_TO_SERVER_GROUP span_id: 7574 ) suffix_op: (suffix_op.Unary op_id:Id.VTest_ColonHyphen arg_word:(word.Empty)) ) ) } {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:7581) ) ] action: [ (command.ControlFlow token: (Token id:Id.ControlFlow_Return val:return span_id:7586) ) ] spids: [7562 7583] ) ] ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(-n)} { (DQ (braced_var_sub token: (Token id:Id.VSub_Name val:SUDO_USER span_id:7601) suffix_op: (suffix_op.Unary op_id:Id.VTest_ColonHyphen arg_word:(word.Empty)) ) ) } {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:7607) ) ] action: [ (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(prompt-yesno)} { (DQ ("Add user '") ($ Id.VSub_DollarName '$SUDO_USER') ("' to group '") ($ Id.VSub_DollarName '$SERVER_USER') ("'?") ) } {(no)} ) terminator: (Token id:Id.Op_Semi val:';' span_id:7626) ) ] action: [ (C {(usermod)} {(-a)} {(-G)} {(DQ ($ Id.VSub_DollarName '$SERVER_USER'))} {(DQ ($ Id.VSub_DollarName '$SUDO_USER'))} ) (C {(echo)} { (DQ ( "Added. Don't forget that group changes only apply at next login." ) ) } ) ] spids: [7612 7628] ) ] ) ] spids: [7593 7609] ) ] ) ] ) ) (command.ShFunction name: choose_port body: (command.BraceGroup children: [ (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(Id.KW_Bang '!')} {(-z)} { (DQ (braced_var_sub token: (Token id:Id.VSub_Name val:PORT span_id:7682) suffix_op: (suffix_op.Unary op_id:Id.VTest_ColonHyphen arg_word:(word.Empty)) ) ) } {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:7689) ) ] action: [ (command.ControlFlow token: (Token id:Id.ControlFlow_Return val:return span_id:7694) ) ] spids: [7672 7691] ) ] ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:PORT) op: assign_op.Equal rhs: { (command_sub left_token: (Token id:Id.Left_DollarParen val:'$(' span_id:7702) command_list: (command.CommandList children: [ (C {(prompt-numeric)} {(DQ ('Server main HTTP port:'))} {($ Id.VSub_DollarName '$DEFAULT_PORT')} ) ] ) ) } spids: [7701] ) ] ) (command.WhileUntil keyword: (Token id:Id.KW_While val:while span_id:7714) cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(DQ ($ Id.VSub_DollarName '$PORT'))} {(-lt)} {(1024)} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:7727) ) ] body: (command.DoGroup children: [ (C {(echo)} { (DQ ( 'Ports below 1024 require root privileges. Sandstorm does not run as root.' ) ) } ) (C {(echo)} { (DQ ('To use port ') ($ Id.VSub_DollarName '$PORT') (", you'll need to set up a reverse proxy like nginx that ") ) } ) (C {(echo)} { (DQ ( 'forwards to the internal higher-numbered port. The Sandstorm git repo ' ) ) } ) (C {(echo)} {(DQ ('contains an example nginx config for this.'))}) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:PORT) op: assign_op.Equal rhs: { (command_sub left_token: (Token id: Id.Left_DollarParen val: '$(' span_id: 7763 ) command_list: (command.CommandList children: [ (C {(prompt-numeric)} {(DQ ('Server main HTTP port:'))} {($ Id.VSub_DollarName '$DEFAULT_PORT')} ) ] ) ) } spids: [7762] ) ] ) ] ) ) ] ) ) (command.ShFunction name: choose_mongo_port body: (command.BraceGroup children: [ (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(Id.KW_Bang '!')} {(-z)} { (DQ (braced_var_sub token: (Token id:Id.VSub_Name val:MONGO_PORT span_id:7800) suffix_op: (suffix_op.Unary op_id:Id.VTest_ColonHyphen arg_word:(word.Empty)) ) ) } {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:7807) ) ] action: [ (command.ControlFlow token: (Token id:Id.ControlFlow_Return val:return span_id:7812) ) ] spids: [7790 7809] ) ] ) (C {(local)} {(Id.Lit_VarLike 'DEFAULT_MONGO_PORT=') (DQ (word_part.ArithSub anode: (arith_expr.Binary op_id: Id.Arith_Plus left: (arith_expr.VarRef token: (Token id:Id.Lit_ArithVarLike val:PORT span_id:7832) ) right: (arith_expr.ArithWord w:{(Id.Lit_Digits 1)}) ) ) ) } ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(DQ ($ Id.VSub_DollarName '$PORT'))} {(-lt)} {(1024)} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:7856) ) ] action: [ (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:DEFAULT_MONGO_PORT) op: assign_op.Equal rhs: {(DQ (6081))} spids: [7861] ) ] ) ] spids: [7842 7858] ) ] ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:MONGO_PORT) op: assign_op.Equal rhs: { (command_sub left_token: (Token id:Id.Left_DollarParen val:'$(' span_id:7872) command_list: (command.CommandList children: [ (C {(prompt-numeric)} {(DQ ('Database port (choose any unused port):'))} {(DQ (${ Id.VSub_Name DEFAULT_MONGO_PORT))} ) ] ) ) } spids: [7871] ) ] ) ] ) ) (command.ShFunction name: choose_external_or_internal body: (command.BraceGroup children: [ (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(DQ (yes))} {(Id.KW_Bang '!') (Id.Lit_Equals '=')} {(DQ ($ Id.VSub_DollarName '$USE_EXTERNAL_INTERFACE'))} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:7916) ) ] action: [ (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(prompt-yesno)} {(DQ ('Expose to localhost only?'))} {(yes)}) terminator: (Token id:Id.Op_Semi val:';' span_id:7931) ) ] action: [ (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:USE_EXTERNAL_INTERFACE) op: assign_op.Equal rhs: {(DQ (no))} spids: [7936] ) ] ) ] spids: [7921 7933] ) ] else_action: [ (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:USE_EXTERNAL_INTERFACE) op: assign_op.Equal rhs: {(DQ (yes))} spids: [7945] ) ] ) ] ) ] spids: [7900 7918] ) ] ) ] ) ) (command.ShFunction name: configure_auto_updates body: (command.BraceGroup children: [ (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(-n)} { (DQ (braced_var_sub token: (Token id: Id.VSub_Name val: UPDATE_CHANNEL span_id: 7978 ) suffix_op: (suffix_op.Unary op_id:Id.VTest_ColonHyphen arg_word:(word.Empty)) ) ) } {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:7984) ) ] action: [ (command.ControlFlow token: (Token id:Id.ControlFlow_Return val:return span_id:7989) ) ] spids: [7970 7986] ) ] ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(prompt-yesno)} {(DQ ('Automatically keep Sandstorm updated?'))} {(yes)} ) terminator: (Token id:Id.Op_Semi val:';' span_id:8009) ) ] action: [ (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:UPDATE_CHANNEL) op: assign_op.Equal rhs: {($ Id.VSub_DollarName '$DEFAULT_UPDATE_CHANNEL')} spids: [8014] ) ] ) ] spids: [8000 8011] ) ] else_action: [ (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:UPDATE_CHANNEL) op: assign_op.Equal rhs: {(none)} spids: [8021] ) ] ) ] ) ] ) ) (command.ShFunction name: configure_dev_accounts body: (command.BraceGroup children: [ (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(DQ (yes))} {(Id.Lit_Equals '=')} {(DQ (${ Id.VSub_Name ALLOW_DEV_ACCOUNTS))} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:8058) ) ] action: [ (command.ControlFlow token: (Token id:Id.ControlFlow_Return val:return span_id:8063) ) ] spids: [8041 8060] ) ] ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(DQ (yes))} {(Id.Lit_Equals '=')} {(DQ (${ Id.VSub_Name USE_EXTERNAL_INTERFACE))} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:8096) ) ] action: [ (command.ControlFlow token: (Token id:Id.ControlFlow_Return val:return span_id:8101) ) ] spids: [8078 8098] ) ] ) (C {(echo)} {(DQ ("Sandstorm supports 'dev accounts', a feature that lets anyone log in"))} ) (C {(echo)} {(DQ ('as admin and other sample users to a Sandstorm server. We recommend'))} ) (C {(echo)} {(DQ ('it for app development, and absolutely do not recommend it for'))} ) (C {(echo)} {(DQ ('a server on the public Internet.'))}) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(prompt-yesno)} {(DQ ('Enable dev accounts?'))} {(DQ (yes))}) terminator: (Token id:Id.Op_Semi val:';' span_id:8149) ) ] action: [ (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:ALLOW_DEV_ACCOUNTS) op: assign_op.Equal rhs: {(yes)} spids: [8154] ) ] ) ] spids: [8137 8151] ) ] ) ] ) ) (command.ShFunction name: save_config body: (command.BraceGroup children: [ (command.Simple words: [ {(writeConfig)} {(SERVER_USER)} {(PORT)} {(MONGO_PORT)} {(BIND_IP)} {(BASE_URL)} {(WILDCARD_HOST)} {(UPDATE_CHANNEL)} {(ALLOW_DEV_ACCOUNTS)} {(SMTP_LISTEN_PORT)} ] redirects: [ (redir.Redir op: (Token id:Id.Redir_Great val:'>' span_id:8190) fd: -1 arg_word: {(sandstorm.conf)} ) ] ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(DQ (yes))} {(Id.Lit_Equals '=')} {(DQ ($ Id.VSub_DollarName '$SANDCATS_SUCCESSFUL'))} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:8211) ) ] action: [ (command.Simple words: [{(writeConfig)} {(SANDCATS_BASE_DOMAIN)}] redirects: [ (redir.Redir op: (Token id:Id.Redir_DGreat val:'>>' span_id:8220) fd: -1 arg_word: {(sandstorm.conf)} ) ] ) ] spids: [8195 8213] ) ] ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(DQ (yes))} {(Id.Lit_Equals '=')} {(DQ ($ Id.VSub_DollarName '$SANDCATS_HTTPS_SUCCESSFUL'))} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:8244) ) ] action: [ (command.Simple words: [{(writeConfig)} {(HTTPS_PORT)}] redirects: [ (redir.Redir op: (Token id:Id.Redir_DGreat val:'>>' span_id:8253) fd: -1 arg_word: {(sandstorm.conf)} ) ] ) ] spids: [8228 8246] ) ] ) (C {(echo)}) (C {(echo)} {(DQ ('Config written to ') ($ Id.VSub_DollarName '$PWD') (/sandstorm.conf.))} ) ] ) ) (command.ShFunction name: download_latest_bundle_and_extract_if_needed body: (command.BraceGroup children: [ (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(-n)} { (DQ (braced_var_sub token: (Token id:Id.VSub_Name val:BUNDLE_FILE span_id:8299) suffix_op: (suffix_op.Unary op_id:Id.VTest_ColonHyphen arg_word:(word.Empty)) ) ) } {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:8305) ) ] action: [ (command.ControlFlow token: (Token id:Id.ControlFlow_Return val:return span_id:8310) ) ] spids: [8291 8307] ) ] ) (C {(echo)} { (DQ ('Finding latest build for ') ($ Id.VSub_DollarName '$DEFAULT_UPDATE_CHANNEL') (' channel...') ) } ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:BUILD) op: assign_op.Equal rhs: { (DQ (command_sub left_token: (Token id:Id.Left_DollarParen val:'$(' span_id:8344) command_list: (command.CommandList children: [ (C {(curl)} {(-A)} {(DQ ($ Id.VSub_DollarName '$CURL_USER_AGENT'))} {(-fs)} { (DQ ('https://install.sandstorm.io/') ($ Id.VSub_DollarName '$DEFAULT_UPDATE_CHANNEL') ('?from=0&type=install_v2') ) } ) ] ) ) ) } spids: [8342] ) ] ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:BUILD_DIR) op: assign_op.Equal rhs: {(DQ (sandstorm-) (${ Id.VSub_Name BUILD))} spids: [8364] ) ] ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (command.DBracket expr: (bool_expr.LogicalNot child: (bool_expr.Binary op_id: Id.BoolBinary_EqualTilde left: {(DQ ($ Id.VSub_DollarName '$BUILD'))} right: {(Id.Lit_Other '^') (Id.Lit_Other '[') (0-9) (Id.Lit_Other ']') (Id.Lit_Other '+') (Id.Lit_Other '$') } ) ) ) terminator: (Token id:Id.Op_Semi val:';' span_id:8394) ) ] action: [ (C {(fail)} {(DQ (E_INVALID_BUILD_NUM))} { (DQ ('Server returned invalid build number: ') ($ Id.VSub_DollarName '$BUILD') ) } ) ] spids: [8374 8396] ) ] ) (command.ShFunction name: do-download body: (command.BraceGroup children: [ (C {(rm)} {(-rf)} {(DQ (${ Id.VSub_Name BUILD_DIR))}) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:WORK_DIR) op: assign_op.Equal rhs: { (DQ (command_sub left_token: (Token id: Id.Left_DollarParen val: '$(' span_id: 8435 ) command_list: (command.CommandList children: [ (C {(mktemp)} {(-d)} {(./sandstorm-installer.XXXXXXXXXX)} ) ] ) ) ) } spids: [8433] ) ] ) (C {(local)} {(Id.Lit_VarLike 'URL=') (DQ ('https://dl.sandstorm.io/sandstorm-') ($ Id.VSub_DollarName '$BUILD') (.tar.xz) ) } ) (C {(echo)} {(DQ ('Downloading: ') ($ Id.VSub_DollarName '$URL'))}) (C {(retryable_curl)} {(DQ ($ Id.VSub_DollarName '$URL'))} { (DQ ($ Id.VSub_DollarName '$WORK_DIR') (/sandstorm-) ($ Id.VSub_DollarName '$BUILD') (.tar.xz) ) } ) (C {(retryable_curl)} {(DQ ($ Id.VSub_DollarName '$URL') (.sig))} { (DQ ($ Id.VSub_DollarName '$WORK_DIR') (/sandstorm-) ($ Id.VSub_DollarName '$BUILD') (.tar.xz.sig) ) } ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (command.Simple words: [{(which)} {(gpg)}] redirects: [ (redir.Redir op: (Token id:Id.Redir_Great val:'>' span_id:8499) fd: -1 arg_word: {(/dev/null)} ) ] ) terminator: (Token id:Id.Op_Semi val:';' span_id:8502) ) ] action: [ (C {(export)} {(Id.Lit_VarLike 'GNUPGHOME=') (DQ ($ Id.VSub_DollarName '$WORK_DIR') (/.gnupg)) } ) (C {(mkdir)} {(-m)} {(0700)} {(-p)} {(DQ ($ Id.VSub_DollarName '$GNUPGHOME'))} ) (command.Simple words: [{(gpg)} {(--dearmor)}] redirects: [ (redir.Redir op: (Token id:Id.Redir_Great val:'>' span_id:8538) fd: -1 arg_word: { (DQ ($ Id.VSub_DollarName '$WORK_DIR') (/sandstorm-keyring.gpg) ) } ) (redir.HereDoc op: (Token id:Id.Redir_DLess val:'<<' span_id:8545) fd: -1 here_begin: {(__EOF__)} here_end_span_id: 8580 stdin_parts: [ ('-----BEGIN PGP PUBLIC KEY BLOCK-----\n') ('Version: GnuPG v1\n') ('\n') ( 'mQENBFX8ypkBCAC8sjX5yZqKdW8nY7aE/GpVeS+qSCbpYSJwixYNFXbz3MQihR3S\n' ) ( 'suvg5uw1KyuQb23c0LwirfxazVf7txKhQNaNU3ek62LG3wcGeBrvQGsIUMbkatay\n' ) ( '/163CLeVWfSK1Z4pFc4dhdjXYSOz0oZxd7Mp78crBbGKmyn7PtzdAqt+XfEXNuee\n' ) ( 'cDbx++P57n5s5xc5fQWznt333IMgmgTREGUROfh4kL376rFAS208XIywJlUVkoKM\n' ) ( 'kIzgcjevFGwYKdsLigHXCDp9toQHl8oPjFV+RE8Br8ciJlMp9CqCfHGwj0Orxasc\n' ) ( 'e9moLqqUc+iKdg9bQfuAbJ/jFNhGmV/CVv9tABEBAAG0LlNhbmRzdG9ybS5pbyAo\n' ) ( 'cmVsZWFzZXMpIDxzdXBwb3J0QHNhbmRzdG9ybS5pbz6JATgEEwECACIFAlX8ypkC\n' ) ( 'GwMGCwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJEGPyJ0mdqMy91bYH/iTg9qbw\n' ) ( 'G3th57Yf70NtyMJE3UBFDYDNAgT45UBEHoHhQM5cdFu/EIHggOKl/A2zL19Nh555\n' ) ( '5F5o3jiJChQ0cvpoVnDdA5lRKD9iK6hzAba9fCVAx/od1PULQP7KV+uHTQuclSFO\n' ) ( 'DBvpgT8bMY9LmlpTl+l2lvYd+c50w3jZMFwh8JrJYAc3X0kBfVEywVZkjH8Nw5nD\n' ) ( 'v/j5Of3XXfEg84tNyWSYUMrYVORJyfHtA9e3JXNv5BMxH73AVLnyCJhCaodQsC6Z\n' ) ( 'hFkHUvvRb58ZqKXMtLYTd/8XLIvpkgRNX6EHWDslJh3BaBwHSuqDNssh1TW5xPjA\n' ) ( '9vkPDzeZfLkuxpy5AQ0EVfzKmQEIANyi22M/3KhkghsPA6Rpha1lx6JJCb4p7E21\n' ) ( 'y82OGFUwcMpZkSgh1lARgp/Mvc2CHhAXi6NkGbgYc1q5rgARSvim2EMZNQOEqRb9\n' ) ( 'teEeI3w7Nz8Q/WoWck9WaXg8EdELtBOXYgVEirVddUl6ftUvCeBh3hE2Y/CLQSXL\n' ) ( 'CYXdQ2/MN6xV8tepuWOu0aPxxPUNea9ceDNZ8/CXEL32pzv9SUX/3KgSnFTzmxNP\n' ) ( 'thzXGuaAQGMZRu3cdTSeK9UUX4L3lxv7p0nE/2K18MU3FayTJqspfUCc4BgHZRMN\n' ) ( 'sh+2/YNfJgi0uWex1WnU94ZIp4A0uic54bU1ZECSwxg81KHaEEkAEQEAAYkBHwQY\n' ) ( 'AQIACQUCVfzKmQIbDAAKCRBj8idJnajMvZgPB/0THpTPnfsYNkwQrBsrTq413ZTF\n' ) ( 'JmVyeZ9xnGDImOdyHhGLlnLC1YEnaNUVEyMKifya4TF2utrLrsMT9TC/dWvFsYlJ\n' ) ( 'oMcUpaSlrFoAoPp3pdOGCIRYNhWGHoxy0Ti1WAa/6A+GoHJpUEz85/jD4vjgYlCX\n' ) ( 'ZFW1Pji9PbdIZFZQR4FyYBkkZOUq6yyTNR0syQPVy3EsPVvXzszm2zV/1YjGymgj\n' ) ( 'MKeYR9+VU+PlFAY9wwLWLTFeSzxTyVjbPwF5bWHV32GM8g0/NgA6a1JLL40v7pqf\n' ) ( 'uYvFk2KJpo3gZNGJ72gLkSzie7Eu1/V67JIG9TwfrJUEj8Uwd5zPv1MOqfWl\n' ) ('=OiS5\n') ('-----END PGP PUBLIC KEY BLOCK-----\n') ] ) ] ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (command.Pipeline children: [ (command.Simple words: [ {(gpg)} {(--no-default-keyring)} {(--keyring)} {($ Id.VSub_DollarName '$WORK_DIR') (/sandstorm-keyring.gpg) } {(--status-fd)} {(1)} {(--verify)} (word.BracedTree parts: [ ($ Id.VSub_DollarName '$WORK_DIR') (/sandstorm-) ($ Id.VSub_DollarName '$BUILD') (.tar.xz) (word_part.BracedTuple words: [{(.sig)} {}] ) ] ) ] redirects: [ (redir.Redir op: (Token id: Id.Redir_Great val: '2>' span_id: 8611 ) fd: 2 arg_word: {(/dev/null)} ) ] ) (C {(grep)} {(-q)} { (SQ (Token id: Id.Lit_Chars val: '^\\[GNUPG:\\] VALIDSIG 160D2D577518B58D94C9800B63F227499DA8CCBD ' span_id: 8623 ) ) } ) ] negated: F ) terminator: (Token id:Id.Op_Semi val:';' span_id:8625) ) ] action: [(C {(echo)} {(DQ ('GPG signature is valid.'))})] spids: [8583 8627] ) ] else_action: [ (C {(rm)} {(-rf)} {(sandstorm-) ($ Id.VSub_DollarName '$BUILD')}) (C {(fail)} {(DQ (E_INVALID_GPG_SIG))} { (DQ ( 'GPG signature is NOT valid! Please report to security@sandstorm.io immediately!' ) ) } ) ] ) (C {(unset)} {(GNUPGHOME)}) ] spids: [8493 8504] ) ] else_action: [ (command.Simple words: [ {(echo)} { (DQ ( "WARNING: gpg not installed; not verifying signatures (but it's HTTPS so you're probably fine)" ) ) } ] redirects: [ (redir.Redir op: (Token id:Id.Redir_GreatAnd val:'>&' span_id:8677) fd: -1 arg_word: {(2)} ) ] ) ] ) (C {(tar)} {(Jxof)} { (DQ ($ Id.VSub_DollarName '$WORK_DIR') (/sandstorm-) ($ Id.VSub_DollarName '$BUILD') (.tar.xz) ) } ) (C {(rm)} {(-rf)} {(DQ ($ Id.VSub_DollarName '$WORK_DIR'))}) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(Id.KW_Bang '!')} {(-e)} {(DQ ($ Id.VSub_DollarName '$BUILD_DIR'))} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:8720) ) ] action: [ (C {(fail)} {(DQ (E_BAD_PACKAGE))} { (DQ ('Bad package -- did not contain ') ($ Id.VSub_DollarName '$BUILD_DIR') (' directory.') ) } ) ] spids: [8707 8722] ) ] ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (command.AndOr ops: [Id.Op_DPipe] children: [ (C {(Id.Lit_LBracket '[')} {(Id.KW_Bang '!')} {(-e)} {(DQ ($ Id.VSub_DollarName '$BUILD_DIR') (/buildstamp))} {(Id.Lit_RBracket ']')} ) (C {(Id.Lit_LBracket '[')} { (command_sub left_token: (Token id: Id.Left_DollarParen val: '$(' span_id: 8763 ) command_list: (command.CommandList children: [ (C {(stat)} {(-c)} {(Id.Lit_Other '%') (Y)} { (DQ ($ Id.VSub_DollarName '$BUILD_DIR') (/buildstamp) ) } ) ] ) ) } {(-lt)} { (word_part.ArithSub anode: (arith_expr.Binary op_id: Id.Arith_Minus left: (arith_expr.ArithWord w: { (command_sub left_token: (Token id: Id.Left_DollarParen val: '$(' span_id: 8781 ) command_list: (command.CommandList children: [ (C {(date)} {(Id.Lit_Other '+') (Id.Lit_Other '%') (s) } ) ] ) ) } ) right: (arith_expr.Binary op_id: Id.Arith_Star left: (arith_expr.Binary op_id: Id.Arith_Star left: (arith_expr.Binary op_id: Id.Arith_Star left: (arith_expr.ArithWord w: {(Id.Lit_Digits 30)} ) right: (arith_expr.ArithWord w: {(Id.Lit_Digits 24)} ) ) right: (arith_expr.ArithWord w: {(Id.Lit_Digits 60)} ) ) right: (arith_expr.ArithWord w: {(Id.Lit_Digits 60)} ) ) ) ) } {(Id.Lit_RBracket ']')} ) ] ) terminator: (Token id:Id.Op_Semi val:';' span_id:8803) ) ] action: [ (C {(rm)} {(-rf)} {(DQ ($ Id.VSub_DollarName '$BUILD_DIR'))}) (C {(fail)} {(DQ (E_PKG_STALE))} { (DQ ( 'The downloaded package seems to be more than a month old. Please verify that your' ) ) } {(DQ ("computer's clock is correct and try again. It could also be that an attacker is"))} { (DQ ( 'trying to trick you into installing an old version. Please contact' ) ) } {(DQ ('security@sandstorm.io if the problem persists.'))} ) ] spids: [8742 8805] ) ] ) ] ) ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(-e)} {($ Id.VSub_DollarName '$BUILD_DIR')} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:8862) ) ] action: [ (C {(echo)} { (DQ ($ Id.VSub_DollarName '$BUILD_DIR') (' is already present. Should I use it or re-download?') ) } ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (command.Pipeline children: [ (C {(prompt-yesno)} {(DQ ('Use existing copy?'))} {(yes)}) ] negated: T ) terminator: (Token id:Id.Op_Semi val:';' span_id:8886) ) ] action: [(C {(do-download)})] spids: [8875 8888] ) ] ) ] spids: [8853 8864] ) ] else_action: [(C {(do-download)})] ) ] ) ) (command.ShFunction name: extract_bundle_if_provided body: (command.BraceGroup children: [ (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(-z)} { (DQ (braced_var_sub token: (Token id:Id.VSub_Name val:BUNDLE_FILE span_id:8931) suffix_op: (suffix_op.Unary op_id:Id.VTest_ColonHyphen arg_word:(word.Empty)) ) ) } {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:8937) ) ] action: [ (command.ControlFlow token: (Token id:Id.ControlFlow_Return val:return span_id:8942) ) ] spids: [8923 8939] ) ] ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {($ Id.VSub_DollarName '$BUILD')} {(Id.Lit_Equals '=')} {(0)} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:8965) ) ] action: [ (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:BUILD_DIR) op: assign_op.Equal rhs: {(sandstorm-custom.) (command_sub left_token: (Token id: Id.Left_DollarParen val: '$(' span_id: 8972 ) command_list: (command.CommandList children: [ (C {(date)} {(Id.Lit_Other '+') (SQ (Token id: Id.Lit_Chars val: '%Y-%m-%d_%H-%M-%S' span_id: 8977 ) ) } ) ] ) ) } spids: [8970] ) ] ) ] spids: [8954 8967] ) ] else_action: [ (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:BUILD_DIR) op: assign_op.Equal rhs: {(sandstorm-) ($ Id.VSub_DollarName '$BUILD')} spids: [8985] ) ] ) ] ) (C {(rm)} {(-rf)} {(DQ ($ Id.VSub_DollarName '$BUILD_DIR'))}) (C {(mkdir)} {(DQ ($ Id.VSub_DollarName '$BUILD_DIR'))}) (command.Subshell command_list: (command.CommandList children: [ (command.AndOr ops: [Id.Op_DAmp] children: [ (C {(cd)} {(DQ ($ Id.VSub_DollarName '$BUILD_DIR'))}) (C {(tar)} {(Jxof)} {(DQ ($ Id.VSub_DollarName '$BUNDLE_FILE'))} {(--strip) (Id.Lit_Equals '=') (1)} ) ] ) ] ) ) ] ) ) (command.ShFunction name: make_runtime_directories body: (command.BraceGroup children: [ (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:GROUP) op: assign_op.Equal rhs: { (command_sub left_token: (Token id:Id.Left_DollarParen val:'$(' span_id:9043) command_list: (command.CommandList children: [ (C {(id)} {(-g)} {($ Id.VSub_DollarName '$SERVER_USER')}) ] ) ) } spids: [9042] ) ] ) (C {(mkdir)} {(-p)} (word.BracedTree parts: [(var/) (word_part.BracedTuple words:[{(log)} {(pid)} {(mongo)}])] ) (word.BracedTree parts: [ (var/sandstorm/) (word_part.BracedTuple words: [{(apps)} {(grains)} {(downloads)}] ) ] ) ) (C {(ln)} {(-sfT)} {($ Id.VSub_DollarName '$BUILD_DIR')} {(latest)}) (C {(ln)} {(-sfT)} {(latest/sandstorm)} {(sandstorm)}) ] ) ) (command.ShFunction name: set_permissions body: (command.BraceGroup children: [ (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(DQ (yes))} {(Id.KW_Bang '!') (Id.Lit_Equals '=')} {(DQ ($ Id.VSub_DollarName '$CURRENTLY_UID_ZERO'))} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:9136) ) ] action: [ (command.ControlFlow token: (Token id:Id.ControlFlow_Return val:return span_id:9141) ) ] spids: [9120 9138] ) ] ) (C {(local)} {(Id.Lit_VarLike 'ADMIN_TOKEN_PATH=')}) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(-e)} {(DQ (${ Id.VSub_Name ADMIN_TOKEN_PATH))} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:9167) ) ] action: [ (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:ADMIN_TOKEN_PATH) op: assign_op.Equal rhs: {(DQ (var/sandstorm/adminToken))} spids: [9172] ) ] ) ] spids: [9153 9169] ) ] ) (C {(chown)} {(-R)} {($ Id.VSub_DollarName '$SERVER_USER') (Id.Lit_Other ':') ($ Id.VSub_DollarName '$GROUP') } (word.BracedTree parts:[(var/) (word_part.BracedTuple words:[{(log)} {(pid)} {(mongo)}])]) (word.BracedTree parts: [ (var/sandstorm/) (word_part.BracedTuple words: [{(apps)} {(grains)} {(downloads)}] ) ] ) {($ Id.VSub_DollarName '$ADMIN_TOKEN_PATH')} ) (C {(chown)} {(root) (Id.Lit_Other ':') ($ Id.VSub_DollarName '$GROUP')} (word.BracedTree parts: [ (var/) (word_part.BracedTuple words: [{(log)} {(pid)} {(mongo)} {(sandstorm)}] ) ] ) (word.BracedTree parts: [ (var/sandstorm/) (word_part.BracedTuple words: [{(apps)} {(grains)} {(downloads)}] ) ] ) {($ Id.VSub_DollarName '$ADMIN_TOKEN_PATH')} ) (C {(chmod)} {(-R)} {(Id.Lit_VarLike 'g=') (rwX) (Id.Lit_Comma ',') (Id.Lit_VarLike 'o=')} (word.BracedTree parts: [ (var/) (word_part.BracedTuple words: [{(log)} {(pid)} {(mongo)} {(sandstorm)}] ) ] ) (word.BracedTree parts: [ (var/sandstorm/) (word_part.BracedTuple words: [{(apps)} {(grains)} {(downloads)}] ) ] ) {($ Id.VSub_DollarName '$ADMIN_TOKEN_PATH')} ) ] ) ) (command.ShFunction name: install_sandstorm_symlinks body: (command.BraceGroup children: [ (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(DQ (yes))} {(Id.KW_Bang '!') (Id.Lit_Equals '=')} {(DQ ($ Id.VSub_DollarName '$CURRENTLY_UID_ZERO'))} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:9313) ) ] action: [ (command.ControlFlow token: (Token id:Id.ControlFlow_Return val:return span_id:9318) ) ] spids: [9297 9315] ) ] ) (C {(local)} {(Id.Lit_VarLike 'FAILED_TO_WRITE_SYMLINK=') (DQ (no))}) (command.AndOr ops: [Id.Op_DPipe] children: [ (C {(ln)} {(-sfT)} {($ Id.VSub_DollarName '$PWD') (/sandstorm)} {(/usr/local/bin/sandstorm)} ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:FAILED_TO_WRITE_SYMLINK) op: assign_op.Equal rhs: {(yes)} spids: [9349] ) ] ) ] ) (command.AndOr ops: [Id.Op_DPipe] children: [ (C {(ln)} {(-sfT)} {($ Id.VSub_DollarName '$PWD') (/sandstorm)} {(/usr/local/bin/spk)} ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:FAILED_TO_WRITE_SYMLINK) op: assign_op.Equal rhs: {(yes)} spids: [9364] ) ] ) ] ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(DQ (${ Id.VSub_Name FAILED_TO_WRITE_SYMLINK))} {(Id.Lit_Equals '=')} {(DQ (yes))} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:9399) ) ] action: [ (C {(echo)} {(DQ )}) (C {(echo)} { (DQ ( '*** WARNING: /usr/local/bin was not writeable. To run sandstorm or spk manually, use:' ) ) } ) (C {(echo)} {(DQ (' - ') ($ Id.VSub_DollarName '$PWD') (/sandstorm))}) (C {(echo)} {(DQ (' - ') ($ Id.VSub_DollarName '$PWD') ('/sandstorm spk'))}) (C {(echo)} {(DQ )}) (command.ControlFlow token: (Token id:Id.ControlFlow_Return val:return span_id:9441) ) ] spids: [9381 9401] ) ] ) ] ) ) (command.ShFunction name: ask_about_starting_at_boot body: (command.BraceGroup children: [ (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(DQ ($ Id.VSub_DollarName '$CURRENTLY_UID_ZERO'))} {(Id.KW_Bang '!') (Id.Lit_Equals '=')} {(DQ (yes))} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:9478) ) ] action: [ (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:START_AT_BOOT) op: assign_op.Equal rhs: {(DQ (no))} spids: [9483] ) ] ) ] spids: [9461 9480] ) ] ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(Id.KW_Bang '!')} {(-z)} { (DQ (braced_var_sub token: (Token id:Id.VSub_Name val:START_AT_BOOT span_id:9507) suffix_op: (suffix_op.Unary op_id:Id.VTest_ColonHyphen arg_word:(word.Empty)) ) ) } {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:9514) ) ] action: [ (command.ControlFlow token: (Token id:Id.ControlFlow_Return val:return span_id:9519) ) ] spids: [9497 9516] ) ] ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(prompt-yesno)} { (DQ ('Start sandstorm at system boot (using ') ($ Id.VSub_DollarName '$INIT_SYSTEM') (')?') ) } {(yes)} ) terminator: (Token id:Id.Op_Semi val:';' span_id:9537) ) ] action: [ (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:START_AT_BOOT) op: assign_op.Equal rhs: {(yes)} spids: [9542] ) ] ) ] spids: [9526 9539] ) ] ) ] ) ) (command.ShFunction name: configure_start_at_boot_if_desired body: (command.BraceGroup children: [ (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:SANDSTORM_NEEDS_TO_BE_STARTED) op: assign_op.Equal rhs: {(DQ (yes))} spids: [9558] ) ] ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(DQ (yes))} {(Id.KW_Bang '!') (Id.Lit_Equals '=')} { (DQ (braced_var_sub token: (Token id:Id.VSub_Name val:START_AT_BOOT span_id:9586) suffix_op: (suffix_op.Unary op_id:Id.VTest_ColonHyphen arg_word:(word.Empty)) ) ) } {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:9593) ) ] action: [ (command.ControlFlow token: (Token id:Id.ControlFlow_Return val:return span_id:9598) ) ] spids: [9573 9595] ) ] ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(DQ (systemd))} {(Id.Lit_Equals '=')} {(DQ (${ Id.VSub_Name INIT_SYSTEM))} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:9623) ) ] action: [ (C {(configure_systemd_init_system)}) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:SANDSTORM_NEEDS_TO_BE_STARTED) op: assign_op.Equal rhs: {(no)} spids: [9631] ) ] ) ] spids: [9605 9625] ) (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(DQ (sysvinit))} {(Id.Lit_Equals '=')} {(DQ (${ Id.VSub_Name INIT_SYSTEM))} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:9653) ) ] action: [ (C {(configure_sysvinit_init_system)}) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:SANDSTORM_NEEDS_TO_BE_STARTED) op: assign_op.Equal rhs: {(no)} spids: [9661] ) ] ) ] spids: [9635 9655] ) ] else_action: [ (C {(echo)} { (DQ ( "Note: I don't know how to set up sandstorm to auto-run at startup on" ) ) } ) (C {(echo)} {(DQ (' your system. :('))}) (C {(echo)}) ] ) ] ) ) (command.ShFunction name: configure_systemd_init_system body: (command.BraceGroup children: [ (C {(local)} {(Id.Lit_VarLike 'SYSTEMD_UNIT=') (DQ (sandstorm.service))}) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (command.Pipeline children: [ (C {(systemctl)} {(list-unit-files)}) (C {(grep)} {(-q)} {($ Id.VSub_DollarName '$SYSTEMD_UNIT')}) ] negated: F ) terminator: (Token id:Id.Op_Semi val:';' span_id:9736) ) ] action: [ (command.AndOr ops: [Id.Op_DPipe] children: [(C {(systemctl)} {(stop)} {(sandstorm)}) (C {(true)})] ) ] spids: [9723 9738] ) ] ) (command.ForEach iter_name: SYSTEMD_UNIT_PATH iter_words: [ {(/etc/systemd/system)} {(/run/systemd/system)} {(/usr/lib/systemd/system)} ] do_arg_iter: F body: (command.DoGroup children: [ (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(-e)} {($ Id.VSub_DollarName '$SYSTEMD_UNIT_PATH') (/) ($ Id.VSub_DollarName '$SYSTEMD_UNIT') } {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:9788) ) ] action: [ (C {(rm)} {($ Id.VSub_DollarName '$SYSTEMD_UNIT_PATH') (/) ($ Id.VSub_DollarName '$SYSTEMD_UNIT') } ) ] spids: [9776 9790] ) ] ) ] ) ) (command.Simple words: [{(cat)}] redirects: [ (redir.Redir op: (Token id:Id.Redir_Great val:'>' span_id:9809) fd: -1 arg_word: {(/etc/systemd/system/) ($ Id.VSub_DollarName '$SYSTEMD_UNIT')} ) (redir.HereDoc op: (Token id:Id.Redir_DLess val:'<<' span_id:9814) fd: -1 here_begin: {(__EOF__)} here_end_span_id: 9835 stdin_parts: [ ('[Unit]\n') ('Description=Sandstorm server\n') ('After=local-fs.target remote-fs.target network.target\n') ('Requires=local-fs.target remote-fs.target network.target\n') ('\n') ('[Service]\n') ('Type=forking\n') ('ExecStart=') ($ Id.VSub_DollarName '$PWD') ('/sandstorm start\n') ('ExecStop=') ($ Id.VSub_DollarName '$PWD') ('/sandstorm stop\n') ('\n') ('[Install]\n') ('WantedBy=multi-user.target\n') ] ) ] ) (C {(systemctl)} {(enable)} {(sandstorm)}) (C {(systemctl)} {(start)} {(sandstorm)}) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:STARTED_SANDSTORM) op: assign_op.Equal rhs: {(DQ (yes))} spids: [9851] ) ] ) ] ) ) (command.ShFunction name: configure_sysvinit_init_system body: (command.BraceGroup children: [ (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(-e)} {(/etc/init.d/sandstorm)} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:9893) ) ] action: [ (command.AndOr ops: [Id.Op_DPipe] children: [(C {(service)} {(sandstorm)} {(stop)}) (C {(true)})] ) ] spids: [9883 9895] ) ] ) (command.Simple words: [{(cat)}] redirects: [ (redir.Redir op: (Token id:Id.Redir_Great val:'>' span_id:9924) fd: -1 arg_word: {(/etc/init.d/sandstorm)} ) (redir.HereDoc op: (Token id:Id.Redir_DLess val:'<<' span_id:9928) fd: -1 here_begin: {(__EOF__)} here_end_span_id: 9983 stdin_parts: [ ('#! /bin/bash\n') ('### BEGIN INIT INFO\n') ('# Provides: sandstorm\n') ('# Required-Start: ') (word_part.EscapedLiteral token: (Token id:Id.Lit_EscapedChar val:'\\$' span_id:9936) ) ('local_fs ') (word_part.EscapedLiteral token: (Token id:Id.Lit_EscapedChar val:'\\$' span_id:9938) ) ('remote_fs ') (word_part.EscapedLiteral token: (Token id:Id.Lit_EscapedChar val:'\\$' span_id:9940) ) ('networking ') (word_part.EscapedLiteral token: (Token id:Id.Lit_EscapedChar val:'\\$' span_id:9942) ) ('syslog\n') ('# Required-Stop: ') (word_part.EscapedLiteral token: (Token id:Id.Lit_EscapedChar val:'\\$' span_id:9945) ) ('local_fs ') (word_part.EscapedLiteral token: (Token id:Id.Lit_EscapedChar val:'\\$' span_id:9947) ) ('remote_fs ') (word_part.EscapedLiteral token: (Token id:Id.Lit_EscapedChar val:'\\$' span_id:9949) ) ('networking ') (word_part.EscapedLiteral token: (Token id:Id.Lit_EscapedChar val:'\\$' span_id:9951) ) ('syslog\n') ('# Default-Start: 2 3 4 5\n') ('# Default-Stop: 0 1 6\n') ('# Short-Description: starts Sandstorm personal cloud server\n') ('### END INIT INFO\n') ('\n') ('DESC=') (Id.Right_DoubleQuote '"') ('Sandstorm server') (Id.Right_DoubleQuote '"') ('\n') ('DAEMON=') ($ Id.VSub_DollarName '$PWD') ('/sandstorm\n') ('\n') ( '# The Sandstorm runner supports all the common init commands directly.\n' ) ('# We use -a to set the program name to make help text look nicer.\n') ('# This requires bash, though.\n') ('exec -a ') (Id.Right_DoubleQuote '"') ('service sandstorm') (Id.Right_DoubleQuote '"') (' ') (word_part.EscapedLiteral token: (Token id:Id.Lit_EscapedChar val:'\\$' span_id:9975) ) ('DAEMON ') (Id.Right_DoubleQuote '"') (word_part.EscapedLiteral token: (Token id:Id.Lit_EscapedChar val:'\\$' span_id:9978) ) ('@') (Id.Right_DoubleQuote '"') ('\n') ] ) ] ) (C {(chmod)} {(Id.Lit_Other '+') (x)} {(/etc/init.d/sandstorm)}) (C {(update-rc.d)} {(sandstorm)} {(defaults)}) (C {(service)} {(sandstorm)} {(start)}) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:STARTED_SANDSTORM) op: assign_op.Equal rhs: {(DQ (yes))} spids: [10017] ) ] ) ] ) ) (command.ShFunction name: generate_admin_token body: (command.BraceGroup children: [ (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(DQ (yes))} {(Id.Lit_Equals '=')} {(DQ (${ Id.VSub_Name ALLOW_DEV_ACCOUNTS))} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:10054) ) ] action: [ (command.ControlFlow token: (Token id:Id.ControlFlow_Return val:return span_id:10059) ) ] spids: [10036 10056] ) ] ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(Id.KW_Bang '!')} {(-z)} { (DQ (braced_var_sub token: (Token id:Id.VSub_Name val:ADMIN_TOKEN span_id:10084) suffix_op: (suffix_op.Unary op_id:Id.VTest_ColonHyphen arg_word:(word.Empty)) ) ) } {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:10091) ) ] action: [ (C {(local)} {(Id.Lit_VarLike 'TMPFILENAME=') (DQ (command_sub left_token: (Token id:Id.Left_DollarParen val:'$(' span_id:10100) command_list: (command.CommandList children: [ (C {(mktemp)} {(./var/sandstorm/adminTokenTmp.XXXXXXXXXX)}) ] ) ) ) } ) (command.Simple words: [{(echo)} {(-n)} {(DQ ($ Id.VSub_DollarName '$ADMIN_TOKEN'))}] redirects: [ (redir.Redir op: (Token id:Id.Redir_Great val:'>' span_id:10116) fd: -1 arg_word: {(DQ ($ Id.VSub_DollarName '$TMPFILENAME'))} ) ] ) (C {(local)} {(Id.Lit_VarLike 'FILENAME=') (DQ (./var/sandstorm/adminToken))} ) (C {(mv)} {(DQ ($ Id.VSub_DollarName '$TMPFILENAME'))} {(DQ ($ Id.VSub_DollarName '$FILENAME'))} ) (C {(chmod)} {(0640)} {(DQ ($ Id.VSub_DollarName '$FILENAME'))}) (C {(chgrp)} {(DQ ($ Id.VSub_DollarName '$SERVER_USER'))} {(DQ ($ Id.VSub_DollarName '$FILENAME'))} ) (command.ControlFlow token: (Token id:Id.ControlFlow_Return val:return span_id:10162) ) ] spids: [10074 10093] ) ] ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:ADMIN_TOKEN) op: assign_op.Equal rhs: { (command_sub left_token: (Token id:Id.Left_DollarParen val:'$(' span_id:10170) command_list: (command.CommandList children: [(C {(./sandstorm)} {(admin-token)} {(--quiet)})] ) ) } spids: [10169] ) ] ) ] ) ) (command.ShFunction name: print_success body: (command.BraceGroup children: [ (C {(echo)} {(DQ )}) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(DQ (yes))} {(Id.Lit_Equals '=')} {(DQ ($ Id.VSub_DollarName '$SANDSTORM_NEEDS_TO_BE_STARTED'))} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:10210) ) ] action: [ (C {(echo)} {(DQ ('Installation complete. To start your server now, run:'))}) (C {(echo)} {(DQ (' ') ($ Id.VSub_DollarName '$DIR') ('/sandstorm start'))}) (C {(echo)} {(DQ ("Once that's done, visit this link to start using it:"))}) ] spids: [10194 10212] ) ] else_action: [ (C {(echo)} {(-n)} {(DQ ('Your server is now online! '))}) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(DQ (${ Id.VSub_Name SANDCATS_HTTPS_SUCCESSFUL))} {(Id.Lit_Equals '=')} {(DQ (yes))} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:10268) ) ] action: [ (C {(echo)} {(DQ ('It should work immediately if you use Chrome.'))}) ] spids: [10250 10270] ) ] ) (C {(echo)} {(DQ ('Visit this link to start using it:'))}) ] ) (C {(echo)} {(DQ )}) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(Id.KW_Bang '!')} {(-z)} { (DQ (braced_var_sub token: (Token id:Id.VSub_Name val:ADMIN_TOKEN span_id:10319) suffix_op: (suffix_op.Unary op_id:Id.VTest_ColonHyphen arg_word:(word.Empty)) ) ) } {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:10326) ) ] action: [ (C {(echo)} { (DQ (' ') (braced_var_sub token: (Token id:Id.VSub_Name val:BASE_URL span_id:10336) suffix_op: (suffix_op.Unary op_id: Id.VTest_ColonHyphen arg_word: {('(unknown; bad config)')} ) ) (/setup/token/) ($ Id.VSub_DollarName '$ADMIN_TOKEN') ) } ) (C {(echo)} {(DQ )}) (C {(echo)} { (DQ ( 'NOTE: This URL expires in 15 minutes. You can generate a new setup URL by running' ) ) } ) (C {(echo)} {(DQ ("'sudo sandstorm admin-token' from the command line."))}) ] spids: [10309 10328] ) ] else_action: [ (C {(echo)} { (DQ (' ') (braced_var_sub token: (Token id:Id.VSub_Name val:BASE_URL span_id:10373) suffix_op: (suffix_op.Unary op_id: Id.VTest_ColonHyphen arg_word: {('(unknown; bad config)')} ) ) (/) ) } ) ] ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(DQ (yes))} {(Id.Lit_Equals '=')} {(DQ (${ Id.VSub_Name ALLOW_DEV_ACCOUNTS))} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:10402) ) ] action: [ (C {(echo)} {(DQ )}) (C {(echo)} { (DQ ( "NOTE: Use the passwordless admin account called Alice for convenient dev login (since you have 'dev accounts' enabled)." ) ) } ) ] spids: [10384 10404] ) ] ) (C {(echo)} {(DQ )}) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(DQ (${ Id.VSub_Name SANDCATS_HTTPS_SUCCESSFUL))} {(Id.Lit_Equals '=')} {(DQ (yes))} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:10448) ) ] action: [ (C {(echo)} {(DQ )}) (C {(echo)} { (DQ ( '(If your browser shows you an OCSP error, wait 10 minutes for it to auto-resolve' ) ) } ) (C {(echo)} {(DQ ('and try Chrome until then.)'))}) ] spids: [10430 10450] ) ] ) (C {(echo)}) (C {(echo)} {(DQ ('To learn how to control the server, run:'))}) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(DQ (yes))} {(Id.Lit_Equals '=')} {(DQ ($ Id.VSub_DollarName '$CURRENTLY_UID_ZERO'))} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:10502) ) ] action: [(C {(echo)} {(DQ (' sandstorm help'))})] spids: [10486 10504] ) ] else_action: [ (C {(echo)} {(DQ (' ') ($ Id.VSub_DollarName '$DIR') ('/sandstorm help'))}) ] ) ] ) ) (command.ShFunction name: sandcats_provide_help body: (command.BraceGroup children: [ (C {(echo)} { (DQ ( 'Sandcats.io is a free dynamic DNS service run by the Sandstorm development team.' ) ) } ) (C {(echo)} {(DQ )}) (C {(echo)} {(DQ ('You can:'))}) (C {(echo)} {(DQ )}) (C {(echo)} {(DQ ('* Read more about it at:'))}) (C {(echo)} {(DQ (' https://github.com/sandstorm-io/sandstorm/wiki/Sandcats-dynamic-DNS'))} ) (C {(echo)} {(DQ )}) (C {(echo)} {(DQ ('* Recover access to a domain you once registered with sandcats'))} ) (C {(echo)} {(DQ )}) (C {(echo)} {(DQ ('* Just press enter to go to the previous question.'))}) (C {(sandcats_recover_domain)}) ] ) ) (command.ShFunction name: sandcats_recover_domain body: (command.BraceGroup children: [ (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:DESIRED_SANDCATS_NAME) op: assign_op.Equal rhs: { (command_sub left_token: (Token id:Id.Left_DollarParen val:'$(' span_id:10617) command_list: (command.CommandList children: [ (C {(prompt)} {(DQ ('What Sandcats subdomain do you want to recover?'))} {(DQ (none))} ) ] ) ) } spids: [10616] ) ] ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(DQ (none))} {(Id.Lit_Equals '=')} {(DQ ($ Id.VSub_DollarName '$DESIRED_SANDCATS_NAME'))} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:10651) ) ] action: [ (C {(sandcats_register_name)}) (command.ControlFlow token: (Token id:Id.ControlFlow_Return val:return span_id:10659) ) ] spids: [10635 10653] ) ] ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (command.DBracket expr: (bool_expr.Binary op_id: Id.BoolBinary_EqualTilde left: {($ Id.VSub_DollarName '$DESIRED_SANDCATS_NAME')} right: {(Id.Lit_Other '[') (Id.Lit_Other .) (Id.Lit_Other ']')} ) ) terminator: (Token id:Id.Op_Semi val:';' span_id:10684) ) ] action: [ (C {(echo)} {(DQ )}) (C {(echo)} {(DQ ('You entered: ') ($ Id.VSub_DollarName '$DESIRED_SANDCATS_NAME'))} ) (C {(echo)} {(DQ )}) (C {(echo)} { (DQ ( 'but this function just wants the name of your subdomain, not including any dot characters.' ) ) } ) (C {(echo)} {(DQ ('Please try again.'))}) (C {(echo)} {(DQ )}) (C {(sandcats_recover_domain)}) (command.ControlFlow token: (Token id:Id.ControlFlow_Return val:return span_id:10732) ) ] spids: [10670 10686] ) ] ) (C {(echo)} { (DQ ( 'OK. We will send a recovery token to the email address on file. Type no to abort.' ) ) } ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:OK_TO_CONTINUE) op: assign_op.Equal rhs: { (command_sub left_token: (Token id:Id.Left_DollarParen val:'$(' span_id:10747) command_list: (command.CommandList children: [(C {(prompt)} {(DQ ('OK to continue?'))} {(DQ (yes))})] ) ) } spids: [10746] ) ] ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(DQ (no))} {(Id.Lit_Equals '=')} {(DQ ($ Id.VSub_DollarName '$OK_TO_CONTINUE'))} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:10776) ) ] action: [ (C {(sandcats_register_name)}) (command.ControlFlow token: (Token id:Id.ControlFlow_Return val:return span_id:10784) ) ] spids: [10760 10778] ) ] ) (C {(local)} {(Id.Lit_VarLike 'LOG_PATH=') (DQ (var/sandcats/sendrecoverytoken-log))} ) (C {(touch)} {(DQ ($ Id.VSub_DollarName '$LOG_PATH'))}) (C {(chmod)} {(0640)} {(DQ ($ Id.VSub_DollarName '$LOG_PATH'))}) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:HTTP_STATUS) op: assign_op.Equal rhs: { (command_sub left_token: (Token id:Id.Left_DollarParen val:'$(' span_id:10820) command_list: (command.CommandList children: [ (C {(dotdotdot_curl)} {(--silent)} {(--max-time)} {(20)} {($ Id.VSub_DollarName '$SANDCATS_CURL_PARAMS')} {(-A)} {(DQ ($ Id.VSub_DollarName '$CURL_USER_AGENT'))} {(-X)} {(POST)} {(--data-urlencode)} { (DQ ('rawHostname=') ($ Id.VSub_DollarName '$DESIRED_SANDCATS_NAME') ) } {(--output)} {(DQ ($ Id.VSub_DollarName '$LOG_PATH'))} {(-w)} { (SQ (Token id: Id.Lit_Chars val: '%{http_code}' span_id: 10875 ) ) } {(-H)} {(SQ (Token id:Id.Lit_Chars val:'X-Sand: cats' span_id:10883))} {(-H)} {(DQ ('Accept: text/plain'))} {(DQ (${ Id.VSub_Name SANDCATS_API_BASE) (/sendrecoverytoken))} ) ] ) ) } spids: [10819] ) ] ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(DQ (200))} {(Id.KW_Bang '!') (Id.Lit_Equals '=')} {(DQ ($ Id.VSub_DollarName '$HTTP_STATUS'))} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:10923) ) ] action: [ (C {(error)} { (DQ (command_sub left_token: (Token id:Id.Left_DollarParen val:'$(' span_id:10931) command_list: (command.CommandList children: [(C {(cat)} {($ Id.VSub_DollarName '$LOG_PATH')})] ) ) ) } ) (C {(sandcats_recover_domain)}) (command.ControlFlow token: (Token id:Id.ControlFlow_Return val:return span_id:10942) ) ] spids: [10906 10925] ) ] ) (C {(cat)} {(DQ ($ Id.VSub_DollarName '$LOG_PATH'))}) (C {(echo)} {(SQ )}) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:TOKEN) op: assign_op.Equal rhs: { (command_sub left_token: (Token id:Id.Left_DollarParen val:'$(' span_id:10975) command_list: (command.CommandList children: [ (C {(prompt)} { (DQ ('Please enter the token that we sent to you by email.') ) } {(SQ )} ) ] ) ) } spids: [10974] ) ] ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(-z)} {(DQ ($ Id.VSub_DollarName '$TOKEN'))} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:11004) ) ] action: [ (C {(error)} {(DQ ('Empty tokens are not valid.'))}) (C {(sandcats_recover_domain)}) (command.ControlFlow token: (Token id:Id.ControlFlow_Return val:return span_id:11019) ) ] spids: [10992 11006] ) ] ) (C {(local)} {(Id.Lit_VarLike 'LOG_PATH=') (DQ (var/sandcats/recover-log))}) (C {(touch)} {(DQ ($ Id.VSub_DollarName '$LOG_PATH'))}) (C {(chmod)} {(0640)} {(DQ ($ Id.VSub_DollarName '$LOG_PATH'))}) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:HTTP_STATUS) op: assign_op.Equal rhs: { (command_sub left_token: (Token id:Id.Left_DollarParen val:'$(' span_id:11071) command_list: (command.CommandList children: [ (C {(dotdotdot_curl)} {(--silent)} {(--max-time)} {(20)} {($ Id.VSub_DollarName '$SANDCATS_CURL_PARAMS')} {(-A)} {(DQ ($ Id.VSub_DollarName '$CURL_USER_AGENT'))} {(-X)} {(POST)} {(--data-urlencode)} { (DQ ('rawHostname=') ($ Id.VSub_DollarName '$DESIRED_SANDCATS_NAME') ) } {(--data-urlencode)} {(DQ ('recoveryToken=') ($ Id.VSub_DollarName '$TOKEN'))} {(--output)} {(DQ ($ Id.VSub_DollarName '$LOG_PATH'))} {(-w)} {(SQ (Token id:Id.Lit_Chars val:'%{http_code}' span_id:11135))} {(-H)} { (SQ (Token id: Id.Lit_Chars val: 'X-Sand: cats' span_id: 11143 ) ) } {(-H)} {(DQ ('Accept: text/plain'))} {(--cert)} {(var/sandcats/id_rsa.private_combined)} {(DQ (${ Id.VSub_Name SANDCATS_API_BASE) (/recover))} ) ] ) ) } spids: [11070] ) ] ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(DQ (200))} {(Id.KW_Bang '!') (Id.Lit_Equals '=')} {(DQ ($ Id.VSub_DollarName '$HTTP_STATUS'))} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:11189) ) ] action: [ (C {(error)} { (DQ (command_sub left_token: (Token id:Id.Left_DollarParen val:'$(' span_id:11197) command_list: (command.CommandList children: [(C {(cat)} {($ Id.VSub_DollarName '$LOG_PATH')})] ) ) ) } ) (C {(sandcats_recover_domain)}) (command.ControlFlow token: (Token id:Id.ControlFlow_Return val:return span_id:11208) ) ] spids: [11172 11191] ) ] ) (C {(cat)} {(DQ ($ Id.VSub_DollarName '$LOG_PATH'))}) (C {(echo)} {(SQ )}) (C {(local)} {(Id.Lit_VarLike 'LOG_PATH=') (DQ (var/sandcats/update-log))}) (C {(touch)} {(DQ ($ Id.VSub_DollarName '$LOG_PATH'))}) (C {(chmod)} {(0640)} {(DQ ($ Id.VSub_DollarName '$LOG_PATH'))}) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:HTTP_STATUS) op: assign_op.Equal rhs: { (command_sub left_token: (Token id:Id.Left_DollarParen val:'$(' span_id:11282) command_list: (command.CommandList children: [ (C {(dotdotdot_curl)} {(--silent)} {(--max-time)} {(20)} {($ Id.VSub_DollarName '$SANDCATS_CURL_PARAMS')} {(-A)} {(DQ ($ Id.VSub_DollarName '$CURL_USER_AGENT'))} {(-X)} {(POST)} {(--data-urlencode)} { (DQ ('rawHostname=') ($ Id.VSub_DollarName '$DESIRED_SANDCATS_NAME') ) } {(--output)} {(DQ ($ Id.VSub_DollarName '$LOG_PATH'))} {(-w)} { (SQ (Token id: Id.Lit_Chars val: '%{http_code}' span_id: 11337 ) ) } {(-H)} {(SQ (Token id:Id.Lit_Chars val:'X-Sand: cats' span_id:11345))} {(-H)} {(DQ ('Accept: text/plain'))} {(--cert)} {(var/sandcats/id_rsa.private_combined)} {(DQ (${ Id.VSub_Name SANDCATS_API_BASE) (/update))} ) ] ) ) } spids: [11281] ) ] ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(DQ (200))} {(Id.KW_Bang '!') (Id.Lit_Equals '=')} {(DQ ($ Id.VSub_DollarName '$HTTP_STATUS'))} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:11391) ) ] action: [ (C {(error)} { (DQ (command_sub left_token: (Token id:Id.Left_DollarParen val:'$(' span_id:11399) command_list: (command.CommandList children: [(C {(cat)} {($ Id.VSub_DollarName '$LOG_PATH')})] ) ) ) } ) (C {(sandcats_recover_domain)}) (command.ControlFlow token: (Token id:Id.ControlFlow_Return val:return span_id:11410) ) ] spids: [11374 11393] ) ] ) (C {(cat)} {(DQ ($ Id.VSub_DollarName '$LOG_PATH'))}) (C {(echo)} {(SQ )}) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:SANDCATS_SUCCESSFUL) op: assign_op.Equal rhs: {(DQ (yes))} spids: [11439] ) ] ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:SS_HOSTNAME) op: assign_op.Equal rhs: { (DQ (${ Id.VSub_Name DESIRED_SANDCATS_NAME) (.) (${ Id.VSub_Name SANDCATS_BASE_DOMAIN) ) } spids: [11445] ) ] ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:USE_EXTERNAL_INTERFACE) op: assign_op.Equal rhs: {(DQ (yes))} spids: [11457] ) ] ) (C {(echo)} { (DQ ("Congratulations! You're all configured to use ") (${ Id.VSub_Name DESIRED_SANDCATS_NAME) (.) (${ Id.VSub_Name SANDCATS_BASE_DOMAIN) (.) ) } ) (C {(echo)} { (DQ ('Your credentials to use it are in ') (command_sub left_token: (Token id:Id.Left_DollarParen val:'$(' span_id:11482) command_list: (command.CommandList children: [(C {(readlink)} {(-f)} {(var/sandcats)})] ) ) ('; consider making a backup.') ) } ) ] ) ) (command.ShFunction name: sandcats_registerreserved body: (command.BraceGroup children: [ (C {(echo)} {(DQ ('Registering your pre-reserved domain.'))}) (C {(local)} {(LOG_PATH)}) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:LOG_PATH) op: assign_op.Equal rhs: {(DQ (var/sandcats/registerreserved-log))} spids: [11514] ) ] ) (C {(touch)} {(DQ ($ Id.VSub_DollarName '$LOG_PATH'))}) (C {(chmod)} {(0640)} {(DQ ($ Id.VSub_DollarName '$LOG_PATH'))}) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:HTTP_STATUS) op: assign_op.Equal rhs: { (command_sub left_token: (Token id:Id.Left_DollarParen val:'$(' span_id:11537) command_list: (command.CommandList children: [ (C {(dotdotdot_curl)} {(--silent)} {(--max-time)} {(20)} {($ Id.VSub_DollarName '$SANDCATS_CURL_PARAMS')} {(-A)} {(DQ ($ Id.VSub_DollarName '$CURL_USER_AGENT'))} {(-X)} {(POST)} {(--data-urlencode)} { (DQ ('domainReservationToken=') ($ Id.VSub_DollarName '$SANDCATS_DOMAIN_RESERVATION_TOKEN' ) ) } {(--data-urlencode)} {(DQ ('rawHostname=') ($ Id.VSub_DollarName '$DESIRED_SANDCATS_NAME'))} {(--output)} {(DQ ($ Id.VSub_DollarName '$LOG_PATH'))} {(-w)} { (SQ (Token id: Id.Lit_Chars val: '%{http_code}' span_id: 11601 ) ) } {(-H)} {(SQ (Token id:Id.Lit_Chars val:'X-Sand: cats' span_id:11609))} {(-H)} {(DQ ('Accept: text/plain'))} {(--cert)} {(var/sandcats/id_rsa.private_combined)} {(DQ (${ Id.VSub_Name SANDCATS_API_BASE) (/registerreserved))} ) ] ) ) } spids: [11536] ) ] ) (command.If arms: [ (if_arm cond: [ (C {(Id.Lit_LBracket '[')} {(DQ (200))} {(Id.Lit_Equals '=')} {(DQ ($ Id.VSub_DollarName '$HTTP_STATUS'))} {(Id.Lit_RBracket ']')} ) ] action: [ (C {(cat)} {(DQ ($ Id.VSub_DollarName '$LOG_PATH'))}) (C {(echo)} {(SQ )}) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:SS_HOSTNAME) op: assign_op.Equal rhs: { (DQ (${ Id.VSub_Name DESIRED_SANDCATS_NAME) (.) (${ Id.VSub_Name SANDCATS_BASE_DOMAIN) ) } spids: [11691] ) ] ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:USE_EXTERNAL_INTERFACE) op: assign_op.Equal rhs: {(DQ (yes))} spids: [11703] ) ] ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:SANDCATS_SUCCESSFUL) op: assign_op.Equal rhs: {(DQ (yes))} spids: [11709] ) ] ) (C {(echo)} { (DQ ('Congratulations! We have registered your ') (${ Id.VSub_Name DESIRED_SANDCATS_NAME) (.) (${ Id.VSub_Name SANDCATS_BASE_DOMAIN) (' name.') ) } ) (C {(echo)} { (DQ ('Your credentials to use it are in ') (command_sub left_token: (Token id:Id.Left_DollarParen val:'$(' span_id:11734) command_list: (command.CommandList children: [(C {(readlink)} {(-f)} {(var/sandcats)})] ) ) ('; consider making a backup.') ) } ) ] spids: [11638 11655] ) ] else_action: [ (C {(fail)} {(DQ (E_SANDCATS_REGISTER_RESERVED_SRV_FAIL))} { (DQ (command_sub left_token: (Token id:Id.Left_DollarParen val:'$(' span_id:11771) command_list: (command.CommandList children: [(C {(cat)} {(DQ ($ Id.VSub_DollarName '$LOG_PATH'))})] ) ) ) } ) ] ) ] ) ) (command.ShFunction name: sandcats_register_name body: (command.BraceGroup children: [ (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:SANDCATS_API_BASE) op: assign_op.Equal rhs: { (DQ (braced_var_sub token: (Token id: Id.VSub_Name val: OVERRIDE_SANDCATS_API_BASE span_id: 11808 ) suffix_op: (suffix_op.Unary op_id: Id.VTest_ColonHyphen arg_word: {('https:') (Id.Lit_Slash /) (Id.Lit_Slash /) (sandcats.io)} ) ) ) } spids: [11805] ) ] ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:SANDCATS_CURL_PARAMS) op: assign_op.Equal rhs: { (DQ (braced_var_sub token: (Token id: Id.VSub_Name val: OVERRIDE_SANDCATS_CURL_PARAMS span_id: 11821 ) suffix_op: (suffix_op.Unary op_id:Id.VTest_ColonHyphen arg_word:(word.Empty)) ) ) } spids: [11818] ) ] ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(Id.KW_Bang '!')} {(-z)} { (DQ (braced_var_sub token: (Token id: Id.VSub_Name val: SANDCATS_DOMAIN_RESERVATION_TOKEN span_id: 11846 ) suffix_op: (suffix_op.Unary op_id:Id.VTest_ColonHyphen arg_word:(word.Empty)) ) ) } {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:11853) ) ] action: [ (C {(sandcats_registerreserved)}) (command.ControlFlow token: (Token id:Id.ControlFlow_Return val:return span_id:11861) ) ] spids: [11836 11855] ) ] ) (C {(echo)} { (DQ ( 'Choose your desired Sandcats subdomain (alphanumeric, max 20 characters).' ) ) } ) (C {(echo)} {(DQ ('Type the word none to skip this step, or help for help.'))}) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:DESIRED_SANDCATS_NAME) op: assign_op.Equal rhs: { (command_sub left_token: (Token id:Id.Left_DollarParen val:'$(' span_id:11883) command_list: (command.CommandList children: [ (C {(prompt)} { (DQ ('What *.') (${ Id.VSub_Name SANDCATS_BASE_DOMAIN) (' subdomain would you like?') ) } {(SQ )} ) ] ) ) } spids: [11882] ) ] ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(-z)} {(DQ ($ Id.VSub_DollarName '$DESIRED_SANDCATS_NAME'))} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:11920) ) ] action: [ (C {(sandcats_register_name)}) (command.ControlFlow token: (Token id:Id.ControlFlow_Return val:return span_id:11928) ) ] spids: [11908 11922] ) ] ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(DQ (none))} {(Id.Lit_Equals '=')} {(DQ ($ Id.VSub_DollarName '$DESIRED_SANDCATS_NAME'))} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:11955) ) ] action: [ (command.ControlFlow token: (Token id:Id.ControlFlow_Return val:return span_id:11960) ) ] spids: [11939 11957] ) ] ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(DQ (help))} {(Id.Lit_Equals '=')} {(DQ ($ Id.VSub_DollarName '$DESIRED_SANDCATS_NAME'))} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:11987) ) ] action: [ (C {(sandcats_provide_help)}) (command.ControlFlow token: (Token id:Id.ControlFlow_Return val:return span_id:11995) ) ] spids: [11971 11989] ) ] ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (command.Pipeline children: [ (command.DBracket expr: (bool_expr.Binary op_id: Id.BoolBinary_EqualTilde left: {($ Id.VSub_DollarName '$DESIRED_SANDCATS_NAME')} right: {(Id.Lit_Other '^') (Id.Lit_Other '[') (0-9a-zA-Z-) (Id.Lit_Other ']') (Id.Lit_Other '{') (1) (Id.Lit_Other ',') (20) (Id.Lit_Other '}') (Id.Lit_Other '$') } ) ) ] negated: T ) terminator: (Token id:Id.Op_Semi val:';' span_id:12033) ) ] action: [ (C {(sandcats_register_name)}) (command.ControlFlow token: (Token id:Id.ControlFlow_Return val:return span_id:12041) ) ] spids: [12010 12035] ) ] ) (C {(echo)} { (DQ ( 'We need your email on file so we can help you recover your domain if you lose access. No spam.' ) ) } ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:SANDCATS_REGISTRATION_EMAIL) op: assign_op.Equal rhs: { (command_sub left_token: (Token id:Id.Left_DollarParen val:'$(' span_id:12064) command_list: (command.CommandList children: [(C {(prompt)} {(DQ ('Enter your email address:'))} {(DQ )})] ) ) } spids: [12063] ) ] ) (command.WhileUntil keyword: (Token id:Id.KW_While val:while span_id:12081) cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(DQ )} {(Id.Lit_Equals '=')} {(DQ ($ Id.VSub_DollarName '$SANDCATS_REGISTRATION_EMAIL'))} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:12096) ) ] body: (command.DoGroup children: [ (C {(echo)} { (DQ ( 'For the DNS service, we really do need an email address. To cancel, type: Ctrl-C.' ) ) } ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:SANDCATS_REGISTRATION_EMAIL) op: assign_op.Equal rhs: { (command_sub left_token: (Token id: Id.Left_DollarParen val: '$(' span_id: 12109 ) command_list: (command.CommandList children: [ (C {(prompt)} {(DQ ('Enter your email address:'))} {(DQ )}) ] ) ) } spids: [12108] ) ] ) ] ) ) (C {(echo)} {(DQ ('Registering your domain.'))}) (C {(local)} {(LOG_PATH)}) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:LOG_PATH) op: assign_op.Equal rhs: {(DQ (var/sandcats/register-log))} spids: [12137] ) ] ) (C {(touch)} {(DQ ($ Id.VSub_DollarName '$LOG_PATH'))}) (C {(chmod)} {(0640)} {(DQ ($ Id.VSub_DollarName '$LOG_PATH'))}) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:HTTP_STATUS) op: assign_op.Equal rhs: { (command_sub left_token: (Token id:Id.Left_DollarParen val:'$(' span_id:12160) command_list: (command.CommandList children: [ (C {(dotdotdot_curl)} {(--silent)} {(--max-time)} {(20)} {($ Id.VSub_DollarName '$SANDCATS_CURL_PARAMS')} {(-A)} {(DQ ($ Id.VSub_DollarName '$CURL_USER_AGENT'))} {(-X)} {(POST)} {(--data-urlencode)} { (DQ ('rawHostname=') ($ Id.VSub_DollarName '$DESIRED_SANDCATS_NAME') ) } {(--data-urlencode)} {(DQ ('email=') ($ Id.VSub_DollarName '$SANDCATS_REGISTRATION_EMAIL'))} {(--output)} {(DQ ($ Id.VSub_DollarName '$LOG_PATH'))} {(-w)} { (SQ (Token id: Id.Lit_Chars val: '%{http_code}' span_id: 12224 ) ) } {(-H)} {(SQ (Token id:Id.Lit_Chars val:'X-Sand: cats' span_id:12232))} {(-H)} {(DQ ('Accept: text/plain'))} {(--cert)} {(var/sandcats/id_rsa.private_combined)} {(DQ (${ Id.VSub_Name SANDCATS_API_BASE) (/register))} ) ] ) ) } spids: [12159] ) ] ) (command.If arms: [ (if_arm cond: [ (C {(Id.Lit_LBracket '[')} {(DQ (200))} {(Id.Lit_Equals '=')} {(DQ ($ Id.VSub_DollarName '$HTTP_STATUS'))} {(Id.Lit_RBracket ']')} ) ] action: [ (C {(cat)} {(DQ ($ Id.VSub_DollarName '$LOG_PATH'))}) (C {(echo)} {(SQ )}) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:SS_HOSTNAME) op: assign_op.Equal rhs: { (DQ (${ Id.VSub_Name DESIRED_SANDCATS_NAME) (.) (${ Id.VSub_Name SANDCATS_BASE_DOMAIN) ) } spids: [12314] ) ] ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:USE_EXTERNAL_INTERFACE) op: assign_op.Equal rhs: {(DQ (yes))} spids: [12326] ) ] ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:SANDCATS_SUCCESSFUL) op: assign_op.Equal rhs: {(DQ (yes))} spids: [12332] ) ] ) (C {(echo)} { (DQ ('Congratulations! We have registered your ') (${ Id.VSub_Name DESIRED_SANDCATS_NAME) (.) (${ Id.VSub_Name SANDCATS_BASE_DOMAIN) (' name.') ) } ) (C {(echo)} { (DQ ('Your credentials to use it are in ') (command_sub left_token: (Token id:Id.Left_DollarParen val:'$(' span_id:12357) command_list: (command.CommandList children: [(C {(readlink)} {(-f)} {(var/sandcats)})] ) ) ('; consider making a backup.') ) } ) ] spids: [12261 12278] ) ] else_action: [ (C {(error)} { (DQ (command_sub left_token: (Token id:Id.Left_DollarParen val:'$(' span_id:12378) command_list: (command.CommandList children: [(C {(cat)} {(DQ ($ Id.VSub_DollarName '$LOG_PATH'))})] ) ) ) } ) (C {(sandcats_register_name)}) (command.ControlFlow token: (Token id:Id.ControlFlow_Return val:return span_id:12391) ) ] ) ] ) ) (command.ShFunction name: sandcats_configure_https body: (command.BraceGroup children: [ (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(DQ (yes))} {(Id.KW_Bang '!') (Id.Lit_Equals '=')} {(DQ ($ Id.VSub_DollarName '$SANDCATS_GETCERTIFICATE'))} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:12431) ) ] action: [ (command.ControlFlow token: (Token id:Id.ControlFlow_Return val:return span_id:12436) ) ] spids: [12414 12433] ) ] ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(DQ (yes))} {(Id.KW_Bang '!') (Id.Lit_Equals '=')} {(DQ ($ Id.VSub_DollarName '$SANDCATS_SUCCESSFUL'))} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:12464) ) ] action: [ (command.ControlFlow token: (Token id:Id.ControlFlow_Return val:return span_id:12469) ) ] spids: [12447 12466] ) ] ) (C {(echo)} {(DQ ("Now we're going to auto-configure HTTPS for your server."))}) (C {(echo)} {(DQ )}) (C {(echo)} {(DQ ('* This will take about 30 seconds, and needs no input from you.'))} ) (C {(echo)} {(DQ ('* Thanks to GlobalSign for their help making this happen.'))}) (C {(echo)} {(DQ )}) (C {(local)} {(Id.Lit_VarLike 'HTTPS_BASE_DIR=') (DQ (var/sandcats/https))}) (C {(local)} {(Id.Lit_VarLike 'HTTPS_CONFIG_DIR=') (DQ ($ Id.VSub_DollarName '$HTTPS_BASE_DIR') (/) ($ Id.VSub_DollarName '$SS_HOSTNAME') ) } ) (C {(mkdir)} {(-p)} {(-m)} {(0700)} {(DQ ($ Id.VSub_DollarName '$HTTPS_CONFIG_DIR'))}) (C {(chmod)} {(0700)} {(DQ ($ Id.VSub_DollarName '$HTTPS_CONFIG_DIR'))}) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(DQ (yes))} {(Id.Lit_Equals '=')} {(DQ ($ Id.VSub_DollarName '$CURRENTLY_UID_ZERO'))} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:12615) ) ] action: [ (C {(chown)} {(-R)} {(DQ ($ Id.VSub_DollarName '$SERVER_USER')) (Id.Lit_Other ':') (DQ ($ Id.VSub_DollarName '$SERVER_USER')) } {(DQ ($ Id.VSub_DollarName '$HTTPS_BASE_DIR'))} ) ] spids: [12599 12617] ) ] ) (C {(echo)} {(DQ ('Generating certificate request...'))}) (command.Simple words: [ {(openssl)} {(req)} {(command_sub left_token:(Token id:Id.Left_Backtick val:'`' span_id:12678) command_list:(command.NoOp))} {(-nodes)} {(command_sub left_token:(Token id:Id.Left_Backtick val:'`' span_id:12689) command_list:(command.NoOp))} {(-newkey)} {(rsa) (Id.Lit_Other ':') (4096)} {(command_sub left_token:(Token id:Id.Left_Backtick val:'`' span_id:12704) command_list:(command.NoOp))} {(command_sub left_token:(Token id:Id.Left_Backtick val:'`' span_id:12713) command_list:(command.NoOp))} {(-subj)} {(DQ ('/CN=*.') (${ Id.VSub_Name SS_HOSTNAME) (/))} {(-keyout)} {(DQ ($ Id.VSub_DollarName '$HTTPS_CONFIG_DIR')) (/0)} {(command_sub left_token:(Token id:Id.Left_Backtick val:'`' span_id:12741) command_list:(command.NoOp))} {(-out)} {(DQ ($ Id.VSub_DollarName '$HTTPS_CONFIG_DIR')) (/0.csr)} {(command_sub left_token:(Token id:Id.Left_Backtick val:'`' span_id:12757) command_list:(command.NoOp))} {(command_sub left_token:(Token id:Id.Left_Backtick val:'`' span_id:12769) command_list:(command.NoOp))} ] redirects: [ (redir.Redir op: (Token id:Id.Redir_Great val:'2>' span_id:12766) fd: 2 arg_word: {(/dev/null)} ) ] ) (C {(chmod)} {(0600)} {(DQ ($ Id.VSub_DollarName '$HTTPS_CONFIG_DIR')) (/0)}) (C {(chmod)} {(0600)} {(DQ ($ Id.VSub_DollarName '$HTTPS_CONFIG_DIR')) (/0.csr)}) (C {(echo)} {(DQ ('Requesting certificate (BE PATIENT)...'))}) (C {(local)} {(LOG_PATH)}) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:LOG_PATH) op: assign_op.Equal rhs: {(DQ ($ Id.VSub_DollarName '$HTTPS_CONFIG_DIR') (/0.response-json))} spids: [12835] ) ] ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:HTTP_STATUS) op: assign_op.Equal rhs: { (command_sub left_token: (Token id:Id.Left_DollarParen val:'$(' span_id:12843) command_list: (command.CommandList children: [ (C {(dotdotdot_curl)} {(--silent)} {(--max-time)} {(60)} {($ Id.VSub_DollarName '$SANDCATS_CURL_PARAMS')} {(-A)} {(DQ ($ Id.VSub_DollarName '$CURL_USER_AGENT'))} {(-X)} {(POST)} {(--data-urlencode)} { (DQ ('rawHostname=') ($ Id.VSub_DollarName '$DESIRED_SANDCATS_NAME') ) } {(--data-urlencode)} { (DQ ('certificateSigningRequest=') (command_sub left_token: (Token id: Id.Left_DollarParen val: '$(' span_id: 12891 ) command_list: (command.CommandList children: [ (C {(cat)} { (DQ ($ Id.VSub_DollarName '$HTTPS_CONFIG_DIR') (/0.csr) ) } ) ] ) ) ) } {(--output)} {(DQ ($ Id.VSub_DollarName '$LOG_PATH'))} {(-w)} { (SQ (Token id: Id.Lit_Chars val: '%{http_code}' span_id: 12914 ) ) } {(-H)} {(SQ (Token id:Id.Lit_Chars val:'X-Sand: cats' span_id:12922))} {(--cert)} {(var/sandcats/id_rsa.private_combined)} { (DQ (${ Id.VSub_Name SANDCATS_API_BASE) (/) (braced_var_sub token: (Token id: Id.VSub_Name val: OVERRIDE_SANDCATS_GETCERTIFICATE_API_PATH span_id: 12939 ) suffix_op: (suffix_op.Unary op_id: Id.VTest_ColonHyphen arg_word: {(getcertificate)} ) ) ) } ) ] ) ) } spids: [12842] ) ] ) (C {(chmod)} {(0600)} {(DQ ($ Id.VSub_DollarName '$LOG_PATH'))}) (C {(chown)} {(DQ ($ Id.VSub_DollarName '$SERVER_USER')) (Id.Lit_Other ':') (DQ ($ Id.VSub_DollarName '$SERVER_USER')) } {(DQ ($ Id.VSub_DollarName '$HTTPS_CONFIG_DIR') (/)) (Id.Lit_Star '*')} ) (command.If arms: [ (if_arm cond: [ (C {(Id.Lit_LBracket '[')} {(DQ (200))} {(Id.Lit_Equals '=')} {(DQ ($ Id.VSub_DollarName '$HTTP_STATUS'))} {(Id.Lit_RBracket ']')} ) ] action: [ (C {(echo)} {(DQ ('Successfully auto-configured HTTPS!'))}) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:SANDCATS_HTTPS_SUCCESSFUL) op: assign_op.Equal rhs: {(DQ (yes))} spids: [13019] ) ] ) ] spids: [12980 12997] ) ] else_action: [ (C {(error)} { (DQ ( 'Some part of HTTPS autoconfiguration failed. Log data available in ' ) ($ Id.VSub_DollarName '$LOG_PATH') ) } ) (command.ControlFlow token: (Token id:Id.ControlFlow_Return val:return span_id:13040) ) ] ) ] ) ) (command.ShFunction name: wait_for_server_bind_to_its_port body: (command.BraceGroup children: [ (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(DQ (yes))} {(Id.KW_Bang '!') (Id.Lit_Equals '=')} {(DQ (${ Id.VSub_Name STARTED_SANDSTORM))} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:13078) ) ] action: [ (command.ControlFlow token: (Token id:Id.ControlFlow_Return val:return span_id:13083) ) ] spids: [13059 13080] ) ] ) (C {(local)} {(Id.Lit_VarLike 'PORT_TO_CHECK=') (DQ (braced_var_sub token: (Token id:Id.VSub_Name val:HTTPS_PORT span_id:13107) suffix_op: (suffix_op.Unary op_id: Id.VTest_ColonHyphen arg_word: {($ Id.VSub_DollarName '$PORT')} ) ) ) } ) (C {(echo)} {(-n)} {(DQ ('Your server is coming online. Waiting up to 90 seconds...'))} ) (C {(local)} {(Id.Lit_VarLike 'ONLINE_YET=') (DQ (no))}) (command.ForEach iter_name: waited_n_seconds iter_words: [ { (command_sub left_token: (Token id:Id.Left_DollarParen val:'$(' span_id:13137) command_list: (command.CommandList children:[(C {(seq)} {(0)} {(89)})]) ) } ] do_arg_iter: F body: (command.DoGroup children: [ (command.AndOr ops: [Id.Op_DAmp] children: [ (C {(is_port_bound)} {(DQ (${ Id.VSub_Name BIND_IP))} {(DQ (${ Id.VSub_Name PORT_TO_CHECK))} ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:ONLINE_YET) op: assign_op.Equal rhs: {(DQ (yes))} spids: [13165] ) ] ) ] ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(DQ ($ Id.VSub_DollarName '$ONLINE_YET'))} {(Id.Lit_Equals '=') (Id.Lit_Equals '=')} {(DQ (yes))} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:13188) ) ] action: [ (C {(echo)} {(SQ )}) (command.ControlFlow token: (Token id:Id.ControlFlow_Break val:break span_id:13199) ) ] spids: [13171 13190] ) ] ) (C {(echo)} {(-n)} {(DQ (.))}) (C {(sleep)} {(1)}) ] ) ) (command.AndOr ops: [Id.Op_DAmp] children: [ (C {(is_port_bound)} {(DQ (${ Id.VSub_Name BIND_IP))} {(DQ (${ Id.VSub_Name PORT_TO_CHECK))} ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:ONLINE_YET) op: assign_op.Equal rhs: {(DQ (yes))} spids: [13243] ) ] ) ] ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(DQ ($ Id.VSub_DollarName '$ONLINE_YET'))} {(Id.Lit_Equals '=') (Id.Lit_Equals '=')} {(DQ (yes))} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:13266) ) ] action: [ (command.ControlFlow token: (Token id:Id.ControlFlow_Return val:return span_id:13271) ) ] spids: [13250 13268] ) ] else_action: [ (C {(fail)} {(DQ (E_NEVER_LISTENED))} {(DQ ('Your server never started listening.'))} ) ] ) ] ) ) (command.ShFunction name: sandcats_generate_keys body: (command.BraceGroup children: [ (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(-f)} {(var/sandcats/id_rsa.private_combined)} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:13314) ) ] action: [ (command.ControlFlow token: (Token id:Id.ControlFlow_Return val:return span_id:13319) ) ] spids: [13304 13316] ) ] ) (C {(echo)} {(-n)} {(SQ (Token id:Id.Lit_Chars val:... span_id:13339))}) (C {(mkdir)} {(-p)} {(-m)} {(0700)} {(var/sandcats)}) (C {(chmod)} {(0700)} {(var/sandcats)}) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(DQ (yes))} {(Id.Lit_Equals '=')} {(DQ ($ Id.VSub_DollarName '$CURRENTLY_UID_ZERO'))} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:13395) ) ] action: [ (C {(chown)} {(DQ ($ Id.VSub_DollarName '$SERVER_USER')) (Id.Lit_Other ':') (DQ ($ Id.VSub_DollarName '$SERVER_USER')) } {(var/sandcats)} ) ] spids: [13379 13397] ) ] ) (command.Simple words: [ {(openssl)} {(req)} {(command_sub left_token:(Token id:Id.Left_Backtick val:'`' span_id:13435) command_list:(command.NoOp))} {(-new)} {(command_sub left_token:(Token id:Id.Left_Backtick val:'`' span_id:13446) command_list:(command.NoOp))} {(-newkey)} {(rsa) (Id.Lit_Other ':') (4096)} {(command_sub left_token:(Token id:Id.Left_Backtick val:'`' span_id:13461) command_list:(command.NoOp))} {(-days)} {(3650)} {(command_sub left_token:(Token id:Id.Left_Backtick val:'`' span_id:13474) command_list:(command.NoOp))} {(-nodes)} {(command_sub left_token:(Token id:Id.Left_Backtick val:'`' span_id:13485) command_list:(command.NoOp))} {(-x509)} {(command_sub left_token:(Token id:Id.Left_Backtick val:'`' span_id:13496) command_list:(command.NoOp))} {(command_sub left_token:(Token id:Id.Left_Backtick val:'`' span_id:13505) command_list:(command.NoOp))} {(command_sub left_token:(Token id:Id.Left_Backtick val:'`' span_id:13514) command_list:(command.NoOp))} {(-subj)} {(DQ ('/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd'))} {(-keyout)} {(var/sandcats/id_rsa)} {(command_sub left_token:(Token id:Id.Left_Backtick val:'`' span_id:13535) command_list:(command.NoOp))} {(-out)} {(var/sandcats/id_rsa.pub)} {(command_sub left_token:(Token id:Id.Left_Backtick val:'`' span_id:13548) command_list:(command.NoOp))} {(command_sub left_token:(Token id:Id.Left_Backtick val:'`' span_id:13560) command_list:(command.NoOp))} ] redirects: [ (redir.Redir op: (Token id:Id.Redir_Great val:'2>' span_id:13557) fd: 2 arg_word: {(/dev/null)} ) ] ) (command.Simple words: [{(cat)} {(var/sandcats/id_rsa)} {(var/sandcats/id_rsa.pub)}] redirects: [ (redir.Redir op: (Token id:Id.Redir_Great val:'>' span_id:13583) fd: -1 arg_word: {(var/sandcats/id_rsa.private_combined)} ) ] ) (C {(chmod)} {(0640)} {(var/sandcats/id_rsa)} {(var/sandcats/id_rsa.pub)} {(var/sandcats/id_rsa.private_combined)} ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (C {(Id.Lit_LBracket '[')} {(DQ (yes))} {(Id.Lit_Equals '=')} {(DQ ($ Id.VSub_DollarName '$CURRENTLY_UID_ZERO'))} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:13633) ) ] action: [ (C {(chown)} {(DQ ($ Id.VSub_DollarName '$SERVER_USER')) (Id.Lit_Other ':') (DQ ($ Id.VSub_DollarName '$SERVER_USER')) } (word.BracedTree parts: [ (var/sandcats/id_rsa) (word_part.BracedTuple words: [{} {(.pub)} {(.private_combined)}] ) ] ) ) ] spids: [13617 13635] ) ] ) (C {(echo)} {(-ne)} {(SQ (Token id:Id.Lit_Chars val:'\\r' span_id:13678))}) ] ) ) (C {(handle_args)} {(DQ ($ Id.VSub_At '$@'))}) (C {(set_umask)}) (C {(assert_on_terminal)}) (C {(assert_linux_x86_64)}) (C {(assert_usable_kernel)}) (C {(detect_current_uid)}) (C {(assert_dependencies)}) (C {(assert_valid_bundle_file)}) (C {(detect_init_system)}) (C {(choose_install_mode)}) (C {(maybe_enable_userns_sysctl)}) (C {(choose_external_or_internal)}) (C {(choose_install_dir)}) (C {(choose_smtp_port)}) (C {(load_existing_settings)}) (C {(choose_server_user_if_needed)}) (C {(create_server_user_if_needed)}) (C {(configure_auto_updates)}) (C {(configure_dev_accounts)}) (C {(configure_hostnames)}) (C {(save_config)}) (C {(download_latest_bundle_and_extract_if_needed)}) (C {(extract_bundle_if_provided)}) (C {(make_runtime_directories)}) (C {(generate_admin_token)}) (C {(set_permissions)}) (C {(install_sandstorm_symlinks)}) (C {(ask_about_starting_at_boot)}) (C {(configure_start_at_boot_if_desired)}) (C {(wait_for_server_bind_to_its_port)}) (C {(print_success)}) ] ) ) (C {(_)} {(DQ ($ Id.VSub_Number '$0'))} {(DQ ($ Id.VSub_At '$@'))}) ] )