From cf7dab016ea1f67a571252b601b3bbef6d31854e Mon Sep 17 00:00:00 2001 From: obarun <eric@obarun.org> Date: Tue, 30 Nov 2021 22:21:54 +1100 Subject: [PATCH] [WIP] adapt to new graph API. Add field requiredby. Add -o options --- src/66/66-inservice.c | 778 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 717 insertions(+), 61 deletions(-) diff --git a/src/66/66-inservice.c b/src/66/66-inservice.c index 8280fab0..334155f3 100644 --- a/src/66/66-inservice.c +++ b/src/66/66-inservice.c @@ -21,7 +21,6 @@ #include <oblibs/sastr.h> #include <oblibs/log.h> -#include <oblibs/obgetopt.h> #include <oblibs/types.h> #include <oblibs/string.h> #include <oblibs/files.h> @@ -33,6 +32,7 @@ #include <skalibs/bytestr.h> #include <skalibs/djbunix.h> #include <skalibs/buffer.h> +#include <skalibs/sgetopt.h> #include <66/info.h> #include <66/utils.h> @@ -65,6 +65,7 @@ static void info_display_version(char const *field, ss_resolve_t *res) ; static void info_display_source(char const *field, ss_resolve_t *res) ; static void info_display_live(char const *field, ss_resolve_t *res) ; static void info_display_deps(char const *field, ss_resolve_t *res) ; +static void info_display_requiredby(char const *field, ss_resolve_t *res) ; static void info_display_optsdeps(char const *field, ss_resolve_t *res) ; static void info_display_extdeps(char const *field, ss_resolve_t *res) ; static void info_display_start(char const *field, ss_resolve_t *res) ; @@ -77,6 +78,356 @@ static void info_display_logfile(char const *field, ss_resolve_t *res) ; ss_resolve_graph_style *STYLE = &graph_default ; + + + +#include <stdlib.h> //a garder + +#include <stdio.h>// a effacer + + + +#include <oblibs/graph.h> + + + + + + +typedef int ss_info_graph_func(char const *name, char const *obj) ; +typedef ss_info_graph_func *ss_info_graph_func_t_ref ; + +int ss_info_graph_display_service(char const *name, char const *obj) +{ + stralloc tree = STRALLOC_ZERO ; + ss_resolve_t res = RESOLVE_ZERO ; + + int r = ss_resolve_svtree(&tree, name, obj), err = 0 ; + + if (r != 2) { + if (r == 1) + log_warnu("find: ", name, " at tree: ", !obj ? tree.s : obj) ; + if (r > 2) + log_1_warn(name, " is set on different tree -- please use -t options") ; + + goto freed ; + } + + if (!ss_resolve_check(tree.s, name)) + goto freed ; + + if (!ss_resolve_read(&res, tree.s, name)) + goto freed ; + + char str_pid[UINT_FMT] ; + uint8_t pid_color = 0 ; + char *ppid ; + ss_state_t sta = STATE_ZERO ; + s6_svstatus_t status = S6_SVSTATUS_ZERO ; + + if (res.type == TYPE_CLASSIC || res.type == TYPE_LONGRUN) { + + s6_svstatus_read(res.sa.s + res.runat ,&status) ; + pid_color = !status.pid ? 1 : 2 ; + str_pid[uint_fmt(str_pid, status.pid)] = 0 ; + ppid = &str_pid[0] ; + + } else { + + char *ste = res.sa.s + res.state ; + char *name = res.sa.s + res.name ; + if (!ss_state_check(ste,name)) { + + ppid = "unitialized" ; + goto dis ; + } + + if (!ss_state_read(&sta,ste,name)) { + + log_warnu("read state of: ",name) ; + goto freed ; + } + if (sta.init) { + + ppid = "unitialized" ; + goto dis ; + + } else if (!sta.state) { + + ppid = "down" ; + pid_color = 1 ; + + } else if (sta.state) { + + ppid = "up" ; + pid_color = 2 ; + } + } + + dis: + + if (!bprintf(buffer_1,"(%s%s%s,%s%s%s,%s) %s", \ + + pid_color > 1 ? log_color->valid : pid_color ? log_color->error : log_color->warning, \ + ppid, \ + log_color->off, \ + + res.disen ? log_color->off : log_color->error, \ + res.disen ? "Enabled" : "Disabled", \ + log_color->off, \ + + get_key_by_enum(ENUM_TYPE,res.type), \ + + name)) + goto freed ; + + err = 1 ; + + freed: + ss_resolve_free(&res) ; + stralloc_free(&tree) ; + + return err ; + +} + +int ss_info_graph_display(char const *name, char const *obj, ss_info_graph_func *func, depth_t *depth, int last, int padding, ss_resolve_graph_style *style) +{ + log_flow() ; + + int level = 1 ; + + const char *tip = "" ; + + tip = last ? style->last : style->tip ; + + while(depth->prev) + depth = depth->prev ; + + while(depth->next) + { + if (!bprintf(buffer_1,"%*s%-*s",style->indent * (depth->level - level) + (level == 1 ? padding : 0), "", style->indent, style->limb)) + return 0 ; + + level = depth->level + 1 ; + depth = depth->next ; + } + + if (!bprintf(buffer_1,"%*s%*s%s", \ + level == 1 ? padding : 0,"", \ + style->indent * (depth->level - level), "", \ + tip)) return 0 ; + + int r = (*func)(name, obj) ; + if (!r) return 0 ; + if (buffer_putsflush(buffer_1,"\n") < 0) + return 0 ; + + return 1 ; +} + +/** make a list of edge ordered by start order + * Return the number of edge on success + * Return -1 on fail */ +int ss_info_walk_edge(stralloc *sa, graph_t *g, char const *name, uint8_t requiredby) +{ + + size_t pos = 0 ; + int count = -1 ; + + stralloc tmp = STRALLOC_ZERO ; + stralloc vertex = STRALLOC_ZERO ; + graph_t gc = GRAPH_ZERO ; + + count = graph_matrix_get_edge_g(&vertex, g, name, requiredby) ; + + if (count <= 0) { + count = 0 ; + goto freed ; + } + + FOREACH_SASTR(&vertex, pos) { + + char *ename = vertex.s + pos ; + + if (!graph_vertex_add(&gc, ename)) { + + log_warnu("add vertex: ",ename) ; + goto freed ; + } + + sa->len = 0 ; + + unsigned int c = graph_matrix_get_edge_g(sa, g, ename, requiredby) ; + + if (c == -1) + { count = -1 ; goto freed ; } + + { + size_t bpos = 0 ; + + FOREACH_SASTR(sa, bpos) { + + char *edge = sa->s + bpos ; + + if (!graph_vertex_add_with_edge(&gc, ename, edge)) { + + log_warnu("add edge: ",ename," to vertex: ", edge) ; + goto freed ; + } + + if (!graph_vertex_add(&gc, edge)) { + + log_warnu("add vertex: ",edge) ; + goto freed ; + } + } + } + + if (!sastr_add_string(&tmp, ename)) + { count = -1 ; goto freed ; } ; + } + + if (!graph_matrix_build(&gc)) { + + log_warnu("build the matrix") ; + goto freed ; + } + + if (!graph_matrix_analyze_cycle(&gc)) { + log_warnu("found cycle") ; + goto freed ; + } + if (!graph_matrix_sort(&gc)) { + + log_warnu("sort the matrix") ; + goto freed ; + } + + count = sa->len = pos = 0 ; + + for(; pos < gc.sort_count ; pos++) { + + char *name = gc.data.s + genalloc_s(graph_hash_t,&gc.hash)[gc.sort[pos]].vertex ; + + if (sastr_find(&tmp, name) >= 0) { + count++ ; + if (!sastr_add_string(sa, name)) + { count = -1 ; goto freed ; } + } + } + + freed: + stralloc_free(&vertex) ; + stralloc_free(&tmp) ; + graph_free_all(&gc) ; + + return count ; +} + +int ss_info_walk(graph_t *g, char const *name, char const *obj, ss_info_graph_func *func, uint8_t requiredby, uint8_t reverse, depth_t *depth, int padding, ss_resolve_graph_style *style) +{ + log_flow() ; + + uint8_t e = 0 ; + + if ((unsigned int) depth->level > MAXDEPTH) + return 1 ; + + stralloc vertex = STRALLOC_ZERO ; + stralloc edge = STRALLOC_ZERO ; + + int count = ss_info_walk_edge(&vertex, g, name, requiredby) ; + + if (count == -1) goto err ; + + if (!vertex.len) + goto freed ; + + size_t pos = 0 ; + int idx = 0; + + if (reverse) + if (!sastr_reverse(&vertex)) + goto err ; + + for (; pos < vertex.len ; pos += strlen(vertex.s + pos) + 1, idx++ ) { + + int last = idx + 1 < count ? 0 : 1 ; + char *name = vertex.s + pos ; + + if (!ss_info_graph_display(name, obj, func, depth, last, padding, style)) + goto err ; + + edge.len = 0 ; + + if (ss_info_walk_edge(&edge, g, name, requiredby) == -1) + goto err ; + + if (edge.len) + { + depth_t d = + { + depth, + NULL, + depth->level + 1 + } ; + depth->next = &d; + + if(last) + { + if(depth->prev) + { + depth->prev->next = &d; + d.prev = depth->prev; + depth = &d; + + } + else + d.prev = NULL; + } + if (!ss_info_walk(g, name, obj, func, requiredby, reverse, &d, padding, style)) + goto err ; + depth->next = NULL ; + } + } + + freed: + e = 1 ; + + err: + stralloc_free(&vertex) ; + stralloc_free(&edge) ; + + return e ; + +} + +depth_t ss_info_graph_init(void) +{ + log_flow() ; + + depth_t d = { + NULL, + NULL, + 1 + } ; + + return d ; +} + + + + + + + + + + + + + info_opts_map_t const opts_sv_table[] = { { .str = "name", .svfunc = &info_display_name, .id = 0 }, @@ -88,19 +439,20 @@ info_opts_map_t const opts_sv_table[] = { .str = "source", .svfunc = &info_display_source, .id = 6 }, { .str = "live", .svfunc = &info_display_live, .id = 7 }, { .str = "depends", .svfunc = &info_display_deps, .id = 8 }, - { .str = "extdepends", .svfunc = &info_display_extdeps, .id = 9 }, - { .str = "optsdepends", .svfunc = &info_display_optsdeps, .id = 10 }, - { .str = "start", .svfunc = &info_display_start, .id = 11 }, - { .str = "stop", .svfunc = &info_display_stop, .id = 12 }, - { .str = "envat", .svfunc = &info_display_envat, .id = 13 }, - { .str = "envfile", .svfunc = &info_display_envfile, .id = 14 }, - { .str = "logname", .svfunc = &info_display_logname, .id = 15 }, - { .str = "logdst", .svfunc = &info_display_logdst, .id = 16 }, - { .str = "logfile", .svfunc = &info_display_logfile, .id = 17 }, + { .str = "requiredby", .svfunc = &info_display_requiredby, .id = 9 }, + { .str = "extdepends", .svfunc = &info_display_extdeps, .id = 10 }, + { .str = "optsdepends", .svfunc = &info_display_optsdeps, .id = 11 }, + { .str = "start", .svfunc = &info_display_start, .id = 12 }, + { .str = "stop", .svfunc = &info_display_stop, .id = 13 }, + { .str = "envat", .svfunc = &info_display_envat, .id = 14 }, + { .str = "envfile", .svfunc = &info_display_envfile, .id = 15 }, + { .str = "logname", .svfunc = &info_display_logname, .id = 16 }, + { .str = "logdst", .svfunc = &info_display_logdst, .id = 17 }, + { .str = "logfile", .svfunc = &info_display_logfile, .id = 18 }, { .str = 0, .svfunc = 0, .id = -1 } } ; -#define MAXOPTS 19 +#define MAXOPTS 20 #define checkopts(n) if (n >= MAXOPTS) log_die(LOG_EXIT_USER, "too many options") #define DELIM ',' @@ -124,7 +476,7 @@ static inline void info_help (void) " -t: only search service at the specified tree\n" " -p: print n last lines of the log file\n" "\n" -"valid field for -o options are:\n" +"valid fields for -o options are:\n" "\n" " name: displays the name\n" " version: displays the version of the service\n" @@ -135,6 +487,7 @@ static inline void info_help (void) " source: displays the source of the service's frontend file\n" " live: displays the service's live directory\n" " depends: displays the service's dependencies\n" +" requiredby: displays the service(s) which depends on service\n" " extdepends: displays the service's external dependencies\n" " optsdepends: displays the service's optional dependencies\n" " start: displays the service's start script\n" @@ -320,74 +673,371 @@ static void info_display_live(char const *field,ss_resolve_t *res) info_display_string(res->sa.s + res->runat) ; } -static void info_display_deps(char const *field, ss_resolve_t *res) + +/* +int graph_service_compute_deps(stralloc *deps, char const *str) { - int r ; - size_t padding = 1, pos = 0, el ; - ss_resolve_t gres = RESOLVE_ZERO ; - ss_resolve_graph_t graph = RESOLVE_GRAPH_ZERO ; - stralloc salist = STRALLOC_ZERO ; + stralloc tmp = STRALLOC_ZERO ; + size_t pos = 0 ; + + if (!sastr_clean_string(&tmp,str)) + log_warnu_return(LOG_EXIT_ZERO,"rebuild dependencies list") ; + + FOREACH_SASTR(&tmp,pos) { + + if (!sastr_add_string(deps, tmp.s + pos)) + return 0 ; + } + + stralloc_free(&tmp) ; + + return 1 ; +} +*/ + +int graph_service_add_deps(graph_t *g, char const *service, char const *sdeps) +{ + stralloc deps = STRALLOC_ZERO ; + uint8_t e = 0 ; + if (!sastr_clean_string(&deps,sdeps)) { + log_warnu("rebuild dependencies list") ; + goto freed ; + } + + if (!graph_vertex_add_with_nedge(g, service, &deps)) { + log_warnu("add edges at vertex: ", service) ; + goto freed ; + } + + e = 1 ; + freed: + stralloc_free(&deps) ; + + return e ; +} + + +void ss_graph_matrix_add_classic(graph_t *g, genalloc *gares) +{ + size_t pos = 0, bpos = 0, ccount = 0 ; + size_t cl[SS_MAX_SERVICE] ; + + for (; pos < genalloc_len(ss_resolve_t, gares) ; pos++) { + + ss_resolve_t_ref res = &genalloc_s(ss_resolve_t, gares)[pos] ; + + if (res->type == TYPE_CLASSIC) { + + cl[ccount++] = pos ; + + } + } + + if (ccount) { + + for (pos = 0 ; pos < ccount ; pos++) { + + char *str = genalloc_s(ss_resolve_t, gares)[cl[pos]].sa.s ; + char *sv = str + genalloc_s(ss_resolve_t, gares)[cl[pos]].name ; + + graph_array_reverse(g->sort, g->sort_count) ; + + for (bpos = 0 ; bpos < g->sort_count ; bpos++) { + + char *service = g->data.s + genalloc_s(graph_hash_t,&g->hash)[g->sort[bpos]].vertex ; + + int idx = ss_resolve_search(gares, service) ; + if (genalloc_s(ss_resolve_t, gares)[idx].type == TYPE_CLASSIC || + !strcmp(service, sv)) + continue ; + + if (!graph_edge_add_g(g, service, sv)) + log_die(LOG_EXIT_SYS,"add edge: ", sv, " at vertex: ", service) ; + + graph_free_matrix(g) ; + graph_free_sort(g) ; + + if (!graph_matrix_build(g)) { + graph_free_all(g) ; + log_dieu(LOG_EXIT_SYS,"build the graph") ; + } + + if (!graph_matrix_analyze_cycle(g)) + log_die(LOG_EXIT_SYS,"found cycle") ; + } + + graph_array_reverse(g->sort, g->sort_count) ; + } + } + +} + +/** what = 0 -> only classic + * what = 1 -> only atomic + * what = 2 -> both + * @Return 0 on fail + * + * This function append the logger to @gares is case of classic service. */ +int ss_tree_get_sv_resolve(genalloc *gares, char const *dir, uint8_t what) +{ + log_flow() ; + + stralloc sa = STRALLOC_ZERO ; + ss_resolve_t res = RESOLVE_ZERO ; + ss_resolve_t reslog = RESOLVE_ZERO ; + + int e = 0 ; + size_t dirlen = strlen(dir), pos = 0 ; + + char solve[dirlen + SS_RESOLVE_LEN + 1] ; + + auto_strings(solve, dir, SS_RESOLVE) ; + + char const *exclude[2] = { SS_MASTER + 1, 0 } ; + if (!sastr_dir_get(&sa,solve,exclude,S_IFREG)) + goto err ; + + FOREACH_SASTR(&sa, pos) { + + char *name = sa.s + pos ; + + if (!ss_resolve_check(dir,name)) + goto err ; + + if (!ss_resolve_read(&res,dir,name)) + goto err ; + + if (ss_resolve_search(gares,name) == -1) { + + if ((!what || what == 2) && (res.type == TYPE_CLASSIC)) { + + if (res.logger) { + + if (!ss_resolve_read(&reslog, dir, res.sa.s + res.logger)) + goto err ; + + if (ss_resolve_search(gares,res.sa.s + res.logger) == -1) { + + if (!ss_resolve_append(gares,&reslog)) + goto err ; + } + } + + if (!ss_resolve_append(gares,&res)) + goto err ; + + continue ; + } + + if (what) { + + if (!ss_resolve_append(gares,&res)) + goto err ; + } + } + } + + e = 1 ; + err: + stralloc_free(&sa) ; + ss_resolve_free(&res) ; + ss_resolve_free(&reslog) ; + return e ; +} + +/** @tree: absolute path of the tree*/ +static void ss_graph_matrix_build_bytree(graph_t *g, char const *tree, uint8_t what) +{ + stralloc services = STRALLOC_ZERO ; + stralloc deps = STRALLOC_ZERO ; genalloc gares = GENALLOC_ZERO ; + size_t treelen = strlen(tree), pos = 0 ; + char src[treelen + SS_SVDIRS_LEN + 1] ; + + auto_strings(src, tree, SS_SVDIRS) ; + + if (!ss_tree_get_sv_resolve(&gares, src, what)) + log_dieu(LOG_EXIT_SYS,"get resolve files of tree: ", tree) ; + + if (genalloc_len(ss_resolve_t, &gares) >= SS_MAX_SERVICE) + log_die(LOG_EXIT_SYS, "too many services to handle") ; + + pos = 0 ; + + for (; pos < genalloc_len(ss_resolve_t, &gares) ; pos++) { + + ss_resolve_t_ref res = &genalloc_s(ss_resolve_t, &gares)[pos] ; + + char *str = res->sa.s ; + + char *service = str + res->name ; + + if (!graph_vertex_add(g, service)) + log_dieu(LOG_EXIT_SYS,"add vertex: ", service) ; + + deps.len = 0 ; + + if (res->ndeps > 0) { + + if (res->type == TYPE_MODULE || res->type == TYPE_BUNDLE) { + + uint32_t tdeps = res->type == TYPE_MODULE ? what > 1 ? res->contents : res->deps : res->deps ; + + if (!graph_service_add_deps(g, service, str + tdeps)) + log_dieu(LOG_EXIT_ZERO,"add dependencies of service: ",service) ; + + } else { + + if (!graph_service_add_deps(g, service,str + res->deps)) + log_dieu(LOG_EXIT_ZERO,"add dependencies of service: ",service) ; + + } + } + } + + + if (!graph_matrix_build(g)) + log_dieu(LOG_EXIT_SYS,"build the graph") ; + + if (!graph_matrix_analyze_cycle(g)) + log_die(LOG_EXIT_SYS,"found cycle") ; + + if (!graph_matrix_sort(g)) + log_dieu(LOG_EXIT_SYS,"sort the graph") ; + + if (!what || what == 2) + ss_graph_matrix_add_classic(g, &gares) ; + + stralloc_free(&services) ; + stralloc_free(&deps) ; +} + + + +static void info_display_requiredby(char const *field, ss_resolve_t *res) +{ + size_t padding = 1 ; + int r ; + graph_t graph = GRAPH_ZERO ; + if (NOFIELD) padding = info_display_field_name(field) ; else { field = 0 ; padding = 0 ; } - if (!res->ndeps) goto empty ; + /** + * + * + * ATTENTION A LA SORTIE D ERREUR + * + * */ - if (res->type == TYPE_MODULE) - { - if (!sastr_clean_string(&salist,res->sa.s + res->contents)) - log_dieu(LOG_EXIT_SYS,"rebuild dependencies list") ; + ss_graph_matrix_build_bytree(&graph, res->sa.s + res->tree, 2) ; - if (!ss_resolve_sort_bytype(&gares,&salist,src.s)) - log_dieu(LOG_EXIT_SYS,"sort list by type") ; - for (pos = 0 ; pos < genalloc_len(ss_resolve_t,&gares) ; pos++) - if (!ss_resolve_graph_build(&graph,&genalloc_s(ss_resolve_t,&gares)[pos],src.s,REVERSE)) - log_dieu(LOG_EXIT_SYS,"build the graph from: ",src.s) ; + unsigned int list[graph.mlen] ; + + int count = graph_matrix_get_requiredby(list, &graph, res->sa.s + res->name , 0) ; + + if (count == -1) + log_dieu(LOG_EXIT_SYS,"get requiredby for service: ", res->sa.s + res->name) ; + + if (!count) goto empty ; + + if (GRAPH) { + + if (!bprintf(buffer_1,"%s\n","/")) + log_dieusys(LOG_EXIT_SYS,"write to stdout") ; + + depth_t d = ss_info_graph_init() ; + + if (!ss_info_walk(&graph, res->sa.s + res->name, res->sa.s + res->treename, &ss_info_graph_display_service, 1, REVERSE, &d, padding, STYLE)) + log_dieu(LOG_EXIT_SYS,"display the requiredby graphic") ; + + return ; - r = ss_resolve_graph_publish(&graph,0) ; - if (r < 0) log_die(LOG_EXIT_USER,"cyclic graph detected") ; - else if (!r) log_dieusys(LOG_EXIT_SYS,"publish service graph") ; + } else { - salist.len = 0 ; - for (pos = 0 ; pos < genalloc_len(ss_resolve_t,&graph.sorted) ; pos++) + deps.len = 0 ; + r = ss_info_walk_edge(&deps,&graph, res->sa.s + res->name, 1) ; + if (r == -1) + log_dieu(LOG_EXIT_SYS, "get requiredby list") ; + + if (!r) + goto empty ; + + if (REVERSE) + if (!sastr_reverse(&deps)) + log_dieu(LOG_EXIT_SYS,"reverse dependencies list") ; + + info_display_list(field,&deps) ; + + return ; + } + + empty: + if (GRAPH) { - char *string = genalloc_s(ss_resolve_t,&graph.sorted)[pos].sa.s ; - char *name = string + genalloc_s(ss_resolve_t,&graph.sorted)[pos].name ; - if (!stralloc_catb(&salist,name,strlen(name)+1)) log_die_nomem("stralloc") ; + if (!bprintf(buffer_1,"%s\n","/")) + log_dieusys(LOG_EXIT_SYS,"write to stdout") ; + if (!bprintf(buffer_1,"%*s%s%s%s%s\n",padding, "", STYLE->last, log_color->warning,"None",log_color->off)) + log_dieusys(LOG_EXIT_SYS,"write to stdout") ; } - genalloc_deepfree(ss_resolve_t,&gares,ss_resolve_free) ; - ss_resolve_graph_free(&graph) ; - } - else { - if (!sastr_clean_string(&salist,res->sa.s + res->deps)) - log_dieu(LOG_EXIT_SYS,"rebuild dependencies list") ; - } + else + { + if (!bprintf(buffer_1,"%s%s%s\n",log_color->warning,"None",log_color->off)) + log_dieusys(LOG_EXIT_SYS,"write to stdout") ; + } +} + +static void info_display_deps(char const *field, ss_resolve_t *res) +{ + int r ; + size_t padding = 1 ; + graph_t graph = GRAPH_ZERO ; + + stralloc deps = STRALLOC_ZERO ; + + if (NOFIELD) padding = info_display_field_name(field) ; + else { field = 0 ; padding = 0 ; } + + ss_graph_matrix_build_bytree(&graph, res->sa.s + res->tree, 2) ; + + unsigned int list[graph.mlen] ; + + int count = graph_matrix_get_edge(list, &graph, res->sa.s + res->name , 0) ; + + if (count == -1) + log_dieu(LOG_EXIT_SYS,"get requiredby for service: ", res->sa.s + res->name) ; + + if (!count) goto empty ; if (GRAPH) { if (!bprintf(buffer_1,"%s\n","/")) log_dieusys(LOG_EXIT_SYS,"write to stdout") ; - el = sastr_len(&salist) ; - if (!sastr_rebuild_in_oneline(&salist)) log_dieu(LOG_EXIT_SYS,"rebuild dependencies list") ; + depth_t d = ss_info_graph_init() ; - ss_resolve_init(&gres) ; - gres.ndeps = el ; - gres.deps = ss_resolve_add_string(&gres,salist.s) ; - - if (!info_graph_init(&gres,src.s,REVERSE, padding, STYLE)) - log_dieu(LOG_EXIT_SYS,"display graph of: ",gres.sa.s + gres.name) ; + if (!ss_info_walk(&graph, res->sa.s + res->name, res->sa.s + res->treename, &ss_info_graph_display_service, 0, REVERSE, &d, padding, STYLE)) + log_dieu(LOG_EXIT_SYS,"display the dependencies graphic") ; goto freed ; } else { + deps.len = 0 ; + r = ss_info_walk_edge(&deps,&graph, res->sa.s + res->name, 0) ; + if (r == -1) + log_dieu(LOG_EXIT_SYS, "get requiredby list") ; + + if (!r) + goto empty ; + if (REVERSE) - if (!sastr_reverse(&salist)) + if (!sastr_reverse(&deps)) log_dieu(LOG_EXIT_SYS,"reverse dependencies list") ; - info_display_list(field,&salist) ; + info_display_list(field,&deps) ; + goto freed ; } empty: @@ -395,6 +1045,7 @@ static void info_display_deps(char const *field, ss_resolve_t *res) { if (!bprintf(buffer_1,"%s\n","/")) log_dieusys(LOG_EXIT_SYS,"write to stdout") ; + if (!bprintf(buffer_1,"%*s%s%s%s%s\n",padding, "", STYLE->last, log_color->warning,"None",log_color->off)) log_dieusys(LOG_EXIT_SYS,"write to stdout") ; } @@ -405,8 +1056,7 @@ static void info_display_deps(char const *field, ss_resolve_t *res) } freed: - ss_resolve_free(&gres) ; - stralloc_free(&salist) ; + stralloc_free(&deps) ; } static void info_display_with_source_tree(stralloc *list,ss_resolve_t *res) @@ -416,12 +1066,14 @@ static void info_display_with_source_tree(stralloc *list,ss_resolve_t *res) stralloc ntree = STRALLOC_ZERO ; stralloc src = STRALLOC_ZERO ; stralloc tmp = STRALLOC_ZERO ; + char const *exclude[3] = { SS_BACKUP + 1, SS_RESOLVE + 1, 0 } ; char *treename = 0 ; if (!auto_stra(&src,home.s)) log_die_nomem("stralloc") ; newlen = src.len ; - if (!sastr_dir_get(&ntree,home.s,SS_BACKUP + 1,S_IFDIR)) + + if (!sastr_dir_get(&ntree,home.s,exclude,S_IFDIR)) log_dieu(LOG_EXIT_SYS,"get list of trees of: ",home.s) ; for (pos = 0 ; pos < ntree.len ; pos += strlen(ntree.s + pos) + 1) @@ -433,7 +1085,9 @@ static void info_display_with_source_tree(stralloc *list,ss_resolve_t *res) if (!auto_stra(&src,treename,SS_SVDIRS,SS_RESOLVE)) log_die_nomem("stralloc") ; - if (!sastr_dir_get(&svlist,src.s,SS_MASTER + 1,S_IFREG)) + exclude[0] = SS_MASTER + 1 ; + exclude[1] = 0 ; + if (!sastr_dir_get(&svlist,src.s,exclude,S_IFREG)) log_dieu(LOG_EXIT_SYS,"get contents of tree: ",src.s) ; for (lpos = 0 ; lpos < list->len ; lpos += strlen(list->s + lpos) + 1) @@ -596,6 +1250,7 @@ static void info_display_envfile(char const *field,ss_resolve_t *res) stralloc sa = STRALLOC_ZERO ; stralloc salink = STRALLOC_ZERO ; stralloc list = STRALLOC_ZERO ; + char const *exclude[1] = { 0 } ; if (res->srconf) { @@ -613,7 +1268,7 @@ static void info_display_envfile(char const *field,ss_resolve_t *res) newlen = salink.len - 1 ; - if (!sastr_dir_get(&list,salink.s,"",S_IFREG)) + if (!sastr_dir_get(&list,salink.s,exclude,S_IFREG)) log_dieusys(LOG_EXIT_SYS,"get list of environment file from: ",src) ; if (!sastr_sort(&list)) @@ -852,6 +1507,7 @@ int main(int argc, char const *const *argv, char const *const *envp) "Source", "Live", "Dependencies", + "Required by", "External dependencies" , "Optional dependencies" , "Start script", @@ -868,9 +1524,9 @@ int main(int argc, char const *const *argv, char const *const *envp) for (;;) { - int opt = getopt_args(argc,argv, ">hzv:cno:grd:t:p:", &l) ; + int opt = subgetopt_r(argc,argv, "hzv:cno:grd:t:p:", &l) ; if (opt == -1) break ; - if (opt == -2) log_die(LOG_EXIT_USER,"options must be set first") ; + switch (opt) { case 'h' : info_help(); return 0 ; @@ -909,7 +1565,7 @@ int main(int argc, char const *const *argv, char const *const *envp) setlocale(LC_ALL, ""); - if(!str_diff(nl_langinfo(CODESET), "UTF-8")) { + if(!strcmp(nl_langinfo(CODESET), "UTF-8")) { STYLE = &graph_utf8; } if (!set_ownersysdir(&home,owner)) log_dieusys(LOG_EXIT_SYS, "set owner directory") ; -- GitLab