Statistics
| Branch: | Revision:

root / slirp / misc.c @ b9e82a59

History | View | Annotate | Download (18.3 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
#include <slirp.h>
9

    
10
u_int curtime, time_fasttimo, last_slowtimo;
11

    
12
#if 0
13
int x_port = -1;
14
int x_display = 0;
15
int x_screen = 0;
16

17
int
18
show_x(buff, inso)
19
        char *buff;
20
        struct socket *inso;
21
{
22
        if (x_port < 0) {
23
                lprint("X Redir: X not being redirected.\r\n");
24
        } else {
25
                lprint("X Redir: In sh/bash/zsh/etc. type: DISPLAY=%s:%d.%d; export DISPLAY\r\n",
26
                      inet_ntoa(our_addr), x_port, x_screen);
27
                lprint("X Redir: In csh/tcsh/etc. type:    setenv DISPLAY %s:%d.%d\r\n",
28
                      inet_ntoa(our_addr), x_port, x_screen);
29
                if (x_display)
30
                   lprint("X Redir: Redirecting to display %d\r\n", x_display);
31
        }
32

33
        return CFG_OK;
34
}
35

36

37
/*
38
 * XXX Allow more than one X redirection?
39
 */
40
void
41
redir_x(inaddr, start_port, display, screen)
42
        u_int32_t inaddr;
43
        int start_port;
44
        int display;
45
        int screen;
46
{
47
        int i;
48

49
        if (x_port >= 0) {
50
                lprint("X Redir: X already being redirected.\r\n");
51
                show_x(0, 0);
52
        } else {
53
                for (i = 6001 + (start_port-1); i <= 6100; i++) {
54
                        if (solisten(htons(i), inaddr, htons(6000 + display), 0)) {
55
                                /* Success */
56
                                x_port = i - 6000;
57
                                x_display = display;
58
                                x_screen = screen;
59
                                show_x(0, 0);
60
                                return;
61
                        }
62
                }
63
                lprint("X Redir: Error: Couldn't redirect a port for X. Weird.\r\n");
64
        }
65
}
66
#endif
67

    
68
/*
69
 * Get our IP address and put it in our_addr
70
 */
71
void
72
getouraddr(void)
73
{
74
        char buff[256];
75
        struct hostent *he = NULL;
76

    
77
        if (gethostname(buff,256) == 0)
78
            he = gethostbyname(buff);
79
        if (he)
80
            our_addr = *(struct in_addr *)he->h_addr;
81
        if (our_addr.s_addr == 0)
82
            our_addr.s_addr = loopback_addr.s_addr;
83
}
84

    
85
struct quehead {
86
        struct quehead *qh_link;
87
        struct quehead *qh_rlink;
88
};
89

    
90
inline void
91
insque(void *a, void *b)
92
{
93
        register struct quehead *element = (struct quehead *) a;
94
        register struct quehead *head = (struct quehead *) b;
95
        element->qh_link = head->qh_link;
96
        head->qh_link = (struct quehead *)element;
97
        element->qh_rlink = (struct quehead *)head;
98
        ((struct quehead *)(element->qh_link))->qh_rlink
99
        = (struct quehead *)element;
100
}
101

    
102
inline void
103
remque(void *a)
104
{
105
  register struct quehead *element = (struct quehead *) a;
106
  ((struct quehead *)(element->qh_link))->qh_rlink = element->qh_rlink;
107
  ((struct quehead *)(element->qh_rlink))->qh_link = element->qh_link;
108
  element->qh_rlink = NULL;
109
  /*  element->qh_link = NULL;  TCP FIN1 crashes if you do this.  Why ? */
110
}
111

    
112
/* #endif */
113

    
114

    
115
int
116
add_exec(struct ex_list **ex_ptr, int do_pty, char *exec, int addr, int port)
117
{
118
        struct ex_list *tmp_ptr;
119

    
120
        /* First, check if the port is "bound" */
121
        for (tmp_ptr = *ex_ptr; tmp_ptr; tmp_ptr = tmp_ptr->ex_next) {
122
                if (port == tmp_ptr->ex_fport && addr == tmp_ptr->ex_addr)
123
                   return -1;
124
        }
125

    
126
        tmp_ptr = *ex_ptr;
127
        *ex_ptr = (struct ex_list *)malloc(sizeof(struct ex_list));
128
        (*ex_ptr)->ex_fport = port;
129
        (*ex_ptr)->ex_addr = addr;
130
        (*ex_ptr)->ex_pty = do_pty;
131
        (*ex_ptr)->ex_exec = (do_pty == 3) ? exec : strdup(exec);
132
        (*ex_ptr)->ex_next = tmp_ptr;
133
        return 0;
134
}
135

    
136
#ifndef HAVE_STRERROR
137

    
138
/*
139
 * For systems with no strerror
140
 */
141

    
142
extern int sys_nerr;
143
extern char *sys_errlist[];
144

    
145
char *
146
strerror(error)
147
        int error;
148
{
149
        if (error < sys_nerr)
150
           return sys_errlist[error];
151
        else
152
           return "Unknown error.";
153
}
154

    
155
#endif
156

    
157

    
158
#ifdef _WIN32
159

    
160
int
161
fork_exec(struct socket *so, const char *ex, int do_pty)
162
{
163
    /* not implemented */
164
    return 0;
165
}
166

    
167
#else
168

    
169
#ifndef CONFIG_QEMU
170
int
171
slirp_openpty(amaster, aslave)
172
     int *amaster, *aslave;
173
{
174
        register int master, slave;
175

    
176
#ifdef HAVE_GRANTPT
177
        char *ptr;
178

    
179
        if ((master = open("/dev/ptmx", O_RDWR)) < 0 ||
180
            grantpt(master) < 0 ||
181
            unlockpt(master) < 0 ||
182
            (ptr = ptsname(master)) == NULL)  {
183
                close(master);
184
                return -1;
185
        }
186

    
187
        if ((slave = open(ptr, O_RDWR)) < 0 ||
188
            ioctl(slave, I_PUSH, "ptem") < 0 ||
189
            ioctl(slave, I_PUSH, "ldterm") < 0 ||
190
            ioctl(slave, I_PUSH, "ttcompat") < 0) {
191
                close(master);
192
                close(slave);
193
                return -1;
194
        }
195

    
196
        *amaster = master;
197
        *aslave = slave;
198
        return 0;
199

    
200
#else
201

    
202
        static char line[] = "/dev/ptyXX";
203
        register const char *cp1, *cp2;
204

    
205
        for (cp1 = "pqrsPQRS"; *cp1; cp1++) {
206
                line[8] = *cp1;
207
                for (cp2 = "0123456789abcdefghijklmnopqrstuv"; *cp2; cp2++) {
208
                        line[9] = *cp2;
209
                        if ((master = open(line, O_RDWR, 0)) == -1) {
210
                                if (errno == ENOENT)
211
                                   return (-1);    /* out of ptys */
212
                        } else {
213
                                line[5] = 't';
214
                                /* These will fail */
215
                                (void) chown(line, getuid(), 0);
216
                                (void) chmod(line, S_IRUSR|S_IWUSR|S_IWGRP);
217
#ifdef HAVE_REVOKE
218
                                (void) revoke(line);
219
#endif
220
                                if ((slave = open(line, O_RDWR, 0)) != -1) {
221
                                        *amaster = master;
222
                                        *aslave = slave;
223
                                        return 0;
224
                                }
225
                                (void) close(master);
226
                                line[5] = 'p';
227
                        }
228
                }
229
        }
230
        errno = ENOENT; /* out of ptys */
231
        return (-1);
232
#endif
233
}
234
#endif
235

    
236
/*
237
 * XXX This is ugly
238
 * We create and bind a socket, then fork off to another
239
 * process, which connects to this socket, after which we
240
 * exec the wanted program.  If something (strange) happens,
241
 * the accept() call could block us forever.
242
 *
243
 * do_pty = 0   Fork/exec inetd style
244
 * do_pty = 1   Fork/exec using slirp.telnetd
245
 * do_ptr = 2   Fork/exec using pty
246
 */
247
int
248
fork_exec(struct socket *so, const char *ex, int do_pty)
249
{
250
        int s;
251
        struct sockaddr_in addr;
252
        socklen_t addrlen = sizeof(addr);
253
        int opt;
254
        int master = -1;
255
        const char *argv[256];
256
#if 0
257
        char buff[256];
258
#endif
259
        /* don't want to clobber the original */
260
        char *bptr;
261
        const char *curarg;
262
        int c, i, ret;
263

    
264
        DEBUG_CALL("fork_exec");
265
        DEBUG_ARG("so = %lx", (long)so);
266
        DEBUG_ARG("ex = %lx", (long)ex);
267
        DEBUG_ARG("do_pty = %lx", (long)do_pty);
268

    
269
        if (do_pty == 2) {
270
#if 0
271
                if (slirp_openpty(&master, &s) == -1) {
272
                        lprint("Error: openpty failed: %s\n", strerror(errno));
273
                        return 0;
274
                }
275
#else
276
                return 0;
277
#endif
278
        } else {
279
                addr.sin_family = AF_INET;
280
                addr.sin_port = 0;
281
                addr.sin_addr.s_addr = INADDR_ANY;
282

    
283
                if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0 ||
284
                    bind(s, (struct sockaddr *)&addr, addrlen) < 0 ||
285
                    listen(s, 1) < 0) {
286
                        lprint("Error: inet socket: %s\n", strerror(errno));
287
                        closesocket(s);
288

    
289
                        return 0;
290
                }
291
        }
292

    
293
        switch(fork()) {
294
         case -1:
295
                lprint("Error: fork failed: %s\n", strerror(errno));
296
                close(s);
297
                if (do_pty == 2)
298
                   close(master);
299
                return 0;
300

    
301
         case 0:
302
                /* Set the DISPLAY */
303
                if (do_pty == 2) {
304
                        (void) close(master);
305
#ifdef TIOCSCTTY /* XXXXX */
306
                        (void) setsid();
307
                        ioctl(s, TIOCSCTTY, (char *)NULL);
308
#endif
309
                } else {
310
                        getsockname(s, (struct sockaddr *)&addr, &addrlen);
311
                        close(s);
312
                        /*
313
                         * Connect to the socket
314
                         * XXX If any of these fail, we're in trouble!
315
                          */
316
                        s = socket(AF_INET, SOCK_STREAM, 0);
317
                        addr.sin_addr = loopback_addr;
318
                        do {
319
                            ret = connect(s, (struct sockaddr *)&addr, addrlen);
320
                        } while (ret < 0 && errno == EINTR);
321
                }
322

    
323
#if 0
324
                if (x_port >= 0) {
325
#ifdef HAVE_SETENV
326
                        sprintf(buff, "%s:%d.%d", inet_ntoa(our_addr), x_port, x_screen);
327
                        setenv("DISPLAY", buff, 1);
328
#else
329
                        sprintf(buff, "DISPLAY=%s:%d.%d", inet_ntoa(our_addr), x_port, x_screen);
330
                        putenv(buff);
331
#endif
332
                }
333
#endif
334
                dup2(s, 0);
335
                dup2(s, 1);
336
                dup2(s, 2);
337
                for (s = getdtablesize() - 1; s >= 3; s--)
338
                   close(s);
339

    
340
                i = 0;
341
                bptr = strdup(ex); /* No need to free() this */
342
                if (do_pty == 1) {
343
                        /* Setup "slirp.telnetd -x" */
344
                        argv[i++] = "slirp.telnetd";
345
                        argv[i++] = "-x";
346
                        argv[i++] = bptr;
347
                } else
348
                   do {
349
                        /* Change the string into argv[] */
350
                        curarg = bptr;
351
                        while (*bptr != ' ' && *bptr != (char)0)
352
                           bptr++;
353
                        c = *bptr;
354
                        *bptr++ = (char)0;
355
                        argv[i++] = strdup(curarg);
356
                   } while (c);
357

    
358
                argv[i] = NULL;
359
                execvp(argv[0], (char **)argv);
360

    
361
                /* Ooops, failed, let's tell the user why */
362
                  {
363
                          char buff[256];
364

    
365
                          snprintf(buff, sizeof(buff),
366
                                   "Error: execvp of %s failed: %s\n",
367
                                   argv[0], strerror(errno));
368
                          write(2, buff, strlen(buff)+1);
369
                  }
370
                close(0); close(1); close(2); /* XXX */
371
                exit(1);
372

    
373
         default:
374
                if (do_pty == 2) {
375
                        close(s);
376
                        so->s = master;
377
                } else {
378
                        /*
379
                         * XXX this could block us...
380
                         * XXX Should set a timer here, and if accept() doesn't
381
                          * return after X seconds, declare it a failure
382
                          * The only reason this will block forever is if socket()
383
                          * of connect() fail in the child process
384
                          */
385
                        do {
386
                            so->s = accept(s, (struct sockaddr *)&addr, &addrlen);
387
                        } while (so->s < 0 && errno == EINTR);
388
                        closesocket(s);
389
                        opt = 1;
390
                        setsockopt(so->s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int));
391
                        opt = 1;
392
                        setsockopt(so->s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int));
393
                }
394
                fd_nonblock(so->s);
395

    
396
                /* Append the telnet options now */
397
                if (so->so_m != NULL && do_pty == 1)  {
398
                        sbappend(so, so->so_m);
399
                        so->so_m = NULL;
400
                }
401

    
402
                return 1;
403
        }
404
}
405
#endif
406

    
407
#ifndef HAVE_STRDUP
408
char *
409
strdup(str)
410
        const char *str;
411
{
412
        char *bptr;
413

    
414
        bptr = (char *)malloc(strlen(str)+1);
415
        strcpy(bptr, str);
416

    
417
        return bptr;
418
}
419
#endif
420

    
421
#if 0
422
void
423
snooze_hup(num)
424
        int num;
425
{
426
        int s, ret;
427
#ifndef NO_UNIX_SOCKETS
428
        struct sockaddr_un sock_un;
429
#endif
430
        struct sockaddr_in sock_in;
431
        char buff[256];
432

    
433
        ret = -1;
434
        if (slirp_socket_passwd) {
435
                s = socket(AF_INET, SOCK_STREAM, 0);
436
                if (s < 0)
437
                   slirp_exit(1);
438
                sock_in.sin_family = AF_INET;
439
                sock_in.sin_addr.s_addr = slirp_socket_addr;
440
                sock_in.sin_port = htons(slirp_socket_port);
441
                if (connect(s, (struct sockaddr *)&sock_in, sizeof(sock_in)) != 0)
442
                   slirp_exit(1); /* just exit...*/
443
                sprintf(buff, "kill %s:%d", slirp_socket_passwd, slirp_socket_unit);
444
                write(s, buff, strlen(buff)+1);
445
        }
446
#ifndef NO_UNIX_SOCKETS
447
          else {
448
                s = socket(AF_UNIX, SOCK_STREAM, 0);
449
                if (s < 0)
450
                   slirp_exit(1);
451
                sock_un.sun_family = AF_UNIX;
452
                strcpy(sock_un.sun_path, socket_path);
453
                if (connect(s, (struct sockaddr *)&sock_un,
454
                              sizeof(sock_un.sun_family) + sizeof(sock_un.sun_path)) != 0)
455
                   slirp_exit(1);
456
                sprintf(buff, "kill none:%d", slirp_socket_unit);
457
                write(s, buff, strlen(buff)+1);
458
        }
459
#endif
460
        slirp_exit(0);
461
}
462

    
463

    
464
void
465
snooze()
466
{
467
        sigset_t s;
468
        int i;
469

    
470
        /* Don't need our data anymore */
471
        /* XXX This makes SunOS barf */
472
/*        brk(0); */
473

    
474
        /* Close all fd's */
475
        for (i = 255; i >= 0; i--)
476
           close(i);
477

    
478
        signal(SIGQUIT, slirp_exit);
479
        signal(SIGHUP, snooze_hup);
480
        sigemptyset(&s);
481

    
482
        /* Wait for any signal */
483
        sigsuspend(&s);
484

    
485
        /* Just in case ... */
486
        exit(255);
487
}
488

    
489
void
490
relay(s)
491
        int s;
