Newer
Older
* All rights reserved.
* This file is part of Obarun. It is subject to the license terms in
* the LICENSE file found in the top-level directory of this
* distribution.
* This file may not be copied, modified, propagated, or distributed
* except according to the terms contained in the LICENSE file./
*/
#include <string.h>
#include <locale.h>
#include <langinfo.h>
#include <sys/types.h>
#include <wchar.h>
#include <unistd.h>//access
#include <oblibs/sastr.h>
#include <oblibs/types.h>
#include <oblibs/string.h>
#include <skalibs/genalloc.h>
#include <skalibs/lolstdio.h>
#include <skalibs/bytestr.h>
#include <skalibs/buffer.h>
#include <66/info.h>
#include <66/constants.h>
#include <66/tree.h>
#include <66/enum.h>
#include <66/resolve.h>
#include <66/state.h>
static unsigned int REVERSE = 0 ;
static unsigned int NOFIELD = 1 ;
static unsigned int GRAPH = 0 ;
static wchar_t const field_suffix[] = L" :" ;

Eric Vidal
committed
static char fields[INFO_NKEY][INFO_FIELD_MAXLEN] = {{ 0 }} ;
static void info_display_name(char const *field,char const *treename) ;
static void info_display_current(char const *field,char const *treename) ;
static void info_display_enabled(char const *field,char const *treename) ;
//static void info_display_init(char const *field,char const *treename) ;
static void info_display_depends(char const *field,char const *treename) ;
static void info_display_requiredby(char const *field,char const *treename) ;
static void info_display_allow(char const *field,char const *treename) ;
static void info_display_contents(char const *field,char const *treename) ;
static void info_display_groups(char const *field,char const *treename) ;
static info_graph_style *T_STYLE = &graph_default ;
info_opts_map_t const opts_tree_table[] =
{
{ .str = "name", .func = &info_display_name, .id = 0 },
{ .str = "current", .func = &info_display_current, .id = 1 },
{ .str = "enabled", .func = &info_display_enabled, .id = 2 },
// { .str = "init", .func = &info_display_init, .id = 3 },
{ .str = "allowed", .func = &info_display_allow, .id = 3 },
{ .str = "groups", .func = &info_display_groups, .id = 4 },
{ .str = "depends", .func = &info_display_depends, .id = 5 },
{ .str = "requiredby", .func = &info_display_requiredby, .id = 6 },
{ .str = "contents", .func = &info_display_contents, .id = 7 },
#define checkopts(n) if (n >= MAXOPTS) log_die(LOG_EXIT_USER, "too many options")
#define DELIM ','
static void info_display_name(char const *field, char const *treename)
{
if (NOFIELD) info_display_field_name(field) ;
if (!bprintf(buffer_1,"%s",treename))
log_dieusys(LOG_EXIT_SYS,"write to stdout") ;
if (buffer_putsflush(buffer_1,"\n") == -1)
log_dieusys(LOG_EXIT_SYS,"write to stdout") ;
static void info_display_current(char const *field,char const *treename)
int current = tree_iscurrent(pinfo->base.s, treename) ;
if (current < 0)
log_dieu(LOG_EXIT_SYS, "read resolve file of: ", treename) ;
if (NOFIELD) info_display_field_name(field) ;
if (!bprintf(buffer_1,"%s%s%s", current ? log_color->valid : log_color->warning, current ? "yes":"no",log_color->off))
log_dieusys(LOG_EXIT_SYS,"write to stdout") ;
if (buffer_putsflush(buffer_1,"\n") == -1)
log_dieusys(LOG_EXIT_SYS,"write to stdout") ;
static void info_display_enabled(char const *field,char const *treename)
int enabled = tree_isenabled(pinfo->base.s, treename) ;
if (enabled < 0)
log_dieu(LOG_EXIT_SYS, "read resolve file of: ", treename) ;
if (NOFIELD) info_display_field_name(field) ;
if (!bprintf(buffer_1,"%s%s%s",enabled ? log_color->valid : log_color->warning, enabled ? "yes":"no",log_color->off))
log_dieusys(LOG_EXIT_SYS,"write to stdout") ;
if (buffer_putsflush(buffer_1,"\n") == -1)
log_dieusys(LOG_EXIT_SYS,"write to stdout") ;
static void info_display_init(char const *field,char const *treename)
it not possible to write the resolve file of a tree at boot
if the filesystem is ro. So consider tree as never initiated.
ssexec_{start,stop,free,...} will deal with the live state of
the services anyway.
unsigned int init = tree_isinitialized(pinfo->base.s, treename) ;
if (init == -1) log_dieu(LOG_EXIT_SYS, "resolve file of tree: ", treename) ;
if (NOFIELD) info_display_field_name(field) ;
if (!bprintf(buffer_1,"%s%s%s",init ? log_color->valid : log_color->warning, init ? "yes":"no",log_color->off))
log_dieusys(LOG_EXIT_SYS,"write to stdout") ;
if (buffer_putsflush(buffer_1,"\n") == -1)
log_dieusys(LOG_EXIT_SYS,"write to stdout") ;
static void info_display_allow(char const *field, char const *treename)
{
stralloc sa = STRALLOC_ZERO ;
resolve_tree_t tres = RESOLVE_TREE_ZERO ;
resolve_wrapper_t_ref wres = resolve_set_struct(DATA_TREE, &tres) ;
if (resolve_read_g(wres, pinfo->base.s, treename) <= 0)
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
log_dieusys(LOG_EXIT_SYS,"read resolve file of tree: ", treename) ;
if (NOFIELD)
info_display_field_name(field) ;
if (tres.nallow) {
if (!sastr_clean_string(&sa, tres.sa.s + tres.allow))
log_dieu(LOG_EXIT_SYS,"clean groups string") ;
if (!sa.len)
goto empty ;
size_t len = sa.len, pos = 0 ;
char t[len + 1] ;
sastr_to_char(t, &sa) ;
sa.len = 0 ;
for (; pos < len ; pos += strlen(t + pos) + 1) {
char *suid = t + pos ;
uid_t uid = 0 ;
if (!uid0_scan(suid, &uid))
log_dieusys(LOG_EXIT_SYS,"get uid of: ",suid) ;
if (pos)
if (!stralloc_cats(&sa," ")) log_die_nomem("stralloc") ;
if (!get_namebyuid(uid,&sa))
log_dieusys(LOG_EXIT_SYS, "get name of uid: ", suid) ;
}
if (!stralloc_0(&sa)) log_die_nomem("stralloc") ;
if (!sastr_rebuild_in_oneline(&sa)) log_dieu(LOG_EXIT_SYS,"rebuild list") ;
if (!stralloc_0(&sa)) log_die_nomem("stralloc") ;
info_display_list(field,&sa) ;
} else {
empty:
if (!bprintf(buffer_1,"%s%s%s\n",log_color->warning,"None",log_color->off))
log_dieusys(LOG_EXIT_SYS,"write to stdout") ;
}
resolve_free(wres) ;
stralloc_free(&sa) ;
}
static void info_display_groups(char const *field, char const *treename)
{
stralloc sa = STRALLOC_ZERO ;
resolve_tree_t tres = RESOLVE_TREE_ZERO ;
resolve_wrapper_t_ref wres = resolve_set_struct(DATA_TREE, &tres) ;
if (resolve_read_g(wres, pinfo->base.s, treename) <= 0)
log_dieusys(LOG_EXIT_SYS,"read resolve file of: ", treename) ;
if (NOFIELD)
info_display_field_name(field) ;
if (tres.ngroups) {
if (!sastr_clean_string(&sa, tres.sa.s + tres.groups))
log_dieu(LOG_EXIT_SYS,"clean groups string") ;
info_display_list(field,&sa) ;
} else {
if (!bprintf(buffer_1,"%s%s%s\n",log_color->warning,"None",log_color->off))
log_dieusys(LOG_EXIT_SYS,"write to stdout") ;
}
resolve_free(wres) ;
stralloc_free(&sa) ;
static void info_display_depends(char const *field, char const *treename)
size_t padding = 1 ;
graph_t graph = GRAPH_ZERO ;
stralloc sa = STRALLOC_ZERO ;
struct resolve_hash_tree_s *htres = NULL ;
if (NOFIELD) padding = info_display_field_name(field) ;
else { field = 0 ; padding = 0 ; }
graph_build_tree(&graph, &htres, pinfo->base.s, E_RESOLVE_TREE_MASTER_CONTENTS) ;
r = graph_matrix_get_edge_g_sorted_sa(&sa, &graph, treename, 0, 0) ;
if (r < 0)
log_dieu(LOG_EXIT_SYS, "get the dependencies list") ;
if (!r || !sa.len)
goto empty ;
if (GRAPH) {
if (!bprintf(buffer_1,"%s\n","\\"))
log_dieusys(LOG_EXIT_SYS,"write to stdout") ;
depth_t d = info_graph_init() ;
if (!info_walk(&graph, treename, 0, &info_graph_display_tree, 0, REVERSE, &d, padding, T_STYLE))
log_dieu(LOG_EXIT_SYS,"display the graph dependencies") ;
goto freed ;
} else {
if (REVERSE)
if (!sastr_reverse(&sa))
log_dieu(LOG_EXIT_SYS,"reverse the dependencies list") ;
info_display_list(field,&sa) ;
goto freed ;
}
empty:
if (GRAPH) {
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, "", T_STYLE->last, log_color->warning,"None",log_color->off))
log_dieusys(LOG_EXIT_SYS,"write to stdout") ;
} else {
if (!bprintf(buffer_1,"%s%s%s\n",log_color->warning,"None",log_color->off))
log_dieusys(LOG_EXIT_SYS,"write to stdout") ;
}
freed:
graph_free_all(&graph) ;
stralloc_free(&sa) ;
}
static void info_display_requiredby(char const *field, char const *treename)
{
int r ;
size_t padding = 1 ;
graph_t graph = GRAPH_ZERO ;
stralloc sa = STRALLOC_ZERO ;
struct resolve_hash_tree_s *htres = NULL ;
if (NOFIELD) padding = info_display_field_name(field) ;
else { field = 0 ; padding = 0 ; }
graph_build_tree(&graph, &htres, pinfo->base.s, E_RESOLVE_TREE_MASTER_CONTENTS) ;
r = graph_matrix_get_edge_g_sorted_sa(&sa, &graph, treename, 1, 0) ;
if (r < 0)
log_dieu(LOG_EXIT_SYS, "get the dependencies list") ;
if (!r || !sa.len)
goto empty ;
if (GRAPH) {
if (!bprintf(buffer_1,"%s\n","\\"))
log_dieusys(LOG_EXIT_SYS,"write to stdout") ;
depth_t d = info_graph_init() ;
if (!info_walk(&graph, treename, 0, &info_graph_display_tree, 1, REVERSE, &d, padding, T_STYLE))
log_dieu(LOG_EXIT_SYS,"display the graph dependencies") ;
goto freed ;
} else {
if (REVERSE)
if (!sastr_reverse(&sa))
log_dieu(LOG_EXIT_SYS,"reverse the dependencies list") ;
info_display_list(field,&sa) ;
goto freed ;
empty:
if (GRAPH) {
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, "", T_STYLE->last, log_color->warning,"None",log_color->off))
log_dieusys(LOG_EXIT_SYS,"write to stdout") ;
} else {
if (!bprintf(buffer_1,"%s%s%s\n",log_color->warning,"None",log_color->off))
log_dieusys(LOG_EXIT_SYS,"write to stdout") ;
}
freed:
graph_free_all(&graph) ;
stralloc_free(&sa) ;
static void info_display_contents(char const *field, char const *treename)
stralloc sa = STRALLOC_ZERO ;
struct resolve_hash_s *hres = NULL ;
if (NOFIELD) padding = info_display_field_name(field) ;
else { field = 0 ; padding = 0 ; }
if (!resolve_get_field_tosa_g(&sa, pinfo->base.s, treename, DATA_TREE, E_RESOLVE_TREE_CONTENTS))
log_dieu(LOG_EXIT_SYS, "get field contents of tree: ", treename) ;
if (!sa.len)
goto empty ;

