From owner-p4-projects@FreeBSD.ORG Sun Aug 8 13:49:00 2010 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id E33451065670; Sun, 8 Aug 2010 13:48:59 +0000 (UTC) Delivered-To: perforce@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 8F50B106566B for ; Sun, 8 Aug 2010 13:48:59 +0000 (UTC) (envelope-from trasz@freebsd.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id 7BAA38FC08 for ; Sun, 8 Aug 2010 13:48:59 +0000 (UTC) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.4/8.14.4) with ESMTP id o78Dmx7J007841 for ; Sun, 8 Aug 2010 13:48:59 GMT (envelope-from trasz@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.4/8.14.4/Submit) id o78DmxdN007839 for perforce@freebsd.org; Sun, 8 Aug 2010 13:48:59 GMT (envelope-from trasz@freebsd.org) Date: Sun, 8 Aug 2010 13:48:59 GMT Message-Id: <201008081348.o78DmxdN007839@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to trasz@freebsd.org using -f From: Edward Tomasz Napierala To: Perforce Change Reviews Precedence: bulk Cc: Subject: PERFORCE change 182086 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 08 Aug 2010 13:49:00 -0000 http://p4web.freebsd.org/@@182086?ac=10 Change 182086 by trasz@trasz_victim on 2010/08/08 13:47:59 Add "-h" option to hrl(8), so I don't have to count digits anymore. Affected files ... .. //depot/projects/soc2009/trasz_limits/usr.sbin/hrl/hrl.8#4 edit .. //depot/projects/soc2009/trasz_limits/usr.sbin/hrl/hrl.c#26 edit Differences ... ==== //depot/projects/soc2009/trasz_limits/usr.sbin/hrl/hrl.8#4 (text+ko) ==== @@ -33,17 +33,20 @@ .Nd display and update Hierarchical Resource Limits database .Sh SYNOPSIS .Nm +.Op Fl h .Op Ar filter .Nm .Fl a .Op Ar rule .Nm +.Op Fl h .Fl l .Op Ar filter .Nm .Fl r .Op Ar filter .Nm +.Op Fl h .Fl u .Op Ar filter .Sh DESCRIPTION @@ -67,10 +70,14 @@ Remove rules matching .Ar filter from the HRL database. -.It Fl l Ar filter +.It Fl u Ar filter Display resource usage for a subject (process, user, login class or jail) matching the .Ar filter . +.It Fl h +"Human-readable" output. +Use unit suffixes: Byte, Kilobyte, Megabyte, +Gigabyte, Terabyte and Petabyte. .Pp .Sh RULE SYNTAX Syntax for a rule is subject:subject-id:resource:action=amount/per. ==== //depot/projects/soc2009/trasz_limits/usr.sbin/hrl/hrl.c#26 (text+ko) ==== @@ -169,46 +169,124 @@ else asprintf(&expanded, "%s:%s:%s:%s=%ld/%s", subject, subject_id, resource, action, num, per); + if (expanded == NULL) + err(1, "asprintf"); + return (expanded); } +static char * +humanize_ids(char *rule) +{ + id_t id; + struct passwd *pwd; + struct group *grp; + const char *subject, *textid, *rest; + char *humanized; + + subject = strsep(&rule, ":"); + textid = strsep(&rule, ":"); + if (textid == NULL) + errx(1, "rule passed from the kernel didn't contain subject"); + if (rule != NULL) + rest = rule; + else + rest = ""; + + /* Replace numerical user and group ids with names. */ + if (strcasecmp(subject, "user") == 0) { + id = parse_user(textid); + pwd = getpwuid(id); + if (pwd != NULL) + textid = pwd->pw_name; + } else if (strcasecmp(subject, "group") == 0) { + id = parse_group(textid); + grp = getgrgid(id); + if (grp != NULL) + textid = grp->gr_name; + } + + asprintf(&humanized, "%s:%s:%s", subject, textid, rest); + + if (humanized == NULL) + err(1, "asprintf"); + + return (humanized); +} + +static int +str2int64(const char *str, int64_t *value) +{ + char *end; + + if (str == NULL) + return (EINVAL); + + *value = strtoul(str, &end, 10); + if ((size_t)(end - str) != strlen(str)) + return (EINVAL); + + return (0); +} + +static char * +humanize_amount(char *rule) +{ + int64_t num; + const char *subject, *subject_id, *resource, *action, *amount, *per; + char *copy, *humanized, buf[6]; + + copy = strdup(rule); + if (copy == NULL) + err(1, "strdup"); + + subject = strsep(©, ":"); + subject_id = strsep(©, ":"); + resource = strsep(©, ":"); + action = strsep(©, "=/"); + amount = strsep(©, "/"); + per = copy; + + if (amount == NULL || strlen(amount) == 0 || str2int64(amount, &num) != 0) { + free(copy); + return (rule); + } + + assert(subject != NULL); + assert(subject_id != NULL); + assert(resource != NULL); + assert(action != NULL); + + if (humanize_number(buf, sizeof(buf), num, "", HN_AUTOSCALE, HN_DECIMAL | HN_NOSPACE) == -1) + err(1, "humanize_number"); + + if (per == NULL) + asprintf(&humanized, "%s:%s:%s:%s=%s", subject, subject_id, resource, action, buf); + else + asprintf(&humanized, "%s:%s:%s:%s=%s/%s", subject, subject_id, resource, action, buf, per); + + if (humanized == NULL) + err(1, "asprintf"); + + return (humanized); +} + /* - * Print rules, one per line, */ + * Print rules, one per line. + */ static void -print_rules(char *rules) +print_rules(char *rules, int hflag) { char *rule; - const char *subject, *textid, *rest; - id_t id; - struct passwd *pwd; - struct group *grp; while ((rule = strsep(&rules, ",")) != NULL) { if (rule[0] == '\0') break; /* XXX */ - subject = strsep(&rule, ":"); - textid = strsep(&rule, ":"); - if (textid == NULL) - errx(1, "rule passed from the kernel didn't contain subject"); - if (rule != NULL) - rest = rule; - else - rest = ""; - - /* Replace numerical user and group ids with names. */ - if (strcasecmp(subject, "user") == 0) { - id = parse_user(textid); - pwd = getpwuid(id); - if (pwd != NULL) - textid = pwd->pw_name; - } else if (strcasecmp(subject, "group") == 0) { - id = parse_group(textid); - grp = getgrgid(id); - if (grp != NULL) - textid = grp->gr_name; - } - - printf("%s:%s:%s\n", subject, textid, rest); + rule = humanize_ids(rule); + if (hflag) + rule = humanize_amount(rule); + printf("%s\n", rule); + free(rule); } } @@ -224,7 +302,7 @@ } static void -show_limits(char *filter) +show_limits(char *filter, int hflag) { int error; char *outbuf = NULL; @@ -241,7 +319,7 @@ err(1, "hrl_get_limits"); } while (error && errno == ERANGE); - print_rules(outbuf); + print_rules(outbuf, hflag); free(filter); free(outbuf); } @@ -257,11 +335,41 @@ free(filter); } +static char * +humanize_usage_amount(char *usage) +{ + int64_t num; + const char *resource, *amount; + char *copy, *humanized, buf[6]; + + copy = strdup(usage); + if (copy == NULL) + err(1, "strdup"); + + resource = strsep(©, "="); + amount = copy; + + assert(resource != NULL); + assert(amount != NULL); + + if (str2int64(amount, &num) != 0 || + humanize_number(buf, sizeof(buf), num, "", HN_AUTOSCALE, HN_DECIMAL | HN_NOSPACE) == -1) { + free(copy); + return (usage); + } + + asprintf(&humanized, "%s=%s", resource, buf); + if (humanized == NULL) + err(1, "asprintf"); + + return (humanized); +} + /* * Query the kernel about a resource usage and print it out. */ static void -show_usage(char *filter) +show_usage(char *filter, int hflag) { int error; char *outbuf = NULL, *tmp; @@ -278,11 +386,16 @@ err(1, "hrl_get_usage"); } while (error && errno == ERANGE); - for (tmp = outbuf; *tmp != '\0'; tmp++) - if (*tmp == ',') - *tmp = '\n'; + while ((tmp = strsep(&outbuf, ",")) != NULL) { + if (tmp[0] == '\0') + break; /* XXX */ + + if (hflag) + tmp = humanize_usage_amount(tmp); + + printf("%s\n", tmp); + } - printf("%s\n", outbuf); free(filter); free(outbuf); } @@ -291,7 +404,7 @@ * Query the kernel about resource limit rules and print them out. */ static void -show_rules(char *filter) +show_rules(char *filter, int hflag) { int error; char *outbuf = NULL; @@ -313,7 +426,7 @@ err(1, "hrl_get_rules"); } while (error && errno == ERANGE); - print_rules(outbuf); + print_rules(outbuf, hflag); free(outbuf); } @@ -321,22 +434,25 @@ usage(void) { - fprintf(stderr, "usage: hrl [-a rule | -l filter | -r filter | -u filter | filter]\n"); + fprintf(stderr, "usage: hrl [ -h ] [-a rule | -l filter | -r filter | -u filter | filter]\n"); exit(1); } int main(int argc __unused, char **argv __unused) { - int ch, aflag = 0, lflag = 0, rflag = 0, uflag = 0; + int ch, aflag = 0, hflag = 0, lflag = 0, rflag = 0, uflag = 0; char *rule = NULL; - while ((ch = getopt(argc, argv, "a:l:r:u:")) != -1) { + while ((ch = getopt(argc, argv, "a:hl:r:u:")) != -1) { switch (ch) { case 'a': aflag = 1; rule = strdup(optarg); break; + case 'h': + hflag = 1; + break; case 'l': lflag = 1; rule = strdup(optarg); @@ -363,7 +479,7 @@ usage(); if (rule == NULL) { - if ( argc == 1) + if (argc == 1) rule = strdup(argv[0]); else rule = strdup("::"); @@ -382,7 +498,7 @@ } if (lflag) { - show_limits(rule); + show_limits(rule, hflag); return (0); } @@ -392,10 +508,10 @@ } if (uflag) { - show_usage(rule); + show_usage(rule, hflag); return (0); } - show_rules(rule); + show_rules(rule, hflag); return (0); }