492
{
493
        char buf[8192];
494
        int n;
495
        fd_set readfds;
496
        struct ttys *ttyp;
497

    
498
        /* Don't need our data anymore */
499
        /* XXX This makes SunOS barf */
500
/*        brk(0); */
501

    
502
        signal(SIGQUIT, slirp_exit);
503
        signal(SIGHUP, slirp_exit);
504
        signal(SIGINT, slirp_exit);
505
        signal(SIGTERM, slirp_exit);
506

    
507
        /* Fudge to get term_raw and term_restore to work */
508
        if (NULL == (ttyp = tty_attach (0, slirp_tty))) {
509
         lprint ("Error: tty_attach failed in misc.c:relay()\r\n");
510
         slirp_exit (1);
511
    }
512
        ttyp->fd = 0;
513
        ttyp->flags |= TTY_CTTY;
514
        term_raw(ttyp);
515

    
516
        while (1) {
517
                FD_ZERO(&readfds);
518

    
519
                FD_SET(0, &readfds);
520
                FD_SET(s, &readfds);
521

    
522
                n = select(s+1, &readfds, (fd_set *)0, (fd_set *)0, (struct timeval *)0);
523

    
524
                if (n <= 0)
525
                   slirp_exit(0);
526

    
527
                if (FD_ISSET(0, &readfds)) {
528
                        n = read(0, buf, 8192);
529
                        if (n <= 0)
530
                           slirp_exit(0);
531
                        n = writen(s, buf, n);
532
                        if (n <= 0)
533
                           slirp_exit(0);
534
                }
535

    
536
                if (FD_ISSET(s, &readfds)) {
537
                        n = read(s, buf, 8192);
538
                        if (n <= 0)
539
                           slirp_exit(0);
540
                        n = writen(0, buf, n);
541
                        if (n <= 0)
542
                           slirp_exit(0);
543
                }
544
        }
545

    
546
        /* Just in case.... */
547
        exit(1);
548
}
549
#endif
550

    
551
#ifdef CONFIG_QEMU
552
#include "monitor.h"
553

    
554
void lprint(const char *format, ...)
555
{
556
    va_list args;
557

    
558
    va_start(args, format);
559
    monitor_vprintf(cur_mon, format, args);
560
    va_end(args);
561
}
562
#else
563
int (*lprint_print) _P((void *, const char *, va_list));
564
char *lprint_ptr, *lprint_ptr2, **lprint_arg;
565

    
566
void
567
#ifdef __STDC__
568
lprint(const char *format, ...)
569
#else
570
lprint(va_alist) va_dcl
571
#endif
572
{
573
        va_list args;
574

    
575
#ifdef __STDC__
576
        va_start(args, format);
577
#else
578
        char *format;
579
        va_start(args);
580
        format = va_arg(args, char *);
581
#endif
582
#if 0
583
        /* If we're printing to an sbuf, make sure there's enough room */
584
        /* XXX +100? */
585
        if (lprint_sb) {
586
                if ((lprint_ptr - lprint_sb->sb_wptr) >=
587
                    (lprint_sb->sb_datalen - (strlen(format) + 100))) {
588
                        int deltaw = lprint_sb->sb_wptr - lprint_sb->sb_data;
589
                        int deltar = lprint_sb->sb_rptr - lprint_sb->sb_data;
590
                        int deltap = lprint_ptr -         lprint_sb->sb_data;
591

592
                        lprint_sb->sb_data = (char *)realloc(lprint_sb->sb_data,
593
                                                             lprint_sb->sb_datalen + TCP_SNDSPACE);
594

595
                        /* Adjust all values */
596
                        lprint_sb->sb_wptr = lprint_sb->sb_data + deltaw;
597
                        lprint_sb->sb_rptr = lprint_sb->sb_data + deltar;
598
                        lprint_ptr =         lprint_sb->sb_data + deltap;
599

600
                        lprint_sb->sb_datalen += TCP_SNDSPACE;
601
                }
602
        }
603
#endif
604
        if (lprint_print)
605
           lprint_ptr += (*lprint_print)(*lprint_arg, format, args);
606

    
607
        /* Check if they want output to be logged to file as well */
608
        if (lfd) {
609
                /*
610
                 * Remove \r's
611
                 * otherwise you'll get ^M all over the file
612
                 */
613
                int len = strlen(format);
614
                char *bptr1, *bptr2;
615

    
616
                bptr1 = bptr2 = strdup(format);
617

    
618
                while (len--) {
619
                        if (*bptr1 == '\r')
620
                           memcpy(bptr1, bptr1+1, len+1);
621
                        else
622
                           bptr1++;
623
                }
624
                vfprintf(lfd, bptr2, args);
625
                free(bptr2);
626
        }
627
        va_end(args);
628
}
629

    
630
void
631
add_emu(buff)
632
        char *buff;
