X-Git-Url: http://git.maemo.org/git/?a=blobdiff_plain;f=slirp%2Fmisc.c;h=0137e75ed1a609a9e9cb6d62e099178f8004790c;hb=fd93a79999c728dd1f30bb2e726ce12bdf704e6d;hp=5b809a853a706036da831d882343d574025e549d;hpb=f3ff649d3bf7c206460faa130d10406d1284bae0;p=qemu diff --git a/slirp/misc.c b/slirp/misc.c index 5b809a8..0137e75 100644 --- a/slirp/misc.c +++ b/slirp/misc.c @@ -1,15 +1,13 @@ /* * Copyright (c) 1995 Danny Gasparovski. - * + * * Please read the file COPYRIGHT for the * terms and conditions of the copyright. */ -#define WANT_SYS_IOCTL_H #include -u_int curtime, time_fasttimo, last_slowtimo, detach_time; -u_int detach_wait = 600000; /* 10 minutes */ +u_int curtime, time_fasttimo, last_slowtimo; #if 0 int x_port = -1; @@ -31,7 +29,7 @@ show_x(buff, inso) if (x_display) lprint("X Redir: Redirecting to display %d\r\n", x_display); } - + return CFG_OK; } @@ -47,7 +45,7 @@ redir_x(inaddr, start_port, display, screen) int screen; { int i; - + if (x_port >= 0) { lprint("X Redir: X already being redirected.\r\n"); show_x(0, 0); @@ -67,79 +65,30 @@ redir_x(inaddr, start_port, display, screen) } #endif -#ifndef HAVE_INET_ATON -int -inet_aton(cp, ia) - const char *cp; - struct in_addr *ia; -{ - u_int32_t addr = inet_addr(cp); - if (addr == 0xffffffff) - return 0; - ia->s_addr = addr; - return 1; -} -#endif - /* * Get our IP address and put it in our_addr */ void -getouraddr() +getouraddr(void) { char buff[256]; - struct hostent *he; - - if (gethostname(buff,256) < 0) - return; - - if ((he = gethostbyname(buff)) == NULL) - return; - - our_addr = *(struct in_addr *)he->h_addr; + struct hostent *he = NULL; + + if (gethostname(buff,256) == 0) + he = gethostbyname(buff); + if (he) + our_addr = *(struct in_addr *)he->h_addr; + if (our_addr.s_addr == 0) + our_addr.s_addr = loopback_addr.s_addr; } -#if SIZEOF_CHAR_P == 8 - -struct quehead_32 { - u_int32_t qh_link; - u_int32_t qh_rlink; -}; - -inline void -insque_32(a, b) - void *a; - void *b; -{ - register struct quehead_32 *element = (struct quehead_32 *) a; - register struct quehead_32 *head = (struct quehead_32 *) b; - element->qh_link = head->qh_link; - head->qh_link = (u_int32_t)element; - element->qh_rlink = (u_int32_t)head; - ((struct quehead_32 *)(element->qh_link))->qh_rlink - = (u_int32_t)element; -} - -inline void -remque_32(a) - void *a; -{ - register struct quehead_32 *element = (struct quehead_32 *) a; - ((struct quehead_32 *)(element->qh_link))->qh_rlink = element->qh_rlink; - ((struct quehead_32 *)(element->qh_rlink))->qh_link = element->qh_link; - element->qh_rlink = 0; -} - -#endif /* SIZEOF_CHAR_P == 8 */ - struct quehead { struct quehead *qh_link; struct quehead *qh_rlink; }; inline void -insque(a, b) - void *a, *b; +insque(void *a, void *b) { register struct quehead *element = (struct quehead *) a; register struct quehead *head = (struct quehead *) b; @@ -151,8 +100,7 @@ insque(a, b) } inline void -remque(a) - void *a; +remque(void *a) { register struct quehead *element = (struct quehead *) a; ((struct quehead *)(element->qh_link))->qh_rlink = element->qh_rlink; @@ -165,27 +113,22 @@ remque(a) int -add_exec(ex_ptr, do_pty, exec, addr, port) - struct ex_list **ex_ptr; - int do_pty; - char *exec; - int addr; - int port; +add_exec(struct ex_list **ex_ptr, int do_pty, char *exec, int addr, int port) { struct ex_list *tmp_ptr; - + /* First, check if the port is "bound" */ for (tmp_ptr = *ex_ptr; tmp_ptr; tmp_ptr = tmp_ptr->ex_next) { if (port == tmp_ptr->ex_fport && addr == tmp_ptr->ex_addr) return -1; } - + tmp_ptr = *ex_ptr; *ex_ptr = (struct ex_list *)malloc(sizeof(struct ex_list)); (*ex_ptr)->ex_fport = port; (*ex_ptr)->ex_addr = addr; (*ex_ptr)->ex_pty = do_pty; - (*ex_ptr)->ex_exec = strdup(exec); + (*ex_ptr)->ex_exec = (do_pty == 3) ? exec : strdup(exec); (*ex_ptr)->ex_next = tmp_ptr; return 0; } @@ -215,10 +158,7 @@ strerror(error) #ifdef _WIN32 int -fork_exec(so, ex, do_pty) - struct socket *so; - char *ex; - int do_pty; +fork_exec(struct socket *so, const char *ex, int do_pty) { /* not implemented */ return 0; @@ -226,6 +166,7 @@ fork_exec(so, ex, do_pty) #else +#ifndef CONFIG_QEMU int slirp_openpty(amaster, aslave) int *amaster, *aslave; @@ -234,7 +175,7 @@ slirp_openpty(amaster, aslave) #ifdef HAVE_GRANTPT char *ptr; - + if ((master = open("/dev/ptmx", O_RDWR)) < 0 || grantpt(master) < 0 || unlockpt(master) < 0 || @@ -242,7 +183,7 @@ slirp_openpty(amaster, aslave) close(master); return -1; } - + if ((slave = open(ptr, O_RDWR)) < 0 || ioctl(slave, I_PUSH, "ptem") < 0 || ioctl(slave, I_PUSH, "ldterm") < 0 || @@ -251,16 +192,16 @@ slirp_openpty(amaster, aslave) close(slave); return -1; } - + *amaster = master; *aslave = slave; return 0; - + #else - + static char line[] = "/dev/ptyXX"; register const char *cp1, *cp2; - + for (cp1 = "pqrsPQRS"; *cp1; cp1++) { line[8] = *cp1; for (cp2 = "0123456789abcdefghijklmnopqrstuv"; *cp2; cp2++) { @@ -290,6 +231,7 @@ slirp_openpty(amaster, aslave) return (-1); #endif } +#endif /* * XXX This is ugly @@ -297,56 +239,57 @@ slirp_openpty(amaster, aslave) * process, which connects to this socket, after which we * exec the wanted program. If something (strange) happens, * the accept() call could block us forever. - * + * * do_pty = 0 Fork/exec inetd style * do_pty = 1 Fork/exec using slirp.telnetd * do_ptr = 2 Fork/exec using pty */ int -fork_exec(so, ex, do_pty) - struct socket *so; - char *ex; - int do_pty; +fork_exec(struct socket *so, const char *ex, int do_pty) { int s; struct sockaddr_in addr; - int addrlen = sizeof(addr); + socklen_t addrlen = sizeof(addr); int opt; - int master; - char *argv[256]; + int master = -1; + const char *argv[256]; #if 0 char buff[256]; #endif /* don't want to clobber the original */ char *bptr; - char *curarg; - int c, i; - + const char *curarg; + int c, i, ret; + DEBUG_CALL("fork_exec"); DEBUG_ARG("so = %lx", (long)so); DEBUG_ARG("ex = %lx", (long)ex); DEBUG_ARG("do_pty = %lx", (long)do_pty); - + if (do_pty == 2) { +#if 0 if (slirp_openpty(&master, &s) == -1) { lprint("Error: openpty failed: %s\n", strerror(errno)); return 0; } +#else + return 0; +#endif } else { addr.sin_family = AF_INET; addr.sin_port = 0; addr.sin_addr.s_addr = INADDR_ANY; - + if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0 || bind(s, (struct sockaddr *)&addr, addrlen) < 0 || listen(s, 1) < 0) { lprint("Error: inet socket: %s\n", strerror(errno)); closesocket(s); - + return 0; } } - + switch(fork()) { case -1: lprint("Error: fork failed: %s\n", strerror(errno)); @@ -354,7 +297,7 @@ fork_exec(so, ex, do_pty) if (do_pty == 2) close(master); return 0; - + case 0: /* Set the DISPLAY */ if (do_pty == 2) { @@ -372,9 +315,11 @@ fork_exec(so, ex, do_pty) */ s = socket(AF_INET, SOCK_STREAM, 0); addr.sin_addr = loopback_addr; - connect(s, (struct sockaddr *)&addr, addrlen); + do { + ret = connect(s, (struct sockaddr *)&addr, addrlen); + } while (ret < 0 && errno == EINTR); } - + #if 0 if (x_port >= 0) { #ifdef HAVE_SETENV @@ -385,13 +330,13 @@ fork_exec(so, ex, do_pty) putenv(buff); #endif } -#endif +#endif dup2(s, 0); dup2(s, 1); dup2(s, 2); - for (s = 3; s <= 255; s++) + for (s = getdtablesize() - 1; s >= 3; s--) close(s); - + i = 0; bptr = strdup(ex); /* No need to free() this */ if (do_pty == 1) { @@ -409,21 +354,22 @@ fork_exec(so, ex, do_pty) *bptr++ = (char)0; argv[i++] = strdup(curarg); } while (c); - - argv[i] = 0; - execvp(argv[0], argv); - + + argv[i] = NULL; + execvp(argv[0], (char **)argv); + /* Ooops, failed, let's tell the user why */ { char buff[256]; - - sprintf(buff, "Error: execvp of %s failed: %s\n", - argv[0], strerror(errno)); + + snprintf(buff, sizeof(buff), + "Error: execvp of %s failed: %s\n", + argv[0], strerror(errno)); write(2, buff, strlen(buff)+1); } close(0); close(1); close(2); /* XXX */ exit(1); - + default: if (do_pty == 2) { close(s); @@ -436,21 +382,23 @@ fork_exec(so, ex, do_pty) * The only reason this will block forever is if socket() * of connect() fail in the child process */ - so->s = accept(s, (struct sockaddr *)&addr, &addrlen); - closesocket(s); + do { + so->s = accept(s, (struct sockaddr *)&addr, &addrlen); + } while (so->s < 0 && errno == EINTR); + closesocket(s); opt = 1; setsockopt(so->s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int)); opt = 1; setsockopt(so->s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int)); } fd_nonblock(so->s); - + /* Append the telnet options now */ - if (so->so_m != 0 && do_pty == 1) { + if (so->so_m != NULL && do_pty == 1) { sbappend(so, so->so_m); - so->so_m = 0; + so->so_m = NULL; } - + return 1; } } @@ -462,10 +410,10 @@ strdup(str) const char *str; { char *bptr; - + bptr = (char *)malloc(strlen(str)+1); strcpy(bptr, str); - + return bptr; } #endif @@ -481,7 +429,7 @@ snooze_hup(num) #endif struct sockaddr_in sock_in; char buff[256]; - + ret = -1; if (slirp_socket_passwd) { s = socket(AF_INET, SOCK_STREAM, 0); @@ -511,29 +459,29 @@ snooze_hup(num) #endif slirp_exit(0); } - - + + void snooze() { sigset_t s; int i; - + /* Don't need our data anymore */ /* XXX This makes SunOS barf */ /* brk(0); */ - + /* Close all fd's */ for (i = 255; i >= 0; i--) close(i); - + signal(SIGQUIT, slirp_exit); signal(SIGHUP, snooze_hup); sigemptyset(&s); - + /* Wait for any signal */ sigsuspend(&s); - + /* Just in case ... */ exit(255); } @@ -546,16 +494,16 @@ relay(s) int n; fd_set readfds; struct ttys *ttyp; - + /* Don't need our data anymore */ /* XXX This makes SunOS barf */ /* brk(0); */ - + signal(SIGQUIT, slirp_exit); signal(SIGHUP, slirp_exit); signal(SIGINT, slirp_exit); signal(SIGTERM, slirp_exit); - + /* Fudge to get term_raw and term_restore to work */ if (NULL == (ttyp = tty_attach (0, slirp_tty))) { lprint ("Error: tty_attach failed in misc.c:relay()\r\n"); @@ -564,18 +512,18 @@ relay(s) ttyp->fd = 0; ttyp->flags |= TTY_CTTY; term_raw(ttyp); - + while (1) { FD_ZERO(&readfds); - + FD_SET(0, &readfds); FD_SET(s, &readfds); - + n = select(s+1, &readfds, (fd_set *)0, (fd_set *)0, (struct timeval *)0); - + if (n <= 0) slirp_exit(0); - + if (FD_ISSET(0, &readfds)) { n = read(0, buf, 8192); if (n <= 0) @@ -584,7 +532,7 @@ relay(s) if (n <= 0) slirp_exit(0); } - + if (FD_ISSET(s, &readfds)) { n = read(s, buf, 8192); if (n <= 0) @@ -594,12 +542,24 @@ relay(s) slirp_exit(0); } } - + /* Just in case.... */ exit(1); } #endif +#ifdef CONFIG_QEMU +#include "monitor.h" + +void lprint(const char *format, ...) +{ + va_list args; + + va_start(args, format); + monitor_vprintf(cur_mon, format, args); + va_end(args); +} +#else int (*lprint_print) _P((void *, const char *, va_list)); char *lprint_ptr, *lprint_ptr2, **lprint_arg; @@ -611,7 +571,7 @@ lprint(va_alist) va_dcl #endif { va_list args; - + #ifdef __STDC__ va_start(args, format); #else @@ -628,33 +588,33 @@ lprint(va_alist) va_dcl int deltaw = lprint_sb->sb_wptr - lprint_sb->sb_data; int deltar = lprint_sb->sb_rptr - lprint_sb->sb_data; int deltap = lprint_ptr - lprint_sb->sb_data; - + lprint_sb->sb_data = (char *)realloc(lprint_sb->sb_data, lprint_sb->sb_datalen + TCP_SNDSPACE); - + /* Adjust all values */ lprint_sb->sb_wptr = lprint_sb->sb_data + deltaw; lprint_sb->sb_rptr = lprint_sb->sb_data + deltar; lprint_ptr = lprint_sb->sb_data + deltap; - + lprint_sb->sb_datalen += TCP_SNDSPACE; } } -#endif +#endif if (lprint_print) lprint_ptr += (*lprint_print)(*lprint_arg, format, args); - + /* Check if they want output to be logged to file as well */ if (lfd) { - /* + /* * Remove \r's * otherwise you'll get ^M all over the file */ int len = strlen(format); char *bptr1, *bptr2; - + bptr1 = bptr2 = strdup(format); - + while (len--) { if (*bptr1 == '\r') memcpy(bptr1, bptr1+1, len+1); @@ -677,12 +637,12 @@ add_emu(buff) char *buff3 = buff4; struct emu_t *emup; struct socket *so; - + if (sscanf(buff, "%256s %256s", buff2, buff1) != 2) { lprint("Error: Bad arguments\r\n"); return; } - + if (sscanf(buff1, "%d:%d", &lport, &fport) != 2) { lport = 0; if (sscanf(buff1, "%d", &fport) != 1) { @@ -690,7 +650,7 @@ add_emu(buff) return; } } - + if (sscanf(buff2, "%128[^:]:%128s", buff1, buff3) != 2) { buff3 = 0; if (sscanf(buff2, "%256s", buff1) != 1) { @@ -698,7 +658,7 @@ add_emu(buff) return; } } - + if (buff3) { if (strcmp(buff3, "lowdelay") == 0) tos = IPTOS_LOWDELAY; @@ -709,7 +669,7 @@ add_emu(buff) return; } } - + if (strcmp(buff1, "ftp") == 0) emu = EMU_FTP; else if (strcmp(buff1, "irc") == 0) @@ -720,7 +680,7 @@ add_emu(buff) lprint("Error: Unknown service\r\n"); return; } - + /* First, check that it isn't already emulated */ for (emup = tcpemu; emup; emup = emup->next) { if (emup->lport == lport && emup->fport == fport) { @@ -728,7 +688,7 @@ add_emu(buff) return; } } - + /* link it */ emup = (struct emu_t *)malloc(sizeof (struct emu_t)); emup->lport = (u_int16_t)lport; @@ -737,7 +697,7 @@ add_emu(buff) emup->emu = emu; emup->next = tcpemu; tcpemu = emup; - + /* And finally, mark all current sessions, if any, as being emulated */ for (so = tcb.so_next; so != &tcb; so = so->so_next) { if ((lport && lport == ntohs(so->so_lport)) || @@ -748,9 +708,10 @@ add_emu(buff) so->so_iptos = tos; } } - + lprint("Adding emulation for %s to port %d/%d\r\n", buff1, emup->lport, emup->fport); } +#endif #ifdef BAD_SPRINTF @@ -795,17 +756,16 @@ sprintf_len(va_alist) va_dcl #endif void -u_sleep(usec) - int usec; +u_sleep(int usec) { struct timeval t; fd_set fdset; - + FD_ZERO(&fdset); - + t.tv_sec = 0; t.tv_usec = usec * 1000; - + select(0, &fdset, &fdset, &fdset, &t); } @@ -814,16 +774,19 @@ u_sleep(usec) */ void -fd_nonblock(fd) - int fd; +fd_nonblock(int fd) { #ifdef FIONBIO - int opt = 1; - +#ifdef _WIN32 + long opt = 1; +#else + int opt = 1; +#endif + ioctlsocket(fd, FIONBIO, &opt); #else int opt; - + opt = fcntl(fd, F_GETFL, 0); opt |= O_NONBLOCK; fcntl(fd, F_SETFL, opt); @@ -831,16 +794,15 @@ fd_nonblock(fd) } void -fd_block(fd) - int fd; +fd_block(int fd) { #ifdef FIONBIO int opt = 0; - + ioctlsocket(fd, FIONBIO, &opt); #else int opt; - + opt = fcntl(fd, F_GETFL, 0); opt &= ~O_NONBLOCK; fcntl(fd, F_SETFL, opt); @@ -864,10 +826,10 @@ rsh_exec(so,ns, user, host, args) int fd0[2]; int s; char buff[256]; - + DEBUG_CALL("rsh_exec"); DEBUG_ARG("so = %lx", (long)so); - + if (pipe(fd)<0) { lprint("Error: pipe failed: %s\n", strerror(errno)); return 0; @@ -888,7 +850,7 @@ rsh_exec(so,ns, user, host, args) return 0; } #endif - + switch(fork()) { case -1: lprint("Error: fork failed: %s\n", strerror(errno)); @@ -897,11 +859,11 @@ rsh_exec(so,ns, user, host, args) close(fd0[0]); close(fd0[1]); return 0; - + case 0: close(fd[0]); close(fd0[0]); - + /* Set the DISPLAY */ if (x_port >= 0) { #ifdef HAVE_SETENV @@ -912,29 +874,29 @@ rsh_exec(so,ns, user, host, args) putenv(buff); #endif } - + dup2(fd0[1], 0); dup2(fd0[1], 1); dup2(fd[1], 2); for (s = 3; s <= 255; s++) close(s); - + execlp("rsh","rsh","-l", user, host, args, NULL); - + /* Ooops, failed, let's tell the user why */ - - sprintf(buff, "Error: execlp of %s failed: %s\n", + + sprintf(buff, "Error: execlp of %s failed: %s\n", "rsh", strerror(errno)); write(2, buff, strlen(buff)+1); close(0); close(1); close(2); /* XXX */ exit(1); - + default: close(fd[1]); close(fd0[1]); ns->s=fd[0]; so->s=fd0[0]; - + return 1; } }