fix some unistd functions
[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_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)
121
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);
125 }
126
127 char *_getcwd_r(struct _reent *ptr, char *buf, size_t size) {
128     if(buf != NULL) {
129         buf = __getcwd_r(ptr,buf,size);
130         return (long)buf == -1 ? NULL : buf;
131     }
132     
133     size = 256;
134     for(;;) {
135         buf = malloc(size);
136         char *ret = __getcwd_r(ptr,buf,size);
137         if((long)ret != -1) return ret;
138         free(buf);
139         size *= 2;
140         if(ptr->_errno != ERANGE) return NULL;
141     }
142 }
143
144 pid_t _wait_r(struct _reent *ptr, int *status) {
145     return _waitpid_r(ptr,-1,status,0);
146 }
147
148 long _pathconf_r(struct _reent *ptr,const char *path, int name) {
149     switch(name) {
150         default:
151             fprintf(stderr,"WARNING: pathconf: Unknown \"name\": %d\n",name);
152             ptr->_errno = EINVAL;
153             return -1;
154     }
155 }
156
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; }
161     
162     switch(name[1]) {
163         default:
164             fprintf(stderr,"WARNING: sysctl: Unknown name: %d\n",name[1]);
165             ptr->_errno = EINVAL;
166             return -1;
167     }
168 }
169
170 int sync() {
171     /* do nothing*/
172     return 0;
173 }
174
175 char *ttyname(int fd) {
176     return isatty(fd) ? "/dev/console" : NULL;
177 }
178
179 int sigaction(int sig, const struct sigaction *act, struct sigaction *oact) {
180     _sig_func_ptr old;
181     _sig_func_ptr new;
182     if(act) {
183         if(act->sa_flags || act->sa_mask != ~((sigset_t)0)) { errno = EINVAL; return -1; }
184         old = signal(sig,act->sa_handler);
185     } else if(oact) {
186         old = signal(sig,SIG_DFL);
187         signal(sig,old);
188     }
189     if(oact) {
190         oact->sa_handler = old;
191         oact->sa_mask = 0;
192         oact->sa_mask = ~((sigset_t)0);
193     }
194     return 0;
195 }
196
197 DIR *opendir(const char *path) {
198     struct stat sb;
199     int fd;
200     DIR *dir;
201     
202     fd = open(path,O_RDONLY);
203     if(fd < 0) return NULL;
204     
205     if(fstat(fd,&sb) < 0 || !S_ISDIR(sb.st_mode)) {
206         close(fd);
207         errno = ENOTDIR;
208         return NULL;
209     }
210     
211     dir = malloc(sizeof(*dir));
212     if(dir == NULL) {
213         close(fd);
214         errno = ENOMEM;
215         return NULL;
216     }
217     dir->dd_fd = fd;
218     dir->dd_buf = malloc(sizeof(struct dirent));
219     dir->dd_size = sizeof(struct dirent);
220     if(dir->dd_buf == NULL) {
221         close(fd);
222         free(dir);
223         return NULL;
224     }
225     dir->dd_loc = 0;
226     dir->dd_len = 0;
227     return dir;
228 }
229
230 struct dirent *readdir(DIR *dir) {
231     struct dirent *dp;
232     errno = 0;
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);
235         dir->dd_loc = 0;
236         if(dir->dd_len <= 0) { dir->dd_len = 0; return NULL; }
237     }
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;
241     return dp;
242 }
243
244 int closedir(DIR *dir) {
245     int fd = dir->dd_fd;
246     free(dir->dd_buf);
247     free(dir);
248     return close(fd);
249 }
250
251 /*
252  * Networking/Socket stuff
253  */
254
255 /* This should really be part of the newlib _reent structure */
256 int h_errno;
257
258 char *inet_ntoa(struct in_addr in) {
259     static char buf[18];
260     const unsigned char *p = (void*) &in;
261     snprintf(buf,sizeof(buf),"%u.%u.%u.%u",p[0],p[1],p[2],p[3]);
262     return buf;
263 }
264
265 struct servent *getservbyname(const char *name,const char *proto) {
266     return NULL;
267 }
268
269 static const char *h_errlist[] = { "No Error","Unknown host", "Host name lookup failure","Unknown server error","No address associated with name" };
270
271 const char *hstrerror(int err) {
272     if(err < 0 || err > 4) return "Unknown Error";
273     return h_errlist[err];
274 }
275
276 void herror(const char *string) {
277     fprintf(stderr,"%s: %s\n",string,hstrerror(h_errno));
278 }
279
280 extern int _resolve_ip(int addr, char *buf, size_t size);
281
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];
288     int err,i;
289     
290     if(type != AF_INET || len != 4) return NULL;
291     memcpy(&i,addr,4);
292     memcpy(addr_list_buf,addr,4);
293     err = _resolve_ip(i,name,sizeof(name));
294     if(err != 0) { h_errno = err; return NULL; }
295     
296     hostent.h_name = name;
297     hostent.h_aliases = aliases;
298     aliases[0] = NULL;
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;
303     
304     return &hostent;
305 }
306
307 extern int _resolve_hostname(const char *, char *buf, size_t *size);
308
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];
316     
317     unsigned char buf[MAX_ADDRS*sizeof(struct in_addr)];
318     size_t size = sizeof(buf);
319     int err,i,n=0;
320     
321     err = _resolve_hostname(hostname,buf,&size);
322     if(err != 0) { h_errno = err; return NULL; }
323     
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];
326     addr_list[n] = NULL;
327     strncpy(saved_hostname,hostname,sizeof(saved_hostname));
328     aliases[0] = NULL;
329     
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;
335     
336     return &hostent;
337 }
338
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];
351
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;
357     gr_mem[0] = NULL;
358     return 0;
359 }
360
361 static int pw_parse_body(const char *buf) {
362     int pos;
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 = "";
370     return 0;
371 }
372
373 struct group *getgrnam(const char *name) {
374     FILE *fp;
375     char buf[1024];
376     
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) {
381             fclose(fp);
382             return NULL;
383         }
384         if(strcmp(name,gr_name)==0) {
385             fclose(fp);
386             return &gr_group;
387         }
388     }
389     fclose(fp);
390     return NULL;
391 }
392
393 struct group *getgrgid(gid_t gid) {
394     FILE *fp;
395     char buf[1024];
396     
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) {
401             fclose(fp);
402             return NULL;
403         }
404         if(gid == gr_group.gr_gid) {
405             fclose(fp);
406             return &gr_group;
407         }
408     }
409     fclose(fp);
410     return NULL;
411 }
412     
413 struct group *getgrent() {
414     char buf[1024];
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;
419     return &gr_group;
420 }
421
422 void setgrent() { 
423     if(group_fp != NULL) fclose(group_fp);
424     group_fp = fopen("/etc/group","r");
425 }
426
427 void endgrent() {
428     if(group_fp != NULL) fclose(group_fp);
429     group_fp = NULL;
430 }
431
432 struct passwd *getpwnam(const char *name) {
433     FILE *fp;
434     char buf[1024];
435     
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) {
440             fclose(fp);
441             return NULL;
442         }
443         if(strcmp(name,pw_name)==0) {
444             fclose(fp);
445             return &pw_passwd;
446         }
447     }
448     fclose(fp);
449     return NULL;
450 }
451
452 struct passwd *getpwuid(uid_t uid) {
453     FILE *fp;
454     char buf[1024];
455     
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) {
460             fclose(fp);
461             return NULL;
462         }
463         if(uid == pw_passwd.pw_uid) {
464             fclose(fp);
465             return &pw_passwd;
466         }
467     }
468     fclose(fp);
469     return NULL;
470 }
471
472 struct passwd *getpwent() {
473     char buf[1024];
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;
478     return &pw_passwd;
479 }
480
481 void setpwent() { 
482     if(passwd_fp != NULL) fclose(passwd_fp);
483     passwd_fp = fopen("/etc/group","r");
484 }
485
486 void endpwent() {
487     if(passwd_fp != NULL) fclose(passwd_fp);
488     passwd_fp = NULL;
489 }
490
491 char *getpass(const char *prompt) {
492     static char buf[1024];
493     int len = 0;
494     fputs(prompt,stderr);
495     fflush(stdout);
496     if(fgets(buf,sizeof(buf),stdin)!=NULL) {
497         len = strlen(buf);
498         if(buf[len-1] == '\n') len--;
499     }
500     fputc('\n',stderr);
501     buf[len] = '\0';
502     return buf;
503 }
504
505 /* Argh... newlib's asprintf is totally broken... */
506 int vasprintf(char **ret, const char *fmt, va_list ap) {
507     int n;
508     char *p;
509     *ret = malloc(128); /* just guess for now */
510     if(!*ret) return -1;
511     n = vsnprintf(*ret,128,fmt,ap);
512     if(n < 128) {
513         return n;
514     } else {
515         p = realloc(*ret,n+1);
516         if(!p) { free(*ret); return -1; }
517         return vsprintf(*ret = p,fmt,ap);
518     }
519 }
520
521 // FIXME: This needs to be in a header
522 char *getlogin() {
523     return getenv("USER");
524 }
525
526
527 /*
528  * Other People's Code 
529  */
530
531 /* FreeBSD's dirname/basename */
532
533 /* FIXME: Put these in a header */
534
535 /*
536  * Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com>
537  * All rights reserved.
538  *
539  * Redistribution and use in source and binary forms, with or without
540  * modification, are permitted provided that the following conditions
541  * are met:
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.
549  *
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.
560  */
561
562 char *
563 dirname(path)
564 const char *path;
565 {
566     static char bname[MAXPATHLEN];
567     register const char *endp;
568     
569     /* Empty or NULL string gets treated as "." */
570     if (path == NULL || *path == '\0') {
571         (void)strcpy(bname, ".");
572         return(bname);
573     }
574     
575     /* Strip trailing slashes */
576     endp = path + strlen(path) - 1;
577     while (endp > path && *endp == '/')
578         endp--;
579     
580     /* Find the start of the dir */
581     while (endp > path && *endp != '/')
582         endp--;
583     
584     /* Either the dir is "/" or there are no slashes */
585     if (endp == path) {
586         (void)strcpy(bname, *endp == '/' ? "/" : ".");
587         return(bname);
588     } else {
589         do {
590             endp--;
591         } while (endp > path && *endp == '/');
592     }
593     
594     if (endp - path + 2 > sizeof(bname)) {
595         errno = ENAMETOOLONG;
596         return(NULL);
597     }
598     (void)strncpy(bname, path, endp - path + 1);
599     bname[endp - path + 1] = '\0';
600     return(bname);
601 }
602
603 char *
604 basename(path)
605 const char *path;
606 {
607     static char bname[MAXPATHLEN];
608     register const char *endp, *startp;
609     
610     /* Empty or NULL string gets treated as "." */
611     if (path == NULL || *path == '\0') {
612         (void)strcpy(bname, ".");
613         return(bname);
614     }
615     
616     /* Strip trailing slashes */
617     endp = path + strlen(path) - 1;
618     while (endp > path && *endp == '/')
619         endp--;
620     
621     /* All slashes becomes "/" */
622     if (endp == path && *endp == '/') {
623         (void)strcpy(bname, "/");
624         return(bname);
625     }
626     
627     /* Find the start of the base */
628     startp = endp;
629     while (startp > path && *(startp - 1) != '/')
630         startp--;
631     
632     if (endp - startp + 2 > sizeof(bname)) {
633         errno = ENAMETOOLONG;
634         return(NULL);
635     }
636     (void)strncpy(bname, startp, endp - startp + 1);
637     bname[endp - startp + 1] = '\0';
638     return(bname);
639 }
640
641 /* FreeBSD's uname */
642 int
643 uname(name)
644 struct utsname *name;
645 {
646         int mib[2], rval;
647         size_t len;
648         char *p;
649         int oerrno;
650     
651         rval = 0;
652     
653         mib[0] = CTL_KERN;
654         mib[1] = KERN_OSTYPE;
655         len = sizeof(name->sysname);
656         oerrno = errno;
657         if (sysctl(mib, 2, &name->sysname, &len, NULL, 0) == -1) {
658                 if(errno == ENOMEM)
659                         errno = oerrno;
660                 else
661                         rval = -1;
662         }
663         name->sysname[sizeof(name->sysname) - 1] = '\0';
664     
665         mib[0] = CTL_KERN;
666         mib[1] = KERN_HOSTNAME;
667         len = sizeof(name->nodename);
668         oerrno = errno;
669         if (sysctl(mib, 2, &name->nodename, &len, NULL, 0) == -1) {
670                 if(errno == ENOMEM)
671                         errno = oerrno;
672                 else
673                         rval = -1;
674         }
675         name->nodename[sizeof(name->nodename) - 1] = '\0';
676     
677         mib[0] = CTL_KERN;
678         mib[1] = KERN_OSRELEASE;
679         len = sizeof(name->release);
680         oerrno = errno;
681         if (sysctl(mib, 2, &name->release, &len, NULL, 0) == -1) {
682                 if(errno == ENOMEM)
683                         errno = oerrno;
684                 else
685                         rval = -1;
686         }
687         name->release[sizeof(name->release) - 1] = '\0';
688     
689         /* The version may have newlines in it, turn them into spaces. */
690         mib[0] = CTL_KERN;
691         mib[1] = KERN_VERSION;
692         len = sizeof(name->version);
693         oerrno = errno;
694         if (sysctl(mib, 2, &name->version, &len, NULL, 0) == -1) {
695                 if (errno == ENOMEM)
696                         errno = oerrno;
697                 else
698                         rval = -1;
699         }
700         name->version[sizeof(name->version) - 1] = '\0';
701         for (p = name->version; len--; ++p) {
702                 if (*p == '\n' || *p == '\t') {
703                         if (len > 1)
704                                 *p = ' ';
705                         else
706                                 *p = '\0';
707                 }
708         }
709     
710         mib[0] = CTL_HW;
711         mib[1] = HW_MACHINE;
712         len = sizeof(name->machine);
713         oerrno = errno;
714         if (sysctl(mib, 2, &name->machine, &len, NULL, 0) == -1) {
715                 if (errno == ENOMEM)
716                         errno = oerrno;
717                 else
718                         rval = -1;
719         }
720         name->machine[sizeof(name->machine) - 1] = '\0';
721         return (rval);
722 }
723
724 /* FreeBSD's gethostname */
725 int
726 gethostname(name, namelen)
727 char *name;
728 int namelen;
729 {
730     int mib[2];
731     size_t size;
732     
733     mib[0] = CTL_KERN;
734     mib[1] = KERN_HOSTNAME;
735     size = namelen;
736     if (sysctl(mib, 2, name, &size, NULL, 0) == -1)
737         return (-1);
738     return (0);
739 }
740
741 /* FreeBSD's daemon() - modified for nestedvm */
742 int
743 daemon(nochdir, noclose)
744 int nochdir, noclose;
745 {
746         int fd;
747     
748         switch (fork()) {
749         case -1:
750             return (-1);
751         case 0:
752             break;
753         default:
754             _exit(0);
755         }
756     
757         if (setsid() == -1)
758                 return (-1);
759     
760         if (!nochdir)
761                 (void)chdir("/");
762     
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);
767                 if (fd > 2)
768                         (void)close(fd);
769         }
770         return (0);
771 }
772
773 /* FreeBSD's inet_addr/inet_aton */
774
775 /* 
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.
781  */
782 int
783 inet_aton(cp, addr)
784 register const char *cp;
785 struct in_addr *addr;
786 {
787         u_long parts[4];
788         in_addr_t val;
789         char *c;
790         char *endptr;
791         int gotend, n;
792     
793         c = (char *)cp;
794         n = 0;
795         /*
796          * Run through the string, grabbing numbers until
797          * the end of the string, or some error
798          */
799         gotend = 0;
800         while (!gotend) {
801                 errno = 0;
802                 val = strtoul(c, &endptr, 0);
803         
804                 if (errno == ERANGE)    /* Fail completely if it overflowed. */
805                         return (0);
806                 
807                 /* 
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
811                  * the next check.
812                  */
813                 if (endptr == c)
814                         return (0);
815                 parts[n] = val;
816                 c = endptr;
817         
818                 /* Check the next character past the previous number's end */
819                 switch (*c) {
820             case '.' :
821                 /* Make sure we only do 3 dots .. */
822                 if (n == 3)     /* Whoops. Quit. */
823                     return (0);
824                 n++;
825                 c++;
826                 break;
827                 
828             case '\0':
829                 gotend = 1;
830                 break;
831                 
832             default:
833                 if (isspace((unsigned char)*c)) {
834                     gotend = 1;
835                     break;
836                 } else
837                     return (0); /* Invalid character, so fail */
838                 }
839         
840         }
841     
842         /*
843          * Concoct the address according to
844          * the number of parts specified.
845          */
846     
847         switch (n) {
848         case 0:                         /* a -- 32 bits */
849             /*
850              * Nothing is necessary here.  Overflow checking was
851              * already done in strtoul().
852              */
853             break;
854         case 1:                         /* a.b -- 8.24 bits */
855             if (val > 0xffffff || parts[0] > 0xff)
856                 return (0);
857             val |= parts[0] << 24;
858             break;
859             
860         case 2:                         /* a.b.c -- 8.8.16 bits */
861             if (val > 0xffff || parts[0] > 0xff || parts[1] > 0xff)
862                 return (0);
863             val |= (parts[0] << 24) | (parts[1] << 16);
864                 break;
865                 
866             case 3:                             /* a.b.c.d -- 8.8.8.8 bits */
867                 if (val > 0xff || parts[0] > 0xff || parts[1] > 0xff ||
868                     parts[2] > 0xff)
869                     return (0);
870                 val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
871                     break;
872         }
873     
874         if (addr != NULL)
875                 addr->s_addr = htonl(val);
876         return (1);
877 }
878
879 /*
880  * ASCII internet address interpretation routine.
881  * The value returned is in network order.
882  */
883 in_addr_t               /* XXX should be struct in_addr :( */
884 inet_addr(cp)
885 register const char *cp;
886 {
887         struct in_addr val;
888     
889         if (inet_aton(cp, &val))
890                 return (val.s_addr);
891         return (INADDR_NONE);
892 }
893
894 int
895 getgrouplist(uname, agroup, groups, grpcnt)
896 const char *uname;
897 gid_t agroup;
898 register gid_t *groups;
899 int *grpcnt;
900 {
901         register struct group *grp;
902         register int i, ngroups;
903         int ret, maxgroups;
904     
905         ret = 0;
906         ngroups = 0;
907         maxgroups = *grpcnt;
908         /*
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.
912          */
913         groups[ngroups++] = agroup;
914         if (maxgroups > 1)
915                 groups[ngroups++] = agroup;
916         /*
917          * Scan the group file to find additional groups.
918          */
919         setgrent();
920         while ((grp = getgrent())) {
921                 for (i = 0; i < ngroups; i++) {
922                         if (grp->gr_gid == groups[i])
923                                 goto skip;
924                 }
925                 for (i = 0; grp->gr_mem[i]; i++) {
926                         if (!strcmp(grp->gr_mem[i], uname)) {
927                                 if (ngroups >= maxgroups) {
928                                         ret = -1;
929                                         break;
930                                 }
931                                 groups[ngroups++] = grp->gr_gid;
932                                 break;
933                         }
934                 }
935 skip: ;
936         }
937         endgrent();
938         *grpcnt = ngroups;
939         return (ret);
940 }
941
942 int
943 initgroups(uname, agroup)
944 const char *uname;
945 gid_t agroup;
946 {
947     gid_t groups[32], ngroups;
948     
949     ngroups = 32;
950     getgrouplist(uname, agroup, groups, &ngroups);
951     return (setgroups(ngroups, groups));
952 }