udp support
[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
16 #include <nestedvm/socket.h>
17
18 int _syscall_set_errno(struct _reent *ptr, int err) {
19     ptr->_errno = -err;
20     return -1;
21 }
22
23 extern int _stat_r(struct _reent *, const char *, struct stat *);
24 int _access_r(struct _reent *ptr, const char *pathname, int mode) {
25     struct stat statbuf;
26     if(_stat_r(ptr,pathname,&statbuf) < 0) return -1;
27     return 0;
28 }
29
30 /* NestedVM doesn't, and probably never will, support this security related stuff */
31 uid_t getuid() { return 0; }
32 gid_t getgid() { return 0; }
33 uid_t geteuid() { return 0; }
34 gid_t getegid() { return 0; }
35 int getgroups(int gidsetlen, gid_t *gidset) {
36     if(gidsetlen) *gidset = 0;
37     return 1;
38 }
39 mode_t umask(mode_t new) { return 0022; }
40 int _chmod_r(struct _reent *ptr, const char *f, mode_t mode) { return 0; }
41 int _fchmod_r(struct _reent *ptr, int fd, mode_t mode) { return 0; }
42 int _chown_r(struct _reent *ptr, const char *f, uid_t uid, gid_t gid) { return 0; }
43 int _fchown_r(struct _reent *ptr, int fd, uid_t uid, gid_t gid) { return 0; }
44
45 #define REENT_WRAPPER0R(f,rt) \
46     extern rt _##f##_r(struct _reent *ptr); \
47     rt f() { return _##f##_r(_REENT); }
48 #define REENT_WRAPPER0(f) REENT_WRAPPER0R(f,int)
49
50 #define REENT_WRAPPER1R(f,rt,t1) \
51     extern rt _##f##_r(struct _reent *ptr, t1 a); \
52     rt f(t1 a) { return _##f##_r(_REENT,a); }
53 #define REENT_WRAPPER1(f,t1) REENT_WRAPPER1R(f,int,t1)
54
55 #define REENT_WRAPPER2R(f,rt,t1,t2) \
56     extern rt _##f##_r(struct _reent *ptr, t1 a, t2 b); \
57     rt f(t1 a, t2 b) { return _##f##_r(_REENT,a,b); }
58 #define REENT_WRAPPER2(f,t1,t2) REENT_WRAPPER2R(f,int,t1,t2)
59
60 #define REENT_WRAPPER3R(f,rt,t1,t2,t3) \
61     extern rt _##f##_r(struct _reent *ptr, t1 a, t2 b, t3 c); \
62     rt f(t1 a, t2 b, t3 c) { return _##f##_r(_REENT,a,b,c); }
63 #define REENT_WRAPPER3(f,t1,t2,t3) REENT_WRAPPER3R(f,int,t1,t2,t3)
64
65 #define REENT_WRAPPER4R(f,rt,t1,t2,t3,t4) \
66 extern rt _##f##_r(struct _reent *ptr, t1 a, t2 b, t3 c, t4 d); \
67 rt f(t1 a, t2 b, t3 c, t4 d) { return _##f##_r(_REENT,a,b,c,d); }
68 #define REENT_WRAPPER4(f,t1,t2,t3,t4) REENT_WRAPPER4R(f,int,t1,t2,t3,t4)
69
70 #define REENT_WRAPPER5R(f,rt,t1,t2,t3,t4,t5) \
71 extern rt _##f##_r(struct _reent *ptr, t1 a, t2 b, t3 c, t4 d, t5 e); \
72 rt f(t1 a, t2 b, t3 c, t4 d, t5 e) { return _##f##_r(_REENT,a,b,c,d,e); }
73 #define REENT_WRAPPER5(f,t1,t2,t3,t4,t5) REENT_WRAPPER5R(f,int,t1,t2,t3,t4,t5)
74
75 #define REENT_WRAPPER6R(f,rt,t1,t2,t3,t4,t5,t6) \
76 extern rt _##f##_r(struct _reent *ptr, t1 a, t2 b, t3 c, t4 d, t5 e, t6 f); \
77 rt f(t1 a, t2 b, t3 c, t4 d, t5 e, t6 f) { return _##f##_r(_REENT,a,b,c,d,e,f); }
78 #define REENT_WRAPPER6(f,t1,t2,t3,t4,t5,t6) REENT_WRAPPER6R(f,int,t1,t2,t3,t4,t5,t6)
79
80 REENT_WRAPPER2(mkdir,const char *,mode_t)
81 REENT_WRAPPER2(access,const char *,int)
82 REENT_WRAPPER1(rmdir,const char *)
83 REENT_WRAPPER1R(sysconf,long,int)
84 REENT_WRAPPER1(chdir,const char*)
85 REENT_WRAPPER2(utime,const char *,const struct utimbuf *)
86 REENT_WRAPPER1(pipe,int *)
87 REENT_WRAPPER2(dup2,int,int)
88 REENT_WRAPPER3(waitpid,pid_t,int *,int)
89 REENT_WRAPPER2R(getcwd,char *,char *,size_t)
90 REENT_WRAPPER2R(_getcwd,char *,char *,size_t)
91 REENT_WRAPPER2(symlink,const char *,const char *)
92 REENT_WRAPPER3(readlink,const char *, char *,int)
93 REENT_WRAPPER3(chown,const char *,uid_t,gid_t)
94 REENT_WRAPPER3(fchown,int,uid_t,gid_t)
95 REENT_WRAPPER3(lchown,const char *,uid_t,gid_t)
96 REENT_WRAPPER2(chmod,const char *,mode_t)
97 REENT_WRAPPER2(fchmod,int,mode_t)
98 REENT_WRAPPER2(lstat,const char *,struct stat *)
99 REENT_WRAPPER4(getdents,int, char *, size_t,long *)
100 REENT_WRAPPER1(dup,int)
101 REENT_WRAPPER2R(pathconf,long,const char *,int)
102 REENT_WRAPPER0(vfork)
103 REENT_WRAPPER1(chroot,const char *)
104 REENT_WRAPPER3(mknod,const char *,mode_t,dev_t)
105 REENT_WRAPPER2(ftruncate,int,off_t)
106 REENT_WRAPPER1(usleep,unsigned int)
107 REENT_WRAPPER2(mkfifo,const char *, mode_t)
108 REENT_WRAPPER3(klogctl,int,char*,int)
109 REENT_WRAPPER2R(realpath,char *,const char *,char *)
110 REENT_WRAPPER6(_sysctl,int *,int, void *, size_t*, void *, size_t)
111 REENT_WRAPPER6(sysctl,int *, int, void *, size_t*, void *, size_t)
112 REENT_WRAPPER2(getpriority,int,int)
113 REENT_WRAPPER3(setpriority,int,int,int)
114 REENT_WRAPPER3(connect,int,const struct sockaddr *,socklen_t)
115 REENT_WRAPPER3(socket,int,int,int)
116 REENT_WRAPPER3(_resolve_hostname,const char *,char*,size_t*)
117 REENT_WRAPPER3(accept,int,struct sockaddr *,socklen_t*)
118 REENT_WRAPPER5(getsockopt,int,int,int,void*,socklen_t*)
119 REENT_WRAPPER5(setsockopt,int,int,int,const void*,socklen_t)
120 REENT_WRAPPER3(bind,int,const struct sockaddr *,socklen_t)
121 REENT_WRAPPER2(listen,int,int)
122 REENT_WRAPPER2(shutdown,int,int)
123 REENT_WRAPPER6(sendto,int,const void*,size_t,int,const struct sockaddr*,socklen_t)
124 REENT_WRAPPER6(recvfrom,int,void*,size_t,int,struct sockaddr*,socklen_t*)
125 REENT_WRAPPER5(select,int,fd_set*,fd_set*,fd_set*,struct timeval*)
126
127 extern int __execve_r(struct _reent *ptr, const char *path, char *const argv[], char *const envp[]);
128 int _execve(const char *path, char *const argv[], char *const envp[]) {
129     return __execve_r(_REENT,path,argv,envp);
130 }
131
132 char *_getcwd_r(struct _reent *ptr, char *buf, size_t size) {
133     if(buf != NULL) {
134         buf = __getcwd_r(ptr,buf,size);
135         return (long)buf == -1 ? NULL : buf;
136     }
137     
138     size = 256;
139     for(;;) {
140         buf = malloc(size);
141         char *ret = __getcwd_r(ptr,buf,size);
142         if((long)ret != -1) return ret;
143         free(buf);
144         size *= 2;
145         if(ptr->_errno != ERANGE) return NULL;
146     }
147 }
148
149 pid_t _wait_r(struct _reent *ptr, int *status) {
150     return _waitpid_r(ptr,-1,status,0);
151 }
152
153 long _pathconf_r(struct _reent *ptr,const char *path, int name) {
154     switch(name) {
155         default:
156             fprintf(stderr,"WARNING: pathconf: Unknown \"name\": %d\n",name);
157             ptr->_errno = EINVAL;
158             return -1;
159     }
160 }
161
162 int _sysctl_r(struct _reent *ptr, int *name, int namelen, void *oldp, size_t *oldlen, void *newp, size_t newlen) {
163     if(name[0] != CTL_USER) return _sysctl(name,namelen,oldp,oldlen,newp,newlen);
164     if(newp != NULL) { ptr->_errno = EPERM; return -1; }
165     if(namelen != 2) { ptr->_errno = EINVAL; return -1; }
166     
167     switch(name[1]) {
168         default:
169             fprintf(stderr,"WARNING: sysctl: Unknown name: %d\n",name[1]);
170             ptr->_errno = EINVAL;
171             return -1;
172     }
173 }
174
175 void sync() {
176     /* do nothing*/
177 }
178
179 int fsync(int fd) {
180     /* do nothing */
181     return 0;
182 }
183
184 char *ttyname(int fd) {
185     return isatty(fd) ? "/dev/console" : NULL;
186 }
187
188 int sigaction(int sig, const struct sigaction *act, struct sigaction *oact) {
189     _sig_func_ptr old;
190     _sig_func_ptr new;
191     if(act) {
192         if(act->sa_flags || act->sa_mask != ~((sigset_t)0)) { errno = EINVAL; return -1; }
193         old = signal(sig,act->sa_handler);
194     } else if(oact) {
195         old = signal(sig,SIG_DFL);
196         signal(sig,old);
197     }
198     if(oact) {
199         oact->sa_handler = old;
200         oact->sa_mask = 0;
201         oact->sa_mask = ~((sigset_t)0);
202     }
203     return 0;
204 }
205
206 int sigfillset(sigset_t *set) {
207     *set = ~((sigset_t)0);
208     return 0;
209 }
210
211 int sigemptyset(sigset_t *set) {
212     *set = (sigset_t) 0;
213     return 0;
214 }
215
216 DIR *opendir(const char *path) {
217     struct stat sb;
218     int fd;
219     DIR *dir;
220     
221     fd = open(path,O_RDONLY);
222     if(fd < 0) return NULL;
223     
224     if(fstat(fd,&sb) < 0 || !S_ISDIR(sb.st_mode)) {
225         close(fd);
226         errno = ENOTDIR;
227         return NULL;
228     }
229     
230     dir = malloc(sizeof(*dir));
231     if(dir == NULL) {
232         close(fd);
233         errno = ENOMEM;
234         return NULL;
235     }
236     dir->dd_fd = fd;
237     dir->dd_buf = malloc(sizeof(struct dirent));
238     dir->dd_size = sizeof(struct dirent);
239     if(dir->dd_buf == NULL) {
240         close(fd);
241         free(dir);
242         return NULL;
243     }
244     dir->dd_loc = 0;
245     dir->dd_len = 0;
246     return dir;
247 }
248
249 struct dirent *readdir(DIR *dir) {
250     struct dirent *dp;
251     errno = 0;
252     if(dir->dd_loc == 0 || dir->dd_loc == dir->dd_len) {
253         dir->dd_len = getdents(dir->dd_fd,dir->dd_buf,dir->dd_size,NULL);
254         dir->dd_loc = 0;
255         if(dir->dd_len <= 0) { dir->dd_len = 0; return NULL; }
256     }
257     dp = (struct dirent*) (dir->dd_buf + dir->dd_loc);
258     if(dp->d_reclen == 0 || dp->d_reclen > dir->dd_len - dir->dd_loc) return NULL;
259     dir->dd_loc += dp->d_reclen;
260     return dp;
261 }
262
263 int closedir(DIR *dir) {
264     int fd = dir->dd_fd;
265     free(dir->dd_buf);
266     free(dir);
267     return close(fd);
268 }
269
270 /*
271  * Networking/Socket stuff
272  */
273
274 /* This should really be part of the newlib _reent structure */
275 int h_errno;
276
277 char *inet_ntoa(struct in_addr in) {
278     static char buf[18];
279     const unsigned char *p = (void*) &in;
280     snprintf(buf,sizeof(buf),"%u.%u.%u.%u",p[0],p[1],p[2],p[3]);
281     return buf;
282 }
283
284 struct servent *getservbyname(const char *name,const char *proto) {
285     return NULL;
286 }
287
288 static const char *h_errlist[] = { "No Error","Unknown host", "Host name lookup failure","Unknown server error","No address associated with name" };
289
290 const char *hstrerror(int err) {
291     if(err < 0 || err > 4) return "Unknown Error";
292     return h_errlist[err];
293 }
294
295 void herror(const char *string) {
296     fprintf(stderr,"%s: %s\n",string,hstrerror(h_errno));
297 }
298
299 extern int _resolve_hostname(const char *, char *buf, size_t *size);
300
301 struct hostent *gethostbyname(const char *hostname) {
302 #define MAX_ADDRS 256
303     static struct hostent hostent;
304     static char saved_hostname[128];
305     static char *addr_list[MAX_ADDRS+1];
306     static char addr_list_buf[MAX_ADDRS*sizeof(struct in_addr)];
307     static char *aliases[1];
308     
309     unsigned char buf[MAX_ADDRS*sizeof(struct in_addr)];
310     size_t size = sizeof(buf);
311     int err,i,n=0;
312     
313     err = _resolve_hostname(hostname,buf,&size);
314     if(err != 0) { h_errno = err; return NULL; }
315     
316     memcpy(addr_list_buf,buf,size);
317     for(i=0;i<size;i += sizeof(struct in_addr)) addr_list[n++] = &addr_list_buf[i];
318     addr_list[n] = NULL;
319     strncpy(saved_hostname,hostname,sizeof(saved_hostname));
320     aliases[0] = NULL;
321     
322     hostent.h_name = saved_hostname;
323     hostent.h_aliases = aliases;
324     hostent.h_addrtype = AF_INET;
325     hostent.h_length = sizeof(struct in_addr);
326     hostent.h_addr_list = addr_list;
327     
328     return &hostent;
329 }
330
331 /*
332  * Other People's Code 
333  */
334
335 /* FreeBSD's dirname/basename */
336
337 /* FIXME: Put these in a header */
338
339 /*
340  * Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com>
341  * All rights reserved.
342  *
343  * Redistribution and use in source and binary forms, with or without
344  * modification, are permitted provided that the following conditions
345  * are met:
346  * 1. Redistributions of source code must retain the above copyright
347  *    notice, this list of conditions and the following disclaimer.
348  * 2. Redistributions in binary form must reproduce the above copyright
349  *    notice, this list of conditions and the following disclaimer in the
350  *    documentation and/or other materials provided with the distribution.
351  * 3. The name of the author may not be used to endorse or promote products
352  *    derived from this software without specific prior written permission.
353  *
354  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
355  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
356  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
357  * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
358  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
359  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
360  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
361  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
362  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
363  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
364  */
365
366 char *
367 dirname(path)
368 const char *path;
369 {
370     static char bname[MAXPATHLEN];
371     register const char *endp;
372     
373     /* Empty or NULL string gets treated as "." */
374     if (path == NULL || *path == '\0') {
375         (void)strcpy(bname, ".");
376         return(bname);
377     }
378     
379     /* Strip trailing slashes */
380     endp = path + strlen(path) - 1;
381     while (endp > path && *endp == '/')
382         endp--;
383     
384     /* Find the start of the dir */
385     while (endp > path && *endp != '/')
386         endp--;
387     
388     /* Either the dir is "/" or there are no slashes */
389     if (endp == path) {
390         (void)strcpy(bname, *endp == '/' ? "/" : ".");
391         return(bname);
392     } else {
393         do {
394             endp--;
395         } while (endp > path && *endp == '/');
396     }
397     
398     if (endp - path + 2 > sizeof(bname)) {
399         errno = ENAMETOOLONG;
400         return(NULL);
401     }
402     (void)strncpy(bname, path, endp - path + 1);
403     bname[endp - path + 1] = '\0';
404     return(bname);
405 }
406
407 char *
408 basename(path)
409 const char *path;
410 {
411     static char bname[MAXPATHLEN];
412     register const char *endp, *startp;
413     
414     /* Empty or NULL string gets treated as "." */
415     if (path == NULL || *path == '\0') {
416         (void)strcpy(bname, ".");
417         return(bname);
418     }
419     
420     /* Strip trailing slashes */
421     endp = path + strlen(path) - 1;
422     while (endp > path && *endp == '/')
423         endp--;
424     
425     /* All slashes becomes "/" */
426     if (endp == path && *endp == '/') {
427         (void)strcpy(bname, "/");
428         return(bname);
429     }
430     
431     /* Find the start of the base */
432     startp = endp;
433     while (startp > path && *(startp - 1) != '/')
434         startp--;
435     
436     if (endp - startp + 2 > sizeof(bname)) {
437         errno = ENAMETOOLONG;
438         return(NULL);
439     }
440     (void)strncpy(bname, startp, endp - startp + 1);
441     bname[endp - startp + 1] = '\0';
442     return(bname);
443 }
444
445 /* FreeBSD's uname */
446 int
447 uname(name)
448 struct utsname *name;
449 {
450         int mib[2], rval;
451         size_t len;
452         char *p;
453         int oerrno;
454     
455         rval = 0;
456     
457         mib[0] = CTL_KERN;
458         mib[1] = KERN_OSTYPE;
459         len = sizeof(name->sysname);
460         oerrno = errno;
461         if (sysctl(mib, 2, &name->sysname, &len, NULL, 0) == -1) {
462                 if(errno == ENOMEM)
463                         errno = oerrno;
464                 else
465                         rval = -1;
466         }
467         name->sysname[sizeof(name->sysname) - 1] = '\0';
468     
469         mib[0] = CTL_KERN;
470         mib[1] = KERN_HOSTNAME;
471         len = sizeof(name->nodename);
472         oerrno = errno;
473         if (sysctl(mib, 2, &name->nodename, &len, NULL, 0) == -1) {
474                 if(errno == ENOMEM)
475                         errno = oerrno;
476                 else
477                         rval = -1;
478         }
479         name->nodename[sizeof(name->nodename) - 1] = '\0';
480     
481         mib[0] = CTL_KERN;
482         mib[1] = KERN_OSRELEASE;
483         len = sizeof(name->release);
484         oerrno = errno;
485         if (sysctl(mib, 2, &name->release, &len, NULL, 0) == -1) {
486                 if(errno == ENOMEM)
487                         errno = oerrno;
488                 else
489                         rval = -1;
490         }
491         name->release[sizeof(name->release) - 1] = '\0';
492     
493         /* The version may have newlines in it, turn them into spaces. */
494         mib[0] = CTL_KERN;
495         mib[1] = KERN_VERSION;
496         len = sizeof(name->version);
497         oerrno = errno;
498         if (sysctl(mib, 2, &name->version, &len, NULL, 0) == -1) {
499                 if (errno == ENOMEM)
500                         errno = oerrno;
501                 else
502                         rval = -1;
503         }
504         name->version[sizeof(name->version) - 1] = '\0';
505         for (p = name->version; len--; ++p) {
506                 if (*p == '\n' || *p == '\t') {
507                         if (len > 1)
508                                 *p = ' ';
509                         else
510                                 *p = '\0';
511                 }
512         }
513     
514         mib[0] = CTL_HW;
515         mib[1] = HW_MACHINE;
516         len = sizeof(name->machine);
517         oerrno = errno;
518         if (sysctl(mib, 2, &name->machine, &len, NULL, 0) == -1) {
519                 if (errno == ENOMEM)
520                         errno = oerrno;
521                 else
522                         rval = -1;
523         }
524         name->machine[sizeof(name->machine) - 1] = '\0';
525         return (rval);
526 }
527
528 /* FreeBSD's daemon() - modified for nestedvm */
529 int
530 daemon(nochdir, noclose)
531 int nochdir, noclose;
532 {
533         int fd;
534     
535         switch (fork()) {
536         case -1:
537             return (-1);
538         case 0:
539             break;
540         default:
541             _exit(0);
542         }
543     
544         /*if (setsid() == -1)
545                 return (-1);*/
546     
547         if (!nochdir)
548                 (void)chdir("/");
549     
550         if (!noclose && (fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) {
551                 (void)dup2(fd, STDIN_FILENO);
552                 (void)dup2(fd, STDOUT_FILENO);
553                 (void)dup2(fd, STDERR_FILENO);
554                 if (fd > 2)
555                         (void)close(fd);
556         }
557         return (0);
558 }