Eric Vidal
committed
service_graph_g(sa.s, sa.len, &graph, &hres, pinfo, STATE_FLAGS_TOPROPAGATE|STATE_FLAGS_WANTUP) ;
if (!bprintf(buffer_1,"%s\n","\\"))
log_dieusys(LOG_EXIT_SYS,"write to stdout") ;
if (!info_walk(&graph, 0, 0, &info_graph_display_service, 0, REVERSE, &d, padding, T_STYLE))
log_dieu(LOG_EXIT_SYS,"display the graph dependencies") ;
log_dieu(LOG_EXIT_SYS,"reverse the dependencies list") ;
if (GRAPH) {
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, "", T_STYLE->last, log_color->warning,"None",log_color->off))
log_dieusys(LOG_EXIT_SYS,"write to stdout") ;
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_all(char const *treename,int *what)
{
unsigned int idx = what[i] ;
(*opts_tree_table[idx].func)(fields[opts_tree_table[idx].id],treename) ;
}
}
static void info_parse_options(char const *str,int *what)
{
_alloc_stk_(stk, strlen(str) + 1) ;
if (!lexer_trim_with_delim(&stk, str, DELIM))
log_dieu(LOG_EXIT_SYS,"parse options") ;
unsigned int nopts = 0 , old ;
checkopts(stk.count) ;
t = opts_tree_table ;
old = nopts ;
for (; t->str; t++) {
what[nopts++] = t->id ;
if (old == nopts)
log_die(LOG_EXIT_SYS,"invalid option: ",o) ;
int ssexec_tree_status(int argc, char const *const *argv, ssexec_t *info)
struct resolve_hash_tree_s *htres = NULL ;
char const *treename = 0 ;
for (int i = 0 ; i < MAXOPTS ; i++)
what[i] = -1 ;
char buf[MAXOPTS][INFO_FIELD_MAXLEN] = {
"Name",
"Current",
"Enabled",
"Groups",
"Depends",
"Required by",
subgetopt l = SUBGETOPT_ZERO ;
int opt = subgetopt_r(argc, argv, OPTS_TREE_STATUS, &l) ;
switch (opt)
{
case 'n' : NOFIELD = 0 ; break ;
case 'o' : legacy = 0 ; info_parse_options(l.arg,what) ; break ;
case 'g' : GRAPH = 1 ; break ;
case 'r' : REVERSE = 1 ; break ;
case 'd' : if (!uint0_scan(l.arg, &MAXDEPTH)) log_usage(info->usage, "\n", info->help) ; break ;
default : log_usage(info->usage, "\n", info->help) ;
}
}
argc -= l.ind ; argv += l.ind ;
}
if (argv[0]) treename = argv[0] ;
unsigned int i = 0 ;
for (; i < MAXOPTS - 1 ; i++)
what[i] = i ;
what[i] = -1 ;
}
info_field_align(buf,fields,field_suffix,MAXOPTS) ;
setlocale(LC_ALL, "");
if(!str_diff(nl_langinfo(CODESET), "UTF-8"))
/** should never happens as long as we have
* a default created */
char src[info->base.len + SS_SYSTEM_LEN + 1] ;
auto_strings(src, info->base.s, SS_SYSTEM) ;
if (!scan_mode(src, S_IFDIR)) {
if (!tree_isvalid(info->base.s, treename))
log_dieusys(LOG_EXIT_SYS, "find tree: ", treename) ;
if (!strcmp(treename, SS_MASTER + 1))
log_die(LOG_EXIT_USER, "you can not view the status of the Master tree -- please use \'66 tree resolve Master\' instead") ;
info_display_all(treename, what) ;
graph_build_tree(&graph, &htres, pinfo->base.s, E_RESOLVE_TREE_MASTER_CONTENTS) ;
if (!graph_matrix_sort_tosa(&sa, &graph))
log_dieu(LOG_EXIT_SYS, "get the sorted list of trees") ;
info_display_all(sa.s + pos, what) ;
if (buffer_puts(buffer_1,"\n") == -1)
log_dieusys(LOG_EXIT_SYS,"write to stdout") ;
goto freed ;
}
}
if (buffer_flush(buffer_1) == -1)
log_dieusys(LOG_EXIT_SYS, "write to stdout") ;
freed: