11 * a generic printf style format string parser
12 * takes a character pointer, returns pointer to next non
13 * parsed character, next token, optionally
14 * does a callback, fills in a format struct
22 fmt = parse_format_str(fmt, &f);
23 if (!f.found) break; /* done */
25 /* literal/noformat */
26 putchar(f.found); /* or whatever */
30 case 'a': /* handle %a */
32 default: /* handle unknown formatting character */
38 struct format_string {
39 int found; /* the 'd' in '%d' */
40 unsigned flags; /* 1 = found, 0 = none found */
43 char *format_string_parse(char *s, struct format_string *f) {
47 if (!*s) return s; /* done */
49 /* literal non-format specifier */
61 void stat_one(char *fmt, char *timefmt, char *filename) {
65 struct format_string f;
72 fmt = format_string_parse(fmt, &f);
73 if (!f.found) break; /* done */
75 /* literal/noformat */
76 putchar(f.found); /* or whatever */
80 case 'y': /* handle mtime */
81 tm = gmtime(&buf.st_mtime);
82 strftime(timestr, 1023, timefmt, tm);
84 printf("%s", timestr);
86 case 'a': /* octal mode */
87 printf("%o", (int)buf.st_mode & 07777);
89 case 'u': /* handle uid */
90 printf("%0d", buf.st_uid);
92 case 'U': /* handle username */
93 pw = getpwuid(buf.st_uid);
95 printf("%s", pw->pw_name);
97 case 'g': /* handle gid */
98 printf("%0d", buf.st_gid);
100 case 'G': /* handle groupname */
101 gr = getgrgid(buf.st_gid);
103 printf("%s", gr->gr_name);
105 default: /* handle unknown formatting character */
106 printf("%c", f.found);
113 int main(int ac, char *av[]) {
114 char *fmt = "%y"; /* default stat is mtime */
115 char *timefmt = "%s"; /* default time fmt is unix ts */
119 while ((c = getopt(ac, av, "f:t:")) != -1) {
127 case ':': /* -f or -t without operand */
129 "Option -%c requires an operand\n", optopt);
134 "Unrecognized option: '-%c'\n", optopt);
139 fprintf(stderr, "zpm-stat [-f <format>] [-t <timefmt>]");
142 for ( ; optind < ac; optind++) {
143 stat_one(fmt, timefmt, av[optind]);