Statistics
| Branch: | Revision:

root / slirp / misc.c @ f4e15b4b

History | View | Annotate | Download (19.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
#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 = NULL;
92
        
93
        if (gethostname(buff,256) == 0)
94
            he = gethostbyname(buff);
95
        if (he)
96
            our_addr = *(struct in_addr *)he->h_addr;
97
        /* If the host doesn't have a useful IP address then use the
98
           guest side address.  */
99
        if (our_addr.s_addr == 0 || our_addr.s_addr == loopback_addr.s_addr)
100
            our_addr.s_addr = special_addr.s_addr | htonl(CTL_ALIAS);
101
}
102

    
103
#if SIZEOF_CHAR_P == 8
104

    
105
struct quehead_32 {
106
        u_int32_t qh_link;
107
        u_int32_t qh_rlink;
108
};
109

    
110
inline void
111
insque_32(a, b)
112
        void *a;
113
        void *b;
114
{
115
        register struct quehead_32 *element = (struct quehead_32 *) a;
116
        register struct quehead_32 *head = (struct quehead_32 *) b;
117
        element->qh_link = head->qh_link;
118
        head->qh_link = (u_int32_t)element;
119
        element->qh_rlink = (u_int32_t)head;
120
        ((struct quehead_32 *)(element->qh_link))->qh_rlink
121
        = (u_int32_t)element;
122
}
123

    
124
inline void
125
remque_32(a)
126
        void *a;
127
{
128
        register struct quehead_32 *element = (struct quehead_32 *) a;
129
        ((struct quehead_32 *)(element->qh_link))->qh_rlink = element->qh_rlink;
130
        ((struct quehead_32 *)(element->qh_rlink))->qh_link = element->qh_link;
131
        element->qh_rlink = 0;
132
}
133

    
134
#endif /* SIZEOF_CHAR_P == 8 */
135

    
136
struct quehead {
137
        struct quehead *qh_link;
138
        struct quehead *qh_rlink;
139
};
140

    
141
inline void
142
insque(a, b)
143
        void *a, *b;
144
{
145
        register struct quehead *element = (struct quehead *) a;
146
        register struct quehead *head = (struct quehead *) b;
147
        element->qh_link = head->qh_link;
148
        head->qh_link = (struct quehead *)element;
149
        element->qh_rlink = (struct quehead *)head;
150
        ((struct quehead *)(element->qh_link))->qh_rlink
151
        = (struct quehead *)element;
152
}
153

    
154
inline void
155
remque(a)
156
     void *a;
157
{
158
  register struct quehead *element = (struct quehead *) a;
159
  ((struct quehead *)(element->qh_link))->qh_rlink = element->qh_rlink;
160
  ((struct quehead *)(element->qh_rlink))->qh_link = element->qh_link;
161
  element->qh_rlink = NULL;
162
  /*  element->qh_link = NULL;  TCP FIN1 crashes if you do this.  Why ? */
163
}
164

    
165
/* #endif */
166

    
167

    
168
int
169
add_exec(ex_ptr, do_pty, exec, addr, port)
170
        struct ex_list **ex_ptr;
171
        int do_pty;
172
        char *exec;
173
        int addr;
174
        int port;
175
{
176
        struct ex_list *tmp_ptr;
177
        
178
        /* First, check if the port is "bound" */
179
        for (tmp_ptr = *ex_ptr; tmp_ptr; tmp_ptr = tmp_ptr->ex_next) {
180
                if (port == tmp_ptr->ex_fport && addr == tmp_ptr->ex_addr)
181
                   return -1;
182
        }
183
        
184
        tmp_ptr = *ex_ptr;
185
        *ex_ptr = (struct ex_list *)malloc(sizeof(struct ex_list));
186
        (*ex_ptr)->ex_fport = port;
187
        (*ex_ptr)->ex_addr = addr;
188
        (*ex_ptr)->ex_pty = do_pty;
189
        (*ex_ptr)->ex_exec = strdup(exec);
190
        (*ex_ptr)->ex_next = tmp_ptr;
191
        return 0;
192
}
193

    
194
#ifndef HAVE_STRERROR
195

    
196
/*
197
 * For systems with no strerror
198
 */
