+ return NULL;
+}
+
+static int start_api(struct api_desc *api);
+
+/**
+ * Start the apis of the 'array'
+ */
+static int start_array_apis(struct api_array *array)
+{
+ int i, rc = 0, rc2;
+
+ i = 0;
+ while (i < array->count) {
+ rc2 = array->apis[i]->status;
+ if (rc2 == NOT_STARTED) {
+ rc2 = start_api(array->apis[i]);
+ if (rc2 < 0)
+ rc = rc2;
+ i = 0;
+ } else {
+ if (rc2)
+ rc = -1;
+ i++;
+ }
+ }
+ return rc;
+}
+
+/**
+ * Start the class 'cla' (start the apis that provide it).
+ */
+static int start_class(struct api_class *cla)
+{
+ return start_array_apis(&cla->providers);
+}
+
+/**
+ * Start the classes of the 'array'
+ */
+static int start_array_classes(struct api_array *array)
+{
+ int i, rc = 0, rc2;
+
+ i = array->count;
+ while (i) {
+ rc2 = start_class(array->classes[--i]);
+ if (rc2 < 0) {
+ rc = rc2;
+ }
+ }
+ return rc;
+}
+
+/**
+ * Start the depends of the 'array'
+ */
+static int start_array_depends(struct api_array *array)
+{
+ struct api_desc *api;
+ int i, rc = 0, rc2;
+
+ i = 0;
+ while (i < array->count) {
+ api = searchrec(array->depends[i]->set, array->depends[i]->name);
+ if (!api) {
+ rc = -1;
+ i++;
+ } else {
+ rc2 = api->status;
+ if (rc2 == NOT_STARTED) {
+ rc2 = start_api(api);
+ if (rc2 < 0)
+ rc = rc2;
+ i = 0;
+ } else {
+ if (rc2)
+ rc = -1;
+ i++;
+ }
+ }
+ }
+
+ return rc;
+}
+
+/**
+ * Starts the service 'api'.
+ * @param api the api
+ * @return zero on success, -1 on error
+ */
+static int start_api(struct api_desc *api)
+{
+ int rc;
+
+ if (api->status != NOT_STARTED) {
+ if (api->status > 0) {
+ errno = api->status;
+ return -1;
+ }
+ return 0;
+ }
+
+ NOTICE("API %s starting...", api->name);
+ api->status = EBUSY;
+ rc = start_array_classes(&api->require.classes);
+ if (rc < 0)
+ ERROR("Cannot start classes needed by api %s", api->name);
+ else {
+ rc = start_array_depends(&api->require.apis);
+ if (rc < 0)
+ ERROR("Cannot start apis needed by api %s", api->name);
+ else if (api->api.itf->service_start) {
+ rc = api->api.itf->service_start(api->api.closure);
+ if (rc < 0)
+ ERROR("The api %s failed to start", api->name);
+ }
+ }
+ if (rc < 0) {
+ api->status = errno ?: ECANCELED;
+ return -1;
+ }
+ INFO("API %s started", api->name);
+ api->status = 0;
+ return 0;
+}
+
+/**
+ * Get from the 'set' the API of 'name' in 'api'
+ * @param set the set of API
+ * @param name the name of the API to get
+ * @param rec if not zero look also recursively in subsets
+ * @return a pointer to the API item in case of success or NULL in case of error
+ */
+const struct afb_api_item *afb_apiset_lookup_started(struct afb_apiset *set, const char *name, int rec)
+{
+ struct api_desc *desc;
+
+ desc = lookup(set, name, rec);
+ if (!desc) {
+ errno = ENOENT;
+ return NULL;
+ }
+ if (start_api(desc)) {
+ errno = desc->status;
+ return NULL;
+ }
+ return &desc->api;