633
{
634
        u_int lport, fport;
635
        u_int8_t tos = 0, emu = 0;
636
        char buff1[256], buff2[256], buff4[128];
637
        char *buff3 = buff4;
638
        struct emu_t *emup;
639
        struct socket *so;
640

    
641
        if (sscanf(buff, "%256s %256s", buff2, buff1) != 2) {
642
                lprint("Error: Bad arguments\r\n");
643
                return;
644
        }
645

    
646
        if (sscanf(buff1, "%d:%d", &lport, &fport) != 2) {
647
                lport = 0;
648
                if (sscanf(buff1, "%d", &fport) != 1) {
649
                        lprint("Error: Bad first argument\r\n");
650
                        return;
651
                }
652
        }
653

    
654
        if (sscanf(buff2, "%128[^:]:%128s", buff1, buff3) != 2) {
655
                buff3 = 0;
656
                if (sscanf(buff2, "%256s", buff1) != 1) {
657
                        lprint("Error: Bad second argument\r\n");
658
                        return;
659
                }
660
        }
661

    
662
        if (buff3) {
663
                if (strcmp(buff3, "lowdelay") == 0)
664
                   tos = IPTOS_LOWDELAY;
665
                else if (strcmp(buff3, "throughput") == 0)
666
                   tos = IPTOS_THROUGHPUT;
667
                else {
668
                        lprint("Error: Expecting \"lowdelay\"/\"throughput\"\r\n");
669
                        return;
670
                }
671
        }
672

    
673
        if (strcmp(buff1, "ftp") == 0)
674
           emu = EMU_FTP;
675
        else if (strcmp(buff1, "irc") == 0)
676
           emu = EMU_IRC;
677
        else if (strcmp(buff1, "none") == 0)
678
           emu = EMU_NONE; /* ie: no emulation */
679
        else {
680
                lprint("Error: Unknown service\r\n");
681
                return;
682
        }
683

    
684
        /* First, check that it isn't already emulated */
685
        for (emup = tcpemu; emup; emup = emup->next) {
686
                if (emup->lport == lport && emup->fport == fport) {
687
                        lprint("Error: port already emulated\r\n");
688
                        return;
689
                }
690
        }
691

    
692
        /* link it */
693
        emup = (struct emu_t *)malloc(sizeof (struct emu_t));
694
        emup->lport = (u_int16_t)lport;
695
        emup->fport = (u_int16_t)fport;
696
        emup->tos = tos;
697
        emup->emu = emu;
698
        emup->next = tcpemu;
699
        tcpemu = emup;
700

    
701
        /* And finally, mark all current sessions, if any, as being emulated */
702
        for (so = tcb.so_next; so != &tcb; so = so->so_next) {
703
                if ((lport && lport == ntohs(so->so_lport)) ||
704
                    (fport && fport == ntohs(so->so_fport))) {
705
                        if (emu)
706
                           so->so_emu = emu;
707
                        if (tos)
708
                           so->so_iptos = tos;
709
                }
710
        }
711

    
712
        lprint("Adding emulation for %s to port %d/%d\r\n", buff1, emup->lport, emup->fport);
713
}
714
#endif
715

    
716
#ifdef BAD_SPRINTF
717

    
718
#undef vsprintf
719
#undef sprintf
720

    
721
/*
722
 * Some BSD-derived systems have a sprintf which returns char *
723
 */