199

    
200
extern int sys_nerr;
201
extern char *sys_errlist[];
202

    
203
char *
204
strerror(error)
205
        int error;
206
{
207
        if (error < sys_nerr)
208
           return sys_errlist[error];
209
        else
210
           return "Unknown error.";
211
}
212

    
213
#endif
214

    
215

    
216
#ifdef _WIN32
217

    
218
int
219
fork_exec(so, ex, do_pty)
220
        struct socket *so;
221
        char *ex;
222
        int do_pty;
223
{
224
    /* not implemented */
225
    return 0;
226
}
227

    
228
#else
229

    
230
int
231
slirp_openpty(amaster, aslave)
232
     int *amaster, *aslave;
233
{
234
        register int master, slave;
235

    
236
#ifdef HAVE_GRANTPT
237
        char *ptr;
238
        
239
        if ((master = open("/dev/ptmx", O_RDWR)) < 0 ||
240
            grantpt(master) < 0 ||
241
            unlockpt(master) < 0 ||
242
            (ptr = ptsname(master)) == NULL)  {
243
                close(master);
244
                return -1;
245
        }
246
        
247
        if ((slave = open(ptr, O_RDWR)) < 0 ||
248
            ioctl(slave, I_PUSH, "ptem") < 0 ||
249
            ioctl(slave, I_PUSH, "ldterm") < 0 ||
250
            ioctl(slave, I_PUSH, "ttcompat") < 0) {
251
                close(master);
252
                close(slave);
253
                return -1;
254
        }
255
        
256
        *amaster = master;
257
        *aslave = slave;
258
        return 0;
259
        
260
#else
261
        
262
        static char line[] = "/dev/ptyXX";
263
        register const char *cp1, *cp2;
264
        
265
        for (cp1 = "pqrsPQRS"; *cp1; cp1++) {
266
                line[8] = *cp1;
267
                for (cp2 = "0123456789abcdefghijklmnopqrstuv"; *cp2; cp2++) {
268
                        line[9] = *cp2;
269
                        if ((master = open(line, O_RDWR, 0)) == -1) {
270
                                if (errno == ENOENT)
271
                                   return (-1);    /* out of ptys */
272
                        } else {
273
                                line[5] = 't';
274
                                /* These will fail */
275
                                (void) chown(line, getuid(), 0);
276
                                (void) chmod(line, S_IRUSR|S_IWUSR|S_IWGRP);
277
#ifdef HAVE_REVOKE
278
                                (void) revoke(line);
279
#endif
280
                                if ((slave = open(line, O_RDWR, 0)) != -1) {
281
                                        *amaster = master;
282
                                        *aslave = slave;
283
                                        return 0;
284
                                }
285
                                (void) close(master);
286
                                line[5] = 'p';
287
                        }
288
                }
289
        }
290
        errno = ENOENT; /* out of ptys */
291
        return (-1);
292
#endif
293
}
294

    
295
/*
296
 * XXX This is ugly
297
 * We create and bind a socket, then fork off to another
298
 * process, which connects to this socket, after which we
299
 * exec the wanted program.  If something (strange) happens,
300
 * the accept() call could block us forever.
301
 * 
302
 * do_pty = 0   Fork/exec inetd style
303
 * do_pty = 1   Fork/exec using slirp.telnetd
304
 * do_ptr = 2   Fork/exec using pty
305
 */
306
int
307
fork_exec(so, ex, do_pty)
308
        struct socket *so;
309
        char *ex;
310
        int do_pty;
311
{
312
        int s;
313
        struct sockaddr_in addr;
314
        int addrlen = sizeof(addr);
315
        int opt;
316
        int master;
317
        char *argv[256];
318
#if 0
319
        char buff[256];
320
#endif
321
        /* don't want to clobber the original */
322
        char *bptr;
323
        char *curarg;
324
        int c, i, ret;
325
        
326
        DEBUG_CALL("fork_exec");
327
        DEBUG_ARG("so = %lx", (long)so);
328
        DEBUG_ARG("ex = %lx", (long)ex);
329
        DEBUG_ARG("do_pty = %lx", (long)do_pty);
330
        
331
        if (do_pty == 2) {
332
                if (slirp_openpty(&master, &s) == -1) {
333
                        lprint("Error: openpty failed: %s\n", strerror(errno));
334
                        return 0;
335
                }
336
        } else {
337
                addr.sin_family = AF_INET;
338
                addr.sin_port = 0;
339
                addr.sin_addr.s_addr = INADDR_ANY;
340
                
341
                if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0 ||
342
                    bind(s, (struct sockaddr *)&addr, addrlen) < 0 ||
343
                    listen(s, 1) < 0) {
344
                        lprint("Error: inet socket: %s\n", strerror(errno));
345
                        closesocket(s);
346
                        
347
                        return 0;
348
                }
349
        }
350
        
351
        switch(fork()) {
352
         case -1:
353
                lprint("Error: fork failed: %s\n", strerror(errno));
354
                close(s);
355
                if (do_pty == 2)
356
                   close(master);
357
                return 0;
358
                
359
         case 0:
360
                /* Set the DISPLAY */
361
                if (do_pty == 2) {
362
                        (void) close(master);
363
#ifdef TIOCSCTTY /* XXXXX */
364
                        (void) setsid();
365
                        ioctl(s, TIOCSCTTY, (char *)NULL);
366
#endif
367
                } else {
368
                        getsockname(s, (struct sockaddr *)&addr, &addrlen);
369
                        close(s);
370
                        /*
371
                         * Connect to the socket
372
                         * XXX If any of these fail, we're in trouble!
373
                          */
374
                        s = socket(AF_INET, SOCK_STREAM, 0);
375
                        addr.sin_addr = loopback_addr;
376
                        do {
377
                            ret = connect(s, (struct sockaddr *)&addr, addrlen);
378
                        } while (ret < 0 && errno == EINTR);
379
                }
380
                
381
#if 0
382
                if (x_port >= 0) {
383
#ifdef HAVE_SETENV
384
                        sprintf(buff, "%s:%d.%d", inet_ntoa(our_addr), x_port, x_screen);
385
                        setenv("DISPLAY", buff, 1);
386
#else
387
                        sprintf(buff, "DISPLAY=%s:%d.%d", inet_ntoa(our_addr), x_port, x_screen);
388
                        putenv(buff);
389
#endif
390
                }
391
#endif        
392
                dup2(s, 0);
393
                dup2(s, 1);
394
                dup2(s, 2);
395
                for (s = 3; s <= 255; s++)
396
                   close(s);
397
                
398
                i = 0;
399
                bptr = strdup(ex); /* No need to free() this */
400
                if (do_pty == 1) {
401
                        /* Setup "slirp.telnetd -x" */
402
                        argv[i++] = "slirp.telnetd";
403
                        argv[i++] = "-x";
404
                        argv[i++] = bptr;
405
                } else
406
                   do {
407
                        /* Change the string into argv[] */
408
                        curarg = bptr;
409
                        while (*bptr != ' ' && *bptr != (char)0)
410
                           bptr++;
411
                        c = *bptr;
412
                        *bptr++ = (char)0;
413
                        argv[i++] = strdup(curarg);
414
                   } while (c);
415
                
416
                argv[i] = 0;
417
                execvp(argv[0], argv);
418
                
419
                /* Ooops, failed, let's tell the user why */
420
                  {
421
                          char buff[256];
422
                          
423
                          sprintf(buff, "Error: execvp of %s failed: %s\n", 
424
                                  argv[0], strerror(errno));
425
                          write(2, buff, strlen(buff)+1);
426
                  }
427
                close(0); close(1); close(2); /* XXX */
428
                exit(1);
429
                
430
         default:
431
                if (do_pty == 2) {
432
                        close(s);
433
                        so->s = master;
434
                } else {
435
                        /*
436
                         * XXX this could block us...
437
                         * XXX Should set a timer here, and if accept() doesn't
438
                          * return after X seconds, declare it a failure
439
                          * The only reason this will block forever is if socket()
440
                          * of connect() fail in the child process
441
                          */
442
                        do {
443
                            so->s = accept(s, (struct sockaddr *)&addr, &addrlen);
444
                        } while (so->s < 0 && errno == EINTR);
445
                        closesocket(s);
446
                        opt = 1;
447
                        setsockopt(so->s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int));
448
                        opt = 1;
449
                        setsockopt(so->s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int));
450
                }
451
                fd_nonblock(so->s);
452
                
453
                /* Append the telnet options now */
454
                if (so->so_m != 0 && do_pty == 1)  {
455
                        sbappend(so, so->so_m);
456
                        so->so_m = 0;
457
                }
458
                
459
                return 1;
460
        }
461
}
462
#endif
463

    
464
#ifndef HAVE_STRDUP
465
char *
466
strdup(str)
467
        const char *str;
468
{
469
        char *bptr;
470
        
471
        bptr = (char *)malloc(strlen(str)+1);
472
        strcpy(bptr, str);
473
        
474
        return bptr;
475
}
476
#endif
477

    
478
#if 0
479
void
480
snooze_hup(num)
481
        int num;
482
{
483
        int s, ret;
484
#ifndef NO_UNIX_SOCKETS
485
        struct sockaddr_un sock_un;
486
#endif
487
        struct sockaddr_in sock_in;
488
        char buff[256];
489
        
490
        ret = -1;
491
        if (slirp_socket_passwd) {
492
                s = socket(AF_INET, SOCK_STREAM, 0);
493
                if (s < 0)
494
                   slirp_exit(1);
495
                sock_in.sin_family = AF_INET;
496
                sock_in.sin_addr.s_addr = slirp_socket_addr;
497
                sock_in.sin_port = htons(slirp_socket_port);
498
                if (connect(s, (struct sockaddr *)&sock_in, sizeof(sock_in)) != 0)
499
                   slirp_exit(1); /* just exit...*/
500
                sprintf(buff, "kill %s:%d", slirp_socket_passwd, slirp_socket_unit);
501
                write(s, buff, strlen(buff)+1);
502
        }
503
#ifndef NO_UNIX_SOCKETS
504
          else {
505
                s = socket(AF_UNIX, SOCK_STREAM, 0);
506
                if (s < 0)
507
                   slirp_exit(1);
508
                sock_un.sun_family = AF_UNIX;
509
                strcpy(sock_un.sun_path, socket_path);
510
                if (connect(s, (struct sockaddr *)&sock_un,
511
                              sizeof(sock_un.sun_family) + sizeof(sock_un.sun_path)) != 0)
512
                   slirp_exit(1);
513
                sprintf(buff, "kill none:%d", slirp_socket_unit);
514
                write(s, buff, strlen(buff)+1);
515
        }
516
#endif
517
        slirp_exit(0);
518
}
519
        
520
        
521
void
522
snooze()
523
{
524
        sigset_t s;
525
        int i;
526
        
527
        /* Don't need our data anymore */
528
        /* XXX This makes SunOS barf */
529
/*        brk(0); */
530
        
531
        /* Close all fd's */
532
        for (i = 255; i >= 0; i--)
533
           close(i);
534
        
535
        signal(SIGQUIT, slirp_exit);
536
        signal(SIGHUP, snooze_hup);
537
        sigemptyset(&s);
538
        
539
        /* Wait for any signal */
540
        sigsuspend(&s);
541
        
542
        /* Just in case ... */
543
        exit(255);
544
}
545

    
546
void
547
relay(s)
548
        int s;
549
{
550
        char buf[8192];
551
        int n;
552
        fd_set readfds;
553
        struct ttys *ttyp;
554
        
555
        /* Don't need our data anymore */
556
        /* XXX This makes SunOS barf */
557
/*        brk(0); */
558
        
559
        signal(SIGQUIT, slirp_exit);
560
        signal(SIGHUP, slirp_exit);
561
        signal(SIGINT, slirp_exit);
562
        signal(SIGTERM, slirp_exit);
563
        
564
        /* Fudge to get term_raw and term_restore to work */
565
        if (NULL == (ttyp = tty_attach (0, slirp_tty))) {
566
         lprint ("Error: tty_attach failed in misc.c:relay()\r\n");
567
         slirp_exit (1);
568
    }
569
        ttyp->fd = 0;
570
        ttyp->flags |= TTY_CTTY;
571
        term_raw(ttyp);
572
        
573
        while (1) {
574
                FD_ZERO(&readfds);
575
                
576
                FD_SET(0, &readfds);
577
                FD_SET(s, &readfds);
578
                
579
                n = select(s+1, &readfds, (fd_set *)0, (fd_set *)0, (struct timeval *)0);
580
                
581
                if (n <= 0)
582
                   slirp_exit(0);
583
                
584
                if (FD_ISSET(0, &readfds)) {
585
                        n = read(0, buf, 8192);
586
                        if (n <= 0)
587
                           slirp_exit(0);
588
                        n = writen(s, buf, n);
589
                        if (n <= 0)
590
                           slirp_exit(0);
591
                }
592
                
593
                if (FD_ISSET(s, &readfds)) {
594
                        n = read(s, buf, 8192);
595
                        if (n <= 0)
596
                           slirp_exit(0);
597
                        n = writen(0, buf, n);
598
                        if (n <= 0)
599
                           slirp_exit(0);
600
                }
601
        }
602
        
603
        /* Just in case.... */
604
        exit(1);
605
}
606
#endif
607

    
608
int (*lprint_print) _P((void *, const char *, va_list));
609
char *lprint_ptr, *lprint_ptr2, **lprint_arg;
610

    
611
void
612
#ifdef __STDC__
613
lprint(const char *format, ...)
614
#else
615
lprint(va_alist) va_dcl
616
#endif
617
{
618
        va_list args;
619
        
620
#ifdef __STDC__
621
        va_start(args, format);
622
#else
623
        char *format;
624
        va_start(args);
625
        format = va_arg(args, char *);
626
#endif
627
#if 0
628
        /* If we're printing to an sbuf, make sure there's enough room */
629
        /* XXX +100? */
630
        if (lprint_sb) {
631
                if ((lprint_ptr - lprint_sb->sb_wptr) >=
632
                    (lprint_sb->sb_datalen - (strlen(format) + 100))) {
633
                        int deltaw = lprint_sb->sb_wptr - lprint_sb->sb_data;
634
                        int deltar = lprint_sb->sb_rptr - lprint_sb->sb_data;
635
                        int deltap = lprint_ptr -         lprint_sb->sb_data;
636
                                                
637
                        lprint_sb->sb_data = (char *)realloc(lprint_sb->sb_data,
638
                                                             lprint_sb->sb_datalen + TCP_SNDSPACE);
639
                        
640
                        /* Adjust all values */
641
                        lprint_sb->sb_wptr = lprint_sb->sb_data + deltaw;
642
                        lprint_sb->sb_rptr = lprint_sb->sb_data + deltar;
643
                        lprint_ptr =         lprint_sb->sb_data + deltap;
644
                        
645
                        lprint_sb->sb_datalen += TCP_SNDSPACE;
646
                }
647
        }
648
#endif        
649
        if (lprint_print)
650
           lprint_ptr += (*lprint_print)(*lprint_arg, format, args);
651
        
652
        /* Check if they want output to be logged to file as well */
653
        if (lfd) {
654
                /* 
655
                 * Remove \r's
656
                 * otherwise you'll get ^M all over the file
657
                 */
658
                int len = strlen(format);
659
                char *bptr1, *bptr2;
660
                
661
                bptr1 = bptr2 = strdup(format);
662
                
663
                while (len--) {
664
                        if (*bptr1 == '\r')
665
                           memcpy(bptr1, bptr1+1, len+1);
666
                        else
667
                           bptr1++;
668
                }
669
                vfprintf(lfd, bptr2, args);
670
                free(bptr2);
671
        }
672
        va_end(args);
673
}
674

    
675
void
676
add_emu(buff)
677
        char *buff;
678
{
679
        u_int lport, fport;
680
        u_int8_t tos = 0, emu = 0;
681
        char buff1[256], buff2[256], buff4[128];
682
        char *buff3 = buff4;
683
        struct emu_t *emup;
684
        struct socket *so;
685
        
686
        if (sscanf(buff, "%256s %256s", buff2, buff1) != 2) {
687
                lprint("Error: Bad arguments\r\n");
688
                return;
689
        }
690
        
691
        if (sscanf(buff1, "%d:%d", &lport, &fport) != 2) {
692
                lport = 0;
693
                if (sscanf(buff1, "%d", &fport) != 1) {
694
                        lprint("Error: Bad first argument\r\n");
695
                        return;
696
                }
697
        }
698
        
699
        if (sscanf(buff2, "%128[^:]:%128s", buff1, buff3) != 2) {
700
                buff3 = 0;
701
                if (sscanf(buff2, "%256s", buff1) != 1) {
702
                        lprint("Error: Bad second argument\r\n");
703
                        return;
704
                }
705
        }
706
        
707
        if (buff3) {
708
                if (strcmp(buff3, "lowdelay") == 0)
709
                   tos = IPTOS_LOWDELAY;
710
                else if (strcmp(buff3, "throughput") == 0)
711
                   tos = IPTOS_THROUGHPUT;
712
                else {
713
                        lprint("Error: Expecting \"lowdelay\"/\"throughput\"\r\n");
714
                        return;
715
                }
716
        }
717
        
718
        if (strcmp(buff1, "ftp") == 0)
719
           emu = EMU_FTP;
720
        else if (strcmp(buff1, "irc") == 0)
721
           emu = EMU_IRC;
722
        else if (strcmp(buff1, "none") == 0)
723
           emu = EMU_NONE; /* ie: no emulation */
724
        else {
725
                lprint("Error: Unknown service\r\n");
726
                return;
727
        }
728
        
729
        /* First, check that it isn't already emulated */
730
        for (emup = tcpemu; emup; emup = emup->next) {
731
                if (emup->lport == lport && emup->fport == fport) {
732
                        lprint("Error: port already emulated\r\n");
733
                        return;
734
                }
735
        }
736
        
737
        /* link it */
738
        emup = (struct emu_t *)malloc(sizeof (struct emu_t));
739
        emup->lport = (u_int16_t)lport;
740
        emup->fport = (u_int16_t)fport;
741
        emup->tos = tos;
742
        emup->emu = emu;
743
        emup->next = tcpemu;
744
        tcpemu = emup;
745
        
746
        /* And finally, mark all current sessions, if any, as being emulated */
747
        for (so = tcb.so_next; so != &tcb; so = so->so_next) {
748
                if ((lport && lport == ntohs(so->so_lport)) ||
749
                    (fport && fport == ntohs(so->so_fport))) {
750
                        if (emu)
751
                           so->so_emu = emu;
752
                        if (tos)
753
                           so->so_iptos = tos;
754
                }
755
        }
756
        
757
        lprint("Adding emulation for %s to port %d/%d\r\n", buff1, emup->lport, emup->fport);
758
}
759

    
760
#ifdef BAD_SPRINTF
761

    
762
#undef vsprintf
763
#undef sprintf
764

    
765
/*
766
 * Some BSD-derived systems have a sprintf which returns char *
767
 */
768

    
769
int
770
vsprintf_len(string, format, args)
771
        char *string;
772
        const char *format;
773
        va_list args;
774
{
775
        vsprintf(string, format, args);
776
        return strlen(string);
777
}
778

    
779
int
780
#ifdef __STDC__
781
sprintf_len(char *string, const char *format, ...)
782
#else
783
sprintf_len(va_alist) va_dcl
784
#endif
785
{
786
        va_list args;
787
#ifdef __STDC__
788
        va_start(args, format);
789
#else
790
        char *string;
791
        char *format;
792
        va_start(args);
793
        string = va_arg(args, char *);
794
        format = va_arg(args, char *);
795
#endif
796
        vsprintf(string, format, args);
797
        return strlen(string);
798
}
799

    
800
#endif
801

    
802
void
803
u_sleep(usec)
804
        int usec;
805
{
806
        struct timeval t;
807
        fd_set fdset;
808
        
809
        FD_ZERO(&fdset);
810
        
811
        t.tv_sec = 0;
812
        t.tv_usec = usec * 1000;
813
        
814
        select(0, &fdset, &fdset, &fdset, &t);
815
}
816

    
817
/*
818
 * Set fd blocking and non-blocking
819
 */
820

    
821
void
822
fd_nonblock(fd)
823
        int fd;
824
{
825
#ifdef FIONBIO
826
        int opt = 1;
827
        
828
        ioctlsocket(fd, FIONBIO, &opt);
829
#else
830
        int opt;
831
        
832
        opt = fcntl(fd, F_GETFL, 0);
833
        opt |= O_NONBLOCK;
834
        fcntl(fd, F_SETFL, opt);
835
#endif
836
}
837

    
838
void
839
fd_block(fd)
840
        int fd;
841
{
842
#ifdef FIONBIO
843
        int opt = 0;
844
        
845
        ioctlsocket(fd, FIONBIO, &opt);
846
#else
847
        int opt;
848
        
849
        opt = fcntl(fd, F_GETFL, 0);
850
        opt &= ~O_NONBLOCK;
851
        fcntl(fd, F_SETFL, opt);
852
#endif
853
}
854

    
855

    
856
#if 0
857
/*
858
 * invoke RSH
859
 */
860
int
861
rsh_exec(so,ns, user, host, args)
862
        struct socket *so;
863
        struct socket *ns;
864
        char *user;
865
        char *host;
866
        char *args;
867
{
868
        int fd[2];
869
        int fd0[2];
870
        int s;
871
        char buff[256];
872
        
873
        DEBUG_CALL("rsh_exec");
874
        DEBUG_ARG("so = %lx", (long)so);
875
        
876
        if (pipe(fd)<0) {
877
          lprint("Error: pipe failed: %s\n", strerror(errno));
878
          return 0;
879
        }
880
/* #ifdef HAVE_SOCKETPAIR */
881
#if 1
882
        if (socketpair(PF_UNIX,SOCK_STREAM,0, fd0) == -1) {
883
          close(fd[0]);
884
          close(fd[1]);
885
          lprint("Error: openpty failed: %s\n", strerror(errno));
886
          return 0;
887
        }
888
#else
889
        if (slirp_openpty(&fd0[0], &fd0[1]) == -1) {
890
          close(fd[0]);
891
          close(fd[1]);
892
          lprint("Error: openpty failed: %s\n", strerror(errno));
893
          return 0;
894
        }
895
#endif
896
        
897
        switch(fork()) {
898
         case -1:
899
           lprint("Error: fork failed: %s\n", strerror(errno));
900
           close(fd[0]);
901
           close(fd[1]);
902
           close(fd0[0]);
903
           close(fd0[1]);
904
           return 0;
905
           
906
         case 0:
907
           close(fd[0]);
908
           close(fd0[0]);
909
           
910
                /* Set the DISPLAY */
911
           if (x_port >= 0) {
912
#ifdef HAVE_SETENV
913
             sprintf(buff, "%s:%d.%d", inet_ntoa(our_addr), x_port, x_screen);
914
             setenv("DISPLAY", buff, 1);
915
#else
916
             sprintf(buff, "DISPLAY=%s:%d.%d", inet_ntoa(our_addr), x_port, x_screen);
917
             putenv(buff);
918
#endif
919
           }
920
           
921
           dup2(fd0[1], 0);
922
           dup2(fd0[1], 1);
923
           dup2(fd[1], 2);
924
           for (s = 3; s <= 255; s++)
925
             close(s);
926
           
927
           execlp("rsh","rsh","-l", user, host, args, NULL);
928
           
929
           /* Ooops, failed, let's tell the user why */
930
           
931
           sprintf(buff, "Error: execlp of %s failed: %s\n", 
932
                   "rsh", strerror(errno));
933
           write(2, buff, strlen(buff)+1);
934
           close(0); close(1); close(2); /* XXX */
935
           exit(1);
936
           
937
        default:
938
          close(fd[1]);
939
          close(fd0[1]);
940
          ns->s=fd[0];
941
          so->s=fd0[0];
942
          
943
          return 1;
944
        }
945
}
946
#endif