2 * Copyright (c) 2006-2010 Pawel Jakub Dawidek <pjd@FreeBSD.org>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
29 #include <sys/param.h>
30 #include <sys/types.h>
32 #include <sys/socket.h>
35 #include <sys/mkdev.h>
48 #ifndef HAS_TRUNCATE64
49 #define truncate64 truncate
50 #define ftruncate64 ftruncate
57 #ifdef HAS_FREEBSD_ACL
62 #define ALLPERMS (S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO)
114 #ifdef HAS_FREEBSD_ACL
121 #define TYPE_NONE 0x0000
122 #define TYPE_STRING 0x0001
123 #define TYPE_NUMBER 0x0002
124 #define TYPE_DESCRIPTOR 0x0003
125 #define TYPE_MASK 0x000f
127 #define TYPE_OPTIONAL 0x0100
131 struct syscall_desc {
133 enum action sd_action;
134 int sd_args[MAX_ARGS];
137 static struct syscall_desc syscalls[] = {
138 { "open", ACTION_OPEN, { TYPE_STRING, TYPE_STRING, TYPE_NUMBER | TYPE_OPTIONAL, TYPE_NONE } },
139 { "openat", ACTION_OPENAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_STRING, TYPE_NUMBER | TYPE_OPTIONAL, TYPE_NONE } },
140 { "create", ACTION_CREATE, { TYPE_STRING, TYPE_NUMBER, TYPE_NONE } },
141 { "unlink", ACTION_UNLINK, { TYPE_STRING, TYPE_NONE } },
142 { "unlinkat", ACTION_UNLINKAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_STRING, TYPE_NONE } },
143 { "mkdir", ACTION_MKDIR, { TYPE_STRING, TYPE_NUMBER, TYPE_NONE } },
144 { "mkdirat", ACTION_MKDIRAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NUMBER, TYPE_NONE } },
145 { "rmdir", ACTION_RMDIR, { TYPE_STRING, TYPE_NONE } },
146 { "link", ACTION_LINK, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
147 { "linkat", ACTION_LINKAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_DESCRIPTOR, TYPE_STRING, TYPE_STRING, TYPE_NONE } },
148 { "symlink", ACTION_SYMLINK, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
149 { "symlinkat", ACTION_SYMLINKAT, { TYPE_STRING, TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } },
150 { "rename", ACTION_RENAME, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
151 { "renameat", ACTION_RENAMEAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } },
152 { "mkfifo", ACTION_MKFIFO, { TYPE_STRING, TYPE_NUMBER, TYPE_NONE } },
153 { "mkfifoat", ACTION_MKFIFOAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NUMBER, TYPE_NONE } },
154 { "mknod", ACTION_MKNOD, { TYPE_STRING, TYPE_STRING, TYPE_NUMBER, TYPE_NUMBER, TYPE_NUMBER, TYPE_NONE} },
155 { "mknodat", ACTION_MKNODAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_STRING, TYPE_NUMBER, TYPE_NUMBER, TYPE_NUMBER, TYPE_NONE} },
156 { "bind", ACTION_BIND, { TYPE_STRING, TYPE_NONE } },
157 { "connect", ACTION_CONNECT, { TYPE_STRING, TYPE_NONE } },
158 { "chmod", ACTION_CHMOD, { TYPE_STRING, TYPE_NUMBER, TYPE_NONE } },
159 { "fchmod", ACTION_FCHMOD, { TYPE_DESCRIPTOR, TYPE_NUMBER, TYPE_NONE } },
161 { "lchmod", ACTION_LCHMOD, { TYPE_STRING, TYPE_NUMBER, TYPE_NONE } },
163 { "fchmodat", ACTION_FCHMODAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NUMBER, TYPE_STRING, TYPE_NONE } },
164 { "chown", ACTION_CHOWN, { TYPE_STRING, TYPE_NUMBER, TYPE_NUMBER, TYPE_NONE } },
165 { "fchown", ACTION_FCHOWN, { TYPE_DESCRIPTOR, TYPE_NUMBER, TYPE_NUMBER, TYPE_NONE } },
166 { "lchown", ACTION_LCHOWN, { TYPE_STRING, TYPE_NUMBER, TYPE_NUMBER, TYPE_NONE } },
167 { "fchownat", ACTION_FCHOWNAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NUMBER, TYPE_NUMBER, TYPE_STRING, TYPE_NONE } },
169 { "chflags", ACTION_CHFLAGS, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
172 { "fchflags", ACTION_FCHFLAGS, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } },
175 { "lchflags", ACTION_LCHFLAGS, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
177 { "truncate", ACTION_TRUNCATE, { TYPE_STRING, TYPE_NUMBER, TYPE_NONE } },
178 { "ftruncate", ACTION_FTRUNCATE, { TYPE_DESCRIPTOR, TYPE_NUMBER, TYPE_NONE } },
179 { "stat", ACTION_STAT, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
180 { "fstat", ACTION_FSTAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } },
181 { "lstat", ACTION_LSTAT, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
182 { "fstatat", ACTION_FSTATAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_STRING, TYPE_STRING, TYPE_NONE } },
183 { "pathconf", ACTION_PATHCONF, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
184 { "fpathconf", ACTION_FPATHCONF, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } },
185 { "lpathconf", ACTION_LPATHCONF, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
186 #ifdef HAS_FREEBSD_ACL
187 { "prependacl", ACTION_PREPENDACL, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
188 { "readacl", ACTION_READACL, { TYPE_STRING, TYPE_NONE } },
190 { "write", ACTION_WRITE, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } },
191 { NULL, -1, { TYPE_NONE } }
199 static struct flag open_flags[] = {
201 { O_RDONLY, "O_RDONLY" },
204 { O_WRONLY, "O_WRONLY" },
207 { O_RDWR, "O_RDWR" },
210 { O_NONBLOCK, "O_NONBLOCK" },
213 { O_APPEND, "O_APPEND" },
216 { O_CREAT, "O_CREAT" },
219 { O_TRUNC, "O_TRUNC" },
222 { O_EXCL, "O_EXCL" },
225 { O_SHLOCK, "O_SHLOCK" },
228 { O_EXLOCK, "O_EXLOCK" },
231 { O_DIRECT, "O_DIRECT" },
234 { O_FSYNC, "O_FSYNC" },
237 { O_SYNC, "O_SYNC" },
240 { O_NOFOLLOW, "O_NOFOLLOW" },
243 { O_NOCTTY, "O_NOCTTY" },
246 { O_DIRECTORY, "O_DIRECTORY" },
252 static struct flag chflags_flags[] = {
254 { UF_NODUMP, "UF_NODUMP" },
257 { UF_IMMUTABLE, "UF_IMMUTABLE" },
260 { UF_APPEND, "UF_APPEND" },
263 { UF_NOUNLINK, "UF_NOUNLINK" },
266 { UF_OPAQUE, "UF_OPAQUE" },
269 { SF_ARCHIVED, "SF_ARCHIVED" },
272 { SF_IMMUTABLE, "SF_IMMUTABLE" },
275 { SF_APPEND, "SF_APPEND" },
278 { SF_NOUNLINK, "SF_NOUNLINK" },
281 { SF_SNAPSHOT, "SF_SNAPSHOT" },
287 static struct flag unlinkat_flags[] = {
288 { AT_REMOVEDIR, "AT_REMOVEDIR" },
292 static struct flag linkat_flags[] = {
293 { AT_SYMLINK_FOLLOW, "AT_SYMLINK_FOLLOW" },
297 static struct flag fchmodat_flags[] = {
298 { AT_SYMLINK_NOFOLLOW, "AT_SYMLINK_NOFOLLOW" },
302 static struct flag fchownat_flags[] = {
303 { AT_SYMLINK_NOFOLLOW, "AT_SYMLINK_NOFOLLOW" },
307 static struct flag fstatat_flags[] = {
308 { AT_SYMLINK_NOFOLLOW, "AT_SYMLINK_NOFOLLOW" },
317 static struct name pathconf_names[] = {
319 { _PC_LINK_MAX, "_PC_LINK_MAX" },
322 { _PC_NAME_MAX, "_PC_NAME_MAX" },
325 { _PC_PATH_MAX, "_PC_PATH_MAX" },
327 #ifdef _PC_SYMLINK_MAX
328 { _PC_SYMLINK_MAX, "_PC_SYMLINK_MAX" },
333 static const char *err2str(int error);
335 static int *descriptors;
336 static int ndescriptors;
342 fprintf(stderr, "usage: pjdfstest [-U umask] [-u uid] [-g gid1[,gid2[...]]] syscall args ...\n");
347 str2flags(struct flag *tflags, char *sflags)
353 for (f = strtok(sflags, ","); f != NULL; f = strtok(NULL, ",")) {
354 /* Support magic 'none' flag which just reset all flags. */
355 if (strcmp(f, "none") == 0)
357 for (i = 0; tflags[i].f_str != NULL; i++) {
358 if (strcmp(tflags[i].f_str, f) == 0)
361 if (tflags[i].f_str == NULL) {
362 fprintf(stderr, "unknown flag '%s'\n", f);
365 flags |= tflags[i].f_flag;
372 flags2str(struct flag *tflags, long long flags)
374 static char sflags[1024];
378 for (i = 0; tflags[i].f_str != NULL; i++) {
379 if (flags & tflags[i].f_flag) {
380 if (sflags[0] != '\0')
381 strlcat(sflags, ",", sizeof(sflags));
382 strlcat(sflags, tflags[i].f_str, sizeof(sflags));
385 if (sflags[0] == '\0')
386 strlcpy(sflags, "none", sizeof(sflags));
392 str2name(struct name *names, char *name)
396 for (i = 0; names[i].n_str != NULL; i++) {
397 if (strcmp(names[i].n_str, name) == 0)
398 return (names[i].n_name);
403 static struct syscall_desc *
404 find_syscall(const char *name)
408 for (i = 0; syscalls[i].sd_name != NULL; i++) {
409 if (strcmp(syscalls[i].sd_name, name) == 0)
410 return (&syscalls[i]);
416 show_stat(struct stat64 *sp, const char *what)
419 if (strcmp(what, "mode") == 0)
420 printf("0%o", (unsigned int)(sp->st_mode & ALLPERMS));
421 else if (strcmp(what, "inode") == 0)
422 printf("%lld", (long long)sp->st_ino);
423 else if (strcmp(what, "nlink") == 0)
424 printf("%lld", (long long)sp->st_nlink);
425 else if (strcmp(what, "uid") == 0)
426 printf("%d", (int)sp->st_uid);
427 else if (strcmp(what, "gid") == 0)
428 printf("%d", (int)sp->st_gid);
429 else if (strcmp(what, "size") == 0)
430 printf("%lld", (long long)sp->st_size);
431 else if (strcmp(what, "blocks") == 0)
432 printf("%lld", (long long)sp->st_blocks);
433 else if (strcmp(what, "atime") == 0)
434 printf("%lld", (long long)sp->st_atime);
435 else if (strcmp(what, "mtime") == 0)
436 printf("%lld", (long long)sp->st_mtime);
437 else if (strcmp(what, "ctime") == 0)
438 printf("%lld", (long long)sp->st_ctime);
440 else if (strcmp(what, "flags") == 0)
441 printf("%s", flags2str(chflags_flags, (long long)sp->st_flags));
443 else if (strcmp(what, "major") == 0)
444 printf("%u", (unsigned int)major(sp->st_rdev));
445 else if (strcmp(what, "minor") == 0)
446 printf("%u", (unsigned int)minor(sp->st_rdev));
447 else if (strcmp(what, "type") == 0) {
448 switch (sp->st_mode & S_IFMT) {
480 show_stats(struct stat64 *sp, char *what)
485 for (w = strtok(what, ","); w != NULL; w = strtok(NULL, ",")) {
494 descriptor_add(int fd)
498 if (descriptors == NULL) {
499 descriptors = malloc(sizeof(descriptors[0]) * ndescriptors);
501 descriptors = realloc(descriptors,
502 sizeof(descriptors[0]) * ndescriptors);
504 assert(descriptors != NULL);
505 descriptors[ndescriptors - 1] = fd;
509 descriptor_get(int pos)
512 if (pos < 0 || pos >= ndescriptors) {
513 fprintf(stderr, "invalid descriptor %d\n", pos);
517 return (descriptors[pos]);
521 call_syscall(struct syscall_desc *scall, char *argv[])
532 #ifdef HAS_FREEBSD_ACL
533 int entry_id = ACL_FIRST_ENTRY;
535 acl_entry_t entry, newentry;
539 * Verify correctness of the arguments.
541 for (i = 0; i < sizeof(args)/sizeof(args[0]); i++) {
542 if (scall->sd_args[i] == TYPE_NONE) {
543 if (argv[i] == NULL || strcmp(argv[i], ":") == 0)
545 fprintf(stderr, "too many arguments [%s]\n", argv[i]);
548 if (argv[i] == NULL || strcmp(argv[i], ":") == 0) {
549 if (scall->sd_args[i] & TYPE_OPTIONAL)
551 fprintf(stderr, "too few arguments\n");
554 if ((scall->sd_args[i] & TYPE_MASK) == TYPE_STRING) {
555 if (strcmp(argv[i], "NULL") == 0)
557 else if (strcmp(argv[i], "DEADCODE") == 0)
558 args[i].str = (void *)0xdeadc0de;
560 args[i].str = argv[i];
561 } else if ((scall->sd_args[i] & TYPE_MASK) == TYPE_NUMBER) {
562 args[i].num = strtoll(argv[i], &endp, 0);
563 if (*endp != '\0' && !isspace((unsigned char)*endp)) {
564 fprintf(stderr, "invalid argument %u, number expected [%s]\n", i, endp);
567 } else if ((scall->sd_args[i] & TYPE_MASK) == TYPE_DESCRIPTOR) {
568 if (strcmp(argv[i], "AT_FDCWD") == 0) {
569 args[i].num = AT_FDCWD;
570 } else if (strcmp(argv[i], "BADFD") == 0) {
571 /* In case AT_FDCWD is -1 on some systems... */
579 pos = strtoll(argv[i], &endp, 0);
580 if (*endp != '\0' && !isspace((unsigned char)*endp)) {
581 fprintf(stderr, "invalid argument %u, number expected [%s]\n", i, endp);
584 args[i].num = descriptor_get(pos);
590 * Call the given syscall.
592 #define NUM(n) (args[(n)].num)
593 #define STR(n) (args[(n)].str)
594 switch (scall->sd_action) {
596 flags = str2flags(open_flags, STR(1));
597 if (flags & O_CREAT) {
599 fprintf(stderr, "too few arguments\n");
602 rval = open(STR(0), (int)flags, (mode_t)NUM(2));
605 fprintf(stderr, "too many arguments\n");
608 rval = open(STR(0), (int)flags);
611 descriptor_add(rval);
614 flags = str2flags(open_flags, STR(2));
615 if (flags & O_CREAT) {
617 fprintf(stderr, "too few arguments\n");
620 rval = openat(NUM(0), STR(1), (int)flags, (mode_t)NUM(3));
623 fprintf(stderr, "too many arguments\n");
626 rval = openat(NUM(0), STR(1), (int)flags);
629 descriptor_add(rval);
632 rval = open(STR(0), O_CREAT | O_EXCL, (mode_t)NUM(1));
637 rval = unlink(STR(0));
639 case ACTION_UNLINKAT:
640 rval = unlinkat(NUM(0), STR(1),
641 (int)str2flags(unlinkat_flags, STR(2)));
644 rval = mkdir(STR(0), (mode_t)NUM(1));
647 rval = mkdirat(NUM(0), STR(1), (mode_t)NUM(2));
650 rval = rmdir(STR(0));
653 rval = link(STR(0), STR(1));
656 rval = linkat(NUM(0), STR(1), NUM(2), STR(3),
657 (int)str2flags(linkat_flags, STR(4)));
660 rval = symlink(STR(0), STR(1));
662 case ACTION_SYMLINKAT:
663 rval = symlinkat(STR(0), NUM(1), STR(2));
666 rval = rename(STR(0), STR(1));
668 case ACTION_RENAMEAT:
669 rval = renameat(NUM(0), STR(1), NUM(2), STR(3));
672 rval = mkfifo(STR(0), (mode_t)NUM(1));
674 case ACTION_MKFIFOAT:
675 rval = mkfifoat(NUM(0), STR(1), (mode_t)NUM(2));
684 switch (scall->sd_action) {
695 dev = makedev(NUM(fa + 3), NUM(fa + 4));
696 if (strcmp(STR(fa + 1), "c") == 0) /* character device */
698 else if (strcmp(STR(fa + 1), "b") == 0) /* block device */
700 else if (strcmp(STR(fa + 1), "f") == 0) /* fifo special */
702 else if (strcmp(STR(fa + 1), "d") == 0) /* directory */
704 else if (strcmp(STR(fa + 1), "o") == 0) /* regular file */
707 fprintf(stderr, "wrong argument 1\n");
710 switch (scall->sd_action) {
712 rval = mknod(STR(0), ntype | NUM(2), dev);
715 rval = mknodat(NUM(0), STR(1), ntype | NUM(3), dev);
724 struct sockaddr_un sunx;
726 sunx.sun_family = AF_UNIX;
727 strncpy(sunx.sun_path, STR(0), sizeof(sunx.sun_path) - 1);
728 sunx.sun_path[sizeof(sunx.sun_path) - 1] = '\0';
729 rval = socket(AF_UNIX, SOCK_STREAM, 0);
732 rval = bind(rval, (struct sockaddr *)&sunx, sizeof(sunx));
737 struct sockaddr_un sunx;
739 sunx.sun_family = AF_UNIX;
740 strncpy(sunx.sun_path, STR(0), sizeof(sunx.sun_path) - 1);
741 sunx.sun_path[sizeof(sunx.sun_path) - 1] = '\0';
742 rval = socket(AF_UNIX, SOCK_STREAM, 0);
745 rval = connect(rval, (struct sockaddr *)&sunx, sizeof(sunx));
749 rval = chmod(STR(0), (mode_t)NUM(1));
752 rval = fchmod(NUM(0), (mode_t)NUM(1));
756 rval = lchmod(STR(0), (mode_t)NUM(1));
759 case ACTION_FCHMODAT:
760 rval = fchmodat(NUM(0), STR(1), (mode_t)NUM(2),
761 str2flags(fchmodat_flags, STR(3)));
764 rval = chown(STR(0), (uid_t)NUM(1), (gid_t)NUM(2));
767 rval = fchown(NUM(0), (uid_t)NUM(1), (gid_t)NUM(2));
770 rval = lchown(STR(0), (uid_t)NUM(1), (gid_t)NUM(2));
772 case ACTION_FCHOWNAT:
773 rval = fchownat(NUM(0), STR(1), (uid_t)NUM(2), (gid_t)NUM(3),
774 (int)str2flags(fchownat_flags, STR(4)));
778 rval = chflags(STR(0),
779 (unsigned long)str2flags(chflags_flags, STR(1)));
783 case ACTION_FCHFLAGS:
784 rval = fchflags(NUM(0),
785 (unsigned long)str2flags(chflags_flags, STR(1)));
789 case ACTION_LCHFLAGS:
790 rval = lchflags(STR(0), (int)str2flags(chflags_flags, STR(1)));
793 case ACTION_TRUNCATE:
794 rval = truncate64(STR(0), NUM(1));
796 case ACTION_FTRUNCATE:
797 rval = ftruncate64(NUM(0), NUM(1));
800 rval = stat64(STR(0), &sb);
802 show_stats(&sb, STR(1));
807 rval = fstat64(NUM(0), &sb);
809 show_stats(&sb, STR(1));
814 rval = lstat64(STR(0), &sb);
816 show_stats(&sb, STR(1));
821 rval = fstatat(NUM(0), STR(1), &sb,
822 (int)str2flags(fstatat_flags, STR(2)));
824 show_stats(&sb, STR(3));
828 case ACTION_PATHCONF:
829 case ACTION_FPATHCONF:
830 case ACTION_LPATHCONF:
834 name = str2name(pathconf_names, STR(1));
836 fprintf(stderr, "unknown name %s", STR(1));
840 switch (scall->sd_action) {
841 case ACTION_PATHCONF:
842 lrval = pathconf(STR(0), name);
844 case ACTION_FPATHCONF:
845 lrval = fpathconf(NUM(0), name);
847 case ACTION_LPATHCONF:
848 lrval = lpathconf(STR(0), name);
853 if (lrval == -1 && errno == 0) {
854 printf("unlimited\n");
856 } else if (lrval >= 0) {
857 printf("%ld\n", lrval);
863 #ifdef HAS_FREEBSD_ACL
864 case ACTION_PREPENDACL:
867 acl = acl_get_file(STR(0), ACL_TYPE_NFS4);
871 newacl = acl_from_text(STR(1));
875 while (acl_get_entry(newacl, entry_id, &newentry) == 1) {
876 entry_id = ACL_NEXT_ENTRY;
878 if (acl_create_entry_np(&acl, &entry, 0))
881 if (acl_copy_entry(entry, newentry))
885 rval = acl_set_file(STR(0), ACL_TYPE_NFS4, acl);
888 acl = acl_get_file(STR(0), ACL_TYPE_NFS4);
896 rval = write(NUM(0), STR(1), strlen(STR(1)));
899 fprintf(stderr, "unsupported syscall\n");
907 serrno = err2str(errno);
908 fprintf(stderr, "%s returned %d\n", scall->sd_name, rval);
909 printf("%s\n", serrno);
924 ngroups = sysconf(_SC_NGROUPS_MAX);
926 gidset = malloc(sizeof(*gidset) * ngroups);
927 assert(gidset != NULL);
928 for (i = 0, g = strtok(gids, ","); g != NULL; g = strtok(NULL, ","), i++) {
930 fprintf(stderr, "too many gids\n");
933 gidset[i] = strtol(g, &endp, 0);
934 if (*endp != '\0' && !isspace((unsigned char)*endp)) {
935 fprintf(stderr, "invalid gid '%s' - number expected\n",
940 if (setgroups(i, gidset) < 0) {
941 fprintf(stderr, "cannot change groups: %s\n", strerror(errno));
944 if (setegid(gidset[0]) < 0) {
945 fprintf(stderr, "cannot change effective gid: %s\n", strerror(errno));
952 main(int argc, char *argv[])
954 struct syscall_desc *scall;
963 while ((ch = getopt(argc, argv, "g:u:U:")) != -1) {
969 uid = (int)strtol(optarg, &endp, 0);
970 if (*endp != '\0' && !isspace((unsigned char)*endp)) {
971 fprintf(stderr, "invalid uid '%s' - number "
972 "expected\n", optarg);
977 umsk = (int)strtol(optarg, &endp, 0);
978 if (*endp != '\0' && !isspace((unsigned char)*endp)) {
979 fprintf(stderr, "invalid umask '%s' - number "
980 "expected\n", optarg);
992 fprintf(stderr, "too few arguments\n");
997 fprintf(stderr, "changing groups to %s\n", gids);
1001 fprintf(stderr, "changing uid to %d\n", uid);
1002 if (setuid(uid) < 0) {
1003 fprintf(stderr, "cannot change uid: %s\n",
1009 /* Change umask to requested value or to 0, if not requested. */
1013 scall = find_syscall(argv[0]);
1014 if (scall == NULL) {
1015 fprintf(stderr, "syscall '%s' not supported\n", argv[0]);
1020 n = call_syscall(scall, argv);
1023 if (argv[0] == NULL)
1035 static char errnum[8];
1180 return ("EINPROGRESS");
1184 return ("EALREADY");
1188 return ("ENOTSOCK");
1192 return ("EDESTADDRREQ");
1196 return ("EMSGSIZE");
1200 return ("EPROTOTYPE");
1204 return ("ENOPROTOOPT");
1206 #ifdef EPROTONOSUPPORT
1207 case EPROTONOSUPPORT:
1208 return ("EPROTONOSUPPORT");
1210 #ifdef ESOCKTNOSUPPORT
1211 case ESOCKTNOSUPPORT:
1212 return ("ESOCKTNOSUPPORT");
1216 return ("EOPNOTSUPP");
1220 return ("EPFNOSUPPORT");
1224 return ("EAFNOSUPPORT");
1228 return ("EADDRINUSE");
1230 #ifdef EADDRNOTAVAIL
1232 return ("EADDRNOTAVAIL");
1236 return ("ENETDOWN");
1240 return ("ENETUNREACH");
1244 return ("ENETRESET");
1248 return ("ECONNABORTED");
1252 return ("ECONNRESET");
1264 return ("ENOTCONN");
1268 return ("ESHUTDOWN");
1272 return ("ETOOMANYREFS");
1276 return ("ETIMEDOUT");
1280 return ("ECONNREFUSED");
1288 return ("ENAMETOOLONG");
1292 return ("EHOSTDOWN");
1296 return ("EHOSTUNREACH");
1300 return ("ENOTEMPTY");
1304 return ("EPROCLIM");
1328 return ("ERPCMISMATCH");
1332 return ("EPROGUNAVAIL");
1334 #ifdef EPROGMISMATCH
1336 return ("EPROGMISMATCH");
1340 return ("EPROCUNAVAIL");
1360 return ("ENEEDAUTH");
1372 return ("EOVERFLOW");
1376 return ("ECANCELED");
1396 return ("EMULTIHOP");
1407 snprintf(errnum, sizeof(errnum), "%d", error);