VirtualBox

source: vbox/trunk/src/VBox/Devices/Network/slirp/misc.c@ 1048

最後變更 在這個檔案從1048是 1048,由 vboxsync 提交於 18 年 前

slirp insque/remque fixes for amd64

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette