/* evaluate .if strcmp (i.e. 'str'str') */ static int if_strcmp(int (*next)(void), void (*back)(int)) { char delim[GNLEN]; struct sbuf s1, s2; int ret; charnext(delim, next, back); sbuf_init(&s1); sbuf_init(&s2); read_until(&s1, delim, next, back); read_until(&s2, delim, next, back); cp_reqbeg(); ret = !strcmp(sbuf_buf(&s1), sbuf_buf(&s2)); sbuf_done(&s1); sbuf_done(&s2); return ret; }
/* expand a macro; return zero on success */ static int tok_expand(void) { char *args[10] = {NULL}; struct sbuf sbufs[10]; int i, n = 0; tok_preview(tok); if (src_macro(tok)) { int c = src_next(); src_back(c); if (c == '(') { /* macro arguments follow */ src_next(); while (n <= 9) { sbuf_init(&sbufs[n]); if (tok_readarg(&sbufs[n++])) break; } } for (i = 0; i < n; i++) args[i] = sbuf_buf(&sbufs[i]); src_expand(tok, args); for (i = 0; i < n; i++) sbuf_done(&sbufs[i]); return 0; } tok_unpreview(tok); return 1; }
/* read a string argument of a macro */ static char *read_string(void) { struct sbuf sbuf; int c; int empty; sbuf_init(&sbuf); cp_copymode(1); while ((c = cp_next()) == ' ') ; empty = c <= 0 || c == '\n'; if (c == '"') c = cp_next(); while (c > 0 && c != '\n') { if (c != c_ni) sbuf_add(&sbuf, c); c = cp_next(); } if (c >= 0) cp_back(c); cp_copymode(0); if (empty) { sbuf_done(&sbuf); return NULL; } return sbuf_out(&sbuf); }
/* read the next troff request; return zero if a request was executed. */ int tr_nextreq(void) { char *mac; char *arg0 = NULL; int c; if (!tr_nl) return 1; c = cp_next(); /* transparent line indicator */ if (c == c_ec) { int c2 = cp_next(); if (c2 == '!') { char *args[NARGS + 3] = {"\\!"}; struct sbuf sbuf; sbuf_init(&sbuf); cp_copymode(1); mkargs_eol(&sbuf); cp_copymode(0); chopargs(&sbuf, args + 1); tr_transparent(args); sbuf_done(&sbuf); return 0; } cp_back(c2); } /* not a request, a blank line, or a line with leading spaces */ if (c < 0 || (c != c_cc && c != c_c2 && (c != '\n' || tr_bm < 0) && (c != ' ' || tr_sm < 0))) { cp_back(c); return 1; } cp_reqbeg(); if (c == '\n') { /* blank line macro */ mac = malloc(strlen(map_name(tr_bm)) + 1); strcpy(mac, map_name(tr_bm)); arg0 = dotted(mac, '.'); tr_nextreq_exec(mac, arg0, 0); } else if (c == ' ') { /* leading space macro */ int i; mac = malloc(strlen(map_name(tr_sm)) + 1); strcpy(mac, map_name(tr_sm)); for (i = 0; c == ' '; i++) c = cp_next(); cp_back(c); n_lsn = i; arg0 = dotted(mac, '.'); tr_nextreq_exec(mac, arg0, 0); } else { mac = read_name(n_cp); arg0 = dotted(mac, c); tr_nextreq_exec(mac, arg0, 1); } free(arg0); free(mac); return 0; }
char * sbuf_get(struct sbuf *buf) { assert(buf != NULL); if (sbuf_done(buf) == 0) sbuf_finish(buf); return (sbuf_data(buf)); }
/* read the next macro command */ void tok_macro(void) { char name[NMLEN]; struct sbuf def; tok_preview(name); sbuf_init(&def); tok_macrodef(&def); src_define(name, sbuf_buf(&def)); sbuf_done(&def); }
/* evaluate .if condition */ static int if_eval(int (*next)(void), void (*back)(int)) { struct sbuf sbuf; int ret; sbuf_init(&sbuf); read_until(&sbuf, NULL, next, back); ret = eval(sbuf_buf(&sbuf), '\0') > 0; sbuf_done(&sbuf); return ret; }
char * sbuf_get(struct sbuf *buf) { if (buf == NULL) return (__DECONST(char *, "")); if (sbuf_done(buf) == 0) sbuf_finish(buf); return (sbuf_data(buf)); }
const char * pkg_script_get(struct pkg const * const p, pkg_script i) { if (p->scripts[i] == NULL) return (NULL); if (sbuf_done(p->scripts[i]) == 0) sbuf_finish(p->scripts[i]); return (sbuf_data(p->scripts[i])); }
/* read until .EQ or eqn_beg */ int tok_eqn(void) { struct sbuf ln; int c; tok_cursep = 1; sbuf_init(&ln); while ((c = src_next()) > 0) { if (c == eqn_beg) { printf(".eo\n"); printf(".%s %s \"%s\n", tok_part ? "as" : "ds", EQNS, sbuf_buf(&ln)); sbuf_done(&ln); printf(".ec\n"); tok_part = 1; tok_line = 1; return 0; } sbuf_add(&ln, c); if (c == '\n' && !tok_part) { printf("%s", sbuf_buf(&ln)); tok_lf(sbuf_buf(&ln)); if (tok_eq(sbuf_buf(&ln)) && !tok_en()) { tok_eqen = 1; sbuf_done(&ln); return 0; } } if (c == '\n' && tok_part) { printf(".lf %d\n", src_lineget()); printf("\\*%s%s", escarg(EQNS), sbuf_buf(&ln)); tok_part = 0; } if (c == '\n') sbuf_cut(&ln, 0); } sbuf_done(&ln); return 1; }
static void tr_coa(char **args) { char *src = args[1]; char *dst = args[2]; if (src && dst && str_get(map(src))) { struct sbuf sb; sbuf_init(&sb); if (str_get(map(dst))) sbuf_append(&sb, str_get(map(dst))); sbuf_append(&sb, str_get(map(src))); str_set(map(dst), sbuf_buf(&sb)); sbuf_done(&sb); } }
static void tr_chop(char **args) { struct sbuf sbuf; int id; id = map(args[1]); if (str_get(id)) { sbuf_init(&sbuf); sbuf_append(&sbuf, str_get(id)); if (!sbuf_empty(&sbuf)) { sbuf_cut(&sbuf, sbuf_len(&sbuf) - 1); str_set(id, sbuf_buf(&sbuf)); } sbuf_done(&sbuf); } }
static void tr_de(char **args) { struct sbuf sbuf; int id; if (!args[1]) return; id = map(args[1]); sbuf_init(&sbuf); if (args[0][1] == 'a' && args[0][2] == 'm' && str_get(id)) sbuf_append(&sbuf, str_get(id)); macrobody(&sbuf, args[2] ? args[2] : "."); str_set(id, sbuf_buf(&sbuf)); sbuf_done(&sbuf); if (!n_cp && args[3]) /* parse the arguments as request argv[3] */ str_dset(id, str_dget(map(args[3]))); }
static void tr_coi(char **args) { char *reg = args[1]; char *path = args[2]; char buf[1024]; FILE *fp; if (!reg || !reg[0] || !path || !path[0]) return; if ((fp = fopen(path + 1, "r"))) { struct sbuf sb; sbuf_init(&sb); while (fgets(buf, sizeof(buf), fp)) sbuf_append(&sb, buf); str_set(map(reg), sbuf_buf(&sb)); sbuf_done(&sb); fclose(fp); } }
/* interpolate a macro for tr_nextreq() */ static void tr_nextreq_exec(char *mac, char *arg0, int readargs) { char *args[NARGS + 3] = {arg0}; struct cmd *req = str_dget(map(mac)); char *str = str_get(map(mac)); struct sbuf sbuf; sbuf_init(&sbuf); if (readargs) { if (req && req->args) req->args(&sbuf); if (req && !req->args) mkargs_req(&sbuf); if (!req) mkargs_macro(&sbuf); chopargs(&sbuf, args + 1); } if (str) in_push(str, args); if (!str && req) req->f(args); sbuf_done(&sbuf); }
int pkg_init(const char *path, const char *reposdir) { struct ucl_parser *p = NULL; size_t i; const char *val = NULL; const char *buf, *walk, *value, *key, *k; const char *evkey = NULL; const char *nsname = NULL; const char *evpipe = NULL; ucl_object_t *obj = NULL, *cur, *o, *ncfg; ucl_object_iter_t it = NULL; struct sbuf *ukey = NULL; pkg_get_myarch(myabi, BUFSIZ); if (parsed != false) { pkg_emit_error("pkg_init() must only be called once"); return (EPKG_FATAL); } for (i = 0; i < c_size; i++) { switch (c[i].type) { case PKG_STRING: obj = ucl_object_fromstring_common( c[i].def != NULL ? c[i].def : "", 0, UCL_STRING_TRIM); config = ucl_object_insert_key(config, obj, c[i].key, strlen(c[i].key), false); break; case PKG_INT: config = ucl_object_insert_key(config, ucl_object_fromstring_common(c[i].def, 0, UCL_STRING_PARSE_INT), c[i].key, strlen(c[i].key), false); break; case PKG_BOOL: config = ucl_object_insert_key(config, ucl_object_fromstring_common(c[i].def, 0, UCL_STRING_PARSE_BOOLEAN), c[i].key, strlen(c[i].key), false); break; case PKG_OBJECT: obj = NULL; if (c[i].def == NULL) { obj = ucl_object_typed_new(UCL_OBJECT); } else { walk = buf = c[i].def; while ((buf = strchr(buf, ',')) != NULL) { key = walk; value = walk; while (*value != ',') { if (*value == '=') break; value++; } obj = ucl_object_insert_key(obj, ucl_object_fromstring_common(value + 1, buf - value - 1, UCL_STRING_TRIM), key, value - key, false); buf++; walk = buf; } key = walk; value = walk; while (*value != ',') { if (*value == '=') break; value++; } o = ucl_object_insert_key(o, ucl_object_fromstring_common(value + 1, strlen(value + 1), UCL_STRING_TRIM), key, value - key, false); } config = ucl_object_insert_key(config, obj, c[i].key, strlen(c[i].key), false); break; case PKG_ARRAY: obj = NULL; if (c[i].def == NULL) { obj = ucl_object_typed_new(UCL_ARRAY); } else { walk = buf = c[i].def; while ((buf = strchr(buf, ',')) != NULL) { obj = ucl_array_append(obj, ucl_object_fromstring_common(walk, buf - walk, UCL_STRING_TRIM)); buf++; walk = buf; } obj = ucl_array_append(obj, ucl_object_fromstring_common(walk, strlen(walk), UCL_STRING_TRIM)); } config = ucl_object_insert_key(config, obj, c[i].key, strlen(c[i].key), false); break; } } if (path == NULL) path = PREFIX"/etc/pkg.conf"; p = ucl_parser_new(0); errno = 0; obj = NULL; if (!ucl_parser_add_file(p, path)) { if (errno != ENOENT) pkg_emit_error("%s", ucl_parser_get_error(p)); } else { obj = ucl_parser_get_object(p); } ncfg = NULL; while (obj != NULL && (cur = ucl_iterate_object(obj, &it, true))) { sbuf_init(&ukey); key = ucl_object_key(cur); for (i = 0; key[i] != '\0'; i++) sbuf_putc(ukey, toupper(key[i])); sbuf_done(ukey); o = ucl_object_find_keyl(config, sbuf_data(ukey), sbuf_len(ukey)); /* ignore unknown keys */ if (o == NULL) continue; if (o->type != cur->type) { pkg_emit_error("Malformed key %s, ignoring", key); continue; } ncfg = ucl_object_insert_key(ncfg, ucl_object_ref(cur), key, strlen(key), false); } if (ncfg != NULL) { it = NULL; while (( cur = ucl_iterate_object(ncfg, &it, true))) { key = ucl_object_key(cur); config = ucl_object_replace_key(config, ucl_object_ref(cur), key, strlen(key), false); } ucl_object_unref(ncfg); } ncfg = NULL; it = NULL; while ((cur = ucl_iterate_object(config, &it, true))) { o = NULL; key = ucl_object_key(cur); val = getenv(key); if (val == NULL) continue; switch (cur->type) { case UCL_STRING: o = ucl_object_fromstring_common(val, 0, UCL_STRING_TRIM); break; case UCL_INT: o = ucl_object_fromstring_common(val, 0, UCL_STRING_PARSE_INT); if (o->type != UCL_INT) { pkg_emit_error("Invalid type for environment " "variable %s, got %s, while expecting an integer", key, val); ucl_object_free(o); continue; } break; case UCL_BOOLEAN: o = ucl_object_fromstring_common(val, 0, UCL_STRING_PARSE_BOOLEAN); if (o->type != UCL_BOOLEAN) { pkg_emit_error("Invalid type for environment " "variable %s, got %s, while expecting a boolean", key, val); ucl_object_free(o); continue; } break; case UCL_OBJECT: walk = buf = val; while ((buf = strchr(buf, ',')) != NULL) { k = walk; value = walk; while (*value != ',') { if (*value == '=') break; value++; } o = ucl_object_insert_key(o, ucl_object_fromstring_common(value + 1, buf - value - 1, UCL_STRING_TRIM), k, value - k, false); buf++; walk = buf; } key = walk; value = walk; while (*value != '\0') { if (*value == '=') break; value++; } o = ucl_object_insert_key(o, ucl_object_fromstring_common(value + 1, strlen(value + 1), UCL_STRING_TRIM), k, value - k, false); break; case UCL_ARRAY: walk = buf = val; while ((buf = strchr(buf, ',')) != NULL) { o = ucl_array_append(o, ucl_object_fromstring_common(walk, buf - walk, UCL_STRING_TRIM)); buf++; walk = buf; } o = ucl_array_append(o, ucl_object_fromstring_common(walk, strlen(walk), UCL_STRING_TRIM)); break; default: /* ignore other types */ break; } if (o != NULL) ncfg = ucl_object_insert_key(ncfg, o, key, strlen(key), true); } if (ncfg != NULL) { it = NULL; while (( cur = ucl_iterate_object(ncfg, &it, true))) { key = ucl_object_key(cur); config = ucl_object_replace_key(config, ucl_object_ref(cur), key, strlen(key), false); } ucl_object_unref(ncfg); } disable_plugins_if_static(); parsed = true; ucl_object_unref(obj); ucl_parser_free(p); pkg_debug(1, "%s", "pkg initialized"); /* Start the event pipe */ evpipe = pkg_object_string(pkg_config_get("EVENT_PIPE")); if (evpipe != NULL) connect_evpipe(evpipe); it = NULL; o = ucl_object_find_key(config, "PKG_ENV"); while ((cur = ucl_iterate_object(o, &it, true))) { evkey = ucl_object_key(cur); if (evkey != NULL && evkey[0] != '\0') setenv(evkey, ucl_object_tostring_forced(cur), 1); } /* load the repositories */ load_repositories(reposdir); setenv("HTTP_USER_AGENT", "pkg/"PKGVERSION, 1); /* bypass resolv.conf with specified NAMESERVER if any */ nsname = pkg_object_string(pkg_config_get("NAMESERVER")); if (nsname != NULL) set_nameserver(ucl_object_tostring_forced(o)); return (EPKG_OK); }