3 #include <sys/dirent.h>
12 #include <sys/sysctl.h>
13 #include <sys/utsname.h>
20 #include <nestedvm/socket.h>
22 int _syscall_set_errno(struct _reent *ptr, int err) {
27 #define REENT_WRAPPER0R(f,rt) \
28 extern rt _##f##_r(struct _reent *ptr); \
29 rt f() { return _##f##_r(_REENT); }
30 #define REENT_WRAPPER0(f) REENT_WRAPPER0R(f,int)
32 #define REENT_WRAPPER1R(f,rt,t1) \
33 extern rt _##f##_r(struct _reent *ptr, t1 a); \
34 rt f(t1 a) { return _##f##_r(_REENT,a); }
35 #define REENT_WRAPPER1(f,t1) REENT_WRAPPER1R(f,int,t1)
37 #define REENT_WRAPPER2R(f,rt,t1,t2) \
38 extern rt _##f##_r(struct _reent *ptr, t1 a, t2 b); \
39 rt f(t1 a, t2 b) { return _##f##_r(_REENT,a,b); }
40 #define REENT_WRAPPER2(f,t1,t2) REENT_WRAPPER2R(f,int,t1,t2)
42 #define REENT_WRAPPER3R(f,rt,t1,t2,t3) \
43 extern rt _##f##_r(struct _reent *ptr, t1 a, t2 b, t3 c); \
44 rt f(t1 a, t2 b, t3 c) { return _##f##_r(_REENT,a,b,c); }
45 #define REENT_WRAPPER3(f,t1,t2,t3) REENT_WRAPPER3R(f,int,t1,t2,t3)
47 #define REENT_WRAPPER4R(f,rt,t1,t2,t3,t4) \
48 extern rt _##f##_r(struct _reent *ptr, t1 a, t2 b, t3 c, t4 d); \
49 rt f(t1 a, t2 b, t3 c, t4 d) { return _##f##_r(_REENT,a,b,c,d); }
50 #define REENT_WRAPPER4(f,t1,t2,t3,t4) REENT_WRAPPER4R(f,int,t1,t2,t3,t4)
52 #define REENT_WRAPPER5R(f,rt,t1,t2,t3,t4,t5) \
53 extern rt _##f##_r(struct _reent *ptr, t1 a, t2 b, t3 c, t4 d, t5 e); \
54 rt f(t1 a, t2 b, t3 c, t4 d, t5 e) { return _##f##_r(_REENT,a,b,c,d,e); }
55 #define REENT_WRAPPER5(f,t1,t2,t3,t4,t5) REENT_WRAPPER5R(f,int,t1,t2,t3,t4,t5)
57 #define REENT_WRAPPER6R(f,rt,t1,t2,t3,t4,t5,t6) \
58 extern rt _##f##_r(struct _reent *ptr, t1 a, t2 b, t3 c, t4 d, t5 e, t6 f); \
59 rt f(t1 a, t2 b, t3 c, t4 d, t5 e, t6 f) { return _##f##_r(_REENT,a,b,c,d,e,f); }
60 #define REENT_WRAPPER6(f,t1,t2,t3,t4,t5,t6) REENT_WRAPPER6R(f,int,t1,t2,t3,t4,t5,t6)
62 REENT_WRAPPER2(mkdir,const char *,mode_t)
63 REENT_WRAPPER2(access,const char *,int)
64 REENT_WRAPPER1(rmdir,const char *)
65 REENT_WRAPPER1R(sysconf,long,int)
66 REENT_WRAPPER1(chdir,const char*)
67 REENT_WRAPPER2(utime,const char *,const struct utimbuf *)
68 REENT_WRAPPER1(pipe,int *)
69 REENT_WRAPPER2(dup2,int,int)
70 REENT_WRAPPER3(waitpid,pid_t,int *,int)
71 REENT_WRAPPER2R(getcwd,char *,char *,size_t)
72 REENT_WRAPPER2R(_getcwd,char *,char *,size_t)
73 REENT_WRAPPER2(symlink,const char *,const char *)
74 REENT_WRAPPER3(readlink,const char *, char *,int)
75 REENT_WRAPPER3(chown,const char *,uid_t,gid_t)
76 REENT_WRAPPER3(fchown,int,uid_t,gid_t)
77 REENT_WRAPPER3(lchown,const char *,uid_t,gid_t)
78 REENT_WRAPPER2(chmod,const char *,mode_t)
79 REENT_WRAPPER2(fchmod,int,mode_t)
80 REENT_WRAPPER2(lstat,const char *,struct stat *)
81 REENT_WRAPPER4(getdents,int, char *, size_t,long *)
82 REENT_WRAPPER1(dup,int)
83 REENT_WRAPPER2R(pathconf,long,const char *,int)
85 REENT_WRAPPER1(chroot,const char *)
86 REENT_WRAPPER3(mknod,const char *,mode_t,dev_t)
87 REENT_WRAPPER2(ftruncate,int,off_t)
88 REENT_WRAPPER1R(usleep,unsigned int,unsigned int)
89 REENT_WRAPPER2(mkfifo,const char *, mode_t)
90 REENT_WRAPPER3(klogctl,int,char*,int)
91 REENT_WRAPPER2R(realpath,char *,const char *,char *)
92 REENT_WRAPPER6(_sysctl,int *,int, void *, size_t*, void *, size_t)
93 REENT_WRAPPER6(sysctl,int *, int, void *, size_t*, void *, size_t)
94 REENT_WRAPPER2(getpriority,int,int)
95 REENT_WRAPPER3(setpriority,int,int,int)
96 REENT_WRAPPER3(connect,int,const struct sockaddr *,socklen_t)
97 REENT_WRAPPER3(socket,int,int,int)
98 REENT_WRAPPER3(_resolve_hostname,const char *,char*,size_t*)
99 REENT_WRAPPER3(_resolve_ip,int,char*,size_t)
100 REENT_WRAPPER3(accept,int,struct sockaddr *,socklen_t*)
101 REENT_WRAPPER5(getsockopt,int,int,int,void*,socklen_t*)
102 REENT_WRAPPER5(setsockopt,int,int,int,const void*,socklen_t)
103 REENT_WRAPPER3(bind,int,const struct sockaddr *,socklen_t)
104 REENT_WRAPPER2(listen,int,int)
105 REENT_WRAPPER2(shutdown,int,int)
106 REENT_WRAPPER6(sendto,int,const void*,size_t,int,const struct sockaddr*,socklen_t)
107 REENT_WRAPPER6(recvfrom,int,void*,size_t,int,struct sockaddr*,socklen_t*)
108 REENT_WRAPPER5(select,int,fd_set*,fd_set*,fd_set*,struct timeval*)
109 REENT_WRAPPER4(send,int,const void*,size_t,int)
110 REENT_WRAPPER4(recv,int,void*,size_t,int)
111 REENT_WRAPPER2(getgroups,int,gid_t*)
112 REENT_WRAPPER3(getsockname,int,struct sockaddr*,int*)
113 REENT_WRAPPER3(getpeername,int,struct sockaddr*,int*)
114 REENT_WRAPPER1(setuid,uid_t)
115 REENT_WRAPPER1(seteuid,uid_t)
116 REENT_WRAPPER1(setgid,gid_t)
117 REENT_WRAPPER1(setegid,gid_t)
118 REENT_WRAPPER2(setgroups,int,const gid_t *)
119 REENT_WRAPPER0R(setsid,pid_t)
120 REENT_WRAPPER1(fsync,int)
122 extern int __execve_r(struct _reent *ptr, const char *path, char *const argv[], char *const envp[]);
123 int _execve(const char *path, char *const argv[], char *const envp[]) {
124 return __execve_r(_REENT,path,argv,envp);
127 char *_getcwd_r(struct _reent *ptr, char *buf, size_t size) {
129 buf = __getcwd_r(ptr,buf,size);
130 return (long)buf == -1 ? NULL : buf;
136 char *ret = __getcwd_r(ptr,buf,size);
137 if((long)ret != -1) return ret;
140 if(ptr->_errno != ERANGE) return NULL;
144 pid_t _wait_r(struct _reent *ptr, int *status) {
145 return _waitpid_r(ptr,-1,status,0);
148 long _pathconf_r(struct _reent *ptr,const char *path, int name) {
151 fprintf(stderr,"WARNING: pathconf: Unknown \"name\": %d\n",name);
152 ptr->_errno = EINVAL;
157 int _sysctl_r(struct _reent *ptr, int *name, int namelen, void *oldp, size_t *oldlen, void *newp, size_t newlen) {
158 if(name[0] != CTL_USER) return _sysctl(name,namelen,oldp,oldlen,newp,newlen);
159 if(newp != NULL) { ptr->_errno = EPERM; return -1; }
160 if(namelen != 2) { ptr->_errno = EINVAL; return -1; }
164 fprintf(stderr,"WARNING: sysctl: Unknown name: %d\n",name[1]);
165 ptr->_errno = EINVAL;
175 char *ttyname(int fd) {
176 return isatty(fd) ? "/dev/console" : NULL;
179 int sigaction(int sig, const struct sigaction *act, struct sigaction *oact) {
183 if(act->sa_flags || act->sa_mask != ~((sigset_t)0)) { errno = EINVAL; return -1; }
184 old = signal(sig,act->sa_handler);
186 old = signal(sig,SIG_DFL);
190 oact->sa_handler = old;
192 oact->sa_mask = ~((sigset_t)0);
197 DIR *opendir(const char *path) {
202 fd = open(path,O_RDONLY);
203 if(fd < 0) return NULL;
205 if(fstat(fd,&sb) < 0 || !S_ISDIR(sb.st_mode)) {
211 dir = malloc(sizeof(*dir));
218 dir->dd_buf = malloc(sizeof(struct dirent));
219 dir->dd_size = sizeof(struct dirent);
220 if(dir->dd_buf == NULL) {
230 struct dirent *readdir(DIR *dir) {
233 if(dir->dd_loc == 0 || dir->dd_loc == dir->dd_len) {
234 dir->dd_len = getdents(dir->dd_fd,dir->dd_buf,dir->dd_size,NULL);
236 if(dir->dd_len <= 0) { dir->dd_len = 0; return NULL; }
238 dp = (struct dirent*) (dir->dd_buf + dir->dd_loc);
239 if(dp->d_reclen == 0 || dp->d_reclen > dir->dd_len - dir->dd_loc) return NULL;
240 dir->dd_loc += dp->d_reclen;
244 int closedir(DIR *dir) {
252 * Networking/Socket stuff
255 /* This should really be part of the newlib _reent structure */
258 char *inet_ntoa(struct in_addr in) {
260 const unsigned char *p = (void*) ∈
261 snprintf(buf,sizeof(buf),"%u.%u.%u.%u",p[0],p[1],p[2],p[3]);
265 struct servent *getservbyname(const char *name,const char *proto) {
269 static const char *h_errlist[] = { "No Error","Unknown host", "Host name lookup failure","Unknown server error","No address associated with name" };
271 const char *hstrerror(int err) {
272 if(err < 0 || err > 4) return "Unknown Error";
273 return h_errlist[err];
276 void herror(const char *string) {
277 fprintf(stderr,"%s: %s\n",string,hstrerror(h_errno));
280 extern int _resolve_ip(int addr, char *buf, size_t size);
282 struct hostent *gethostbyaddr(const char *addr, int len, int type) {
283 static struct hostent hostent;
284 static char name[128];
285 static char *aliases[1];
286 static char *addr_list[1];
287 static char addr_list_buf[4];
290 if(type != AF_INET || len != 4) return NULL;
292 memcpy(addr_list_buf,addr,4);
293 err = _resolve_ip(i,name,sizeof(name));
294 if(err != 0) { h_errno = err; return NULL; }
296 hostent.h_name = name;
297 hostent.h_aliases = aliases;
299 hostent.h_addrtype = AF_INET;
300 hostent.h_length = sizeof(struct in_addr);
301 hostent.h_addr_list = addr_list;
302 addr_list[0] = addr_list_buf;
307 extern int _resolve_hostname(const char *, char *buf, size_t *size);
309 struct hostent *gethostbyname(const char *hostname) {
310 #define MAX_ADDRS 256
311 static struct hostent hostent;
312 static char saved_hostname[128];
313 static char *addr_list[MAX_ADDRS+1];
314 static char addr_list_buf[MAX_ADDRS*sizeof(struct in_addr)];
315 static char *aliases[1];
317 unsigned char buf[MAX_ADDRS*sizeof(struct in_addr)];
318 size_t size = sizeof(buf);
321 err = _resolve_hostname(hostname,buf,&size);
322 if(err != 0) { h_errno = err; return NULL; }
324 memcpy(addr_list_buf,buf,size);
325 for(i=0;i<size;i += sizeof(struct in_addr)) addr_list[n++] = &addr_list_buf[i];
327 strncpy(saved_hostname,hostname,sizeof(saved_hostname));
330 hostent.h_name = saved_hostname;
331 hostent.h_aliases = aliases;
332 hostent.h_addrtype = AF_INET;
333 hostent.h_length = sizeof(struct in_addr);
334 hostent.h_addr_list = addr_list;
339 static struct passwd pw_passwd;
340 static struct group gr_group;
341 static FILE *passwd_fp;
342 static FILE *group_fp;
343 static char pw_name[1024];
344 static char pw_password[1024];
345 static char pw_gecos[1024];
346 static char pw_dir[1024];
347 static char pw_shell[1024];
348 static char gr_name[1024];
349 static char gr_passwd[1024];
350 static char *gr_mem[1];
352 static int gr_parse_body(const char *buf) {
353 if(sscanf(buf,"%[^:]:%[^:]:%hu",gr_name,gr_passwd,&gr_group.gr_gid) < 3) return -1;
354 gr_group.gr_name = gr_name;
355 gr_group.gr_passwd = gr_passwd;
356 gr_group.gr_mem = gr_mem;
361 static int pw_parse_body(const char *buf) {
363 if(sscanf(buf,"%[^:]:%[^:]:%d:%d:%[^:]:%[^:]:%s\n",pw_name,pw_password,&pw_passwd.pw_uid,&pw_passwd.pw_gid,pw_gecos,pw_dir,pw_shell) < 7) return -1;
364 pw_passwd.pw_name = pw_name;
365 pw_passwd.pw_passwd = pw_password;
366 pw_passwd.pw_gecos = pw_gecos;
367 pw_passwd.pw_dir = pw_dir;
368 pw_passwd.pw_shell = pw_shell;
369 pw_passwd.pw_comment = "";
373 struct group *getgrnam(const char *name) {
377 if((fp=fopen("/etc/group","r"))==NULL) return NULL;
378 while(fgets(buf,sizeof(buf),fp)) {
379 if(buf[0] == '#') continue;
380 if(gr_parse_body(buf) < 0) {
384 if(strcmp(name,gr_name)==0) {
393 struct group *getgrgid(gid_t gid) {
397 if((fp=fopen("/etc/group","r"))==NULL) return NULL;
398 while(fgets(buf,sizeof(buf),fp)) {
399 if(buf[0] == '#') continue;
400 if(gr_parse_body(buf) < 0) {
404 if(gid == gr_group.gr_gid) {
413 struct group *getgrent() {
415 if(group_fp == NULL) return NULL;
416 if(fgets(buf,sizeof(buf),group_fp) == NULL) return NULL;
417 if(buf[0] == '#') return getgrent();
418 if(gr_parse_body(buf) < 0) return NULL;
423 if(group_fp != NULL) fclose(group_fp);
424 group_fp = fopen("/etc/group","r");
428 if(group_fp != NULL) fclose(group_fp);
432 struct passwd *getpwnam(const char *name) {
436 if((fp=fopen("/etc/passwd","r"))==NULL) return NULL;
437 while(fgets(buf,sizeof(buf),fp)) {
438 if(buf[0] == '#') continue;
439 if(pw_parse_body(buf) < 0) {
443 if(strcmp(name,pw_name)==0) {
452 struct passwd *getpwuid(uid_t uid) {
456 if((fp=fopen("/etc/passwd","r"))==NULL) return NULL;
457 while(fgets(buf,sizeof(buf),fp)) {
458 if(buf[0] == '#') continue;
459 if(pw_parse_body(buf) < 0) {
463 if(uid == pw_passwd.pw_uid) {
472 struct passwd *getpwent() {
474 if(passwd_fp == NULL) return NULL;
475 if(fgets(buf,sizeof(buf),passwd_fp) == NULL) return NULL;
476 if(buf[0] == '#') return getpwent();
477 if(pw_parse_body(buf) < 0) return NULL;
482 if(passwd_fp != NULL) fclose(passwd_fp);
483 passwd_fp = fopen("/etc/group","r");
487 if(passwd_fp != NULL) fclose(passwd_fp);
491 char *getpass(const char *prompt) {
492 static char buf[1024];
494 fputs(prompt,stderr);
496 if(fgets(buf,sizeof(buf),stdin)!=NULL) {
498 if(buf[len-1] == '\n') len--;
505 /* Argh... newlib's asprintf is totally broken... */
506 int vasprintf(char **ret, const char *fmt, va_list ap) {
509 *ret = malloc(128); /* just guess for now */
511 n = vsnprintf(*ret,128,fmt,ap);
515 p = realloc(*ret,n+1);
516 if(!p) { free(*ret); return -1; }
517 return vsprintf(*ret = p,fmt,ap);
521 // FIXME: This needs to be in a header
523 return getenv("USER");
528 * Other People's Code
531 /* FreeBSD's dirname/basename */
533 /* FIXME: Put these in a header */
536 * Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com>
537 * All rights reserved.
539 * Redistribution and use in source and binary forms, with or without
540 * modification, are permitted provided that the following conditions
542 * 1. Redistributions of source code must retain the above copyright
543 * notice, this list of conditions and the following disclaimer.
544 * 2. Redistributions in binary form must reproduce the above copyright
545 * notice, this list of conditions and the following disclaimer in the
546 * documentation and/or other materials provided with the distribution.
547 * 3. The name of the author may not be used to endorse or promote products
548 * derived from this software without specific prior written permission.
550 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
551 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
552 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
553 * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
554 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
555 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
556 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
557 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
558 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
559 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
566 static char bname[MAXPATHLEN];
567 register const char *endp;
569 /* Empty or NULL string gets treated as "." */
570 if (path == NULL || *path == '\0') {
571 (void)strcpy(bname, ".");
575 /* Strip trailing slashes */
576 endp = path + strlen(path) - 1;
577 while (endp > path && *endp == '/')
580 /* Find the start of the dir */
581 while (endp > path && *endp != '/')
584 /* Either the dir is "/" or there are no slashes */
586 (void)strcpy(bname, *endp == '/' ? "/" : ".");
591 } while (endp > path && *endp == '/');
594 if (endp - path + 2 > sizeof(bname)) {
595 errno = ENAMETOOLONG;
598 (void)strncpy(bname, path, endp - path + 1);
599 bname[endp - path + 1] = '\0';
607 static char bname[MAXPATHLEN];
608 register const char *endp, *startp;
610 /* Empty or NULL string gets treated as "." */
611 if (path == NULL || *path == '\0') {
612 (void)strcpy(bname, ".");
616 /* Strip trailing slashes */
617 endp = path + strlen(path) - 1;
618 while (endp > path && *endp == '/')
621 /* All slashes becomes "/" */
622 if (endp == path && *endp == '/') {
623 (void)strcpy(bname, "/");
627 /* Find the start of the base */
629 while (startp > path && *(startp - 1) != '/')
632 if (endp - startp + 2 > sizeof(bname)) {
633 errno = ENAMETOOLONG;
636 (void)strncpy(bname, startp, endp - startp + 1);
637 bname[endp - startp + 1] = '\0';
641 /* FreeBSD's uname */
644 struct utsname *name;
654 mib[1] = KERN_OSTYPE;
655 len = sizeof(name->sysname);
657 if (sysctl(mib, 2, &name->sysname, &len, NULL, 0) == -1) {
663 name->sysname[sizeof(name->sysname) - 1] = '\0';
666 mib[1] = KERN_HOSTNAME;
667 len = sizeof(name->nodename);
669 if (sysctl(mib, 2, &name->nodename, &len, NULL, 0) == -1) {
675 name->nodename[sizeof(name->nodename) - 1] = '\0';
678 mib[1] = KERN_OSRELEASE;
679 len = sizeof(name->release);
681 if (sysctl(mib, 2, &name->release, &len, NULL, 0) == -1) {
687 name->release[sizeof(name->release) - 1] = '\0';
689 /* The version may have newlines in it, turn them into spaces. */
691 mib[1] = KERN_VERSION;
692 len = sizeof(name->version);
694 if (sysctl(mib, 2, &name->version, &len, NULL, 0) == -1) {
700 name->version[sizeof(name->version) - 1] = '\0';
701 for (p = name->version; len--; ++p) {
702 if (*p == '\n' || *p == '\t') {
712 len = sizeof(name->machine);
714 if (sysctl(mib, 2, &name->machine, &len, NULL, 0) == -1) {
720 name->machine[sizeof(name->machine) - 1] = '\0';
724 /* FreeBSD's gethostname */
726 gethostname(name, namelen)
734 mib[1] = KERN_HOSTNAME;
736 if (sysctl(mib, 2, name, &size, NULL, 0) == -1)
741 /* FreeBSD's daemon() - modified for nestedvm */
743 daemon(nochdir, noclose)
744 int nochdir, noclose;
763 if (!noclose && (fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) {
764 (void)dup2(fd, STDIN_FILENO);
765 (void)dup2(fd, STDOUT_FILENO);
766 (void)dup2(fd, STDERR_FILENO);
773 /* FreeBSD's inet_addr/inet_aton */
776 * Check whether "cp" is a valid ASCII representation
777 * of an Internet address and convert to a binary address.
778 * Returns 1 if the address is valid, 0 if not.
779 * This replaces inet_addr, the return value from which
780 * cannot distinguish between failure and a local broadcast address.
784 register const char *cp;
785 struct in_addr *addr;
796 * Run through the string, grabbing numbers until
797 * the end of the string, or some error
802 val = strtoul(c, &endptr, 0);
804 if (errno == ERANGE) /* Fail completely if it overflowed. */
808 * If the whole string is invalid, endptr will equal
809 * c.. this way we can make sure someone hasn't
810 * gone '.12' or something which would get past
818 /* Check the next character past the previous number's end */
821 /* Make sure we only do 3 dots .. */
822 if (n == 3) /* Whoops. Quit. */
833 if (isspace((unsigned char)*c)) {
837 return (0); /* Invalid character, so fail */
843 * Concoct the address according to
844 * the number of parts specified.
848 case 0: /* a -- 32 bits */
850 * Nothing is necessary here. Overflow checking was
851 * already done in strtoul().
854 case 1: /* a.b -- 8.24 bits */
855 if (val > 0xffffff || parts[0] > 0xff)
857 val |= parts[0] << 24;
860 case 2: /* a.b.c -- 8.8.16 bits */
861 if (val > 0xffff || parts[0] > 0xff || parts[1] > 0xff)
863 val |= (parts[0] << 24) | (parts[1] << 16);
866 case 3: /* a.b.c.d -- 8.8.8.8 bits */
867 if (val > 0xff || parts[0] > 0xff || parts[1] > 0xff ||
870 val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
875 addr->s_addr = htonl(val);
880 * ASCII internet address interpretation routine.
881 * The value returned is in network order.
883 in_addr_t /* XXX should be struct in_addr :( */
885 register const char *cp;
889 if (inet_aton(cp, &val))
891 return (INADDR_NONE);
895 getgrouplist(uname, agroup, groups, grpcnt)
898 register gid_t *groups;
901 register struct group *grp;
902 register int i, ngroups;
909 * When installing primary group, duplicate it;
910 * the first element of groups is the effective gid
911 * and will be overwritten when a setgid file is executed.
913 groups[ngroups++] = agroup;
915 groups[ngroups++] = agroup;
917 * Scan the group file to find additional groups.
920 while ((grp = getgrent())) {
921 for (i = 0; i < ngroups; i++) {
922 if (grp->gr_gid == groups[i])
925 for (i = 0; grp->gr_mem[i]; i++) {
926 if (!strcmp(grp->gr_mem[i], uname)) {
927 if (ngroups >= maxgroups) {
931 groups[ngroups++] = grp->gr_gid;
943 initgroups(uname, agroup)
947 gid_t groups[32], ngroups;
950 getgrouplist(uname, agroup, groups, &ngroups);
951 return (setgroups(ngroups, groups));