1 #define _POSIX_C_SOURCE 200112L
13 * a generic printf style format string parser
14 * takes a character pointer, returns pointer to next non
15 * parsed character, next token, optionally
16 * does a callback, fills in a format struct
24 fmt = parse_format_str(fmt, &f);
25 if (!f.found) break; /* done */
27 /* literal/noformat */
28 putchar(f.found); /* or whatever */
32 case 'a': /* handle %a */
34 default: /* handle unknown formatting character */
40 struct format_string {
41 int found; /* the 'd' in '%d' */
42 unsigned flags; /* 1 = found, 0 = none found */
45 char *format_string_parse(char *s, struct format_string *f) {
49 if (!*s) return s; /* done */
51 /* literal non-format specifier */
63 void stat_one(char *fmt, char *timefmt, int zeroterm, char *filename, struct
67 struct format_string f;
72 fmt = format_string_parse(fmt, &f);
73 if (!f.found) break; /* done */
75 if (f.found == '\\') {
90 /* literal/noformat */
91 putchar(f.found); /* or whatever */
95 case 'y': /* handle mtime */
96 tm = gmtime(&buf->st_mtime);
97 strftime(timestr, 1023, timefmt, tm);
99 printf("%s", timestr);
102 printf("%jd", (intmax_t)buf->st_size);
104 case 'a': /* octal mode */
105 printf("%o", (int)buf->st_mode & 07777);
108 if (S_ISBLK(buf->st_mode)) {
110 } else if (S_ISCHR(buf->st_mode)) {
112 } else if (S_ISDIR(buf->st_mode)) {
114 } else if (S_ISFIFO(buf->st_mode)) {
116 } else if (S_ISREG(buf->st_mode)) {
118 } else if (S_ISLNK(buf->st_mode)) {
120 } else if (S_ISSOCK(buf->st_mode)) {
126 case 'u': /* handle uid */
127 printf("%0d", buf->st_uid);
129 case 'U': /* handle username */
130 pw = getpwuid(buf->st_uid);
132 printf("%s", pw->pw_name);
134 case 'g': /* handle gid */
135 printf("%0d", buf->st_gid);
137 case 'G': /* handle groupname */
138 gr = getgrgid(buf->st_gid);
140 printf("%s", gr->gr_name);
143 printf("%s", filename);
150 default: /* handle unknown formatting character */
151 printf("%c", f.found);
166 int main(int ac, char *av[]) {
167 char *fmt = "%y"; /* default stat is mtime */
168 char *timefmt = "%s"; /* default time fmt is unix ts */
174 while ((c = getopt(ac, av, "lf:t:0")) != -1) {
182 case ':': /* -f or -t without operand */
184 "Option -%c requires an operand\n", optopt);
197 "Unrecognized option: '-%c'\n", optopt);
202 fprintf(stderr, "zpm-stat [-f <format>] [-t <timefmt>]\n");
205 for ( ; optind < ac; optind++) {
208 lstat(av[optind], &buf);
210 stat(av[optind], &buf);
212 stat_one(fmt, timefmt, zeroterm, av[optind], &buf);