getuser
[nestedvm.git] / src / org / ibex / nestedvm / support_aux.c
1 #include <string.h>
2 #include <sys/stat.h>
3 #include <sys/dirent.h>
4 #include <sys/types.h>
5 #include <utime.h>
6 #include <errno.h>
7 #include <unistd.h>
8 #include <fcntl.h>
9 #include <stdlib.h>
10 #include <stdio.h>
11 #include <signal.h>
12 #include <sys/sysctl.h>
13 #include <sys/utsname.h>
14 #include <paths.h>
15 #include <ctype.h>
16 #include <pwd.h>
17 #include <grp.h>
18 #include <stdarg.h>
19
20 #include <nestedvm/socket.h>
21
22 int _syscall_set_errno(struct _reent *ptr, int err) {
23     ptr->_errno = -err;
24     return -1;
25 }
26
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)
31
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)
36
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)
41
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)
46
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)
51
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)
56
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)
61
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)
84 REENT_WRAPPER0(vfork)
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_WRAPPER1(usleep,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
121 extern int __execve_r(struct _reent *ptr, const char *path, char *const argv[], char *const envp[]);
122 int _execve(const char *path, char *const argv[], char *const envp[]) {
123     return __execve_r(_REENT,path,argv,envp);
124 }
125
126 char *_getcwd_r(struct _reent *ptr, char *buf, size_t size) {
127     if(buf != NULL) {
128         buf = __getcwd_r(ptr,buf,size);
129         return (long)buf == -1 ? NULL : buf;
130     }
131     
132     size = 256;
133     for(;;) {
134         buf = malloc(size);
135         char *ret = __getcwd_r(ptr,buf,size);
136         if((long)ret != -1) return ret;
137         free(buf);
138         size *= 2;
139         if(ptr->_errno != ERANGE) return NULL;
140     }
141 }
142
143 pid_t _wait_r(struct _reent *ptr, int *status) {
144     return _waitpid_r(ptr,-1,status,0);
145 }
146
147 long _pathconf_r(struct _reent *ptr,const char *path, int name) {
148     switch(name) {
149         default:
150             fprintf(stderr,"WARNING: pathconf: Unknown \"name\": %d\n",name);
151             ptr->_errno = EINVAL;
152             return -1;
153     }
154 }
155
156 int _sysctl_r(struct _reent *ptr, int *name, int namelen, void *oldp, size_t *oldlen, void *newp, size_t newlen) {
157     if(name[0] != CTL_USER) return _sysctl(name,namelen,oldp,oldlen,newp,newlen);
158     if(newp != NULL) { ptr->_errno = EPERM; return -1; }
159     if(namelen != 2) { ptr->_errno = EINVAL; return -1; }
160     
161     switch(name[1]) {
162         default:
163             fprintf(stderr,"WARNING: sysctl: Unknown name: %d\n",name[1]);
164             ptr->_errno = EINVAL;
165             return -1;
166     }
167 }
168
169 void sync() {
170     /* do nothing*/
171 }
172
173 int fsync(int fd) {
174     /* do nothing */
175     return 0;
176 }
177
178 char *ttyname(int fd) {
179     return isatty(fd) ? "/dev/console" : NULL;
180 }
181
182 int sigaction(int sig, const struct sigaction *act, struct sigaction *oact) {
183     _sig_func_ptr old;
184     _sig_func_ptr new;
185     if(act) {
186         if(act->sa_flags || act->sa_mask != ~((sigset_t)0)) { errno = EINVAL; return -1; }
187         old = signal(sig,act->sa_handler);
188     } else if(oact) {
189         old = signal(sig,SIG_DFL);
190         signal(sig,old);
191     }
192     if(oact) {
193         oact->sa_handler = old;
194         oact->sa_mask = 0;
195         oact->sa_mask = ~((sigset_t)0);
196     }
197     return 0;
198 }
199
200 DIR *opendir(const char *path) {
201     struct stat sb;
202     int fd;
203     DIR *dir;
204     
205     fd = open(path,O_RDONLY);
206     if(fd < 0) return NULL;
207     
208     if(fstat(fd,&sb) < 0 || !S_ISDIR(sb.st_mode)) {
209         close(fd);
210         errno = ENOTDIR;
211         return NULL;
212     }
213     
214     dir = malloc(sizeof(*dir));
215     if(dir == NULL) {
216         close(fd);
217         errno = ENOMEM;
218         return NULL;
219     }
220     dir->dd_fd = fd;
221     dir->dd_buf = malloc(sizeof(struct dirent));
222     dir->dd_size = sizeof(struct dirent);
223     if(dir->dd_buf == NULL) {
224         close(fd);
225         free(dir);
226         return NULL;
227     }
228     dir->dd_loc = 0;
229     dir->dd_len = 0;
230     return dir;
231 }
232
233 struct dirent *readdir(DIR *dir) {
234     struct dirent *dp;
235     errno = 0;
236     if(dir->dd_loc == 0 || dir->dd_loc == dir->dd_len) {
237         dir->dd_len = getdents(dir->dd_fd,dir->dd_buf,dir->dd_size,NULL);
238         dir->dd_loc = 0;
239         if(dir->dd_len <= 0) { dir->dd_len = 0; return NULL; }
240     }
241     dp = (struct dirent*) (dir->dd_buf + dir->dd_loc);
242     if(dp->d_reclen == 0 || dp->d_reclen > dir->dd_len - dir->dd_loc) return NULL;
243     dir->dd_loc += dp->d_reclen;
244     return dp;
245 }
246
247 int closedir(DIR *dir) {
248     int fd = dir->dd_fd;
249     free(dir->dd_buf);
250     free(dir);
251     return close(fd);
252 }
253
254 /*
255  * Networking/Socket stuff
256  */
257
258 /* This should really be part of the newlib _reent structure */
259 int h_errno;
260
261 char *inet_ntoa(struct in_addr in) {
262     static char buf[18];
263     const unsigned char *p = (void*) &in;
264     snprintf(buf,sizeof(buf),"%u.%u.%u.%u",p[0],p[1],p[2],p[3]);
265     return buf;
266 }
267
268 struct servent *getservbyname(const char *name,const char *proto) {
269     return NULL;
270 }
271
272 static const char *h_errlist[] = { "No Error","Unknown host", "Host name lookup failure","Unknown server error","No address associated with name" };
273
274 const char *hstrerror(int err) {
275     if(err < 0 || err > 4) return "Unknown Error";
276     return h_errlist[err];
277 }
278
279 void herror(const char *string) {
280     fprintf(stderr,"%s: %s\n",string,hstrerror(h_errno));
281 }
282
283 extern int _resolve_ip(int addr, char *buf, size_t size);
284
285 struct hostent *gethostbyaddr(const char *addr, int len, int type) {
286     static struct hostent hostent;
287     static char name[128];
288     static char *aliases[1];
289     static char *addr_list[1];
290     static char addr_list_buf[4];
291     int err,i;
292     
293     if(type != AF_INET || len != 4) return NULL;
294     memcpy(&i,addr,4);
295     memcpy(addr_list_buf,addr,4);
296     err = _resolve_ip(i,name,sizeof(name));
297     if(err != 0) { h_errno = err; return NULL; }
298     
299     hostent.h_name = name;
300     hostent.h_aliases = aliases;
301     aliases[0] = NULL;
302     hostent.h_addrtype = AF_INET;
303     hostent.h_length = sizeof(struct in_addr);
304     hostent.h_addr_list = addr_list;
305     addr_list[0] = addr_list_buf;
306     
307     return &hostent;
308 }
309
310 extern int _resolve_hostname(const char *, char *buf, size_t *size);
311
312 struct hostent *gethostbyname(const char *hostname) {
313 #define MAX_ADDRS 256
314     static struct hostent hostent;
315     static char saved_hostname[128];
316     static char *addr_list[MAX_ADDRS+1];
317     static char addr_list_buf[MAX_ADDRS*sizeof(struct in_addr)];
318     static char *aliases[1];
319     
320     unsigned char buf[MAX_ADDRS*sizeof(struct in_addr)];
321     size_t size = sizeof(buf);
322     int err,i,n=0;
323     
324     err = _resolve_hostname(hostname,buf,&size);
325     if(err != 0) { h_errno = err; return NULL; }
326     
327     memcpy(addr_list_buf,buf,size);
328     for(i=0;i<size;i += sizeof(struct in_addr)) addr_list[n++] = &addr_list_buf[i];
329     addr_list[n] = NULL;
330     strncpy(saved_hostname,hostname,sizeof(saved_hostname));
331     aliases[0] = NULL;
332     
333     hostent.h_name = saved_hostname;
334     hostent.h_aliases = aliases;
335     hostent.h_addrtype = AF_INET;
336     hostent.h_length = sizeof(struct in_addr);
337     hostent.h_addr_list = addr_list;
338     
339     return &hostent;
340 }
341
342 static struct passwd pw_passwd;
343 static struct group gr_group;
344 static FILE *passwd_fp;
345 static FILE *group_fp;
346 static char pw_name[1024];
347 static char pw_password[1024];
348 static char pw_gecos[1024];
349 static char pw_dir[1024];
350 static char pw_shell[1024];
351 static char gr_name[1024];
352 static char gr_passwd[1024];
353 static char *gr_mem[1];
354
355 static int gr_parse_body(const char *buf) {
356     if(sscanf(buf,"%[^:]:%[^:]:%hu",gr_name,gr_passwd,&gr_group.gr_gid) < 3) return -1;
357     gr_group.gr_name = gr_name;
358     gr_group.gr_passwd = gr_passwd;
359     gr_group.gr_mem = gr_mem;
360     gr_mem[0] = NULL;
361     return 0;
362 }
363
364 static int pw_parse_body(const char *buf) {
365     int pos;
366     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;
367     pw_passwd.pw_name = pw_name;
368     pw_passwd.pw_passwd = pw_password;
369     pw_passwd.pw_gecos = pw_gecos;
370     pw_passwd.pw_dir = pw_dir;
371     pw_passwd.pw_shell = pw_shell;
372     pw_passwd.pw_comment = "";
373     return 0;
374 }
375
376 struct group *getgrnam(const char *name) {
377     FILE *fp;
378     char buf[1024];
379     
380     if((fp=fopen("/etc/group","r"))==NULL) return NULL;
381     while(fgets(buf,sizeof(buf),fp)) {
382         if(buf[0] == '#') continue;
383         if(gr_parse_body(buf) < 0) {
384             fclose(fp);
385             return NULL;
386         }
387         if(strcmp(name,gr_name)==0) {
388             fclose(fp);
389             return &gr_group;
390         }
391     }
392     fclose(fp);
393     return NULL;
394 }
395
396 struct group *getgrgid(gid_t gid) {
397     FILE *fp;
398     char buf[1024];
399     
400     if((fp=fopen("/etc/group","r"))==NULL) return NULL;
401     while(fgets(buf,sizeof(buf),fp)) {
402         if(buf[0] == '#') continue;
403         if(gr_parse_body(buf) < 0) {
404             fclose(fp);
405             return NULL;
406         }
407         if(gid == gr_group.gr_gid) {
408             fclose(fp);
409             return &gr_group;
410         }
411     }
412     fclose(fp);
413     return NULL;
414 }
415     
416 struct group *getgrent() {
417     char buf[1024];
418     if(group_fp == NULL) return NULL;
419     if(fgets(buf,sizeof(buf),group_fp) == NULL) return NULL;
420     if(buf[0] == '#') return getgrent();
421     if(gr_parse_body(buf) < 0) return NULL;
422     return &gr_group;
423 }
424
425 void setgrent() { 
426     if(group_fp != NULL) fclose(group_fp);
427     group_fp = fopen("/etc/group","r");
428 }
429
430 void endgrent() {
431     if(group_fp != NULL) fclose(group_fp);
432     group_fp = NULL;
433 }
434
435 struct passwd *getpwnam(const char *name) {
436     FILE *fp;
437     char buf[1024];
438     
439     if((fp=fopen("/etc/passwd","r"))==NULL) return NULL;
440     while(fgets(buf,sizeof(buf),fp)) {
441         if(buf[0] == '#') continue;
442         if(pw_parse_body(buf) < 0) {
443             fclose(fp);
444             return NULL;
445         }
446         if(strcmp(name,pw_name)==0) {
447             fclose(fp);
448             return &pw_passwd;
449         }
450     }
451     fclose(fp);
452     return NULL;
453 }
454
455 struct passwd *getpwuid(uid_t uid) {
456     FILE *fp;
457     char buf[1024];
458     
459     if((fp=fopen("/etc/passwd","r"))==NULL) return NULL;
460     while(fgets(buf,sizeof(buf),fp)) {
461         if(buf[0] == '#') continue;
462         if(pw_parse_body(buf) < 0) {
463             fclose(fp);
464             return NULL;
465         }
466         if(uid == pw_passwd.pw_uid) {
467             fclose(fp);
468             return &pw_passwd;
469         }
470     }
471     fclose(fp);
472     return NULL;
473 }
474
475 struct passwd *getpwent() {
476     char buf[1024];
477     if(passwd_fp == NULL) return NULL;
478     if(fgets(buf,sizeof(buf),passwd_fp) == NULL) return NULL;
479     if(buf[0] == '#') return getpwent();
480     if(pw_parse_body(buf) < 0) return NULL;
481     return &pw_passwd;
482 }
483
484 void setpwent() { 
485     if(passwd_fp != NULL) fclose(passwd_fp);
486     passwd_fp = fopen("/etc/group","r");
487 }
488
489 void endpwent() {
490     if(passwd_fp != NULL) fclose(passwd_fp);
491     passwd_fp = NULL;
492 }
493
494 char *getpass(const char *prompt) {
495     static char buf[1024];
496     int len = 0;
497     fputs(prompt,stderr);
498     fflush(stdout);
499     if(fgets(buf,sizeof(buf),stdin)!=NULL) {
500         len = strlen(buf);
501         if(buf[len-1] == '\n') len--;
502     }
503     fputc('\n',stderr);
504     buf[len] = '\0';
505     return buf;
506 }
507
508 /* Argh... newlib's asprintf is totally broken... */
509 int vasprintf(char **ret, const char *fmt, va_list ap) {
510     int n;
511     char *p;
512     *ret = malloc(128); /* just guess for now */
513     if(!*ret) return -1;
514     n = vsnprintf(*ret,128,fmt,ap);
515     if(n < 128) {
516         return n;
517     } else {
518         p = realloc(*ret,n+1);
519         if(!p) { free(*ret); return -1; }
520         return vsprintf(*ret = p,fmt,ap);
521     }
522 }
523
524 // FIXME: This needs to be in a header
525 char *getlogin() {
526     return getenv("USER");
527 }
528
529
530 /*
531  * Other People's Code 
532  */
533
534 /* FreeBSD's dirname/basename */
535
536 /* FIXME: Put these in a header */
537
538 /*
539  * Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com>
540  * All rights reserved.
541  *
542  * Redistribution and use in source and binary forms, with or without
543  * modification, are permitted provided that the following conditions
544  * are met:
545  * 1. Redistributions of source code must retain the above copyright
546  *    notice, this list of conditions and the following disclaimer.
547  * 2. Redistributions in binary form must reproduce the above copyright
548  *    notice, this list of conditions and the following disclaimer in the
549  *    documentation and/or other materials provided with the distribution.
550  * 3. The name of the author may not be used to endorse or promote products
551  *    derived from this software without specific prior written permission.
552  *
553  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
554  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
555  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
556  * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
557  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
558  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
559  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
560  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
561  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
562  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
563  */
564
565 char *
566 dirname(path)
567 const char *path;
568 {
569     static char bname[MAXPATHLEN];
570     register const char *endp;
571     
572     /* Empty or NULL string gets treated as "." */
573     if (path == NULL || *path == '\0') {
574         (void)strcpy(bname, ".");
575         return(bname);
576     }
577     
578     /* Strip trailing slashes */
579     endp = path + strlen(path) - 1;
580     while (endp > path && *endp == '/')
581         endp--;
582     
583     /* Find the start of the dir */
584     while (endp > path && *endp != '/')
585         endp--;
586     
587     /* Either the dir is "/" or there are no slashes */
588     if (endp == path) {
589         (void)strcpy(bname, *endp == '/' ? "/" : ".");
590         return(bname);
591     } else {
592         do {
593             endp--;
594         } while (endp > path && *endp == '/');
595     }
596     
597     if (endp - path + 2 > sizeof(bname)) {
598         errno = ENAMETOOLONG;
599         return(NULL);
600     }
601     (void)strncpy(bname, path, endp - path + 1);
602     bname[endp - path + 1] = '\0';
603     return(bname);
604 }
605
606 char *
607 basename(path)
608 const char *path;
609 {
610     static char bname[MAXPATHLEN];
611     register const char *endp, *startp;
612     
613     /* Empty or NULL string gets treated as "." */
614     if (path == NULL || *path == '\0') {
615         (void)strcpy(bname, ".");
616         return(bname);
617     }
618     
619     /* Strip trailing slashes */
620     endp = path + strlen(path) - 1;
621     while (endp > path && *endp == '/')
622         endp--;
623     
624     /* All slashes becomes "/" */
625     if (endp == path && *endp == '/') {
626         (void)strcpy(bname, "/");
627         return(bname);
628     }
629     
630     /* Find the start of the base */
631     startp = endp;
632     while (startp > path && *(startp - 1) != '/')
633         startp--;
634     
635     if (endp - startp + 2 > sizeof(bname)) {
636         errno = ENAMETOOLONG;
637         return(NULL);
638     }
639     (void)strncpy(bname, startp, endp - startp + 1);
640     bname[endp - startp + 1] = '\0';
641     return(bname);
642 }
643
644 /* FreeBSD's uname */
645 int
646 uname(name)
647 struct utsname *name;
648 {
649         int mib[2], rval;
650         size_t len;
651         char *p;
652         int oerrno;
653     
654         rval = 0;
655     
656         mib[0] = CTL_KERN;
657         mib[1] = KERN_OSTYPE;
658         len = sizeof(name->sysname);
659         oerrno = errno;
660         if (sysctl(mib, 2, &name->sysname, &len, NULL, 0) == -1) {
661                 if(errno == ENOMEM)
662                         errno = oerrno;
663                 else
664                         rval = -1;
665         }
666         name->sysname[sizeof(name->sysname) - 1] = '\0';
667     
668         mib[0] = CTL_KERN;
669         mib[1] = KERN_HOSTNAME;
670         len = sizeof(name->nodename);
671         oerrno = errno;
672         if (sysctl(mib, 2, &name->nodename, &len, NULL, 0) == -1) {
673                 if(errno == ENOMEM)
674                         errno = oerrno;
675                 else
676                         rval = -1;
677         }
678         name->nodename[sizeof(name->nodename) - 1] = '\0';
679     
680         mib[0] = CTL_KERN;
681         mib[1] = KERN_OSRELEASE;
682         len = sizeof(name->release);
683         oerrno = errno;
684         if (sysctl(mib, 2, &name->release, &len, NULL, 0) == -1) {
685                 if(errno == ENOMEM)
686                         errno = oerrno;
687                 else
688                         rval = -1;
689         }
690         name->release[sizeof(name->release) - 1] = '\0';
691     
692         /* The version may have newlines in it, turn them into spaces. */
693         mib[0] = CTL_KERN;
694         mib[1] = KERN_VERSION;
695         len = sizeof(name->version);
696         oerrno = errno;
697         if (sysctl(mib, 2, &name->version, &len, NULL, 0) == -1) {
698                 if (errno == ENOMEM)
699                         errno = oerrno;
700                 else
701                         rval = -1;
702         }
703         name->version[sizeof(name->version) - 1] = '\0';
704         for (p = name->version; len--; ++p) {
705                 if (*p == '\n' || *p == '\t') {
706                         if (len > 1)
707                                 *p = ' ';
708                         else
709                                 *p = '\0';
710                 }
711         }
712     
713         mib[0] = CTL_HW;
714         mib[1] = HW_MACHINE;
715         len = sizeof(name->machine);
716         oerrno = errno;
717         if (sysctl(mib, 2, &name->machine, &len, NULL, 0) == -1) {
718                 if (errno == ENOMEM)
719                         errno = oerrno;
720                 else
721                         rval = -1;
722         }
723         name->machine[sizeof(name->machine) - 1] = '\0';
724         return (rval);
725 }
726
727 /* FreeBSD's gethostname */
728 int
729 gethostname(name, namelen)
730 char *name;
731 int namelen;
732 {
733     int mib[2];
734     size_t size;
735     
736     mib[0] = CTL_KERN;
737     mib[1] = KERN_HOSTNAME;
738     size = namelen;
739     if (sysctl(mib, 2, name, &size, NULL, 0) == -1)
740         return (-1);
741     return (0);
742 }
743
744 /* FreeBSD's daemon() - modified for nestedvm */
745 int
746 daemon(nochdir, noclose)
747 int nochdir, noclose;
748 {
749         int fd;
750     
751         switch (fork()) {
752         case -1:
753             return (-1);
754         case 0:
755             break;
756         default:
757             _exit(0);
758         }
759     
760         if (setsid() == -1)
761                 return (-1);
762     
763         if (!nochdir)
764                 (void)chdir("/");
765     
766         if (!noclose && (fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) {
767                 (void)dup2(fd, STDIN_FILENO);
768                 (void)dup2(fd, STDOUT_FILENO);
769                 (void)dup2(fd, STDERR_FILENO);
770                 if (fd > 2)
771                         (void)close(fd);
772         }
773         return (0);
774 }
775
776 /* FreeBSD's inet_addr/inet_aton */
777
778 /* 
779 * Check whether "cp" is a valid ASCII representation
780  * of an Internet address and convert to a binary address.
781  * Returns 1 if the address is valid, 0 if not.
782  * This replaces inet_addr, the return value from which
783  * cannot distinguish between failure and a local broadcast address.
784  */
785 int
786 inet_aton(cp, addr)
787 register const char *cp;
788 struct in_addr *addr;
789 {
790         u_long parts[4];
791         in_addr_t val;
792         char *c;
793         char *endptr;
794         int gotend, n;
795     
796         c = (char *)cp;
797         n = 0;
798         /*
799          * Run through the string, grabbing numbers until
800          * the end of the string, or some error
801          */
802         gotend = 0;
803         while (!gotend) {
804                 errno = 0;
805                 val = strtoul(c, &endptr, 0);
806         
807                 if (errno == ERANGE)    /* Fail completely if it overflowed. */
808                         return (0);
809                 
810                 /* 
811             * If the whole string is invalid, endptr will equal
812                  * c.. this way we can make sure someone hasn't
813                  * gone '.12' or something which would get past
814                  * the next check.
815                  */
816                 if (endptr == c)
817                         return (0);
818                 parts[n] = val;
819                 c = endptr;
820         
821                 /* Check the next character past the previous number's end */
822                 switch (*c) {
823             case '.' :
824                 /* Make sure we only do 3 dots .. */
825                 if (n == 3)     /* Whoops. Quit. */
826                     return (0);
827                 n++;
828                 c++;
829                 break;
830                 
831             case '\0':
832                 gotend = 1;
833                 break;
834                 
835             default:
836                 if (isspace((unsigned char)*c)) {
837                     gotend = 1;
838                     break;
839                 } else
840                     return (0); /* Invalid character, so fail */
841                 }
842         
843         }
844     
845         /*
846          * Concoct the address according to
847          * the number of parts specified.
848          */
849     
850         switch (n) {
851         case 0:                         /* a -- 32 bits */
852             /*
853              * Nothing is necessary here.  Overflow checking was
854              * already done in strtoul().
855              */
856             break;
857         case 1:                         /* a.b -- 8.24 bits */
858             if (val > 0xffffff || parts[0] > 0xff)
859                 return (0);
860             val |= parts[0] << 24;
861             break;
862             
863         case 2:                         /* a.b.c -- 8.8.16 bits */
864             if (val > 0xffff || parts[0] > 0xff || parts[1] > 0xff)
865                 return (0);
866             val |= (parts[0] << 24) | (parts[1] << 16);
867                 break;
868                 
869             case 3:                             /* a.b.c.d -- 8.8.8.8 bits */
870                 if (val > 0xff || parts[0] > 0xff || parts[1] > 0xff ||
871                     parts[2] > 0xff)
872                     return (0);
873                 val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
874                     break;
875         }
876     
877         if (addr != NULL)
878                 addr->s_addr = htonl(val);
879         return (1);
880 }
881
882 /*
883  * ASCII internet address interpretation routine.
884  * The value returned is in network order.
885  */
886 in_addr_t               /* XXX should be struct in_addr :( */
887 inet_addr(cp)
888 register const char *cp;
889 {
890         struct in_addr val;
891     
892         if (inet_aton(cp, &val))
893                 return (val.s_addr);
894         return (INADDR_NONE);
895 }
896
897 int
898 getgrouplist(uname, agroup, groups, grpcnt)
899 const char *uname;
900 gid_t agroup;
901 register gid_t *groups;
902 int *grpcnt;
903 {
904         register struct group *grp;
905         register int i, ngroups;
906         int ret, maxgroups;
907     
908         ret = 0;
909         ngroups = 0;
910         maxgroups = *grpcnt;
911         /*
912          * When installing primary group, duplicate it;
913          * the first element of groups is the effective gid
914          * and will be overwritten when a setgid file is executed.
915          */
916         groups[ngroups++] = agroup;
917         if (maxgroups > 1)
918                 groups[ngroups++] = agroup;
919         /*
920          * Scan the group file to find additional groups.
921          */
922         setgrent();
923         while ((grp = getgrent())) {
924                 for (i = 0; i < ngroups; i++) {
925                         if (grp->gr_gid == groups[i])
926                                 goto skip;
927                 }
928                 for (i = 0; grp->gr_mem[i]; i++) {
929                         if (!strcmp(grp->gr_mem[i], uname)) {
930                                 if (ngroups >= maxgroups) {
931                                         ret = -1;
932                                         break;
933                                 }
934                                 groups[ngroups++] = grp->gr_gid;
935                                 break;
936                         }
937                 }
938 skip: ;
939         }
940         endgrent();
941         *grpcnt = ngroups;
942         return (ret);
943 }
944
945 int
946 initgroups(uname, agroup)
947 const char *uname;
948 gid_t agroup;
949 {
950     gid_t groups[32], ngroups;
951     
952     ngroups = 32;
953     getgrouplist(uname, agroup, groups, &ngroups);
954     return (setgroups(ngroups, groups));
955 }