diff options
author | Dave Reisner <d@falconindy.com> | 2010-12-10 22:38:24 -0500 |
---|---|---|
committer | Dave Reisner <d@falconindy.com> | 2010-12-10 22:48:19 -0500 |
commit | e835af7775599a5c942f3813907dfa72d1227553 (patch) | |
tree | 7a1de0dcf775b274ce1d621d94677ac08cce092f | |
parent | c2d67feae0688c1ba601722edfd3024bc364ce51 (diff) | |
download | expac-e835af7775599a5c942f3813907dfa72d1227553.tar.xz |
allow real printf formatters for simple strings
It's kind of silly to verify this kind of formatting, so I'm just
letting it explode (which happens not too horribly) when the user
inevitably does something stupid.
-rw-r--r-- | README.pod | 6 | ||||
-rw-r--r-- | expac.c | 68 |
2 files changed, 28 insertions, 46 deletions
@@ -119,7 +119,11 @@ The format argument allows the following interpreted sequences: %% literal % -Standard backslash escape sequences are supported. See printf(1). +Note that for any lowercase tokens aside from %m and %k, full printf support is +allowed, e.g. %-20n. This does not apply to any list based, date, or numerical +output. + +Standard backslash escape sequences are supported, as per printf(1). =head1 AUTHOR @@ -42,6 +42,9 @@ #define FORMAT_TOKENS_SYNC "f" #define ESCAPE_TOKENS "\"\\abefnrtv" +static char const digits[] = "0123456789"; +static char const printf_flags[] = "'-+ #0I"; + pmdb_t *db_local = NULL; alpm_list_t *dblist = NULL; alpm_list_t *targets = NULL; @@ -344,45 +347,52 @@ static int print_time(time_t timestamp) { static int print_pkg(pmpkg_t *pkg, const char *format) { const char *f; - int out = 0; + char fmt[32]; + int len, out = 0; for (f = format; *f != '\0'; f++) { bool shortdeps = false; + len = 0; if (*f == '%') { - switch (*++f) { + len = strspn(f + 1 + len, printf_flags); + len += strspn(f + 1 + len, digits); + snprintf(fmt, len + 3, "%ss", f); + fmt[len + 1] = 's'; + f += len + 1; + switch (*f) { /* simple attributes */ case 'f': /* filename */ - out += printf("%s", alpm_pkg_get_filename(pkg)); + out += printf(fmt, alpm_pkg_get_filename(pkg)); break; case 'n': /* package name */ - out += printf("%s", alpm_pkg_get_name(pkg)); + out += printf(fmt, alpm_pkg_get_name(pkg)); break; case 'v': /* version */ - out += printf("%s", alpm_pkg_get_version(pkg)); + out += printf(fmt, alpm_pkg_get_version(pkg)); break; case 'd': /* description */ - out += printf("%s", alpm_pkg_get_desc(pkg)); + out += printf(fmt, alpm_pkg_get_desc(pkg)); break; case 'u': /* project url */ - out += printf("%s", alpm_pkg_get_url(pkg)); + out += printf(fmt, alpm_pkg_get_url(pkg)); break; case 'p': /* packager name */ - out += printf("%s", alpm_pkg_get_packager(pkg)); + out += printf(fmt, alpm_pkg_get_packager(pkg)); break; case 's': /* md5sum */ - out += printf("%s", alpm_pkg_get_md5sum(pkg)); + out += printf(fmt, alpm_pkg_get_md5sum(pkg)); break; case 'a': /* architecutre */ - out += printf("%s", alpm_pkg_get_arch(pkg)); + out += printf(fmt, alpm_pkg_get_arch(pkg)); break; case 'i': /* has install scriptlet? */ - out += printf("%s", alpm_pkg_has_scriptlet(pkg) ? "yes" : "no"); + out += printf(fmt, alpm_pkg_has_scriptlet(pkg) ? "yes" : "no"); break; case 'r': /* repo */ - out += printf("%s", alpm_db_get_name(alpm_pkg_get_db(pkg))); + out += printf(fmt, alpm_db_get_name(alpm_pkg_get_db(pkg))); break; case 'w': /* install reason */ - out += printf("%s", alpm_pkg_get_reason(pkg) ? "dependency" : "explicit"); + out += printf(fmt, alpm_pkg_get_reason(pkg) ? "dependency" : "explicit"); break; /* times */ @@ -462,34 +472,6 @@ static int print_pkg(pmpkg_t *pkg, const char *format) { return(0); } -int verify_format_string(const char *format) { - const char *p; - - for (p = format; *p != '\0'; p++) { - if (*p == '%') { - ++p; - if (!strchr(FORMAT_TOKENS FORMAT_TOKENS_LOCAL FORMAT_TOKENS_SYNC, *p)) { - fprintf(stderr, "error: bad token in format string: %%%c\n", *p); - return(1); - } - - /* check for querytype dependent tokens */ - if (!local && strchr(FORMAT_TOKENS_LOCAL, *p)) { - fprintf(stderr, "error: token not available with local queries: %%%c\n", *p); - return(1); - } else if (local && strchr(FORMAT_TOKENS_SYNC, *p)) { - fprintf(stderr, "error: token not available with sync queries: %%%c\n", *p); - return(1); - } - } else if (*p == '\\' && !strchr(ESCAPE_TOKENS, *++p)) { - fprintf(stderr, "error: bad token in format string: \\%c\n", *p); - return(1); - } - } - - return(0); -} - alpm_list_t *resolve_pkg(alpm_list_t *targets) { char *pkgname, *reponame; alpm_list_t *t, *r, *ret = NULL; @@ -569,10 +551,6 @@ int main(int argc, char *argv[]) { listdelim = listdelim ? listdelim : DEFAULT_LISTDELIM; timefmt = timefmt ? timefmt : DEFAULT_TIMEFMT; - if (verify_format_string(format) != 0) { - return(1); - } - results = resolve_pkg(targets); if (!results) { ret = 1; |