@@ -67,6 +67,51 @@ static struct io_plan *read_more(struct io_conn *conn, struct reckless *rkls)
6767 & rkls -> stdout_new , read_more , rkls );
6868}
6969
70+ static void dup_listavailable_result (struct reckless * reckless ,
71+ struct json_stream * response ,
72+ char * reckless_result ,
73+ const jsmntok_t * results_tok )
74+ {
75+ json_array_start (response , "result" );
76+ size_t plugins , requirements ;
77+ const jsmntok_t * result , * requirement , * requirements_tok ;
78+ const char * plugin_name , * short_description , * long_description , * entrypoint ;
79+
80+ json_for_each_arr (plugins , result , results_tok ) {
81+ json_object_start (response , NULL );
82+
83+ json_scan (tmpctx , reckless_result , result ,
84+ "{name:%,"
85+ "short_description:%,"
86+ "long_description:%,"
87+ "entrypoint:%}" ,
88+ JSON_SCAN_TAL (tmpctx , json_strdup , & plugin_name ),
89+ JSON_SCAN_TAL (tmpctx , json_strdup , & short_description ),
90+ JSON_SCAN_TAL (tmpctx , json_strdup , & long_description ),
91+ JSON_SCAN_TAL (tmpctx , json_strdup , & entrypoint ));
92+
93+ json_add_string (response , "name" , plugin_name );
94+ if (!streq (short_description , "null" ))
95+ json_add_string (response , "short_description" , short_description );
96+ if (!streq (long_description , "null" ))
97+ json_add_string (response , "long_description" , long_description );
98+ json_add_string (response , "entypoint" , entrypoint );
99+
100+ json_array_start (response , "requirements" );
101+ requirements_tok = json_get_member (reckless_result , result , "requirements" );
102+ if (requirements_tok ) {
103+ json_for_each_arr (requirements , requirement , requirements_tok ) {
104+ json_add_string (response , NULL ,
105+ json_strdup (tmpctx , reckless_result , requirement ));
106+ }
107+ }
108+ json_array_end (response );
109+
110+ json_object_end (response );
111+ }
112+ json_array_end (response );
113+ }
114+
70115static struct command_result * reckless_result (struct io_conn * conn ,
71116 struct reckless * reckless )
72117{
@@ -78,19 +123,30 @@ static struct command_result *reckless_result(struct io_conn *conn,
78123 reckless -> process_failed );
79124 return command_finished (reckless -> cmd , response );
80125 }
81- const jsmntok_t * results , * result , * logs , * log , * conf ;
126+
127+ /* The reckless utility outputs utf-8 and ends the transmission with
128+ * \u0004, which jsmn is unable to parse. */
129+ size_t out_length = strlen (reckless -> stdoutbuf );
130+ char * trimmed ;
131+ trimmed = reckless -> stdoutbuf ;
132+ if (reckless -> stdoutbuf [out_length - 1 ] <= 0x07 ) {
133+ plugin_log (plugin , LOG_DBG , "trimming \\u%04x from reckless output" ,reckless -> stdoutbuf [out_length - 1 ]);
134+ trimmed = tal_strndup (tmpctx , reckless -> stdoutbuf , out_length - 1 );
135+ }
136+
137+ const jsmntok_t * results , * result , * logs , * log , * conf , * next ;
82138 size_t i ;
83139 jsmn_parser parser ;
84140 jsmntok_t * toks ;
85141 toks = tal_arr (reckless , jsmntok_t , 5000 );
86142 jsmn_init (& parser );
87143 int res ;
88- res = jsmn_parse (& parser , reckless -> stdoutbuf ,
89- strlen (reckless -> stdoutbuf ), toks , tal_count (toks ));
144+ res = jsmn_parse (& parser , trimmed ,
145+ strlen (trimmed ), toks , tal_count (toks ));
90146 const char * err ;
91147 if (res == JSMN_ERROR_INVAL )
92148 err = tal_fmt (tmpctx , "reckless returned invalid character in json "
93- "output" );
149+ "output. (total length %lu)" , strlen ( reckless -> stdoutbuf ) );
94150 else if (res == JSMN_ERROR_PART )
95151 err = tal_fmt (tmpctx , "reckless returned partial output" );
96152 else if (res == JSMN_ERROR_NOMEM )
@@ -100,39 +156,45 @@ static struct command_result *reckless_result(struct io_conn *conn,
100156 err = NULL ;
101157
102158 if (err ) {
103- plugin_log (plugin , LOG_UNUSUAL , "failed to parse json: %s" , err );
159+ if (res == JSMN_ERROR_INVAL )
160+ plugin_log (plugin , LOG_BROKEN , "invalid char in json" );
104161 response = jsonrpc_stream_fail (reckless -> cmd , PLUGIN_ERROR ,
105162 err );
106163 return command_finished (reckless -> cmd , response );
107164 }
108165
109166 response = jsonrpc_stream_success (reckless -> cmd );
110- results = json_get_member (reckless -> stdoutbuf , toks , "result" );
111- conf = json_get_member (reckless -> stdoutbuf , results , "requested_lightning_conf" );
167+ results = json_get_member (trimmed , toks , "result" );
168+ next = json_get_arr (results , 0 );
169+ conf = json_get_member (trimmed , results , "requested_lightning_conf" );
112170 if (conf ) {
113- plugin_log (plugin , LOG_DBG , "dealing with listconfigs output" );
171+ plugin_log (plugin , LOG_DBG , "ingesting listconfigs output" );
114172 json_object_start (response , "result" );
115173 json_for_each_obj (i , result , results ) {
116- json_add_tok (response , json_strdup (tmpctx , reckless -> stdoutbuf , result ), result + 1 , reckless -> stdoutbuf );
174+ json_add_tok (response , json_strdup (tmpctx , trimmed , result ), result + 1 , trimmed );
117175 }
118176 json_object_end (response );
119177
178+ } else if (next && next -> type == JSMN_OBJECT ) {
179+ plugin_log (plugin , LOG_DBG , "ingesting listavailable output" );
180+ dup_listavailable_result (reckless , response , trimmed , results );
181+
120182 } else {
121183 json_array_start (response , "result" );
122184 json_for_each_arr (i , result , results ) {
123185 json_add_string (response ,
124186 NULL ,
125- json_strdup (reckless , reckless -> stdoutbuf ,
187+ json_strdup (reckless , trimmed ,
126188 result ));
127189 }
128190 json_array_end (response );
129191 }
130192 json_array_start (response , "log" );
131- logs = json_get_member (reckless -> stdoutbuf , toks , "log" );
193+ logs = json_get_member (trimmed , toks , "log" );
132194 json_for_each_arr (i , log , logs ) {
133195 json_add_string (response ,
134196 NULL ,
135- json_strdup (reckless , reckless -> stdoutbuf ,
197+ json_strdup (reckless , trimmed ,
136198 log ));
137199 }
138200 json_array_end (response );
0 commit comments