ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/slirp/misc.c
Revision: 1.4
Committed: 2006-01-24T23:46:19Z (18 years, 9 months ago) by gbeauche
Content type: text/plain
Branch: MAIN
Changes since 1.3: +2 -2 lines
Log Message:
Use the most portable POSIX-style non-blocking I/O (O_NONBLOCK) instead of
BSD-style through FIONBIO. It turns out Tru64 and probably IRIX don't support
the latter when fd is a pipe (slirp case).

File Contents

# User Rev Content
1 gbeauche 1.1 /*
2     * Copyright (c) 1995 Danny Gasparovski.
3     *
4     * Please read the file COPYRIGHT for the
5     * terms and conditions of the copyright.
6     */
7    
8     #define WANT_SYS_IOCTL_H
9     #include <slirp.h>
10    
11     u_int curtime, time_fasttimo, last_slowtimo, detach_time;
12     u_int detach_wait = 600000; /* 10 minutes */
13    
14     #if 0
15     int x_port = -1;
16     int x_display = 0;
17     int x_screen = 0;
18    
19     int
20     show_x(buff, inso)
21     char *buff;
22     struct socket *inso;
23     {
24     if (x_port < 0) {
25     lprint("X Redir: X not being redirected.\r\n");
26     } else {
27     lprint("X Redir: In sh/bash/zsh/etc. type: DISPLAY=%s:%d.%d; export DISPLAY\r\n",
28     inet_ntoa(our_addr), x_port, x_screen);
29     lprint("X Redir: In csh/tcsh/etc. type: setenv DISPLAY %s:%d.%d\r\n",
30     inet_ntoa(our_addr), x_port, x_screen);
31     if (x_display)
32     lprint("X Redir: Redirecting to display %d\r\n", x_display);
33     }
34    
35     return CFG_OK;
36     }
37    
38    
39     /*
40     * XXX Allow more than one X redirection?
41     */
42     void
43     redir_x(inaddr, start_port, display, screen)
44     u_int32_t inaddr;
45     int start_port;
46     int display;
47     int screen;
48     {
49     int i;
50    
51     if (x_port >= 0) {
52     lprint("X Redir: X already being redirected.\r\n");
53     show_x(0, 0);
54     } else {
55     for (i = 6001 + (start_port-1); i <= 6100; i++) {
56     if (solisten(htons(i), inaddr, htons(6000 + display), 0)) {
57     /* Success */
58     x_port = i - 6000;
59     x_display = display;
60     x_screen = screen;
61     show_x(0, 0);
62     return;
63     }
64     }
65     lprint("X Redir: Error: Couldn't redirect a port for X. Weird.\r\n");
66     }
67     }
68     #endif
69    
70     #ifndef HAVE_INET_ATON
71     int
72     inet_aton(cp, ia)
73     const char *cp;
74     struct in_addr *ia;
75     {
76     u_int32_t addr = inet_addr(cp);
77     if (addr == 0xffffffff)
78     return 0;
79     ia->s_addr = addr;
80     return 1;
81     }
82     #endif
83    
84     /*
85     * Get our IP address and put it in our_addr
86     */
87     void
88     getouraddr()
89     {
90     char buff[256];
91     struct hostent *he;
92    
93     if (gethostname(buff,256) < 0)
94     return;
95    
96     if ((he = gethostbyname(buff)) == NULL)
97     return;
98    
99     our_addr = *(struct in_addr *)he->h_addr;
100     }
101    
102     #if SIZEOF_CHAR_P == 8
103    
104     struct quehead_32 {
105     u_int32_t qh_link;
106     u_int32_t qh_rlink;
107     };
108    
109     inline void
110     insque_32(a, b)
111     void *a;
112     void *b;
113     {
114     register struct quehead_32 *element = (struct quehead_32 *) a;
115     register struct quehead_32 *head = (struct quehead_32 *) b;
116     element->qh_link = head->qh_link;
117     head->qh_link = (u_int32_t)element;
118     element->qh_rlink = (u_int32_t)head;
119     ((struct quehead_32 *)(element->qh_link))->qh_rlink
120     = (u_int32_t)element;
121     }
122    
123     inline void
124     remque_32(a)
125     void *a;
126     {
127     register struct quehead_32 *element = (struct quehead_32 *) a;
128     ((struct quehead_32 *)(element->qh_link))->qh_rlink = element->qh_rlink;
129     ((struct quehead_32 *)(element->qh_rlink))->qh_link = element->qh_link;
130     element->qh_rlink = 0;
131     }
132    
133     #endif /* SIZEOF_CHAR_P == 8 */
134    
135     struct quehead {
136     struct quehead *qh_link;
137     struct quehead *qh_rlink;
138     };
139    
140 gbeauche 1.3 void
141 gbeauche 1.1 insque(a, b)
142     void *a, *b;
143     {
144     register struct quehead *element = (struct quehead *) a;
145     register struct quehead *head = (struct quehead *) b;
146     element->qh_link = head->qh_link;
147     head->qh_link = (struct quehead *)element;
148     element->qh_rlink = (struct quehead *)head;
149     ((struct quehead *)(element->qh_link))->qh_rlink
150     = (struct quehead *)element;
151     }
152    
153 gbeauche 1.3 void
154 gbeauche 1.1 remque(a)
155     void *a;
156     {
157     register struct quehead *element = (struct quehead *) a;
158     ((struct quehead *)(element->qh_link))->qh_rlink = element->qh_rlink;
159     ((struct quehead *)(element->qh_rlink))->qh_link = element->qh_link;
160     element->qh_rlink = NULL;
161     /* element->qh_link = NULL; TCP FIN1 crashes if you do this. Why ? */
162     }
163    
164     /* #endif */
165    
166    
167     int
168     add_exec(ex_ptr, do_pty, exec, addr, port)
169     struct ex_list **ex_ptr;
170     int do_pty;
171     char *exec;
172     int addr;
173     int port;
174     {
175     struct ex_list *tmp_ptr;
176    
177     /* First, check if the port is "bound" */
178     for (tmp_ptr = *ex_ptr; tmp_ptr; tmp_ptr = tmp_ptr->ex_next) {
179     if (port == tmp_ptr->ex_fport && addr == tmp_ptr->ex_addr)
180     return -1;
181     }
182    
183     tmp_ptr = *ex_ptr;
184     *ex_ptr = (struct ex_list *)malloc(sizeof(struct ex_list));
185     (*ex_ptr)->ex_fport = port;
186     (*ex_ptr)->ex_addr = addr;
187     (*ex_ptr)->ex_pty = do_pty;
188     (*ex_ptr)->ex_exec = strdup(exec);
189     (*ex_ptr)->ex_next = tmp_ptr;
190     return 0;
191     }
192    
193     #ifndef HAVE_STRERROR
194    
195     /*
196     * For systems with no strerror
197     */
198    
199     extern int sys_nerr;
200     extern char *sys_errlist[];
201    
202     char *
203     strerror(error)
204     int error;
205     {
206     if (error < sys_nerr)
207     return sys_errlist[error];
208     else
209     return "Unknown error.";
210     }
211    
212     #endif
213    
214    
215     #ifdef _WIN32
216    
217     int
218     fork_exec(so, ex, do_pty)
219     struct socket *so;
220     char *ex;
221     int do_pty;
222     {
223     /* not implemented */
224     return 0;
225     }
226    
227     #else
228    
229     int
230     slirp_openpty(amaster, aslave)
231     int *amaster, *aslave;
232     {
233     register int master, slave;
234    
235     #ifdef HAVE_GRANTPT
236     char *ptr;
237    
238     if ((master = open("/dev/ptmx", O_RDWR)) < 0 ||
239     grantpt(master) < 0 ||
240     unlockpt(master) < 0 ||
241     (ptr = ptsname(master)) == NULL) {
242     close(master);
243     return -1;
244     }
245    
246     if ((slave = open(ptr, O_RDWR)) < 0 ||
247     ioctl(slave, I_PUSH, "ptem") < 0 ||
248     ioctl(slave, I_PUSH, "ldterm") < 0 ||
249     ioctl(slave, I_PUSH, "ttcompat") < 0) {
250     close(master);
251     close(slave);
252     return -1;
253     }
254    
255     *amaster = master;
256     *aslave = slave;
257     return 0;
258    
259     #else
260    
261     static char line[] = "/dev/ptyXX";
262     register const char *cp1, *cp2;
263    
264     for (cp1 = "pqrsPQRS"; *cp1; cp1++) {
265     line[8] = *cp1;
266     for (cp2 = "0123456789abcdefghijklmnopqrstuv"; *cp2; cp2++) {
267     line[9] = *cp2;
268     if ((master = open(line, O_RDWR, 0)) == -1) {
269     if (errno == ENOENT)
270     return (-1); /* out of ptys */
271     } else {
272     line[5] = 't';
273     /* These will fail */
274     (void) chown(line, getuid(), 0);
275     (void) chmod(line, S_IRUSR|S_IWUSR|S_IWGRP);
276     #ifdef HAVE_REVOKE
277     (void) revoke(line);
278     #endif
279     if ((slave = open(line, O_RDWR, 0)) != -1) {
280     *amaster = master;
281     *aslave = slave;
282     return 0;
283     }
284     (void) close(master);
285     line[5] = 'p';
286     }
287     }
288     }
289     errno = ENOENT; /* out of ptys */
290     return (-1);
291     #endif
292     }
293    
294     /*
295     * XXX This is ugly
296     * We create and bind a socket, then fork off to another
297     * process, which connects to this socket, after which we
298     * exec the wanted program. If something (strange) happens,
299     * the accept() call could block us forever.
300     *
301     * do_pty = 0 Fork/exec inetd style
302     * do_pty = 1 Fork/exec using slirp.telnetd
303     * do_ptr = 2 Fork/exec using pty
304     */
305     int
306     fork_exec(so, ex, do_pty)
307     struct socket *so;
308     char *ex;
309     int do_pty;
310     {
311     int s;
312     struct sockaddr_in addr;
313 cebix 1.2 socklen_t addrlen = sizeof(addr);
314 gbeauche 1.1 int opt;
315     int master;
316     char *argv[256];
317     #if 0
318     char buff[256];
319     #endif
320     /* don't want to clobber the original */
321     char *bptr;
322     char *curarg;
323     int c, i, ret;
324    
325     DEBUG_CALL("fork_exec");
326     DEBUG_ARG("so = %lx", (long)so);
327     DEBUG_ARG("ex = %lx", (long)ex);
328     DEBUG_ARG("do_pty = %lx", (long)do_pty);
329    
330     if (do_pty == 2) {
331     if (slirp_openpty(&master, &s) == -1) {
332     lprint("Error: openpty failed: %s\n", strerror(errno));
333     return 0;
334     }
335     } else {
336     addr.sin_family = AF_INET;
337     addr.sin_port = 0;
338     addr.sin_addr.s_addr = INADDR_ANY;
339    
340     if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0 ||
341     bind(s, (struct sockaddr *)&addr, addrlen) < 0 ||
342     listen(s, 1) < 0) {
343     lprint("Error: inet socket: %s\n", strerror(errno));
344     closesocket(s);
345    
346     return 0;
347     }
348     }
349    
350     switch(fork()) {
351     case -1:
352     lprint("Error: fork failed: %s\n", strerror(errno));
353     close(s);
354     if (do_pty == 2)
355     close(master);
356     return 0;
357    
358     case 0:
359     /* Set the DISPLAY */
360     if (do_pty == 2) {
361     (void) close(master);
362     #ifdef TIOCSCTTY /* XXXXX */
363     (void) setsid();
364     ioctl(s, TIOCSCTTY, (char *)NULL);
365     #endif
366     } else {
367     getsockname(s, (struct sockaddr *)&addr, &addrlen);
368     close(s);
369     /*
370     * Connect to the socket
371     * XXX If any of these fail, we're in trouble!
372     */
373     s = socket(AF_INET, SOCK_STREAM, 0);
374     addr.sin_addr = loopback_addr;
375     do {
376     ret = connect(s, (struct sockaddr *)&addr, addrlen);
377     } while (ret < 0 && errno == EINTR);
378     }
379    
380     #if 0
381     if (x_port >= 0) {
382     #ifdef HAVE_SETENV
383     sprintf(buff, "%s:%d.%d", inet_ntoa(our_addr), x_port, x_screen);
384     setenv("DISPLAY", buff, 1);
385     #else
386     sprintf(buff, "DISPLAY=%s:%d.%d", inet_ntoa(our_addr), x_port, x_screen);
387     putenv(buff);
388     #endif
389     }
390     #endif
391     dup2(s, 0);
392     dup2(s, 1);
393     dup2(s, 2);
394     for (s = 3; s <= 255; s++)
395     close(s);
396    
397     i = 0;
398     bptr = strdup(ex); /* No need to free() this */
399     if (do_pty == 1) {
400     /* Setup "slirp.telnetd -x" */
401     argv[i++] = "slirp.telnetd";
402     argv[i++] = "-x";
403     argv[i++] = bptr;
404     } else
405     do {
406     /* Change the string into argv[] */
407     curarg = bptr;
408     while (*bptr != ' ' && *bptr != (char)0)
409     bptr++;
410     c = *bptr;
411     *bptr++ = (char)0;
412     argv[i++] = strdup(curarg);
413     } while (c);
414    
415     argv[i] = 0;
416     execvp(argv[0], argv);
417    
418     /* Ooops, failed, let's tell the user why */
419     {
420     char buff[256];
421    
422     sprintf(buff, "Error: execvp of %s failed: %s\n",
423     argv[0], strerror(errno));
424     write(2, buff, strlen(buff)+1);
425     }
426     close(0); close(1); close(2); /* XXX */
427     exit(1);
428    
429     default:
430     if (do_pty == 2) {
431     close(s);
432     so->s = master;
433     } else {
434     /*
435     * XXX this could block us...
436     * XXX Should set a timer here, and if accept() doesn't
437     * return after X seconds, declare it a failure
438     * The only reason this will block forever is if socket()
439     * of connect() fail in the child process
440     */
441     do {
442     so->s = accept(s, (struct sockaddr *)&addr, &addrlen);
443     } while (so->s < 0 && errno == EINTR);
444     closesocket(s);
445     opt = 1;
446     setsockopt(so->s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int));
447     opt = 1;
448     setsockopt(so->s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int));
449     }
450     fd_nonblock(so->s);
451    
452     /* Append the telnet options now */
453     if (so->so_m != 0 && do_pty == 1) {
454     sbappend(so, so->so_m);
455     so->so_m = 0;
456     }
457    
458     return 1;
459     }
460     }
461     #endif
462    
463     #ifndef HAVE_STRDUP
464     char *
465     strdup(str)
466     const char *str;
467     {
468     char *bptr;
469    
470     bptr = (char *)malloc(strlen(str)+1);
471     strcpy(bptr, str);
472    
473     return bptr;
474     }
475     #endif
476    
477     #if 0
478     void
479     snooze_hup(num)
480     int num;
481     {
482     int s, ret;
483     #ifndef NO_UNIX_SOCKETS
484     struct sockaddr_un sock_un;
485     #endif
486     struct sockaddr_in sock_in;
487     char buff[256];
488    
489     ret = -1;
490     if (slirp_socket_passwd) {
491     s = socket(AF_INET, SOCK_STREAM, 0);
492     if (s < 0)
493     slirp_exit(1);
494     sock_in.sin_family = AF_INET;
495     sock_in.sin_addr.s_addr = slirp_socket_addr;
496     sock_in.sin_port = htons(slirp_socket_port);
497     if (connect(s, (struct sockaddr *)&sock_in, sizeof(sock_in)) != 0)
498     slirp_exit(1); /* just exit...*/
499     sprintf(buff, "kill %s:%d", slirp_socket_passwd, slirp_socket_unit);
500     write(s, buff, strlen(buff)+1);
501     }
502     #ifndef NO_UNIX_SOCKETS
503     else {
504     s = socket(AF_UNIX, SOCK_STREAM, 0);
505     if (s < 0)
506     slirp_exit(1);
507     sock_un.sun_family = AF_UNIX;
508     strcpy(sock_un.sun_path, socket_path);
509     if (connect(s, (struct sockaddr *)&sock_un,
510     sizeof(sock_un.sun_family) + sizeof(sock_un.sun_path)) != 0)
511     slirp_exit(1);
512     sprintf(buff, "kill none:%d", slirp_socket_unit);
513     write(s, buff, strlen(buff)+1);
514     }
515     #endif
516     slirp_exit(0);
517     }
518    
519    
520     void
521     snooze()
522     {
523     sigset_t s;
524     int i;
525    
526     /* Don't need our data anymore */
527     /* XXX This makes SunOS barf */
528     /* brk(0); */
529    
530     /* Close all fd's */
531     for (i = 255; i >= 0; i--)
532     close(i);
533    
534     signal(SIGQUIT, slirp_exit);
535     signal(SIGHUP, snooze_hup);
536     sigemptyset(&s);
537    
538     /* Wait for any signal */
539     sigsuspend(&s);
540    
541     /* Just in case ... */
542     exit(255);
543     }
544    
545     void
546     relay(s)
547     int s;
548     {
549     char buf[8192];
550     int n;
551     fd_set readfds;
552     struct ttys *ttyp;
553    
554     /* Don't need our data anymore */
555     /* XXX This makes SunOS barf */
556     /* brk(0); */
557    
558     signal(SIGQUIT, slirp_exit);
559     signal(SIGHUP, slirp_exit);
560     signal(SIGINT, slirp_exit);
561     signal(SIGTERM, slirp_exit);
562    
563     /* Fudge to get term_raw and term_restore to work */
564     if (NULL == (ttyp = tty_attach (0, slirp_tty))) {
565     lprint ("Error: tty_attach failed in misc.c:relay()\r\n");
566     slirp_exit (1);
567     }
568     ttyp->fd = 0;
569     ttyp->flags |= TTY_CTTY;
570     term_raw(ttyp);
571    
572     while (1) {
573     FD_ZERO(&readfds);
574    
575     FD_SET(0, &readfds);
576     FD_SET(s, &readfds);
577    
578     n = select(s+1, &readfds, (fd_set *)0, (fd_set *)0, (struct timeval *)0);
579    
580     if (n <= 0)
581     slirp_exit(0);
582    
583     if (FD_ISSET(0, &readfds)) {
584     n = read(0, buf, 8192);
585     if (n <= 0)
586     slirp_exit(0);
587     n = writen(s, buf, n);
588     if (n <= 0)
589     slirp_exit(0);
590     }
591    
592     if (FD_ISSET(s, &readfds)) {
593     n = read(s, buf, 8192);
594     if (n <= 0)
595     slirp_exit(0);
596     n = writen(0, buf, n);
597     if (n <= 0)
598     slirp_exit(0);
599     }
600     }
601    
602     /* Just in case.... */
603     exit(1);
604     }
605     #endif
606    
607     int (*lprint_print) _P((void *, const char *, va_list));
608     char *lprint_ptr, *lprint_ptr2, **lprint_arg;
609    
610     void
611     #ifdef __STDC__
612     lprint(const char *format, ...)
613     #else
614     lprint(va_alist) va_dcl
615     #endif
616     {
617     va_list args;
618    
619     #ifdef __STDC__
620     va_start(args, format);
621     #else
622     char *format;
623     va_start(args);
624     format = va_arg(args, char *);
625     #endif
626     #if 0
627     /* If we're printing to an sbuf, make sure there's enough room */
628     /* XXX +100? */
629     if (lprint_sb) {
630     if ((lprint_ptr - lprint_sb->sb_wptr) >=
631     (lprint_sb->sb_datalen - (strlen(format) + 100))) {
632     int deltaw = lprint_sb->sb_wptr - lprint_sb->sb_data;
633     int deltar = lprint_sb->sb_rptr - lprint_sb->sb_data;
634     int deltap = lprint_ptr - lprint_sb->sb_data;
635    
636     lprint_sb->sb_data = (char *)realloc(lprint_sb->sb_data,
637     lprint_sb->sb_datalen + TCP_SNDSPACE);
638    
639     /* Adjust all values */
640     lprint_sb->sb_wptr = lprint_sb->sb_data + deltaw;
641     lprint_sb->sb_rptr = lprint_sb->sb_data + deltar;
642     lprint_ptr = lprint_sb->sb_data + deltap;
643    
644     lprint_sb->sb_datalen += TCP_SNDSPACE;
645     }
646     }
647     #endif
648     if (lprint_print)
649     lprint_ptr += (*lprint_print)(*lprint_arg, format, args);
650    
651     /* Check if they want output to be logged to file as well */
652     if (lfd) {
653     /*
654     * Remove \r's
655     * otherwise you'll get ^M all over the file
656     */
657     int len = strlen(format);
658     char *bptr1, *bptr2;
659    
660     bptr1 = bptr2 = strdup(format);
661    
662     while (len--) {
663     if (*bptr1 == '\r')
664     memcpy(bptr1, bptr1+1, len+1);
665     else
666     bptr1++;
667     }
668     vfprintf(lfd, bptr2, args);
669     free(bptr2);
670     }
671     va_end(args);
672     }
673    
674     void
675     add_emu(buff)
676     char *buff;
677     {
678     u_int lport, fport;
679     u_int8_t tos = 0, emu = 0;
680     char buff1[256], buff2[256], buff4[128];
681     char *buff3 = buff4;
682     struct emu_t *emup;
683     struct socket *so;
684    
685     if (sscanf(buff, "%256s %256s", buff2, buff1) != 2) {
686     lprint("Error: Bad arguments\r\n");
687     return;
688     }
689    
690     if (sscanf(buff1, "%d:%d", &lport, &fport) != 2) {
691     lport = 0;
692     if (sscanf(buff1, "%d", &fport) != 1) {
693     lprint("Error: Bad first argument\r\n");
694     return;
695     }
696     }
697    
698     if (sscanf(buff2, "%128[^:]:%128s", buff1, buff3) != 2) {
699     buff3 = 0;
700     if (sscanf(buff2, "%256s", buff1) != 1) {
701     lprint("Error: Bad second argument\r\n");
702     return;
703     }
704     }
705    
706     if (buff3) {
707     if (strcmp(buff3, "lowdelay") == 0)
708     tos = IPTOS_LOWDELAY;
709     else if (strcmp(buff3, "throughput") == 0)
710     tos = IPTOS_THROUGHPUT;
711     else {
712     lprint("Error: Expecting \"lowdelay\"/\"throughput\"\r\n");
713     return;
714     }
715     }
716    
717     if (strcmp(buff1, "ftp") == 0)
718     emu = EMU_FTP;
719     else if (strcmp(buff1, "irc") == 0)
720     emu = EMU_IRC;
721     else if (strcmp(buff1, "none") == 0)
722     emu = EMU_NONE; /* ie: no emulation */
723     else {
724     lprint("Error: Unknown service\r\n");
725     return;
726     }
727    
728     /* First, check that it isn't already emulated */
729     for (emup = tcpemu; emup; emup = emup->next) {
730     if (emup->lport == lport && emup->fport == fport) {
731     lprint("Error: port already emulated\r\n");
732     return;
733     }
734     }
735    
736     /* link it */
737     emup = (struct emu_t *)malloc(sizeof (struct emu_t));
738     emup->lport = (u_int16_t)lport;
739     emup->fport = (u_int16_t)fport;
740     emup->tos = tos;
741     emup->emu = emu;
742     emup->next = tcpemu;
743     tcpemu = emup;
744    
745     /* And finally, mark all current sessions, if any, as being emulated */
746     for (so = tcb.so_next; so != &tcb; so = so->so_next) {
747     if ((lport && lport == ntohs(so->so_lport)) ||
748     (fport && fport == ntohs(so->so_fport))) {
749     if (emu)
750     so->so_emu = emu;
751     if (tos)
752     so->so_iptos = tos;
753     }
754     }
755    
756     lprint("Adding emulation for %s to port %d/%d\r\n", buff1, emup->lport, emup->fport);
757     }
758    
759     #ifdef BAD_SPRINTF
760    
761     #undef vsprintf
762     #undef sprintf
763    
764     /*
765     * Some BSD-derived systems have a sprintf which returns char *
766     */
767    
768     int
769     vsprintf_len(string, format, args)
770     char *string;
771     const char *format;
772     va_list args;
773     {
774     vsprintf(string, format, args);
775     return strlen(string);
776     }
777    
778     int
779     #ifdef __STDC__
780     sprintf_len(char *string, const char *format, ...)
781     #else
782     sprintf_len(va_alist) va_dcl
783     #endif
784     {
785     va_list args;
786     #ifdef __STDC__
787     va_start(args, format);
788     #else
789     char *string;
790     char *format;
791     va_start(args);
792     string = va_arg(args, char *);
793     format = va_arg(args, char *);
794     #endif
795     vsprintf(string, format, args);
796     return strlen(string);
797     }
798    
799     #endif
800    
801     void
802     u_sleep(usec)
803     int usec;
804     {
805     struct timeval t;
806     fd_set fdset;
807    
808     FD_ZERO(&fdset);
809    
810     t.tv_sec = 0;
811     t.tv_usec = usec * 1000;
812    
813     select(0, &fdset, &fdset, &fdset, &t);
814     }
815    
816     /*
817     * Set fd blocking and non-blocking
818     */
819    
820     void
821     fd_nonblock(fd)
822     int fd;
823     {
824 gbeauche 1.4 #if defined USE_FIONBIO && defined FIONBIO
825 gbeauche 1.1 int opt = 1;
826    
827     ioctlsocket(fd, FIONBIO, &opt);
828     #else
829     int opt;
830    
831     opt = fcntl(fd, F_GETFL, 0);
832     opt |= O_NONBLOCK;
833     fcntl(fd, F_SETFL, opt);
834     #endif
835     }
836    
837     void
838     fd_block(fd)
839     int fd;
840     {
841 gbeauche 1.4 #if defined USE_FIONBIO && defined FIONBIO
842 gbeauche 1.1 int opt = 0;
843    
844     ioctlsocket(fd, FIONBIO, &opt);
845     #else
846     int opt;
847    
848     opt = fcntl(fd, F_GETFL, 0);
849     opt &= ~O_NONBLOCK;
850     fcntl(fd, F_SETFL, opt);
851     #endif
852     }
853    
854    
855     #if 0
856     /*
857     * invoke RSH
858     */
859     int
860     rsh_exec(so,ns, user, host, args)
861     struct socket *so;
862     struct socket *ns;
863     char *user;
864     char *host;
865     char *args;
866     {
867     int fd[2];
868     int fd0[2];
869     int s;
870     char buff[256];
871    
872     DEBUG_CALL("rsh_exec");
873     DEBUG_ARG("so = %lx", (long)so);
874    
875     if (pipe(fd)<0) {
876     lprint("Error: pipe failed: %s\n", strerror(errno));
877     return 0;
878     }
879     /* #ifdef HAVE_SOCKETPAIR */
880     #if 1
881     if (socketpair(PF_UNIX,SOCK_STREAM,0, fd0) == -1) {
882     close(fd[0]);
883     close(fd[1]);
884     lprint("Error: openpty failed: %s\n", strerror(errno));
885     return 0;
886     }
887     #else
888     if (slirp_openpty(&fd0[0], &fd0[1]) == -1) {
889     close(fd[0]);
890     close(fd[1]);
891     lprint("Error: openpty failed: %s\n", strerror(errno));
892     return 0;
893     }
894     #endif
895    
896     switch(fork()) {
897     case -1:
898     lprint("Error: fork failed: %s\n", strerror(errno));
899     close(fd[0]);
900     close(fd[1]);
901     close(fd0[0]);
902     close(fd0[1]);
903     return 0;
904    
905     case 0:
906     close(fd[0]);
907     close(fd0[0]);
908    
909     /* Set the DISPLAY */
910     if (x_port >= 0) {
911     #ifdef HAVE_SETENV
912     sprintf(buff, "%s:%d.%d", inet_ntoa(our_addr), x_port, x_screen);
913     setenv("DISPLAY", buff, 1);
914     #else
915     sprintf(buff, "DISPLAY=%s:%d.%d", inet_ntoa(our_addr), x_port, x_screen);
916     putenv(buff);
917     #endif
918     }
919    
920     dup2(fd0[1], 0);
921     dup2(fd0[1], 1);
922     dup2(fd[1], 2);
923     for (s = 3; s <= 255; s++)
924     close(s);
925    
926     execlp("rsh","rsh","-l", user, host, args, NULL);
927    
928     /* Ooops, failed, let's tell the user why */
929    
930     sprintf(buff, "Error: execlp of %s failed: %s\n",
931     "rsh", strerror(errno));
932     write(2, buff, strlen(buff)+1);
933     close(0); close(1); close(2); /* XXX */
934     exit(1);
935    
936     default:
937     close(fd[1]);
938     close(fd0[1]);
939     ns->s=fd[0];
940     so->s=fd0[0];
941    
942     return 1;
943     }
944     }
945     #endif