724

    
725
int
726
vsprintf_len(string, format, args)
727
        char *string;
728
        const char *format;
729
        va_list args;
730
{
731
        vsprintf(string, format, args);
732
        return strlen(string);
733
}
734

    
735
int
736
#ifdef __STDC__
737
sprintf_len(char *string, const char *format, ...)
738
#else
739
sprintf_len(va_alist) va_dcl
740
#endif
741
{
742
        va_list args;
743
#ifdef __STDC__
744
        va_start(args, format);
745
#else
746
        char *string;
747
        char *format;
748
        va_start(args);
749
        string = va_arg(args, char *);
750
        format = va_arg(args, char *);
751
#endif
752
        vsprintf(string, format, args);
753
        return strlen(string);
754
}
755

    
756
#endif
757

    
758
void
759
u_sleep(int usec)
760
{
761
        struct timeval t;
762
        fd_set fdset;
763

    
764
        FD_ZERO(&fdset);
765

    
766
        t.tv_sec = 0;
767
        t.tv_usec = usec * 1000;
768

    
769
        select(0, &fdset, &fdset, &fdset, &t);
770
}
771

    
772
/*
773
 * Set fd blocking and non-blocking
774
 */
775

    
776
void
777
fd_nonblock(int fd)
778
{
779
#ifdef FIONBIO
780
#ifdef _WIN32
781
        long opt = 1;
782
#else
783
        int opt = 1;
784
#endif
785

    
786
        ioctlsocket(fd, FIONBIO, &opt);
787
#else
788
        int opt;
789

    
790
        opt = fcntl(fd, F_GETFL, 0);
791
        opt |= O_NONBLOCK;
792
        fcntl(fd, F_SETFL, opt);
793
#endif
794
}
795

    
796
void
797
fd_block(int fd)
798
{
799
#ifdef FIONBIO
800
        int opt = 0;
801

    
802
        ioctlsocket(fd, FIONBIO, &opt);
803
#else
804
        int opt;
805

    
806
        opt = fcntl(fd, F_GETFL, 0);
807
        opt &= ~O_NONBLOCK;
808
        fcntl(fd, F_SETFL, opt);
809
#endif
810
}
811

    
812

    
813
#if 0
814
/*
815
 * invoke RSH
816
 */
