diff --git a/src/66/66-inresolve.c b/src/66/66-inresolve.c index 60a6aeb9a6469baacd5897b8cad25ccca32cee88..f9729b1433d031c65e2c3a7c311e317cc06bc5fd 100644 --- a/src/66/66-inresolve.c +++ b/src/66/66-inresolve.c @@ -32,13 +32,15 @@ #include <66/info.h> #include <66/utils.h> #include <66/constants.h> +#include <66/config.h> +#include <66/state.h> -#define MAXOPTS 42 +#define MAXOPTS 84 static wchar_t const field_suffix[] = L" :" ; static char fields[INFO_NKEY][INFO_FIELD_MAXLEN] = {{ 0 }} ; -#define USAGE "66-inresolve [ -h ] [ -z ] [ -v verbosity ] [ -t tree ] [ -l ] tree|service name" +#define USAGE "66-inresolve [ -h ] [ -z ] [ -v verbosity ] [ -t tree ] tree|service name" static inline void info_help (void) { @@ -51,7 +53,6 @@ static inline void info_help (void) " -z: use color\n" " -v: increase/decrease verbosity\n" " -t: only search service at the specified tree\n" -" -l: prints information of the associated logger if exist\n" ; log_info(USAGE,"\n",help) ; @@ -81,46 +82,132 @@ static inline unsigned int parse_what (char const *str) return i ; } -static void info_display_string(char const *field,char const *str) +static void info_display_string(char const *field, char const *str, uint32_t element, uint8_t check) { info_display_field_name(field) ; - if (!*str) - { - if (!bprintf(buffer_1,"%s%s",log_color->warning,"None")) - log_dieusys(LOG_EXIT_SYS,"write to stdout") ; - } - else - { - if (!buffer_puts(buffer_1,str)) - log_dieusys(LOG_EXIT_SYS,"write to stdout") ; + if (check && !element) { + + if (!bprintf(buffer_1,"%s%s", log_color->warning, "None")) + log_dieusys(LOG_EXIT_SYS, "write to stdout") ; + + } else { + + if (!buffer_puts(buffer_1, str + element)) + log_dieusys(LOG_EXIT_SYS, "write to stdout") ; } - if (buffer_putsflush(buffer_1,"\n") == -1) - 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_int(char const *field,unsigned int id) +static void info_display_int(char const *field, uint32_t element) { - char *str = 0 ; - char ival[UINT_FMT] ; - ival[uint_fmt(ival,id)] = 0 ; - str = ival ; + info_display_field_name(field) ; + + char ui[UINT_FMT] ; + ui[uint_fmt(ui, element)] = 0 ; + + if (!buffer_puts(buffer_1, ui)) + 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_service_field(resolve_service_t *res) +{ + info_display_string(fields[0], res->sa.s, res->name, 0) ; + info_display_string(fields[1], res->sa.s, res->description, 1) ; + info_display_string(fields[2], res->sa.s, res->version, 1) ; + info_display_int(fields[3], res->type) ; + info_display_int(fields[4], res->notify) ; + info_display_int(fields[5], res->maxdeath) ; + info_display_int(fields[6], res->earlier) ; + info_display_string(fields[7], res->sa.s, res->hiercopy, 1) ; + info_display_string(fields[8], res->sa.s, res->intree, 1) ; + info_display_string(fields[9], res->sa.s, res->ownerstr, 1) ; + info_display_int(fields[10], res->owner) ; + info_display_string(fields[11], res->sa.s, res->treename, 1) ; + info_display_string(fields[12], res->sa.s, res->user, 1) ; + info_display_string(fields[13], res->sa.s, res->inmodule, 1) ; + + info_display_string(fields[14], res->sa.s, res->path.home, 1) ; + info_display_string(fields[15], res->sa.s, res->path.frontend, 1) ; + info_display_string(fields[16], res->sa.s, res->path.tree, 1) ; + info_display_string(fields[17], res->sa.s, res->path.status, 1) ; + + info_display_string(fields[18], res->sa.s, res->dependencies.depends, 1) ; + info_display_string(fields[19], res->sa.s, res->dependencies.requiredby, 1) ; + info_display_string(fields[20], res->sa.s, res->dependencies.optsdeps, 1) ; + info_display_int(fields[21], res->dependencies.ndepends) ; + info_display_int(fields[22], res->dependencies.nrequiredby) ; + info_display_int(fields[23], res->dependencies.noptsdeps) ; + + info_display_string(fields[24], res->sa.s, res->execute.run.run, 1) ; + info_display_string(fields[25], res->sa.s, res->execute.run.run_user, 1) ; + info_display_string(fields[26], res->sa.s, res->execute.run.build, 1) ; + info_display_string(fields[27], res->sa.s, res->execute.run.shebang, 1) ; + info_display_string(fields[28], res->sa.s, res->execute.run.runas, 1) ; + info_display_string(fields[29], res->sa.s, res->execute.finish.run, 1) ; + info_display_string(fields[30], res->sa.s, res->execute.finish.run_user, 1) ; + info_display_string(fields[31], res->sa.s, res->execute.finish.build, 1) ; + info_display_string(fields[32], res->sa.s, res->execute.finish.shebang, 1) ; + info_display_string(fields[33], res->sa.s, res->execute.finish.runas, 1) ; + info_display_int(fields[34], res->execute.timeout.kill) ; + info_display_int(fields[35], res->execute.timeout.finish) ; + info_display_int(fields[36], res->execute.timeout.up) ; + info_display_int(fields[37], res->execute.timeout.down) ; + info_display_int(fields[38], res->execute.down) ; + info_display_int(fields[39], res->execute.downsignal) ; + + info_display_string(fields[40], res->sa.s, res->live.livedir, 1) ; + info_display_string(fields[41], res->sa.s, res->live.scandir, 1) ; + info_display_string(fields[42], res->sa.s, res->live.statedir, 1) ; + info_display_string(fields[43], res->sa.s, res->live.eventdir, 1) ; + info_display_string(fields[44], res->sa.s, res->live.notifdir, 1) ; + info_display_string(fields[45], res->sa.s, res->live.supervisedir, 1) ; + info_display_string(fields[46], res->sa.s, res->live.fdholderdir, 1) ; + info_display_string(fields[47], res->sa.s, res->live.oneshotddir, 1) ; + + info_display_string(fields[48], res->sa.s, res->logger.name, 1) ; + info_display_string(fields[49], res->sa.s, res->logger.destination, 1) ; + info_display_int(fields[50], res->logger.backup) ; + info_display_int(fields[51], res->logger.maxsize) ; + info_display_int(fields[52], res->logger.timestamp) ; + info_display_string(fields[53], res->sa.s, res->logger.execute.run.run, 1) ; + info_display_string(fields[54], res->sa.s, res->logger.execute.run.run_user, 1) ; + info_display_string(fields[55], res->sa.s, res->logger.execute.run.build, 1) ; + info_display_string(fields[56], res->sa.s, res->logger.execute.run.shebang, 1) ; + info_display_string(fields[57], res->sa.s, res->logger.execute.run.runas, 1) ; + info_display_int(fields[58], res->logger.execute.timeout.kill) ; + info_display_int(fields[59], res->logger.execute.timeout.finish) ; + + info_display_string(fields[60], res->sa.s, res->environ.env, 1) ; + info_display_string(fields[61], res->sa.s, res->environ.envdir, 1) ; + info_display_int(fields[62], res->environ.env_overwrite) ; + + info_display_string(fields[63], res->sa.s, res->regex.configure, 1) ; + info_display_string(fields[64], res->sa.s, res->regex.directories, 1) ; + info_display_string(fields[65], res->sa.s, res->regex.files, 1) ; + info_display_string(fields[66], res->sa.s, res->regex.infiles, 1) ; + info_display_int(fields[67], res->regex.ndirectories) ; + info_display_int(fields[68], res->regex.nfiles) ; + info_display_int(fields[69], res->regex.ninfiles) ; - info_display_string(field,str) ; } int main(int argc, char const *const *argv) { int found = 0, what = 0 ; - uint8_t logger = 0, master = 0 ; + uint8_t master = 0 ; - stralloc satree = STRALLOC_ZERO ; - stralloc src = STRALLOC_ZERO ; - stralloc tmp = STRALLOC_ZERO ; - char const *tname = 0 ; + stralloc sa = STRALLOC_ZERO ; char const *svname = 0 ; + char const *treename = 0 ; + char atree[SS_MAX_TREENAME + 1] ; log_color = &log_color_disable ; @@ -130,7 +217,7 @@ int main(int argc, char const *const *argv) for (;;) { - int opt = getopt_args(argc,argv, ">hv:zlt:", &l) ; + int opt = getopt_args(argc,argv, ">hv:zt:", &l) ; if (opt == -1) break ; if (opt == -2) log_die(LOG_EXIT_USER,"options must be set first") ; switch (opt) @@ -153,12 +240,7 @@ int main(int argc, char const *const *argv) case 't' : - tname = l.arg ; - break ; - - case 'l' : - - logger = 1 ; + treename = l.arg ; break ; default : @@ -169,7 +251,7 @@ int main(int argc, char const *const *argv) argc -= l.ind ; argv += l.ind ; } - if (!argc) log_usage(USAGE) ; + if (argc < 2) log_usage(USAGE) ; what = parse_what(*argv) ; if (what == 2) @@ -179,61 +261,110 @@ int main(int argc, char const *const *argv) argc--; svname = *argv ; + if (!set_ownersysdir(&sa, getuid())) + log_dieu(LOG_EXIT_SYS, "set owner directory") ; + if (!what) { char service_buf[MAXOPTS][INFO_FIELD_MAXLEN] = { - "Name", - "Description" , - "Version", - "Logger", - "Logreal", - "Logassoc", - "Dstlog", - "Depends", - "Requiredby", - "Optsdeps", - "Extdeps", - "Contents" , - "Src" , - "Srconf", - "Live", - "Runat", - "Tree", - "Treename", - "State", - "Exec_run" , - "Real_exec_run" , - "Exec_finish" , - "Real_exec_finish" , - "Type" , - "Ndepends" , - "Nrequiredby" , - "Noptsdeps" , - "Nextdeps" , - "Ncontents" , - "Down" , - "Disen", - "Real_logger_name", - "Classic", - "Bundle", - "Longrun", - "Oneshot", - "Module", - "Nclassic", - "Nbundle", - "Nlongrun", - "Noneshot", - "Nmodule" + "name", + "description" , + "version", + "type", + "notify", + "maxdeath", + "earlier", + "hiercopy", + "intree", + "ownerstr", + "owner", + "treename", + "user" , + "inmodule", // 14 + + "home", + "frontend", + "tree", + "status", //18 + + "depends", + "requiredby", + "optsdeps", + "ndepends", + "nrequiredby", + "noptsdeps", // 24 + + "run", + "run_user", + "run_build", + "run_shebang", + "run_runas", + "finish", + "finish_user", + "finish_build", + "finish_shebang", + "finish_runas", + "timeoutkill", + "timeoutfinish", + "timeoutup", + "timeoutdown", + "down", + "downsignal", // 40 + + "livedir", + "scandir", + "statedir", + "eventdir", + "notifdir", + "supervisedir", + "fdholderdir", + "oneshotddir", //48 + + "logname" , + "logdestination" , + "logbackup" , + "logmaxsize" , + "logtimestamp" , + "logrun" , + "logrun_user" , + "logrun_build" , + "logrun_shebang" , + "logrun_runas" , + "logtimeoutkill", + "logtimeoutfinish", // 60 + + "env", + "envdir", + "env_overwrite", // 63 + + "configure", + "directories", + "files", + "infiles", + "ndirectories", + "nfiles", + "ninfiles", // 70 + + "classic", + "bundle", + "oneshot", + "module", + "enabled", + "disabled", + "contents", + "nclassic", + "nbundle", + "noneshot", + "nmodule", + "nenabled", + "ndisabled", + "ncontents" // 84 } ; - resolve_wrapper_t_ref wres = 0 ; - resolve_wrapper_t_ref lwres = 0 ; resolve_service_t res = RESOLVE_SERVICE_ZERO ; - resolve_service_t lres = RESOLVE_SERVICE_ZERO ; resolve_service_master_t mres = RESOLVE_SERVICE_MASTER_ZERO ; - if (!strcmp(svname, SS_MASTER + 1)) { master = 1 ; @@ -242,107 +373,53 @@ int main(int argc, char const *const *argv) } else { wres = resolve_set_struct(DATA_SERVICE, &res) ; - lwres = resolve_set_struct(DATA_SERVICE, &lres) ; } - found = service_intree(&src,svname,tname) ; - if (found == -1) log_dieu(LOG_EXIT_SYS,"resolve tree source of sv: ",svname) ; - else if (!found) { - log_info("no tree exist yet") ; - goto freed ; - } - else if (found > 2) { - log_die(LOG_EXIT_SYS,svname," is set on different tree -- please use -t options") ; - } - else if (found == 1) log_die(LOG_EXIT_SYS,"unknown service: ",svname) ; - if (!resolve_read(wres,src.s,svname)) log_dieusys(LOG_EXIT_SYS,"read resolve file") ; + if (!master) { + + found = service_is_g(atree, svname, STATE_FLAGS_ISPARSED) ; + if (found == -1) + log_dieu(LOG_EXIT_SYS, "get information of service: ", svname, " -- please a bug report") ; + else if (!found) + log_die(LOG_EXIT_USER, "unknown service: ", svname) ; + + if (!resolve_read_g(wres, sa.s, svname)) + log_dieusys(LOG_EXIT_SYS,"read resolve file") ; + + } else { + + char solve[sa.len + SS_SYSTEM_LEN + 1 + strlen(treename) + SS_SVDIRS_LEN + 1] ; + auto_strings(solve, sa.s, SS_SYSTEM, "/", treename, SS_SVDIRS) ; + + if (!resolve_read(wres, solve, SS_MASTER + 1)) + log_dieusys(LOG_EXIT_SYS,"read resolve file") ; + } - info_field_align(service_buf,fields,field_suffix,MAXOPTS) ; + info_field_align(service_buf, fields, field_suffix,MAXOPTS) ; if (!master) { - info_display_string(fields[0],res.sa.s + res.name) ; - info_display_string(fields[1],res.sa.s + res.description) ; - info_display_string(fields[2],res.sa.s + res.version) ; - info_display_string(fields[3],res.sa.s + res.logger) ; - info_display_string(fields[4],res.sa.s + res.logreal) ; - info_display_string(fields[5],res.sa.s + res.logassoc) ; - info_display_string(fields[6],res.sa.s + res.dstlog) ; - info_display_string(fields[7],res.sa.s + res.depends) ; - info_display_string(fields[8],res.sa.s + res.requiredby) ; - info_display_string(fields[9],res.sa.s + res.optsdeps) ; - info_display_string(fields[10],res.sa.s + res.extdeps) ; - info_display_string(fields[11],res.sa.s + res.contents) ; - info_display_string(fields[12],res.sa.s + res.src) ; - info_display_string(fields[13],res.sa.s + res.srconf) ; - info_display_string(fields[14],res.sa.s + res.live) ; - info_display_string(fields[15],res.sa.s + res.runat) ; - info_display_string(fields[16],res.sa.s + res.tree) ; - info_display_string(fields[17],res.sa.s + res.treename) ; - info_display_string(fields[18],res.sa.s + res.state) ; - info_display_string(fields[19],res.sa.s + res.exec_run) ; - info_display_string(fields[20],res.sa.s + res.real_exec_run) ; - info_display_string(fields[21],res.sa.s + res.exec_finish) ; - info_display_string(fields[22],res.sa.s + res.real_exec_finish) ; - info_display_int(fields[23],res.type) ; - info_display_int(fields[24],res.ndepends) ; - info_display_int(fields[25],res.nrequiredby) ; - info_display_int(fields[26],res.noptsdeps) ; - info_display_int(fields[27],res.nextdeps) ; - info_display_int(fields[28],res.ncontents) ; - info_display_int(fields[29],res.down) ; - info_display_int(fields[30],res.disen) ; - - if (res.logger && logger) { - - if (!resolve_read(lwres,src.s,res.sa.s + res.logger)) log_dieusys(111,"read resolve file of: ",res.sa.s + res.logger) ; - - if (buffer_putsflush(buffer_1,"\n") == -1) - log_dieusys(LOG_EXIT_SYS,"write to stdout") ; - - info_display_string(fields[31],res.sa.s + res.logreal) ; - info_display_string(fields[0],lres.sa.s + lres.name) ; - info_display_string(fields[1],lres.sa.s + lres.description) ; - info_display_string(fields[2],lres.sa.s + lres.version) ; - info_display_string(fields[3],lres.sa.s + lres.logger) ; - info_display_string(fields[4],lres.sa.s + lres.logreal) ; - info_display_string(fields[5],lres.sa.s + lres.logassoc) ; - info_display_string(fields[6],lres.sa.s + lres.dstlog) ; - info_display_string(fields[7],lres.sa.s + lres.depends) ; - info_display_string(fields[8],lres.sa.s + lres.requiredby) ; - info_display_string(fields[12],lres.sa.s + lres.src) ; - info_display_string(fields[13],lres.sa.s + lres.srconf) ; - info_display_string(fields[14],lres.sa.s + lres.live) ; - info_display_string(fields[15],lres.sa.s + lres.runat) ; - info_display_string(fields[16],lres.sa.s + lres.tree) ; - info_display_string(fields[17],lres.sa.s + lres.treename) ; - info_display_string(fields[15],lres.sa.s + lres.state) ; - info_display_string(fields[19],lres.sa.s + lres.exec_log_run) ; - info_display_string(fields[20],lres.sa.s + lres.real_exec_log_run) ; - info_display_int(fields[23],lres.type) ; - info_display_int(fields[24],lres.ndepends) ; - info_display_int(fields[25],lres.nrequiredby) ; - info_display_int(fields[29],lres.down) ; - info_display_int(fields[30],lres.disen) ; - - resolve_free(lwres) ; - } + info_display_service_field(&res) ; } else { - info_display_string(fields[0],mres.sa.s + mres.name) ; - info_display_string(fields[32],mres.sa.s + mres.classic) ; - info_display_string(fields[33],mres.sa.s + mres.bundle) ; - info_display_string(fields[34],mres.sa.s + mres.longrun) ; - info_display_string(fields[35],mres.sa.s + mres.oneshot) ; - info_display_string(fields[36],mres.sa.s + mres.module) ; - info_display_int(fields[37],mres.nclassic) ; - info_display_int(fields[38],mres.nbundle) ; - info_display_int(fields[39],mres.nlongrun) ; - info_display_int(fields[40],mres.noneshot) ; - info_display_int(fields[41],mres.nmodule) ; - + info_display_string(fields[0], mres.sa.s, mres.name, 0) ; + info_display_string(fields[70], mres.sa.s, mres.classic, 1) ; + info_display_string(fields[71], mres.sa.s, mres.bundle, 1) ; + info_display_string(fields[72], mres.sa.s, mres.oneshot, 1) ; + info_display_string(fields[73], mres.sa.s, mres.module, 1) ; + info_display_string(fields[74], mres.sa.s, mres.enabled, 1) ; + info_display_string(fields[75], mres.sa.s, mres.disabled, 1) ; + info_display_string(fields[76], mres.sa.s, mres.contents, 1) ; + + info_display_int(fields[77], mres.nclassic) ; + info_display_int(fields[78], mres.nbundle) ; + info_display_int(fields[79], mres.noneshot) ; + info_display_int(fields[80], mres.nmodule) ; + info_display_int(fields[81], mres.nenabled) ; + info_display_int(fields[82], mres.ndisabled) ; + info_display_int(fields[83], mres.ncontents) ; } resolve_free(wres) ; @@ -350,32 +427,32 @@ int main(int argc, char const *const *argv) } else { char tree_buf[MAXOPTS][INFO_FIELD_MAXLEN] = { - "Name", - "Depends" , - "Requiredby", - "Allow", - "Groups", - "Contents", - "Ndepends", - "Nrequiredby", - "Nallow", - "Ngroups", - "Ncontents", - "Init" , - "Disen", + "name", + "depends" , + "requiredby", + "allow", + "groups", + "contents", + "ndepends", + "nrequiredby", + "nallow", + "ngroups", + "ncontents", + "init" , + "disen", // 13 // Master - "Enabled", - "Current", - "Contents", - "Nenabled", - "Ncontents" + "enabled", + "current", + "contents", + "nenabled", + "ncontents" // 18 } ; resolve_wrapper_t_ref wres = 0 ; resolve_tree_t tres = RESOLVE_TREE_ZERO ; resolve_tree_master_t mres = RESOLVE_TREE_MASTER_ZERO ; - if (!strcmp(svname, SS_MASTER + 1)) { + if (!strcmp(argv[0], SS_MASTER + 1)) { master = 1 ; wres = resolve_set_struct(DATA_TREE_MASTER, &mres) ; @@ -385,58 +462,50 @@ int main(int argc, char const *const *argv) wres = resolve_set_struct(DATA_TREE, &tres) ; } - if (!set_ownersysdir(&src, getuid())) - log_dieusys(LOG_EXIT_SYS, "set owner directory") ; - - found = tree_isvalid(src.s,svname) ; + found = tree_isvalid(sa.s, svname) ; if (found < 0) log_diesys(LOG_EXIT_SYS, "invalid tree directory") ; if (!found) - log_dieusys(LOG_EXIT_SYS,"find tree: ", svname) ; + log_dieusys(LOG_EXIT_SYS, "find tree: ", svname) ; - if (!auto_stra(&src, SS_SYSTEM)) - log_die_nomem("stralloc") ; + if (!resolve_read_g(wres, sa.s, svname)) + log_dieusys(LOG_EXIT_SYS, "read resolve file") ; - if (!resolve_read(wres,src.s,svname)) - log_dieusys(LOG_EXIT_SYS,"read resolve file") ; - - info_field_align(tree_buf,fields,field_suffix,MAXOPTS) ; + info_field_align(tree_buf, fields, field_suffix,MAXOPTS) ; if (!master) { - info_display_string(fields[0],tres.sa.s + tres.name) ; - info_display_string(fields[1],tres.sa.s + tres.depends) ; - info_display_string(fields[2],tres.sa.s + tres.requiredby) ; - info_display_string(fields[3],tres.sa.s + tres.allow) ; - info_display_string(fields[4],tres.sa.s + tres.groups) ; - info_display_string(fields[5],tres.sa.s + tres.contents) ; - info_display_int(fields[6],tres.ndepends) ; - info_display_int(fields[7],tres.nrequiredby) ; - info_display_int(fields[8],tres.nallow) ; - info_display_int(fields[9],tres.ngroups) ; - info_display_int(fields[10],tres.ncontents) ; - info_display_int(fields[11],tres.init) ; - info_display_int(fields[12],tres.disen) ; + info_display_string(fields[0], tres.sa.s, tres.name, 0) ; + info_display_string(fields[1], tres.sa.s, tres.depends, 1) ; + info_display_string(fields[2], tres.sa.s, tres.requiredby, 1) ; + info_display_string(fields[3], tres.sa.s, tres.allow, 1) ; + info_display_string(fields[4], tres.sa.s, tres.groups, 1) ; + info_display_string(fields[5], tres.sa.s, tres.contents, 1) ; + info_display_int(fields[6], tres.ndepends) ; + info_display_int(fields[7], tres.nrequiredby) ; + info_display_int(fields[8], tres.nallow) ; + info_display_int(fields[9], tres.ngroups) ; + info_display_int(fields[10], tres.ncontents) ; + info_display_int(fields[11], tres.init) ; + info_display_int(fields[12], tres.disen) ; } else { - info_display_string(fields[0],mres.sa.s + mres.name) ; - info_display_string(fields[3],mres.sa.s + mres.allow) ; - info_display_string(fields[13],mres.sa.s + mres.enabled) ; - info_display_string(fields[14],mres.sa.s + mres.current) ; - info_display_string(fields[15],mres.sa.s + mres.contents) ; - info_display_int(fields[16],mres.nenabled) ; - info_display_int(fields[17],mres.ncontents) ; + info_display_string(fields[0], mres.sa.s, mres.name, 1) ; + info_display_string(fields[3], mres.sa.s, mres.allow, 1) ; + info_display_string(fields[13], mres.sa.s, mres.enabled, 1) ; + info_display_string(fields[14], mres.sa.s, mres.current, 1) ; + info_display_string(fields[15], mres.sa.s, mres.contents, 1) ; + info_display_int(fields[16], mres.nenabled) ; + info_display_int(fields[17], mres.ncontents) ; } resolve_free(wres) ; } - freed: - stralloc_free(&satree) ; - stralloc_free(&src) ; - stralloc_free(&tmp) ; + stralloc_free(&sa) ; + return 0 ; }