int format_exec_cmd(char **dest, const char *in, const char *prefix, const char *plist_file) { struct sbuf *buf = sbuf_new_auto(); char path[MAXPATHLEN + 1]; char *cp; while (in[0] != '\0') { if (in[0] == '%') { in++; switch(in[0]) { case 'D': sbuf_cat(buf, prefix); break; case 'F': sbuf_cat(buf, plist_file); break; case 'f': if (prefix[strlen(prefix) - 1] == '/') snprintf(path, sizeof(path), "%s%s", prefix, plist_file); else snprintf(path, sizeof(path), "%s/%s", prefix, plist_file); cp = strrchr(path, '/'); cp ++; sbuf_cat(buf, cp); break; case 'B': if (prefix[strlen(prefix) - 1] == '/') snprintf(path, sizeof(path), "%s%s", prefix, plist_file); else snprintf(path, sizeof(path), "%s/%s", prefix, plist_file); cp = strrchr(path, '/'); cp[0] = '\0'; sbuf_cat(buf, path); break; default: sbuf_putc(buf, in[0]); break; } } else { sbuf_putc(buf, in[0]); } in++; } sbuf_finish(buf); *dest = strdup(sbuf_data(buf)); sbuf_free(buf); return (0); }
static char * sbuf_json_escape(struct sbuf *buf, const char *str) { sbuf_clear(buf); while (str != NULL && *str != '\0') { if (*str == '"' || *str == '\\') sbuf_putc(buf, '\\'); sbuf_putc(buf, *str); str++; } sbuf_finish(buf); return (sbuf_data(buf)); }
static int sbuf_copy_lines(struct sbuf *to, const char *from, int N) { int cnt = 0; int i; if (N == 0) return (0); for (i = 0; from[i] != '\0'; i++) { if (from[i] == '\n') { cnt++; continue; } if (cnt == N) break; } if (to == NULL) return (i); if (sbuf_len(to) > 0 && sbuf_data(to)[sbuf_len(to)-1] != '\n') sbuf_putc(to, '\n'); sbuf_bcat(to, from, i); sbuf_finish(to); return (i); }
static struct sbuf * read_input(void) { struct sbuf *input; int ch; input = sbuf_new_auto(); for (;;) { ch = getc(stdin); if (ch == EOF) { if (feof(stdin)) break; if (ferror(stdin)) err(EX_NOINPUT, "Failed to read stdin"); } sbuf_putc(input, ch); } #ifdef __DragonFly__ sbuf_finish(input); #else if (sbuf_finish(input) != 0) err(EX_DATAERR, "Could not read value data"); #endif return (input); }
/* construct path to node->name */ static char * mtree_file_path(fsnode *node) { fsnode *pnode; struct sbuf *sb; char *res, *rp[MAKEFS_MAX_TREE_DEPTH]; int depth; depth = 0; rp[depth] = node->name; for (pnode = node->parent; pnode && depth < MAKEFS_MAX_TREE_DEPTH; pnode = pnode->parent) { if (strcmp(pnode->name, ".") == 0) break; rp[++depth] = pnode->name; } sb = sbuf_new_auto(); if (sb == NULL) { errno = ENOMEM; return (NULL); } while (depth > 0) { sbuf_cat(sb, rp[depth--]); sbuf_putc(sb, '/'); } sbuf_cat(sb, rp[depth]); sbuf_finish(sb); res = strdup(sbuf_data(sb)); sbuf_delete(sb); if (res == NULL) errno = ENOMEM; return res; }
static int ucl_sbuf_append_character(unsigned char c, size_t len, void *data) { struct sbuf *buf = data; size_t i; for (i = 0; i < len; i++) sbuf_putc(buf, c); return (0); }
int procfs_doproctype(PFS_FILL_ARGS) { static const char *none = "Not Available"; if (p != NULL && p->p_sysent && p->p_sysent->sv_name) sbuf_printf(sb, "%s", p->p_sysent->sv_name); else sbuf_printf(sb, "%s", none); sbuf_putc(sb, '\n'); return (0); }
static int urldecode(const char *src, struct sbuf **dest) { size_t len; size_t i; char c; char hex[] = {'\0', '\0', '\0'}; sbuf_init(dest); len = strlen(src); for (i = 0; i < len; i++) { if (src[i] != '%') { sbuf_putc(*dest, src[i]); } else { if (i + 2 > len) { pkg_emit_error("unexpected end of string"); return (EPKG_FATAL); } hex[0] = src[++i]; hex[1] = src[++i]; errno = 0; c = strtol(hex, NULL, 16); if (errno != 0) { /* * if it fails consider this is not a urlencoded * information */ sbuf_printf(*dest, "%%%s", hex); } else { sbuf_putc(*dest, c); } } } sbuf_finish(*dest); return (EPKG_OK); }
static int urldecode(const char *src, struct sbuf **dest) { size_t len; size_t i; char c; char hex[] = {'\0', '\0', '\0'}; if (*dest == NULL) *dest = sbuf_new_auto(); else sbuf_reset(*dest); len = strlen(src); for (i = 0; i < len; i++) { if (src[i] != '%') { sbuf_putc(*dest, src[i]); } else { if (i + 2 > len) { pkg_emit_error("unexpected end of string"); return (EPKG_FATAL); } hex[0] = src[++i]; hex[1] = src[++i]; errno = 0; c = strtol(hex, NULL, 16); if (errno != 0) { pkg_emit_errno("strtol()", hex); return (EPKG_FATAL); } sbuf_putc(*dest, c); } } sbuf_finish(*dest); return (EPKG_OK); }
/*------- API comments for these methods can be found in xenstorevar.h -------*/ struct sbuf * xs_join(const char *dir, const char *name) { struct sbuf *sb; sb = sbuf_new_auto(); sbuf_cat(sb, dir); if (name[0] != '\0') { sbuf_putc(sb, '/'); sbuf_cat(sb, name); } sbuf_finish(sb); return (sb); }
static int urlencode(const char *src, struct sbuf **dest) { size_t len; size_t i; sbuf_init(dest); len = strlen(src); for (i = 0; i < len; i++) { if (!isascii(src[i]) || src[i] == '%') sbuf_printf(*dest, "%%%.2x", (unsigned char)src[i]); else sbuf_putc(*dest, src[i]); } sbuf_finish(*dest); return (EPKG_OK); }
int pkg_ini(const char *path, const char *reposdir, pkg_init_flags flags) { 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; const ucl_object_t *cur, *object; ucl_object_t *obj = NULL, *o, *ncfg; ucl_object_iter_t it = NULL; struct sbuf *ukey = NULL; bool fatal_errors = false; k = NULL; o = NULL; pkg_get_myarch(myabi, BUFSIZ); pkg_get_myarch_legacy(myabi_legacy, BUFSIZ); if (parsed != false) { pkg_emit_error("pkg_init() must only be called once"); return (EPKG_FATAL); } if (((flags & PKG_INIT_FLAG_USE_IPV4) == PKG_INIT_FLAG_USE_IPV4) && ((flags & PKG_INIT_FLAG_USE_IPV6) == PKG_INIT_FLAG_USE_IPV6)) { pkg_emit_error("Invalid flags for pkg_init()"); return (EPKG_FATAL); } config = ucl_object_typed_new(UCL_OBJECT); 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); ucl_object_insert_key(config, obj, c[i].key, strlen(c[i].key), false); break; case PKG_INT: 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: 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 = ucl_object_typed_new(UCL_OBJECT); if (c[i].def != NULL) { walk = buf = c[i].def; while ((buf = strchr(buf, ',')) != NULL) { key = walk; value = walk; while (*value != ',') { if (*value == '=') break; value++; } 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++; } if (o == NULL) o = ucl_object_typed_new(UCL_OBJECT); ucl_object_insert_key(o, ucl_object_fromstring_common(value + 1, strlen(value + 1), UCL_STRING_TRIM), key, value - key, false); } ucl_object_insert_key(config, obj, c[i].key, strlen(c[i].key), false); break; case PKG_ARRAY: obj = ucl_object_typed_new(UCL_ARRAY); if (c[i].def != NULL) { walk = buf = c[i].def; while ((buf = strchr(buf, ',')) != NULL) { ucl_array_append(obj, ucl_object_fromstring_common(walk, buf - walk, UCL_STRING_TRIM)); buf++; walk = buf; } ucl_array_append(obj, ucl_object_fromstring_common(walk, strlen(walk), UCL_STRING_TRIM)); } 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("Invalid configuration file: %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_finish(ukey); object = ucl_object_find_keyl(config, sbuf_data(ukey), sbuf_len(ukey)); if (strncasecmp(sbuf_data(ukey), "PACKAGESITE", sbuf_len(ukey)) == 0 || strncasecmp(sbuf_data(ukey), "PUBKEY", sbuf_len(ukey)) == 0 || strncasecmp(sbuf_data(ukey), "MIRROR_TYPE", sbuf_len(ukey)) == 0) { pkg_emit_error("%s in pkg.conf is no longer " "supported. Convert to the new repository style." " See pkg.conf(5)", sbuf_data(ukey)); fatal_errors = true; continue; } /* ignore unknown keys */ if (object == NULL) continue; if (object->type != cur->type) { pkg_emit_error("Malformed key %s, ignoring", key); continue; } if (ncfg == NULL) ncfg = ucl_object_typed_new(UCL_OBJECT); ucl_object_insert_key(ncfg, ucl_object_copy(cur), sbuf_data(ukey), sbuf_len(ukey), true); } if (fatal_errors) { ucl_object_unref(ncfg); ucl_parser_free(p); return (EPKG_FATAL); } if (ncfg != NULL) { it = NULL; while (( cur = ucl_iterate_object(ncfg, &it, true))) { key = ucl_object_key(cur); ucl_object_replace_key(config, ucl_object_ref(cur), key, strlen(key), true); } 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_unref(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_unref(o); continue; } break; case UCL_OBJECT: o = ucl_object_typed_new(UCL_OBJECT); walk = buf = val; while ((buf = strchr(buf, ',')) != NULL) { k = walk; value = walk; while (*value != ',') { if (*value == '=') break; value++; } 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++; } 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: o = ucl_object_typed_new(UCL_ARRAY); walk = buf = val; while ((buf = strchr(buf, ',')) != NULL) { ucl_array_append(o, ucl_object_fromstring_common(walk, buf - walk, UCL_STRING_TRIM)); buf++; walk = buf; } ucl_array_append(o, ucl_object_fromstring_common(walk, strlen(walk), UCL_STRING_TRIM)); break; default: /* ignore other types */ break; } if (o != NULL) { if (ncfg == NULL) ncfg = ucl_object_typed_new(UCL_OBJECT); 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); ucl_object_replace_key(config, ucl_object_ref(cur), key, strlen(key), true); } ucl_object_unref(ncfg); } disable_plugins_if_static(); parsed = true; ucl_object_unref(obj); ucl_parser_free(p); if (strcmp(pkg_object_string(pkg_config_get("ABI")), "unknown") == 0) { pkg_emit_error("Unable to determine ABI"); return (EPKG_FATAL); } 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); debug_level = pkg_object_int(pkg_config_get("DEBUG_LEVEL")); it = NULL; object = ucl_object_find_key(config, "PKG_ENV"); while ((cur = ucl_iterate_object(object, &it, true))) { evkey = ucl_object_key(cur); pkg_debug(1, "Setting env var: %s", evkey); if (evkey != NULL && evkey[0] != '\0') setenv(evkey, ucl_object_tostring_forced(cur), 1); } /* load the repositories */ load_repositories(reposdir, flags); 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); }
int format_exec_cmd(char **dest, const char *in, const char *prefix, const char *plist_file, char *line) { struct sbuf *buf = sbuf_new_auto(); char path[MAXPATHLEN + 1]; char *cp; while (in[0] != '\0') { if (in[0] == '%') { in++; switch(in[0]) { case 'D': sbuf_cat(buf, prefix); break; case 'F': if (plist_file == NULL) { pkg_emit_error("No files defined %%F couldn't be expanded, ignoring %s", in); sbuf_finish(buf); sbuf_free(buf); return (EPKG_FATAL); } sbuf_cat(buf, plist_file); break; case 'f': if (plist_file == NULL) { pkg_emit_error("No files defined %%f couldn't be expanded, ignoring %s", in); sbuf_finish(buf); sbuf_free(buf); return (EPKG_FATAL); } if (prefix[strlen(prefix) - 1] == '/') snprintf(path, sizeof(path), "%s%s", prefix, plist_file); else snprintf(path, sizeof(path), "%s/%s", prefix, plist_file); cp = strrchr(path, '/'); cp ++; sbuf_cat(buf, cp); break; case 'B': if (plist_file == NULL) { pkg_emit_error("No files defined %%B couldn't be expanded, ignoring %s", in); sbuf_finish(buf); sbuf_free(buf); return (EPKG_FATAL); } if (prefix[strlen(prefix) - 1] == '/') snprintf(path, sizeof(path), "%s%s", prefix, plist_file); else snprintf(path, sizeof(path), "%s/%s", prefix, plist_file); cp = strrchr(path, '/'); cp[0] = '\0'; sbuf_cat(buf, path); break; case '%': sbuf_putc(buf, '%'); break; case '@': if (line != NULL) { sbuf_cat(buf, line); break; } /* * no break here because if line is not * given (default exec) %@ does not * exists */ default: sbuf_putc(buf, '%'); sbuf_putc(buf, in[0]); break; } } else { sbuf_putc(buf, in[0]); } in++; } sbuf_finish(buf); *dest = strdup(sbuf_data(buf)); sbuf_free(buf); return (EPKG_OK); }
static void format_str(struct pkg *pkg, struct sbuf *dest, const char *qstr, void *data) { char size[7]; const char *tmp; bool automatic; int64_t flatsize; lic_t licenselogic; sbuf_clear(dest); while (qstr[0] != '\0') { if (qstr[0] == '%') { qstr++; switch (qstr[0]) { case 'n': pkg_get(pkg, PKG_NAME, &tmp); sbuf_cat(dest, tmp); break; case 'v': pkg_get(pkg, PKG_VERSION, &tmp); sbuf_cat(dest, tmp); break; case 'o': pkg_get(pkg, PKG_ORIGIN, &tmp); sbuf_cat(dest, tmp); break; case 'p': pkg_get(pkg, PKG_PREFIX, &tmp); sbuf_cat(dest, tmp); break; case 'm': pkg_get(pkg, PKG_MAINTAINER, &tmp); sbuf_cat(dest, tmp); break; case 'c': pkg_get(pkg, PKG_COMMENT, &tmp); sbuf_cat(dest, tmp); break; case 'w': pkg_get(pkg, PKG_WWW, &tmp); sbuf_cat(dest, tmp); break; case 'a': pkg_get(pkg, PKG_AUTOMATIC, &automatic); sbuf_printf(dest, "%d", automatic); break; case 's': qstr++; pkg_get(pkg, PKG_FLATSIZE, &flatsize); if (qstr[0] == 'h') { humanize_number(size, sizeof(size), flatsize, "B", HN_AUTOSCALE, 0); sbuf_cat(dest, size); } else if (qstr[0] == 'b') { sbuf_printf(dest, "%" PRId64, flatsize); } break; case '?': qstr++; switch (qstr[0]) { case 'd': sbuf_printf(dest, "%d", !pkg_list_is_empty(pkg, PKG_DEPS)); break; case 'r': sbuf_printf(dest, "%d", !pkg_list_is_empty(pkg, PKG_RDEPS)); break; case 'C': sbuf_printf(dest, "%d", !pkg_list_is_empty(pkg, PKG_CATEGORIES)); break; case 'F': sbuf_printf(dest, "%d", !pkg_list_is_empty(pkg, PKG_FILES)); break; case 'O': sbuf_printf(dest, "%d", !pkg_list_is_empty(pkg, PKG_OPTIONS)); break; case 'D': sbuf_printf(dest, "%d", !pkg_list_is_empty(pkg, PKG_DIRS)); break; case 'L': sbuf_printf(dest, "%d", !pkg_list_is_empty(pkg, PKG_LICENSES)); break; case 'U': sbuf_printf(dest, "%d", !pkg_list_is_empty(pkg, PKG_USERS)); break; case 'G': sbuf_printf(dest, "%d", !pkg_list_is_empty(pkg, PKG_GROUPS)); break; } break; case 'l': pkg_get(pkg, PKG_LICENSE_LOGIC, &licenselogic); switch (licenselogic) { case LICENSE_SINGLE: sbuf_cat(dest, "single"); break; case LICENSE_OR: sbuf_cat(dest, "or"); break; case LICENSE_AND: sbuf_cat(dest, "and"); break; } break; case 'd': qstr++; if (qstr[0] == 'n') sbuf_cat(dest, pkg_dep_get((struct pkg_dep *)data, PKG_DEP_NAME)); else if (qstr[0] == 'o') sbuf_cat(dest, pkg_dep_get((struct pkg_dep *)data, PKG_DEP_ORIGIN)); else if (qstr[0] == 'v') sbuf_cat(dest, pkg_dep_get((struct pkg_dep *)data, PKG_DEP_VERSION)); break; case 'r': qstr++; if (qstr[0] == 'n') sbuf_cat(dest, pkg_dep_get((struct pkg_dep *)data, PKG_DEP_NAME)); else if (qstr[0] == 'o') sbuf_cat(dest, pkg_dep_get((struct pkg_dep *)data, PKG_DEP_ORIGIN)); else if (qstr[0] == 'v') sbuf_cat(dest, pkg_dep_get((struct pkg_dep *)data, PKG_DEP_VERSION)); break; case 'C': sbuf_cat(dest, pkg_category_name((struct pkg_category *)data)); break; case 'F': qstr++; if (qstr[0] == 'p') sbuf_cat(dest, pkg_file_get((struct pkg_file *)data, PKG_FILE_PATH)); else if (qstr[0] == 's') sbuf_cat(dest, pkg_file_get((struct pkg_file *)data, PKG_FILE_SUM)); break; case 'S': sbuf_cat(dest, pkg_script_data((struct pkg_script *)data)); break; case 'O': qstr++; if (qstr[0] == 'k') sbuf_cat(dest, pkg_option_opt((struct pkg_option *)data)); else if (qstr[0] == 'v') sbuf_cat(dest, pkg_option_value((struct pkg_option *)data)); break; case 'D': sbuf_cat(dest, pkg_dir_path((struct pkg_dir *)data)); break; case 'L': sbuf_cat(dest, pkg_license_name((struct pkg_license *)data)); break; case 'U': sbuf_cat(dest, pkg_user_name((struct pkg_user *)data)); break; case 'G': sbuf_cat(dest, pkg_group_name((struct pkg_group *)data)); break; case '%': sbuf_putc(dest, '%'); break; } } else if (qstr[0] == '\\') { qstr++; switch (qstr[0]) { case 'n': sbuf_putc(dest, '\n'); break; case 'a': sbuf_putc(dest, '\a'); break; case 'b': sbuf_putc(dest, '\b'); break; case 'f': sbuf_putc(dest, '\f'); break; case 'r': sbuf_putc(dest, '\r'); break; case '\\': sbuf_putc(dest, '\\'); break; case 't': sbuf_putc(dest, '\t'); break; } } else { sbuf_putc(dest, qstr[0]); } qstr++; } sbuf_finish(dest); }
int procfs_doprocstatus(PFS_FILL_ARGS) { struct session *sess; struct thread *tdfirst; struct tty *tp; struct ucred *cr; const char *wmesg; char *pc; char *sep; int pid, ppid, pgid, sid; int i; pid = p->p_pid; PROC_LOCK(p); ppid = p->p_pptr ? p->p_pptr->p_pid : 0; pgid = p->p_pgrp->pg_id; sess = p->p_pgrp->pg_session; SESS_LOCK(sess); sid = sess->s_leader ? sess->s_leader->p_pid : 0; /* comm pid ppid pgid sid tty ctty,sldr start ut st wmsg euid ruid rgid,egid,groups[1 .. ngroups] */ pc = p->p_comm; do { if (*pc < 33 || *pc > 126 || *pc == '\\') sbuf_printf(sb, "\\%03o", *pc); else sbuf_putc(sb, *pc); } while (*++pc); sbuf_printf(sb, " %d %d %d %d ", pid, ppid, pgid, sid); if ((p->p_flag & P_CONTROLT) && (tp = sess->s_ttyp)) sbuf_printf(sb, "%s ", devtoname(tp->t_dev)); else sbuf_printf(sb, "- "); sep = ""; if (sess->s_ttyvp) { sbuf_printf(sb, "%sctty", sep); sep = ","; } if (SESS_LEADER(p)) { sbuf_printf(sb, "%ssldr", sep); sep = ","; } SESS_UNLOCK(sess); if (*sep != ',') { sbuf_printf(sb, "noflags"); } tdfirst = FIRST_THREAD_IN_PROC(p); thread_lock(tdfirst); if (tdfirst->td_wchan != NULL) { KASSERT(tdfirst->td_wmesg != NULL, ("wchan %p has no wmesg", tdfirst->td_wchan)); wmesg = tdfirst->td_wmesg; } else wmesg = "nochan"; thread_unlock(tdfirst); if (p->p_flag & P_INMEM) { struct timeval start, ut, st; PROC_SLOCK(p); calcru(p, &ut, &st); PROC_SUNLOCK(p); start = p->p_stats->p_start; timevaladd(&start, &boottime); sbuf_printf(sb, " %jd,%ld %jd,%ld %jd,%ld", (intmax_t)start.tv_sec, start.tv_usec, (intmax_t)ut.tv_sec, ut.tv_usec, (intmax_t)st.tv_sec, st.tv_usec); } else sbuf_printf(sb, " -1,-1 -1,-1 -1,-1"); sbuf_printf(sb, " %s", wmesg); cr = p->p_ucred; sbuf_printf(sb, " %lu %lu %lu", (u_long)cr->cr_uid, (u_long)cr->cr_ruid, (u_long)cr->cr_rgid); /* egid (cr->cr_svgid) is equal to cr_ngroups[0] see also getegid(2) in /sys/kern/kern_prot.c */ for (i = 0; i < cr->cr_ngroups; i++) { sbuf_printf(sb, ",%lu", (u_long)cr->cr_groups[i]); } if (jailed(cr)) { mtx_lock(&cr->cr_prison->pr_mtx); sbuf_printf(sb, " %s", prison_name(td->td_ucred->cr_prison, cr->cr_prison)); mtx_unlock(&cr->cr_prison->pr_mtx); } else { sbuf_printf(sb, " -"); } PROC_UNLOCK(p); sbuf_printf(sb, "\n"); return (0); }
static void format_str(struct pkg *pkg, struct sbuf *dest, const char *qstr, const void *data) { bool automatic; bool locked; sbuf_clear(dest); while (qstr[0] != '\0') { if (qstr[0] == '%') { qstr++; switch (qstr[0]) { case 'n': pkg_sbuf_printf(dest, "%n", pkg); break; case 'v': pkg_sbuf_printf(dest, "%v", pkg); break; case 'o': pkg_sbuf_printf(dest, "%o", pkg); break; case 'R': pkg_sbuf_printf(dest, "%N", pkg); break; case 'p': pkg_sbuf_printf(dest, "%p", pkg); break; case 'm': pkg_sbuf_printf(dest, "%m", pkg); break; case 'c': pkg_sbuf_printf(dest, "%c", pkg); break; case 'w': pkg_sbuf_printf(dest, "%w", pkg); break; case 'a': pkg_get(pkg, PKG_AUTOMATIC, &automatic); sbuf_printf(dest, "%d", automatic); break; case 'k': pkg_get(pkg, PKG_LOCKED, &locked); sbuf_printf(dest, "%d", locked); break; case 't': pkg_sbuf_printf(dest, "%t", pkg); break; case 's': qstr++; if (qstr[0] == 'h') pkg_sbuf_printf(dest, "%#sB", pkg); else if (qstr[0] == 'b') pkg_sbuf_printf(dest, "%s", pkg); break; case 'e': pkg_sbuf_printf(dest, "%e", pkg); break; case '?': qstr++; switch (qstr[0]) { case 'd': pkg_sbuf_printf(dest, "%?d", pkg); break; case 'r': pkg_sbuf_printf(dest, "%?r", pkg); break; case 'C': pkg_sbuf_printf(dest, "%?C", pkg); break; case 'F': pkg_sbuf_printf(dest, "%?F", pkg); break; case 'O': pkg_sbuf_printf(dest, "%?O", pkg); break; case 'D': pkg_sbuf_printf(dest, "%?D", pkg); break; case 'L': pkg_sbuf_printf(dest, "%?L", pkg); break; case 'U': pkg_sbuf_printf(dest, "%?U", pkg); break; case 'G': pkg_sbuf_printf(dest, "%?G", pkg); break; case 'B': pkg_sbuf_printf(dest, "%?B", pkg); break; case 'b': pkg_sbuf_printf(dest, "%?b", pkg); break; case 'A': pkg_sbuf_printf(dest, "%?A", pkg); break; } break; case '#': qstr++; switch (qstr[0]) { case 'd': pkg_sbuf_printf(dest, "%#d", pkg); break; case 'r': pkg_sbuf_printf(dest, "%#r", pkg); break; case 'C': pkg_sbuf_printf(dest, "%#C", pkg); break; case 'F': pkg_sbuf_printf(dest, "%#F", pkg); break; case 'O': pkg_sbuf_printf(dest, "%#O", pkg); break; case 'D': pkg_sbuf_printf(dest, "%#D", pkg); break; case 'L': pkg_sbuf_printf(dest, "%#L", pkg); break; case 'U': pkg_sbuf_printf(dest, "%#U", pkg); break; case 'G': pkg_sbuf_printf(dest, "%#G", pkg); break; case 'B': pkg_sbuf_printf(dest, "%#B", pkg); break; case 'b': pkg_sbuf_printf(dest, "%#b", pkg); break; case 'A': pkg_sbuf_printf(dest, "%#A", pkg); break; } break; case 'q': pkg_sbuf_printf(dest, "%q", pkg); break; case 'l': pkg_sbuf_printf(dest, "%l", pkg); break; case 'd': qstr++; if (qstr[0] == 'n') pkg_sbuf_printf(dest, "%dn", data); else if (qstr[0] == 'o') pkg_sbuf_printf(dest, "%do", data); else if (qstr[0] == 'v') pkg_sbuf_printf(dest, "%dv", data); break; case 'r': qstr++; if (qstr[0] == 'n') pkg_sbuf_printf(dest, "%rn", data); else if (qstr[0] == 'o') pkg_sbuf_printf(dest, "%ro", data); else if (qstr[0] == 'v') pkg_sbuf_printf(dest, "%rv", data); break; case 'C': pkg_sbuf_printf(dest, "%Cn", data); break; case 'F': qstr++; if (qstr[0] == 'p') pkg_sbuf_printf(dest, "%Fn", data); else if (qstr[0] == 's') pkg_sbuf_printf(dest, "%Fs", data); break; case 'O': qstr++; if (qstr[0] == 'k') pkg_sbuf_printf(dest, "%On", data); else if (qstr[0] == 'v') pkg_sbuf_printf(dest, "%Ov", data); else if (qstr[0] == 'd') /* default value */ pkg_sbuf_printf(dest, "%Od", data); else if (qstr[0] == 'D') /* description */ pkg_sbuf_printf(dest, "%OD", data); break; case 'D': pkg_sbuf_printf(dest, "%Dn", data); break; case 'L': pkg_sbuf_printf(dest, "%Ln", data); break; case 'U': pkg_sbuf_printf(dest, "%Un", data); break; case 'G': pkg_sbuf_printf(dest, "%Gn", data); break; case 'B': pkg_sbuf_printf(dest, "%Bn", data); break; case 'b': pkg_sbuf_printf(dest, "%bn", data); break; case 'A': qstr++; if (qstr[0] == 't') pkg_sbuf_printf(dest, "%An", data); else if (qstr[0] == 'v') pkg_sbuf_printf(dest, "%Av", data); break; case 'M': if (pkg_has_message(pkg)) pkg_sbuf_printf(dest, "%M", pkg); break; case '%': sbuf_putc(dest, '%'); break; } } else if (qstr[0] == '\\') { qstr++; switch (qstr[0]) { case 'n': sbuf_putc(dest, '\n'); break; case 'a': sbuf_putc(dest, '\a'); break; case 'b': sbuf_putc(dest, '\b'); break; case 'f': sbuf_putc(dest, '\f'); break; case 'r': sbuf_putc(dest, '\r'); break; case '\\': sbuf_putc(dest, '\\'); break; case 't': sbuf_putc(dest, '\t'); break; } } else { sbuf_putc(dest, qstr[0]); } qstr++; } sbuf_finish(dest); }
int format_sql_condition(const char *str, struct sbuf *sqlcond, bool for_remote) { state_t state = NONE; unsigned int bracket_level = 0; const char *sqlop; sbuf_cat(sqlcond, " WHERE "); while (str[0] != '\0') { if (state == NONE) { if (str[0] == '%') { str++; switch (str[0]) { case 'n': sbuf_cat(sqlcond, "name"); state = OPERATOR_STRING; break; case 'o': sbuf_cat(sqlcond, "origin"); state = OPERATOR_STRING; break; case 'p': sbuf_cat(sqlcond, "prefix"); state = OPERATOR_STRING; break; case 'm': sbuf_cat(sqlcond, "maintainer"); state = OPERATOR_STRING; break; case 'c': sbuf_cat(sqlcond, "comment"); state = OPERATOR_STRING; break; case 'w': sbuf_cat(sqlcond, "www"); state = OPERATOR_STRING; break; case 's': sbuf_cat(sqlcond, "flatsize"); state = OPERATOR_INT; break; case 'a': if (for_remote) goto bad_option; sbuf_cat(sqlcond, "automatic"); state = OPERATOR_INT; break; case 'q': sbuf_cat(sqlcond, "arch"); state = OPERATOR_STRING; break; case 'k': if (for_remote) goto bad_option; sbuf_cat(sqlcond, "locked"); state = OPERATOR_INT; break; case 'M': if (for_remote) goto bad_option; sbuf_cat(sqlcond, "message"); state = OPERATOR_STRING; break; case 't': if (for_remote) goto bad_option; sbuf_cat(sqlcond, "time"); state = OPERATOR_INT; break; case 'e': sbuf_cat(sqlcond, "desc"); state = OPERATOR_STRING; break; case '#': /* FALLTHROUGH */ case '?': sqlop = (str[0] == '#' ? "COUNT(*)" : "COUNT(*) > 0"); str++; switch (str[0]) { case 'd': sbuf_printf(sqlcond, "(SELECT %s FROM deps AS d WHERE d.package_id=p.id)", sqlop); break; case 'r': sbuf_printf(sqlcond, "(SELECT %s FROM deps AS d WHERE d.origin=p.origin)", sqlop); break; case 'C': sbuf_printf(sqlcond, "(SELECT %s FROM pkg_categories AS d WHERE d.package_id=p.id)", sqlop); break; case 'F': if (for_remote) goto bad_option; sbuf_printf(sqlcond, "(SELECT %s FROM files AS d WHERE d.package_id=p.id)", sqlop); break; case 'O': sbuf_printf(sqlcond, "(SELECT %s FROM pkg_option AS d WHERE d.package_id=p.id)", sqlop); break; case 'D': if (for_remote) goto bad_option; sbuf_printf(sqlcond, "(SELECT %s FROM pkg_directories AS d WHERE d.package_id=p.id)", sqlop); break; case 'L': sbuf_printf(sqlcond, "(SELECT %s FROM pkg_licenses AS d WHERE d.package_id=p.id)", sqlop); break; case 'U': if (for_remote) goto bad_option; sbuf_printf(sqlcond, "(SELECT %s FROM pkg_users AS d WHERE d.package_id=p.id)", sqlop); break; case 'G': if (for_remote) goto bad_option; sbuf_printf(sqlcond, "(SELECT %s FROM pkg_groups AS d WHERE d.package_id=p.id)", sqlop); break; case 'B': sbuf_printf(sqlcond, "(SELECT %s FROM pkg_shlibs_required AS d WHERE d.package_id=p.id)", sqlop); break; case 'b': sbuf_printf(sqlcond, "(SELECT %s FROM pkg_shlibs_provided AS d WHERE d.package_id=p.id)", sqlop); break; case 'A': sbuf_printf(sqlcond, "(SELECT %s FROM pkg_annotation AS d WHERE d.package_id=p.id)", sqlop); break; default: goto bad_option; } state = OPERATOR_INT; break; default: bad_option: fprintf(stderr, "malformed evaluation string\n"); return (EPKG_FATAL); } } else { switch (str[0]) { case '(': bracket_level++; sbuf_putc(sqlcond, str[0]); break; case ' ': case '\t': break; default: fprintf(stderr, "unexpected character: %c\n", str[0]); return (EPKG_FATAL); } } } else if (state == POST_EXPR) { switch (str[0]) { case ')': if (bracket_level == 0) { fprintf(stderr, "too many closing brackets.\n"); return (EPKG_FATAL); } bracket_level--; sbuf_putc(sqlcond, str[0]); break; case ' ': case '\t': break; case '|': if (str[1] == '|') { str++; state = NONE; sbuf_cat(sqlcond, " OR "); break; } else { fprintf(stderr, "unexpected character %c\n", str[1]); return (EPKG_FATAL); } case '&': if (str[1] == '&') { str++; state = NONE; sbuf_cat(sqlcond, " AND "); break; } else { fprintf(stderr, "unexpected character %c\n", str[1]); return (EPKG_FATAL); } default: fprintf(stderr, "unexpected character %c\n", str[0]); return (EPKG_FATAL); } } else if (state == OPERATOR_STRING || state == OPERATOR_INT) { /* only operators or space are allowed here */ if (isspace(str[0])) { /* do nothing */ } else if (str[0] == '~' ) { if (state != OPERATOR_STRING) { fprintf(stderr, "~ expected only for string testing\n"); return (EPKG_FATAL); } state = NEXT_IS_STRING; sbuf_cat(sqlcond, " GLOB "); } else if (str[0] == '>' || str[0] == '<') { if (state != OPERATOR_INT) { fprintf(stderr, "> expected only for integers\n"); return (EPKG_FATAL); } state = NEXT_IS_INT; sbuf_putc(sqlcond, str[0]); if (str[1] == '=') { str++; sbuf_putc(sqlcond, str[0]); } } else if (str[0] == '=') { if (state == OPERATOR_STRING) { state = NEXT_IS_STRING; } else { state = NEXT_IS_INT; } sbuf_putc(sqlcond, str[0]); if (str[1] == '=') { str++; sbuf_putc(sqlcond, str[0]); } } else if (str[0] == '!') { if (str[1] != '=') { fprintf(stderr, "expecting = after !\n"); return (EPKG_FATAL); } if (state == OPERATOR_STRING) { state = NEXT_IS_STRING; } else { state = NEXT_IS_INT; } sbuf_putc(sqlcond, str[0]); str++; sbuf_putc(sqlcond, str[0]); } else { fprintf(stderr, "an operator is expected, got %c\n", str[0]); return (EPKG_FATAL); } } else if (state == NEXT_IS_STRING || state == NEXT_IS_INT) { if (isspace(str[0])) { /* do nothing */ } else { if (state == NEXT_IS_STRING) { if (str[0] == '"') { state = QUOTEDSTRING; } else if (str[0] == '\'') { state = SQUOTEDSTRING; } else { state = STRING; str--; } sbuf_putc(sqlcond, '\''); } else { if (!isdigit(str[0])) { fprintf(stderr, "a number is expected, got: %c\n", str[0]); return (EPKG_FATAL); } state = INT; sbuf_putc(sqlcond, str[0]); } } } else if (state == INT) { if (!isdigit(str[0])) { state = POST_EXPR; str--; } else { sbuf_putc(sqlcond, str[0]); } } else if (state == STRING || state == QUOTEDSTRING || state == SQUOTEDSTRING) { if ((state == STRING && isspace(str[0])) || (state == QUOTEDSTRING && str[0] == '"') || (state == SQUOTEDSTRING && str[0] == '\'')) { sbuf_putc(sqlcond, '\''); state = POST_EXPR; } else { sbuf_putc(sqlcond, str[0]); if (str[0] == '\'') sbuf_putc(sqlcond, str[0]); else if (str[0] == '%' && for_remote) sbuf_putc(sqlcond, str[0]); } } str++; } if (state == STRING) { sbuf_putc(sqlcond, '\''); state = POST_EXPR; } if (state != POST_EXPR && state != INT) { fprintf(stderr, "unexpected end of expression\n"); return (EPKG_FATAL); } else if (bracket_level > 0) { fprintf(stderr, "unexpected end of expression (too many open brackets)\n"); return (EPKG_FATAL); } return (EPKG_OK); }
int format_exec_cmd(char **dest, const char *in, const char *prefix, const char *plist_file, char *line, int argc, char **argv) { struct sbuf *buf = sbuf_new_auto(); char path[MAXPATHLEN]; char *cp; size_t sz; while (in[0] != '\0') { if (in[0] != '%') { sbuf_putc(buf, in[0]); in++; continue; } in++; switch(in[0]) { case 'D': sbuf_cat(buf, prefix); break; case 'F': if (plist_file == NULL || plist_file[0] == '\0') { pkg_emit_error("No files defined %%F couldn't " "be expanded, ignoring %s", in); sbuf_finish(buf); sbuf_free(buf); return (EPKG_FATAL); } sbuf_cat(buf, plist_file); break; case 'f': if (plist_file == NULL || plist_file[0] == '\0') { pkg_emit_error("No files defined %%f couldn't " "be expanded, ignoring %s", in); sbuf_finish(buf); sbuf_free(buf); return (EPKG_FATAL); } if (prefix[strlen(prefix) - 1] == '/') snprintf(path, sizeof(path), "%s%s", prefix, plist_file); else snprintf(path, sizeof(path), "%s/%s", prefix, plist_file); cp = strrchr(path, '/'); cp ++; sbuf_cat(buf, cp); break; case 'B': if (plist_file == NULL || plist_file[0] == '\0') { pkg_emit_error("No files defined %%B couldn't " "be expanded, ignoring %s", in); sbuf_finish(buf); sbuf_free(buf); return (EPKG_FATAL); } if (prefix[strlen(prefix) - 1] == '/') snprintf(path, sizeof(path), "%s%s", prefix, plist_file); else snprintf(path, sizeof(path), "%s/%s", prefix, plist_file); cp = strrchr(path, '/'); cp[0] = '\0'; sbuf_cat(buf, path); break; case '%': sbuf_putc(buf, '%'); break; case '@': if (line != NULL) { sbuf_cat(buf, line); break; } /* * no break here because if line is not * given (default exec) %@ does not * exists */ case '#': sbuf_putc(buf, argc); break; default: if ((sz = strspn(in, "0123456789")) > 0) { int pos = strtol(in, NULL, 10); if (pos > argc) { pkg_emit_error("Requesting argument " "%%%d while only %d arguments are" " available", pos, argc); sbuf_finish(buf); sbuf_free(buf); return (EPKG_FATAL); } sbuf_cat(buf, argv[pos -1]); in += sz -1; break; } sbuf_putc(buf, '%'); sbuf_putc(buf, in[0]); break; } in++; } sbuf_finish(buf); *dest = strdup(sbuf_data(buf)); sbuf_free(buf); return (EPKG_OK); }
struct t_rename_pattern * t_rename_parse(const char *source) { const char sep = '%'; const char *c = source; struct t_rename_pattern *pattern = NULL; struct t_rename_token *token; struct sbuf *sb = NULL; enum { PARSING_STRING, PARSING_SIMPLE_TAG, PARSING_BRACE_TAG } state; sb = sbuf_new_auto(); if (sb == NULL) goto error_label; pattern = malloc(sizeof(struct t_rename_pattern)); if (pattern == NULL) goto error_label; TAILQ_INIT(pattern); state = PARSING_STRING; while (*c != '\0') { /* if we parse a litteral string, check if this is the start of a tag */ if (state == PARSING_STRING && *c == sep) { /* avoid to add a empty token. This can happen when when parsing two consecutive tags like `%tag%tag' */ if (sbuf_len(sb) > 0) { if (sbuf_finish(sb) == -1) goto error_label; token = t_rename_token_new(T_STRING, sbuf_data(sb)); if (token == NULL) goto error_label; TAILQ_INSERT_TAIL(pattern, token, entries); } sbuf_clear(sb); c += 1; if (*c == '{') { c += 1; state = PARSING_BRACE_TAG; } else { state = PARSING_SIMPLE_TAG; } /* if we parse a tag, check for the end of it */ } else if ((state == PARSING_SIMPLE_TAG && (*c == sep || !isalnum(*c))) || (state == PARSING_BRACE_TAG && *c == '}')) { if (sbuf_len(sb) == 0) warnx("empty tag in rename pattern"); if (sbuf_finish(sb) == -1) goto error_label; token = t_rename_token_new(T_TAG, sbuf_data(sb)); if (token == NULL) goto error_label; sbuf_clear(sb); TAILQ_INSERT_TAIL(pattern, token, entries); if (state == PARSING_BRACE_TAG) { /* eat the closing `}' */ c += 1; } state = PARSING_STRING; } else { /* default case for both string and tags. `\' escape everything */ if (*c == '\\') { c += 1; if (*c == '\0') break; } sbuf_putc(sb, *c); c += 1; } } /* we've hit the end of the source. Check in which state we are and try to finish cleany */ switch (state) { case PARSING_BRACE_TAG: warnx("missing closing `}' at the end of the rename pattern"); goto error_label; case PARSING_SIMPLE_TAG: if (sbuf_len(sb) == 0) warnx("empty tag at the end of the rename pattern"); case PARSING_STRING: /* FALLTHROUGH */ default: /* all is right */; } /* finish the last tag unless it is the empty string */ if (state != PARSING_STRING || sbuf_len(sb) > 0) { if (sbuf_finish(sb) == -1) goto error_label; token = t_rename_token_new( (state == PARSING_STRING ? T_STRING : T_TAG), sbuf_data(sb)); if (token == NULL) goto error_label; TAILQ_INSERT_TAIL(pattern, token, entries); } sbuf_delete(sb); return (pattern); /* NOTREACHED */ error_label: sbuf_delete(sb); t_rename_pattern_delete(pattern); return (NULL); }
static void config_parse(const ucl_object_t *obj, pkg_conf_file_t conftype) { struct sbuf *buf = sbuf_new_auto(); const ucl_object_t *cur, *seq; ucl_object_iter_t it = NULL, itseq = NULL; struct config_entry *temp_config; struct config_value *cv; const char *key; int i; size_t j; /* Temporary config for configs that may be disabled. */ temp_config = calloc(CONFIG_SIZE, sizeof(struct config_entry)); while ((cur = ucl_iterate_object(obj, &it, true))) { key = ucl_object_key(cur); if (key == NULL) continue; sbuf_clear(buf); if (conftype == CONFFILE_PKG) { for (j = 0; j < strlen(key); ++j) sbuf_putc(buf, key[j]); sbuf_finish(buf); } else if (conftype == CONFFILE_REPO) { if (strcasecmp(key, "url") == 0) sbuf_cpy(buf, "PACKAGESITE"); else if (strcasecmp(key, "mirror_type") == 0) sbuf_cpy(buf, "MIRROR_TYPE"); else if (strcasecmp(key, "signature_type") == 0) sbuf_cpy(buf, "SIGNATURE_TYPE"); else if (strcasecmp(key, "fingerprints") == 0) sbuf_cpy(buf, "FINGERPRINTS"); else if (strcasecmp(key, "enabled") == 0) { if ((cur->type != UCL_BOOLEAN) || !ucl_object_toboolean(cur)) goto cleanup; } else continue; sbuf_finish(buf); } for (i = 0; i < CONFIG_SIZE; i++) { if (strcmp(sbuf_data(buf), c[i].key) == 0) break; } /* Silently skip unknown keys to be future compatible. */ if (i == CONFIG_SIZE) continue; /* env has priority over config file */ if (c[i].envset) continue; /* Parse sequence value ["item1", "item2"] */ switch (c[i].type) { case PKG_CONFIG_LIST: if (cur->type != UCL_ARRAY) { warnx("Skipping invalid array " "value for %s.\n", c[i].key); continue; } temp_config[i].list = malloc(sizeof(*temp_config[i].list)); STAILQ_INIT(temp_config[i].list); while ((seq = ucl_iterate_object(cur, &itseq, true))) { if (seq->type != UCL_STRING) continue; cv = malloc(sizeof(struct config_value)); cv->value = strdup(ucl_object_tostring(seq)); STAILQ_INSERT_TAIL(temp_config[i].list, cv, next); } break; case PKG_CONFIG_BOOL: temp_config[i].value = strdup(ucl_object_toboolean(cur) ? "yes" : "no"); break; default: /* Normal string value. */ temp_config[i].value = strdup(ucl_object_tostring(cur)); break; } } /* Repo is enabled, copy over all settings from temp_config. */ for (i = 0; i < CONFIG_SIZE; i++) { if (c[i].envset) continue; /* Prevent overriding ABI, ASSUME_ALWAYS_YES, etc. */ if (conftype != CONFFILE_PKG && c[i].main_only == true) continue; switch (c[i].type) { case PKG_CONFIG_LIST: c[i].list = temp_config[i].list; break; default: c[i].value = temp_config[i].value; break; } } cleanup: free(temp_config); sbuf_delete(buf); }
static void format_str(struct pkg *pkg, struct sbuf *dest, const char *qstr, void *data) { char size[7]; const char *tmp; bool tmp2; int64_t flatsize; int64_t timestamp; lic_t licenselogic; sbuf_clear(dest); while (qstr[0] != '\0') { if (qstr[0] == '%') { qstr++; switch (qstr[0]) { case 'n': pkg_get(pkg, PKG_NAME, &tmp); if (tmp != NULL) sbuf_cat(dest, tmp); break; case 'v': pkg_get(pkg, PKG_VERSION, &tmp); if (tmp != NULL) sbuf_cat(dest, tmp); break; case 'o': pkg_get(pkg, PKG_ORIGIN, &tmp); if (tmp != NULL) sbuf_cat(dest, tmp); break; case 'R': pkg_get(pkg, PKG_REPONAME, &tmp); if (tmp != NULL) sbuf_cat(dest, tmp); break; case 'p': pkg_get(pkg, PKG_PREFIX, &tmp); if (tmp != NULL) sbuf_cat(dest, tmp); break; case 'm': pkg_get(pkg, PKG_MAINTAINER, &tmp); if (tmp != NULL) sbuf_cat(dest, tmp); break; case 'c': pkg_get(pkg, PKG_COMMENT, &tmp); if (tmp != NULL) sbuf_cat(dest, tmp); break; case 'w': pkg_get(pkg, PKG_WWW, &tmp); if (tmp != NULL) sbuf_cat(dest, tmp); break; case 'i': pkg_get(pkg, PKG_INFOS, &tmp); if (tmp != NULL) sbuf_cat(dest, tmp); break; case 'a': pkg_get(pkg, PKG_AUTOMATIC, &tmp2); sbuf_printf(dest, "%d", tmp2); break; case 'k': pkg_get(pkg, PKG_LOCKED, &tmp2); sbuf_printf(dest, "%d", tmp2); break; case 't': pkg_get(pkg, PKG_TIME, ×tamp); sbuf_printf(dest, "%" PRId64, timestamp); break; case 's': qstr++; pkg_get(pkg, PKG_FLATSIZE, &flatsize); if (qstr[0] == 'h') { humanize_number(size, sizeof(size), flatsize, "B", HN_AUTOSCALE, 0); sbuf_cat(dest, size); } else if (qstr[0] == 'b') { sbuf_printf(dest, "%" PRId64, flatsize); } break; case 'e': pkg_get(pkg, PKG_DESC, &tmp); if (tmp != NULL) sbuf_cat(dest, tmp); break; case '?': qstr++; switch (qstr[0]) { case 'd': sbuf_printf(dest, "%d", pkg_list_count(pkg, PKG_DEPS) > 0); break; case 'r': sbuf_printf(dest, "%d", pkg_list_count(pkg, PKG_RDEPS) > 0); break; case 'C': sbuf_printf(dest, "%d", pkg_list_count(pkg, PKG_CATEGORIES) > 0); break; case 'F': sbuf_printf(dest, "%d", pkg_list_count(pkg, PKG_FILES) > 0); break; case 'O': sbuf_printf(dest, "%d", pkg_list_count(pkg, PKG_OPTIONS) > 0); break; case 'D': sbuf_printf(dest, "%d", pkg_list_count(pkg, PKG_DIRS) > 0); break; case 'L': sbuf_printf(dest, "%d", pkg_list_count(pkg, PKG_LICENSES) > 0); break; case 'U': sbuf_printf(dest, "%d", pkg_list_count(pkg, PKG_USERS) > 0); break; case 'G': sbuf_printf(dest, "%d", pkg_list_count(pkg, PKG_GROUPS) > 0); break; case 'B': sbuf_printf(dest, "%d", pkg_list_count(pkg, PKG_SHLIBS_REQUIRED) > 0); break; case 'b': sbuf_printf(dest, "%d", pkg_list_count(pkg, PKG_SHLIBS_PROVIDED) > 0); break; case 'A': sbuf_printf(dest, "%d", pkg_list_count(pkg, PKG_ANNOTATIONS) > 0); break; } break; case '#': qstr++; switch (qstr[0]) { case 'd': sbuf_printf(dest, "%d", pkg_list_count(pkg, PKG_DEPS)); break; case 'r': sbuf_printf(dest, "%d", pkg_list_count(pkg, PKG_RDEPS)); break; case 'C': sbuf_printf(dest, "%d", pkg_list_count(pkg, PKG_CATEGORIES)); break; case 'F': sbuf_printf(dest, "%d", pkg_list_count(pkg, PKG_FILES)); break; case 'O': sbuf_printf(dest, "%d", pkg_list_count(pkg, PKG_OPTIONS)); break; case 'D': sbuf_printf(dest, "%d", pkg_list_count(pkg, PKG_DIRS)); break; case 'L': sbuf_printf(dest, "%d", pkg_list_count(pkg, PKG_LICENSES)); break; case 'U': sbuf_printf(dest, "%d", pkg_list_count(pkg, PKG_USERS)); break; case 'G': sbuf_printf(dest, "%d", pkg_list_count(pkg, PKG_GROUPS)); break; case 'B': sbuf_printf(dest, "%d", pkg_list_count(pkg, PKG_SHLIBS_REQUIRED)); break; case 'b': sbuf_printf(dest, "%d", pkg_list_count(pkg, PKG_SHLIBS_PROVIDED)); break; case 'A': sbuf_printf(dest, "%d", pkg_list_count(pkg, PKG_ANNOTATIONS)); break; } break; case 'l': pkg_get(pkg, PKG_LICENSE_LOGIC, &licenselogic); switch (licenselogic) { case LICENSE_SINGLE: sbuf_cat(dest, "single"); break; case LICENSE_OR: sbuf_cat(dest, "or"); break; case LICENSE_AND: sbuf_cat(dest, "and"); break; } break; case 'd': qstr++; if (qstr[0] == 'n') sbuf_cat(dest, pkg_dep_name((struct pkg_dep *)data)); else if (qstr[0] == 'o') sbuf_cat(dest, pkg_dep_origin((struct pkg_dep *)data)); else if (qstr[0] == 'v') sbuf_cat(dest, pkg_dep_version((struct pkg_dep *)data)); break; case 'r': qstr++; if (qstr[0] == 'n') sbuf_cat(dest, pkg_dep_name((struct pkg_dep *)data)); else if (qstr[0] == 'o') sbuf_cat(dest, pkg_dep_origin((struct pkg_dep *)data)); else if (qstr[0] == 'v') sbuf_cat(dest, pkg_dep_version((struct pkg_dep *)data)); break; case 'C': sbuf_cat(dest, pkg_category_name((struct pkg_category *)data)); break; case 'F': qstr++; if (qstr[0] == 'p') sbuf_cat(dest, pkg_file_path((struct pkg_file *)data)); else if (qstr[0] == 's') sbuf_cat(dest, pkg_file_cksum((struct pkg_file *)data)); break; case 'O': qstr++; if (qstr[0] == 'k') sbuf_cat(dest, pkg_option_opt((struct pkg_option *)data)); else if (qstr[0] == 'v') sbuf_cat(dest, pkg_option_value((struct pkg_option *)data)); break; case 'D': sbuf_cat(dest, pkg_dir_path((struct pkg_dir *)data)); break; case 'L': sbuf_cat(dest, pkg_license_name((struct pkg_license *)data)); break; case 'U': sbuf_cat(dest, pkg_user_name((struct pkg_user *)data)); break; case 'G': sbuf_cat(dest, pkg_group_name((struct pkg_group *)data)); break; case 'B': case 'b': sbuf_cat(dest, pkg_shlib_name((struct pkg_shlib *)data)); break; case 'A': qstr++; if (qstr[0] == 't') sbuf_cat(dest, pkg_annotation_tag((struct pkg_note *)data)); else if (qstr[0] == 'v') sbuf_cat(dest, pkg_annotation_value((struct pkg_note *)data)); break; case 'M': pkg_get(pkg, PKG_MESSAGE, &tmp); if (tmp != NULL) sbuf_cat(dest, tmp); break; case '%': sbuf_putc(dest, '%'); break; } } else if (qstr[0] == '\\') { qstr++; switch (qstr[0]) { case 'n': sbuf_putc(dest, '\n'); break; case 'a': sbuf_putc(dest, '\a'); break; case 'b': sbuf_putc(dest, '\b'); break; case 'f': sbuf_putc(dest, '\f'); break; case 'r': sbuf_putc(dest, '\r'); break; case '\\': sbuf_putc(dest, '\\'); break; case 't': sbuf_putc(dest, '\t'); break; } } else { sbuf_putc(dest, qstr[0]); } qstr++; } sbuf_finish(dest); }
int main(int argc, char *argv[]) { struct sbuf *cmdbuf; long arg_max; int ch, debug, i, magic, n, nargs, offset, rval; size_t cmdsize; char *cmd, *name, *p, *shell, *slashp, *tmpshell; debug = 0; magic = '%'; /* Default magic char is `%'. */ nargs = -1; while ((ch = getopt(argc, argv, "a:d0123456789")) != -1) switch (ch) { case 'a': if (optarg[1] != '\0') errx(1, "illegal magic character specification"); magic = optarg[0]; break; case 'd': debug = 1; break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if (nargs != -1) errx(1, "only one -# argument may be specified"); nargs = optopt - '0'; break; default: usage(); } argc -= optind; argv += optind; if (argc < 2) usage(); /* * The command to run is argv[0], and the args are argv[1..]. * Look for %digit references in the command, remembering the * largest one. */ for (n = 0, p = argv[0]; *p != '\0'; ++p) if (p[0] == magic && isdigit(p[1]) && p[1] != '0') { ++p; if (p[0] - '0' > n) n = p[0] - '0'; } /* * Figure out the shell and name arguments to pass to execl() * in exec_shell(). Always malloc() shell and just set name * to point at the last part of shell if there are any backslashes, * otherwise just set it to point at the space malloc()'d. If * SHELL environment variable exists, replace contents of * shell with it. */ shell = name = NULL; tmpshell = getenv("SHELL"); shell = (tmpshell != NULL) ? strdup(tmpshell) : strdup(_PATH_BSHELL); if (shell == NULL) err(1, "strdup() failed"); slashp = strrchr(shell, '/'); name = (slashp != NULL) ? slashp + 1 : shell; /* * If there were any %digit references, then use those, otherwise * build a new command string with sufficient %digit references at * the end to consume (nargs) arguments each time round the loop. * Allocate enough space to hold the maximum command. Save the * size to pass to snprintf(). */ cmdsize = sizeof(EXEC) - 1 + strlen(argv[0]) + 9 * (sizeof(" %1") - 1) + 1; if ((cmd = malloc(cmdsize)) == NULL) err(1, NULL); if (n == 0) { /* If nargs not set, default to a single argument. */ if (nargs == -1) nargs = 1; p = cmd; offset = snprintf(cmd, cmdsize, EXEC "%s", argv[0]); if ((size_t)offset >= cmdsize) errx(1, "snprintf() failed"); p += offset; cmdsize -= offset; for (i = 1; i <= nargs; i++) { offset = snprintf(p, cmdsize, " %c%d", magic, i); if ((size_t)offset >= cmdsize) errx(1, "snprintf() failed"); p += offset; cmdsize -= offset; } /* * If nargs set to the special value 0, eat a single * argument for each command execution. */ if (nargs == 0) nargs = 1; } else { offset = snprintf(cmd, cmdsize, EXEC "%s", argv[0]); if ((size_t)offset >= cmdsize) errx(1, "snprintf() failed"); nargs = n; } cmdbuf = sbuf_new(NULL, NULL, 1024, SBUF_AUTOEXTEND); if (cmdbuf == NULL) err(1, NULL); arg_max = sysconf(_SC_ARG_MAX); /* * (argc) and (argv) are still offset by one to make it simpler to * expand %digit references. At the end of the loop check for (argc) * equals 1 means that all the (argv) has been consumed. */ for (rval = 0; argc > nargs; argc -= nargs, argv += nargs) { sbuf_clear(cmdbuf); /* Expand command argv references. */ for (p = cmd; *p != '\0'; ++p) { if (p[0] == magic && isdigit(p[1]) && p[1] != '0') { if (sbuf_cat(cmdbuf, argv[(++p)[0] - '0']) == -1) errc(1, ENOMEM, "sbuf"); } else { if (sbuf_putc(cmdbuf, *p) == -1) errc(1, ENOMEM, "sbuf"); } if (sbuf_len(cmdbuf) > arg_max) errc(1, E2BIG, NULL); } /* Terminate the command string. */ sbuf_finish(cmdbuf); /* Run the command. */ if (debug) (void)printf("%s\n", sbuf_data(cmdbuf)); else if (exec_shell(sbuf_data(cmdbuf), shell, name)) rval = 1; } if (argc != 1) errx(1, "expecting additional argument%s after \"%s\"", (nargs - argc) ? "s" : "", argv[argc - 1]); free(cmd); sbuf_delete(cmdbuf); free(shell); exit(rval); }
/* mtree_resolve() sets errno to indicate why NULL was returned. */ static char * mtree_resolve(const char *spec, int *istemp) { struct sbuf *sb; char *res, *var; const char *base, *p, *v; size_t len; int c, error, quoted, subst; len = strlen(spec); if (len == 0) { errno = EINVAL; return (NULL); } c = (len > 1) ? (spec[0] == spec[len - 1]) ? spec[0] : 0 : 0; *istemp = (c == '`') ? 1 : 0; subst = (c == '`' || c == '"') ? 1 : 0; quoted = (subst || c == '\'') ? 1 : 0; if (!subst) { res = strdup(spec + quoted); if (res != NULL && quoted) res[len - 2] = '\0'; return (res); } sb = sbuf_new_auto(); if (sb == NULL) { errno = ENOMEM; return (NULL); } base = spec + 1; len -= 2; error = 0; while (len > 0) { p = strchr(base, '$'); if (p == NULL) { sbuf_bcat(sb, base, len); base += len; len = 0; continue; } /* The following is safe. spec always starts with a quote. */ if (p[-1] == '\\') p--; if (base != p) { sbuf_bcat(sb, base, p - base); len -= p - base; base = p; } if (*p == '\\') { sbuf_putc(sb, '$'); base += 2; len -= 2; continue; } /* Skip the '$'. */ base++; len--; /* Handle ${X} vs $X. */ v = base; if (*base == '{') { p = strchr(v, '}'); if (p == NULL) p = v; } else p = v; len -= (p + 1) - base; base = p + 1; if (v == p) { sbuf_putc(sb, *v); continue; } error = ENOMEM; var = calloc(p - v, 1); if (var == NULL) break; memcpy(var, v + 1, p - v - 1); if (strcmp(var, ".CURDIR") == 0) { res = getcwd(NULL, 0); if (res == NULL) break; } else if (strcmp(var, ".PROG") == 0) { res = strdup(getprogname()); if (res == NULL) break; } else { v = getenv(var); if (v != NULL) { res = strdup(v); if (res == NULL) break; } else res = NULL; } error = 0; if (res != NULL) { sbuf_cat(sb, res); free(res); } free(var); } sbuf_finish(sb); res = (error == 0) ? strdup(sbuf_data(sb)) : NULL; sbuf_delete(sb); if (res == NULL) errno = ENOMEM; return (res); }
static int scan(FILE *fp, const char *name, bool quiet) { int c; bool hasid = false; bool subversion = false; analyzer_states state = INIT; struct sbuf *id = sbuf_new_auto(); locale_t l; l = newlocale(LC_ALL_MASK, "C", NULL); if (name != NULL) printf("%s:\n", name); while ((c = fgetc(fp)) != EOF) { switch (state) { case INIT: if (c == '$') { /* Transit to DELIM_SEEN if we see $ */ state = DELIM_SEEN; } else { /* Otherwise, stay in INIT state */ continue; } break; case DELIM_SEEN: if (isalpha_l(c, l)) { /* Transit to KEYWORD if we see letter */ sbuf_clear(id); sbuf_putc(id, '$'); sbuf_putc(id, c); state = KEYWORD; continue; } else if (c == '$') { /* Or, stay in DELIM_SEEN if more $ */ continue; } else { /* Otherwise, transit back to INIT */ state = INIT; } break; case KEYWORD: sbuf_putc(id, c); if (isalpha_l(c, l)) { /* * Stay in KEYWORD if additional letter is seen */ continue; } else if (c == ':') { /* * See ':' for the first time, transit to * PUNC_SEEN. */ state = PUNC_SEEN; subversion = false; } else if (c == '$') { /* * Incomplete ident. Go back to DELIM_SEEN * state because we see a '$' which could be * the beginning of a keyword. */ state = DELIM_SEEN; } else { /* * Go back to INIT state otherwise. */ state = INIT; } break; case PUNC_SEEN: case PUNC_SEEN_SVN: sbuf_putc(id, c); switch (c) { case ':': /* * If we see '::' (seen : in PUNC_SEEN), * activate subversion treatment and transit * to PUNC_SEEN_SVN state. * * If more than two :'s were seen, the ident * is invalid and we would therefore go back * to INIT state. */ if (state == PUNC_SEEN) { state = PUNC_SEEN_SVN; subversion = true; } else { state = INIT; } break; case ' ': /* * A space after ':' or '::' indicates we are at the * last component of potential ident. */ state = TEXT; break; default: /* All other characters are invalid */ state = INIT; break; } break; case TEXT: sbuf_putc(id, c); if (iscntrl_l(c, l)) { /* Control characters are not allowed in this state */ state = INIT; } else if (c == '$') { sbuf_finish(id); /* * valid ident should end with a space. * * subversion extension uses '#' to indicate that * the keyword expansion have exceeded the fixed * width, so it is also permitted if we are in * subversion mode. No length check is enforced * because GNU RCS ident(1) does not do it either. */ c = sbuf_data(id)[sbuf_len(id) - 2]; if (c == ' ' || (subversion && c == '#')) { printf(" %s\n", sbuf_data(id)); hasid = true; } state = INIT; } /* Other characters: stay in the state */ break; } } sbuf_delete(id); freelocale(l); if (!hasid) { if (!quiet) fprintf(stderr, "%s warning: no id keywords in %s\n", getprogname(), name ? name : "standard input"); return (EXIT_FAILURE); } return (EXIT_SUCCESS); }