817
int
818
rsh_exec(so,ns, user, host, args)
819
        struct socket *so;
820
        struct socket *ns;
821
        char *user;
822
        char *host;
823
        char *args;
824
{
825
        int fd[2];
826
        int fd0[2];
827
        int s;
828
        char buff[256];
829

830
        DEBUG_CALL("rsh_exec");
831
        DEBUG_ARG("so = %lx", (long)so);
832

833
        if (pipe(fd)<0) {
834
          lprint("Error: pipe failed: %s\n", strerror(errno));
835
          return 0;
836
        }
837
/* #ifdef HAVE_SOCKETPAIR */
838
#if 1
839
        if (socketpair(PF_UNIX,SOCK_STREAM,0, fd0) == -1) {
840
          close(fd[0]);
841
          close(fd[1]);
842
          lprint("Error: openpty failed: %s\n", strerror(errno));
843
          return 0;
844
        }
845
#else
846
        if (slirp_openpty(&fd0[0], &fd0[1]) == -1) {
847
          close(fd[0]);
848
          close(fd[1]);
849
          lprint("Error: openpty failed: %s\n", strerror(errno));
850
          return 0;
851
        }
852
#endif
853

    
854
        switch(fork()) {
855
         case -1:
856
           lprint("Error: fork failed: %s\n", strerror(errno));
857
           close(fd[0]);
858
           close(fd[1]);
859
           close(fd0[0]);
860
           close(fd0[1]);
861
           return 0;
862

    
863
         case 0:
864
           close(fd[0]);
865
           close(fd0[0]);
866

    
867
                /* Set the DISPLAY */
868
           if (x_port >= 0) {
869
#ifdef HAVE_SETENV
870
             sprintf(buff, "%s:%d.%d", inet_ntoa(our_addr), x_port, x_screen);
871
             setenv("DISPLAY", buff, 1);
872
#else
873
             sprintf(buff, "DISPLAY=%s:%d.%d", inet_ntoa(our_addr), x_port, x_screen);
874
             putenv(buff);
875
#endif
876
           }
877

    
878
           dup2(fd0[1], 0);
879
           dup2(fd0[1], 1);
880
           dup2(fd[1], 2);
881
           for (s = 3; s <= 255; s++)
882
             close(s);
883

    
884
           execlp("rsh","rsh","-l", user, host, args, NULL);
885

    
886
           /* Ooops, failed, let's tell the user why */
887

    
888
           sprintf(buff, "Error: execlp of %s failed: %s\n",
889
                   "rsh", strerror(errno));
890
           write(2, buff, strlen(buff)+1);
891
           close(0); close(1); close(2); /* XXX */
892
           exit(1);
893

    
894
        default:
895
          close(fd[1]);
896
          close(fd0[1]);
897
          ns->s=fd[0];
898
          so->s=fd0[0];
899

    
900
          return 1;
901
        }
902
}
903
#endif