]> CyberLeo.Net >> Repos - FreeBSD/releng/8.1.git/blob - tools/regression/fstest/fstest.c
Copy stable/8 to releng/8.1 in preparation for 8.1-RC1.
[FreeBSD/releng/8.1.git] / tools / regression / fstest / fstest.c
1 /*-
2  * Copyright (c) 2006-2007 Pawel Jakub Dawidek <pjd@FreeBSD.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  * $FreeBSD$
27  */
28
29 #include <sys/param.h>
30 #include <sys/stat.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <unistd.h>
34 #include <fcntl.h>
35 #include <grp.h>
36 #include <string.h>
37 #include <ctype.h>
38 #include <errno.h>
39 #include <assert.h>
40
41 #ifndef HAS_TRUNCATE64
42 #define truncate64      truncate
43 #endif
44 #ifndef HAS_STAT64
45 #define stat64  stat
46 #define lstat64 lstat
47 #endif
48
49 #ifndef ALLPERMS
50 #define ALLPERMS        (S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO)
51 #endif
52
53 enum action {
54         ACTION_OPEN,
55         ACTION_CREATE,
56         ACTION_UNLINK,
57         ACTION_MKDIR,
58         ACTION_RMDIR,
59         ACTION_LINK,
60         ACTION_SYMLINK,
61         ACTION_RENAME,
62         ACTION_MKFIFO,
63         ACTION_CHMOD,
64 #ifdef HAS_LCHMOD
65         ACTION_LCHMOD,
66 #endif
67         ACTION_CHOWN,
68         ACTION_LCHOWN,
69 #ifdef HAS_CHFLAGS
70         ACTION_CHFLAGS,
71 #endif
72 #ifdef HAS_LCHFLAGS
73         ACTION_LCHFLAGS,
74 #endif
75         ACTION_TRUNCATE,
76         ACTION_STAT,
77         ACTION_LSTAT,
78         ACTION_PATHCONF
79 };
80
81 #define TYPE_NONE       0x0000
82 #define TYPE_STRING     0x0001
83 #define TYPE_NUMBER     0x0002
84
85 #define TYPE_OPTIONAL   0x0100
86
87 #define MAX_ARGS        8
88
89 struct syscall_desc {
90         char            *sd_name;
91         enum action      sd_action;
92         int              sd_args[MAX_ARGS];
93 };
94
95 static struct syscall_desc syscalls[] = {
96         { "open", ACTION_OPEN, { TYPE_STRING, TYPE_STRING, TYPE_NUMBER | TYPE_OPTIONAL, TYPE_NONE } },
97         { "create", ACTION_CREATE, { TYPE_STRING, TYPE_NUMBER, TYPE_NONE } },
98         { "unlink", ACTION_UNLINK, { TYPE_STRING, TYPE_NONE } },
99         { "mkdir", ACTION_MKDIR, { TYPE_STRING, TYPE_NUMBER, TYPE_NONE } },
100         { "rmdir", ACTION_RMDIR, { TYPE_STRING, TYPE_NONE } },
101         { "link", ACTION_LINK, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
102         { "symlink", ACTION_SYMLINK, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
103         { "rename", ACTION_RENAME, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
104         { "mkfifo", ACTION_MKFIFO, { TYPE_STRING, TYPE_NUMBER, TYPE_NONE } },
105         { "chmod", ACTION_CHMOD, { TYPE_STRING, TYPE_NUMBER, TYPE_NONE } },
106 #ifdef HAS_LCHMOD
107         { "lchmod", ACTION_LCHMOD, { TYPE_STRING, TYPE_NUMBER, TYPE_NONE } },
108 #endif
109         { "chown", ACTION_CHOWN, { TYPE_STRING, TYPE_NUMBER, TYPE_NUMBER, TYPE_NONE } },
110         { "lchown", ACTION_LCHOWN, { TYPE_STRING, TYPE_NUMBER, TYPE_NUMBER, TYPE_NONE } },
111 #ifdef HAS_CHFLAGS
112         { "chflags", ACTION_CHFLAGS, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
113 #endif
114 #ifdef HAS_LCHFLAGS
115         { "lchflags", ACTION_LCHFLAGS, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
116 #endif
117         { "truncate", ACTION_TRUNCATE, { TYPE_STRING, TYPE_NUMBER, TYPE_NONE } },
118         { "stat", ACTION_STAT, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
119         { "lstat", ACTION_LSTAT, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
120         { "pathconf", ACTION_PATHCONF, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
121         { NULL, -1, { TYPE_NONE } }
122 };
123
124 struct flag {
125         long long        f_flag;
126         char            *f_str;
127 };
128
129 static struct flag open_flags[] = {
130 #ifdef O_RDONLY
131         { O_RDONLY, "O_RDONLY" },
132 #endif
133 #ifdef O_WRONLY
134         { O_WRONLY, "O_WRONLY" },
135 #endif
136 #ifdef O_RDWR
137         { O_RDWR, "O_RDWR" },
138 #endif
139 #ifdef O_NONBLOCK
140         { O_NONBLOCK, "O_NONBLOCK" },
141 #endif
142 #ifdef O_APPEND
143         { O_APPEND, "O_APPEND" },
144 #endif
145 #ifdef O_CREAT
146         { O_CREAT, "O_CREAT" },
147 #endif
148 #ifdef O_TRUNC
149         { O_TRUNC, "O_TRUNC" },
150 #endif
151 #ifdef O_EXCL
152         { O_EXCL, "O_EXCL" },
153 #endif
154 #ifdef O_SHLOCK
155         { O_SHLOCK, "O_SHLOCK" },
156 #endif
157 #ifdef O_EXLOCK
158         { O_EXLOCK, "O_EXLOCK" },
159 #endif
160 #ifdef O_DIRECT
161         { O_DIRECT, "O_DIRECT" },
162 #endif
163 #ifdef O_FSYNC
164         { O_FSYNC, "O_FSYNC" },
165 #endif
166 #ifdef O_SYNC
167         { O_SYNC, "O_SYNC" },
168 #endif
169 #ifdef O_NOFOLLOW
170         { O_NOFOLLOW, "O_NOFOLLOW" },
171 #endif
172 #ifdef O_NOCTTY
173         { O_NOCTTY, "O_NOCTTY" },
174 #endif
175         { 0, NULL }
176 };
177
178 #ifdef HAS_CHFLAGS
179 static struct flag chflags_flags[] = {
180 #ifdef UF_NODUMP
181         { UF_NODUMP, "UF_NODUMP" },
182 #endif
183 #ifdef UF_IMMUTABLE
184         { UF_IMMUTABLE, "UF_IMMUTABLE" },
185 #endif
186 #ifdef UF_APPEND
187         { UF_APPEND, "UF_APPEND" },
188 #endif
189 #ifdef UF_NOUNLINK
190         { UF_NOUNLINK, "UF_NOUNLINK" },
191 #endif
192 #ifdef UF_OPAQUE
193         { UF_OPAQUE, "UF_OPAQUE" },
194 #endif
195 #ifdef SF_ARCHIVED
196         { SF_ARCHIVED, "SF_ARCHIVED" },
197 #endif
198 #ifdef SF_IMMUTABLE
199         { SF_IMMUTABLE, "SF_IMMUTABLE" },
200 #endif
201 #ifdef SF_APPEND
202         { SF_APPEND, "SF_APPEND" },
203 #endif
204 #ifdef SF_NOUNLINK
205         { SF_NOUNLINK, "SF_NOUNLINK" },
206 #endif
207 #ifdef SF_SNAPSHOT
208         { SF_SNAPSHOT, "SF_SNAPSHOT" },
209 #endif
210         { 0, NULL }
211 };
212 #endif
213
214 struct name {
215         int      n_name;
216         char    *n_str;
217 };
218
219 static struct name pathconf_names[] = {
220 #ifdef _PC_LINK_MAX
221         { _PC_LINK_MAX, "_PC_LINK_MAX" },
222 #endif
223 #ifdef _PC_NAME_MAX
224         { _PC_NAME_MAX, "_PC_NAME_MAX" },
225 #endif
226 #ifdef _PC_PATH_MAX
227         { _PC_PATH_MAX, "_PC_PATH_MAX" },
228 #endif
229 #ifdef _PC_SYMLINK_MAX
230         { _PC_SYMLINK_MAX, "_PC_SYMLINK_MAX" },
231 #endif
232         { 0, NULL }
233 };
234
235 static const char *err2str(int error);
236
237 static void
238 usage(void)
239 {
240
241         fprintf(stderr, "usage: fstest [-u uid] [-g gid1[,gid2[...]]] syscall args ...\n");
242         exit(1);
243 }
244
245 static long long
246 str2flags(struct flag *tflags, char *sflags)
247 {
248         long long flags = 0;
249         unsigned int i;
250         char *f;
251
252         for (f = strtok(sflags, ","); f != NULL; f = strtok(NULL, ",")) {
253                 /* Support magic 'none' flag which just reset all flags. */
254                 if (strcmp(f, "none") == 0)
255                         return (0);
256                 for (i = 0; tflags[i].f_str != NULL; i++) {
257                         if (strcmp(tflags[i].f_str, f) == 0)
258                                 break;
259                 }
260                 if (tflags[i].f_str == NULL) {
261                         fprintf(stderr, "unknown flag '%s'\n", f);
262                         exit(1);
263                 }
264                 flags |= tflags[i].f_flag;
265         }
266         return (flags);
267 }
268
269 #ifdef HAS_CHFLAGS
270 static char *
271 flags2str(struct flag *tflags, long long flags)
272 {
273         static char sflags[1024];
274         unsigned int i;
275
276         sflags[0] = '\0';
277         for (i = 0; tflags[i].f_str != NULL; i++) {
278                 if (flags & tflags[i].f_flag) {
279                         if (sflags[0] != '\0')
280                                 strlcat(sflags, ",", sizeof(sflags));
281                         strlcat(sflags, tflags[i].f_str, sizeof(sflags));
282                 }
283         }
284         if (sflags[0] == '\0')
285                 strlcpy(sflags, "none", sizeof(sflags));
286         return (sflags);
287 }
288 #endif
289
290 static int
291 str2name(struct name *names, char *name)
292 {
293         unsigned int i;
294
295         for (i = 0; names[i].n_str != NULL; i++) {
296                 if (strcmp(names[i].n_str, name) == 0)
297                         return (names[i].n_name);
298         }
299         return (-1);
300 }
301
302 static struct syscall_desc *
303 find_syscall(const char *name)
304 {
305         int i;
306
307         for (i = 0; syscalls[i].sd_name != NULL; i++) {
308                 if (strcmp(syscalls[i].sd_name, name) == 0)
309                         return (&syscalls[i]);
310         }
311         return (NULL);
312 }
313
314 static void
315 show_stat(struct stat64 *sp, const char *what)
316 {
317
318         if (strcmp(what, "mode") == 0)
319                 printf("0%o", (unsigned int)(sp->st_mode & ALLPERMS));
320         else if (strcmp(what, "inode") == 0)
321                 printf("%lld", (long long)sp->st_ino);
322         else if (strcmp(what, "nlink") == 0)
323                 printf("%lld", (long long)sp->st_nlink);
324         else if (strcmp(what, "uid") == 0)
325                 printf("%d", (int)sp->st_uid);
326         else if (strcmp(what, "gid") == 0)
327                 printf("%d", (int)sp->st_gid);
328         else if (strcmp(what, "size") == 0)
329                 printf("%lld", (long long)sp->st_size);
330         else if (strcmp(what, "blocks") == 0)
331                 printf("%lld", (long long)sp->st_blocks);
332         else if (strcmp(what, "atime") == 0)
333                 printf("%lld", (long long)sp->st_atime);
334         else if (strcmp(what, "mtime") == 0)
335                 printf("%lld", (long long)sp->st_mtime);
336         else if (strcmp(what, "ctime") == 0)
337                 printf("%lld", (long long)sp->st_ctime);
338 #ifdef HAS_CHFLAGS
339         else if (strcmp(what, "flags") == 0)
340                 printf("%s", flags2str(chflags_flags, (long long)sp->st_flags));
341 #endif
342         else if (strcmp(what, "type") == 0) {
343                 switch (sp->st_mode & S_IFMT) {
344                 case S_IFIFO:
345                         printf("fifo");
346                         break;
347                 case S_IFCHR:
348                         printf("char");
349                         break;
350                 case S_IFDIR:
351                         printf("dir");
352                         break;
353                 case S_IFBLK:
354                         printf("block");
355                         break;
356                 case S_IFREG:
357                         printf("regular");
358                         break;
359                 case S_IFLNK:
360                         printf("symlink");
361                         break;
362                 case S_IFSOCK:
363                         printf("socket");
364                         break;
365                 default:
366                         printf("unknown");
367                         break;
368                 }
369         } else {
370                 printf("unknown");
371         }
372 }
373
374 static void
375 show_stats(struct stat64 *sp, char *what)
376 {
377         const char *s = "";
378         char *w;
379
380         for (w = strtok(what, ","); w != NULL; w = strtok(NULL, ",")) {
381                 printf("%s", s);
382                 show_stat(sp, w);
383                 s = ",";
384         }
385         printf("\n");
386 }
387
388 static unsigned int
389 call_syscall(struct syscall_desc *scall, char *argv[])
390 {
391         struct stat64 sb;
392         long long flags;
393         unsigned int i;
394         char *endp;
395         int name, rval;
396         union {
397                 char *str;
398                 long long num;
399         } args[MAX_ARGS];
400
401         /*
402          * Verify correctness of the arguments.
403          */
404         for (i = 0; i < sizeof(args)/sizeof(args[0]); i++) {
405                 if (scall->sd_args[i] == TYPE_NONE) {
406                         if (argv[i] == NULL || strcmp(argv[i], ":") == 0)
407                                 break;
408                         fprintf(stderr, "too many arguments [%s]\n", argv[i]);
409                         exit(1);
410                 } else {
411                         if (argv[i] == NULL || strcmp(argv[i], ":") == 0) {
412                                 if (scall->sd_args[i] & TYPE_OPTIONAL)
413                                         break;
414                                 fprintf(stderr, "too few arguments\n");
415                                 exit(1);
416                         }
417                         if (scall->sd_args[i] & TYPE_STRING) {
418                                 if (strcmp(argv[i], "NULL") == 0)
419                                         args[i].str = NULL;
420                                 else if (strcmp(argv[i], "DEADCODE") == 0)
421                                         args[i].str = (void *)0xdeadc0de;
422                                 else
423                                         args[i].str = argv[i];
424                         } else if (scall->sd_args[i] & TYPE_NUMBER) {
425                                 args[i].num = strtoll(argv[i], &endp, 0);
426                                 if (*endp != '\0' && !isspace((unsigned char)*endp)) {
427                                         fprintf(stderr, "invalid argument %u, number expected [%s]\n", i, endp);
428                                         exit(1);
429                                 }
430                         }
431                 }
432         }
433         /*
434          * Call the given syscall.
435          */
436 #define NUM(n)  (args[(n)].num)
437 #define STR(n)  (args[(n)].str)
438         switch (scall->sd_action) {
439         case ACTION_OPEN:
440                 flags = str2flags(open_flags, STR(1));
441                 if (flags & O_CREAT) {
442                         if (i == 2) {
443                                 fprintf(stderr, "too few arguments\n");
444                                 exit(1);
445                         }
446                         rval = open(STR(0), (int)flags, (mode_t)NUM(2));
447                 } else {
448                         if (i == 3) {
449                                 fprintf(stderr, "too many arguments\n");
450                                 exit(1);
451                         }
452                         rval = open(STR(0), (int)flags);
453                 }
454                 break;
455         case ACTION_CREATE:
456                 rval = open(STR(0), O_CREAT | O_EXCL, (mode_t)NUM(1));
457                 if (rval >= 0)
458                         close(rval);
459                 break;
460         case ACTION_UNLINK:
461                 rval = unlink(STR(0));
462                 break;
463         case ACTION_MKDIR:
464                 rval = mkdir(STR(0), (mode_t)NUM(1));
465                 break;
466         case ACTION_RMDIR:
467                 rval = rmdir(STR(0));
468                 break;
469         case ACTION_LINK:
470                 rval = link(STR(0), STR(1));
471                 break;
472         case ACTION_SYMLINK:
473                 rval = symlink(STR(0), STR(1));
474                 break;
475         case ACTION_RENAME:
476                 rval = rename(STR(0), STR(1));
477                 break;
478         case ACTION_MKFIFO:
479                 rval = mkfifo(STR(0), (mode_t)NUM(1));
480                 break;
481         case ACTION_CHMOD:
482                 rval = chmod(STR(0), (mode_t)NUM(1));
483                 break;
484 #ifdef HAS_LCHMOD
485         case ACTION_LCHMOD:
486                 rval = lchmod(STR(0), (mode_t)NUM(1));
487                 break;
488 #endif
489         case ACTION_CHOWN:
490                 rval = chown(STR(0), (uid_t)NUM(1), (gid_t)NUM(2));
491                 break;
492         case ACTION_LCHOWN:
493                 rval = lchown(STR(0), (uid_t)NUM(1), (gid_t)NUM(2));
494                 break;
495 #ifdef HAS_CHFLAGS
496         case ACTION_CHFLAGS:
497                 rval = chflags(STR(0), (unsigned long)str2flags(chflags_flags, STR(1)));
498                 break;
499 #endif
500 #ifdef HAS_LCHFLAGS
501         case ACTION_LCHFLAGS:
502                 rval = lchflags(STR(0), (int)str2flags(chflags_flags, STR(1)));
503                 break;
504 #endif
505         case ACTION_TRUNCATE:
506                 rval = truncate64(STR(0), NUM(1));
507                 break;
508         case ACTION_STAT:
509                 rval = stat64(STR(0), &sb);
510                 if (rval == 0) {
511                         show_stats(&sb, STR(1));
512                         return (i);
513                 }
514                 break;
515         case ACTION_LSTAT:
516                 rval = lstat64(STR(0), &sb);
517                 if (rval == 0) {
518                         show_stats(&sb, STR(1));
519                         return (i);
520                 }
521                 break;
522         case ACTION_PATHCONF:
523             {
524                 long lrval;
525
526                 name = str2name(pathconf_names, STR(1));
527                 if (name == -1) {
528                         fprintf(stderr, "unknown name %s", STR(1));
529                         exit(1);
530                 }
531                 errno = 0;
532                 lrval = pathconf(STR(0), name);
533                 if (lrval == -1 && errno == 0) {
534                         printf("unlimited\n");
535                         return (i);
536                 } else if (lrval >= 0) {
537                         printf("%ld\n", lrval);
538                         return (i);
539                 }
540                 rval = -1;
541                 break;
542             }
543         default:
544                 fprintf(stderr, "unsupported syscall\n");
545                 exit(1);
546         }
547 #undef STR
548 #undef NUM
549         if (rval < 0) {
550                 const char *serrno;
551
552                 serrno = err2str(errno);
553                 fprintf(stderr, "%s returned %d\n", scall->sd_name, rval);
554                 printf("%s\n", serrno);
555                 exit(1);
556         }
557         printf("0\n");
558         return (i);
559 }
560
561 static void
562 set_gids(char *gids)
563 {
564         gid_t *gidset;
565         long ngroups;
566         char *g, *endp;
567         unsigned i;
568
569         ngroups = sysconf(_SC_NGROUPS_MAX);
570         assert(ngroups > 0);
571         gidset = malloc(sizeof(*gidset) * ngroups);
572         assert(gidset != NULL);
573         for (i = 0, g = strtok(gids, ","); g != NULL; g = strtok(NULL, ","), i++) {
574                 if (i >= ngroups) {
575                         fprintf(stderr, "too many gids\n");
576                         exit(1);
577                 }
578                 gidset[i] = strtol(g, &endp, 0);
579                 if (*endp != '\0' && !isspace((unsigned char)*endp)) {
580                         fprintf(stderr, "invalid gid '%s' - number expected\n",
581                             g);
582                         exit(1);
583                 }
584         }
585         if (setgroups(i, gidset) < 0) {
586                 fprintf(stderr, "cannot change groups: %s\n", strerror(errno));
587                 exit(1);
588         }
589         if (setegid(gidset[0]) < 0) {
590                 fprintf(stderr, "cannot change effective gid: %s\n", strerror(errno));
591                 exit(1);
592         }
593         free(gidset);
594 }
595
596 int
597 main(int argc, char *argv[])
598 {
599         struct syscall_desc *scall;
600         unsigned int n;
601         char *gids, *endp;
602         int uid, umsk, ch;
603
604         uid = -1;
605         gids = NULL;
606         umsk = 0;
607
608         while ((ch = getopt(argc, argv, "g:u:U:")) != -1) {
609                 switch(ch) {
610                 case 'g':
611                         gids = optarg;
612                         break;
613                 case 'u':
614                         uid = (int)strtol(optarg, &endp, 0);
615                         if (*endp != '\0' && !isspace((unsigned char)*endp)) {
616                                 fprintf(stderr, "invalid uid '%s' - number "
617                                     "expected\n", optarg);
618                                 exit(1);
619                         }
620                         break;
621                 case 'U':
622                         umsk = (int)strtol(optarg, &endp, 0);
623                         if (*endp != '\0' && !isspace((unsigned char)*endp)) {
624                                 fprintf(stderr, "invalid umask '%s' - number "
625                                     "expected\n", optarg);
626                                 exit(1);
627                         }
628                         break;
629                 default:
630                         usage();
631                 }
632         }
633         argc -= optind;
634         argv += optind;
635
636         if (argc < 1) {
637                 fprintf(stderr, "too few arguments\n");
638                 usage();
639         }
640
641         if (gids != NULL) {
642                 fprintf(stderr, "changing groups to %s\n", gids);
643                 set_gids(gids);
644         }
645         if (uid != -1) {
646                 fprintf(stderr, "changing uid to %d\n", uid);
647                 if (setuid(uid) < 0) {
648                         fprintf(stderr, "cannot change uid: %s\n",
649                             strerror(errno));
650                         exit(1);
651                 }
652         }
653
654         /* Change umask to requested value or to 0, if not requested. */
655         umask(umsk);
656
657         for (;;) {
658                 scall = find_syscall(argv[0]);
659                 if (scall == NULL) {
660                         fprintf(stderr, "syscall '%s' not supported\n", argv[0]);
661                         exit(1);
662                 }
663                 argc++;
664                 argv++;
665                 n = call_syscall(scall, argv);
666                 argc += n;
667                 argv += n;
668                 if (argv[0] == NULL)
669                         break;
670                 argc++;
671                 argv++;
672         }
673
674         exit(0);
675 }
676
677 static const char *
678 err2str(int error)
679 {
680         static char errnum[8];
681
682         switch (error) {
683 #ifdef EPERM
684         case EPERM:
685                 return ("EPERM");
686 #endif
687 #ifdef ENOENT
688         case ENOENT:
689                 return ("ENOENT");
690 #endif
691 #ifdef ESRCH
692         case ESRCH:
693                 return ("ESRCH");
694 #endif
695 #ifdef EINTR
696         case EINTR:
697                 return ("EINTR");
698 #endif
699 #ifdef EIO
700         case EIO:
701                 return ("EIO");
702 #endif
703 #ifdef ENXIO
704         case ENXIO:
705                 return ("ENXIO");
706 #endif
707 #ifdef E2BIG
708         case E2BIG:
709                 return ("E2BIG");
710 #endif
711 #ifdef ENOEXEC
712         case ENOEXEC:
713                 return ("ENOEXEC");
714 #endif
715 #ifdef EBADF
716         case EBADF:
717                 return ("EBADF");
718 #endif
719 #ifdef ECHILD
720         case ECHILD:
721                 return ("ECHILD");
722 #endif
723 #ifdef EDEADLK
724         case EDEADLK:
725                 return ("EDEADLK");
726 #endif
727 #ifdef ENOMEM
728         case ENOMEM:
729                 return ("ENOMEM");
730 #endif
731 #ifdef EACCES
732         case EACCES:
733                 return ("EACCES");
734 #endif
735 #ifdef EFAULT
736         case EFAULT:
737                 return ("EFAULT");
738 #endif
739 #ifdef ENOTBLK
740         case ENOTBLK:
741                 return ("ENOTBLK");
742 #endif
743 #ifdef EBUSY
744         case EBUSY:
745                 return ("EBUSY");
746 #endif
747 #ifdef EEXIST
748         case EEXIST:
749                 return ("EEXIST");
750 #endif
751 #ifdef EXDEV
752         case EXDEV:
753                 return ("EXDEV");
754 #endif
755 #ifdef ENODEV
756         case ENODEV:
757                 return ("ENODEV");
758 #endif
759 #ifdef ENOTDIR
760         case ENOTDIR:
761                 return ("ENOTDIR");
762 #endif
763 #ifdef EISDIR
764         case EISDIR:
765                 return ("EISDIR");
766 #endif
767 #ifdef EINVAL
768         case EINVAL:
769                 return ("EINVAL");
770 #endif
771 #ifdef ENFILE
772         case ENFILE:
773                 return ("ENFILE");
774 #endif
775 #ifdef EMFILE
776         case EMFILE:
777                 return ("EMFILE");
778 #endif
779 #ifdef ENOTTY
780         case ENOTTY:
781                 return ("ENOTTY");
782 #endif
783 #ifdef ETXTBSY
784         case ETXTBSY:
785                 return ("ETXTBSY");
786 #endif
787 #ifdef EFBIG
788         case EFBIG:
789                 return ("EFBIG");
790 #endif
791 #ifdef ENOSPC
792         case ENOSPC:
793                 return ("ENOSPC");
794 #endif
795 #ifdef ESPIPE
796         case ESPIPE:
797                 return ("ESPIPE");
798 #endif
799 #ifdef EROFS
800         case EROFS:
801                 return ("EROFS");
802 #endif
803 #ifdef EMLINK
804         case EMLINK:
805                 return ("EMLINK");
806 #endif
807 #ifdef EPIPE
808         case EPIPE:
809                 return ("EPIPE");
810 #endif
811 #ifdef EDOM
812         case EDOM:
813                 return ("EDOM");
814 #endif
815 #ifdef ERANGE
816         case ERANGE:
817                 return ("ERANGE");
818 #endif
819 #ifdef EAGAIN
820         case EAGAIN:
821                 return ("EAGAIN");
822 #endif
823 #ifdef EINPROGRESS
824         case EINPROGRESS:
825                 return ("EINPROGRESS");
826 #endif
827 #ifdef EALREADY
828         case EALREADY:
829                 return ("EALREADY");
830 #endif
831 #ifdef ENOTSOCK
832         case ENOTSOCK:
833                 return ("ENOTSOCK");
834 #endif
835 #ifdef EDESTADDRREQ
836         case EDESTADDRREQ:
837                 return ("EDESTADDRREQ");
838 #endif
839 #ifdef EMSGSIZE
840         case EMSGSIZE:
841                 return ("EMSGSIZE");
842 #endif
843 #ifdef EPROTOTYPE
844         case EPROTOTYPE:
845                 return ("EPROTOTYPE");
846 #endif
847 #ifdef ENOPROTOOPT
848         case ENOPROTOOPT:
849                 return ("ENOPROTOOPT");
850 #endif
851 #ifdef EPROTONOSUPPORT
852         case EPROTONOSUPPORT:
853                 return ("EPROTONOSUPPORT");
854 #endif
855 #ifdef ESOCKTNOSUPPORT
856         case ESOCKTNOSUPPORT:
857                 return ("ESOCKTNOSUPPORT");
858 #endif
859 #ifdef EOPNOTSUPP
860         case EOPNOTSUPP:
861                 return ("EOPNOTSUPP");
862 #endif
863 #ifdef EPFNOSUPPORT
864         case EPFNOSUPPORT:
865                 return ("EPFNOSUPPORT");
866 #endif
867 #ifdef EAFNOSUPPORT
868         case EAFNOSUPPORT:
869                 return ("EAFNOSUPPORT");
870 #endif
871 #ifdef EADDRINUSE
872         case EADDRINUSE:
873                 return ("EADDRINUSE");
874 #endif
875 #ifdef EADDRNOTAVAIL
876         case EADDRNOTAVAIL:
877                 return ("EADDRNOTAVAIL");
878 #endif
879 #ifdef ENETDOWN
880         case ENETDOWN:
881                 return ("ENETDOWN");
882 #endif
883 #ifdef ENETUNREACH
884         case ENETUNREACH:
885                 return ("ENETUNREACH");
886 #endif
887 #ifdef ENETRESET
888         case ENETRESET:
889                 return ("ENETRESET");
890 #endif
891 #ifdef ECONNABORTED
892         case ECONNABORTED:
893                 return ("ECONNABORTED");
894 #endif
895 #ifdef ECONNRESET
896         case ECONNRESET:
897                 return ("ECONNRESET");
898 #endif
899 #ifdef ENOBUFS
900         case ENOBUFS:
901                 return ("ENOBUFS");
902 #endif
903 #ifdef EISCONN
904         case EISCONN:
905                 return ("EISCONN");
906 #endif
907 #ifdef ENOTCONN
908         case ENOTCONN:
909                 return ("ENOTCONN");
910 #endif
911 #ifdef ESHUTDOWN
912         case ESHUTDOWN:
913                 return ("ESHUTDOWN");
914 #endif
915 #ifdef ETOOMANYREFS
916         case ETOOMANYREFS:
917                 return ("ETOOMANYREFS");
918 #endif
919 #ifdef ETIMEDOUT
920         case ETIMEDOUT:
921                 return ("ETIMEDOUT");
922 #endif
923 #ifdef ECONNREFUSED
924         case ECONNREFUSED:
925                 return ("ECONNREFUSED");
926 #endif
927 #ifdef ELOOP
928         case ELOOP:
929                 return ("ELOOP");
930 #endif
931 #ifdef ENAMETOOLONG
932         case ENAMETOOLONG:
933                 return ("ENAMETOOLONG");
934 #endif
935 #ifdef EHOSTDOWN
936         case EHOSTDOWN:
937                 return ("EHOSTDOWN");
938 #endif
939 #ifdef EHOSTUNREACH
940         case EHOSTUNREACH:
941                 return ("EHOSTUNREACH");
942 #endif
943 #ifdef ENOTEMPTY
944         case ENOTEMPTY:
945                 return ("ENOTEMPTY");
946 #endif
947 #ifdef EPROCLIM
948         case EPROCLIM:
949                 return ("EPROCLIM");
950 #endif
951 #ifdef EUSERS
952         case EUSERS:
953                 return ("EUSERS");
954 #endif
955 #ifdef EDQUOT
956         case EDQUOT:
957                 return ("EDQUOT");
958 #endif
959 #ifdef ESTALE
960         case ESTALE:
961                 return ("ESTALE");
962 #endif
963 #ifdef EREMOTE
964         case EREMOTE:
965                 return ("EREMOTE");
966 #endif
967 #ifdef EBADRPC
968         case EBADRPC:
969                 return ("EBADRPC");
970 #endif
971 #ifdef ERPCMISMATCH
972         case ERPCMISMATCH:
973                 return ("ERPCMISMATCH");
974 #endif
975 #ifdef EPROGUNAVAIL
976         case EPROGUNAVAIL:
977                 return ("EPROGUNAVAIL");
978 #endif
979 #ifdef EPROGMISMATCH
980         case EPROGMISMATCH:
981                 return ("EPROGMISMATCH");
982 #endif
983 #ifdef EPROCUNAVAIL
984         case EPROCUNAVAIL:
985                 return ("EPROCUNAVAIL");
986 #endif
987 #ifdef ENOLCK
988         case ENOLCK:
989                 return ("ENOLCK");
990 #endif
991 #ifdef ENOSYS
992         case ENOSYS:
993                 return ("ENOSYS");
994 #endif
995 #ifdef EFTYPE
996         case EFTYPE:
997                 return ("EFTYPE");
998 #endif
999 #ifdef EAUTH
1000         case EAUTH:
1001                 return ("EAUTH");
1002 #endif
1003 #ifdef ENEEDAUTH
1004         case ENEEDAUTH:
1005                 return ("ENEEDAUTH");
1006 #endif
1007 #ifdef EIDRM
1008         case EIDRM:
1009                 return ("EIDRM");
1010 #endif
1011 #ifdef ENOMSG
1012         case ENOMSG:
1013                 return ("ENOMSG");
1014 #endif
1015 #ifdef EOVERFLOW
1016         case EOVERFLOW:
1017                 return ("EOVERFLOW");
1018 #endif
1019 #ifdef ECANCELED
1020         case ECANCELED:
1021                 return ("ECANCELED");
1022 #endif
1023 #ifdef EILSEQ
1024         case EILSEQ:
1025                 return ("EILSEQ");
1026 #endif
1027 #ifdef ENOATTR
1028         case ENOATTR:
1029                 return ("ENOATTR");
1030 #endif
1031 #ifdef EDOOFUS
1032         case EDOOFUS:
1033                 return ("EDOOFUS");
1034 #endif
1035 #ifdef EBADMSG
1036         case EBADMSG:
1037                 return ("EBADMSG");
1038 #endif
1039 #ifdef EMULTIHOP
1040         case EMULTIHOP:
1041                 return ("EMULTIHOP");
1042 #endif
1043 #ifdef ENOLINK
1044         case ENOLINK:
1045                 return ("ENOLINK");
1046 #endif
1047 #ifdef EPROTO
1048         case EPROTO:
1049                 return ("EPROTO");
1050 #endif
1051         default:
1052                 snprintf(errnum, sizeof(errnum), "%d", error);
1053                 return (errnum);
1054         }
1055 }