OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [uclinux/] [userland/] [ftp/] [ftp/] [ftp.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 763 simons
/*
2
 * Copyright (c) 1985, 1989 Regents of the University of California.
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions
7
 * are met:
8
 * 1. Redistributions of source code must retain the above copyright
9
 *    notice, this list of conditions and the following disclaimer.
10
 * 2. Redistributions in binary form must reproduce the above copyright
11
 *    notice, this list of conditions and the following disclaimer in the
12
 *    documentation and/or other materials provided with the distribution.
13
 * 3. All advertising materials mentioning features or use of this software
14
 *    must display the following acknowledgement:
15
 *      This product includes software developed by the University of
16
 *      California, Berkeley and its contributors.
17
 * 4. Neither the name of the University nor the names of its contributors
18
 *    may be used to endorse or promote products derived from this software
19
 *    without specific prior written permission.
20
 *
21
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31
 * SUCH DAMAGE.
32
 */
33
 
34
/*
35
 * From: @(#)ftp.c      5.38 (Berkeley) 4/22/91
36
 */
37
char ftp_rcsid[] =
38
  "$Id: ftp.c,v 1.1 2002-03-25 22:32:01 simons Exp $";
39
 
40
#include <sys/param.h>
41
#include <sys/stat.h>
42
#include <sys/ioctl.h>
43
#include <sys/socket.h>
44
#include <sys/time.h>
45
#include <sys/file.h>
46
 
47
#include <netinet/in.h>
48
#include <netinet/ip.h>
49
#include <arpa/ftp.h>
50
#include <arpa/inet.h>
51
#include <arpa/telnet.h>
52
 
53
#include <stdio.h>
54
#include <signal.h>
55
#include <string.h>
56
#include <stdlib.h>
57
#include <unistd.h>
58
#include <errno.h>
59
#include <netdb.h>
60
#include <pwd.h>
61
#include <stdarg.h>
62
 
63
#include "ftp_var.h"
64
#include "cmds.h"
65
 
66
#ifdef EMBED
67
//typedef unsigned int  socklen_t;
68
char *getlogin(void) { return((char *) NULL); }
69
#endif
70
 
71
#include "../version.h"
72
 
73
int data = -1;
74
off_t restart_point = 0;
75
 
76
static struct sockaddr_in hisctladdr;
77
static struct sockaddr_in data_addr;
78
static struct sockaddr_in myctladdr;
79
static int ptflag = 0;
80
static sigjmp_buf recvabort;
81
static sigjmp_buf sendabort;
82
static sigjmp_buf ptabort;
83
static int ptabflg = 0;
84
static int abrtflag = 0;
85
 
86
void lostpeer(int);
87
extern int connected;
88
 
89
static char *gunique(char *);
90
static void proxtrans(const char *cmd, char *local, char *remote);
91
static int initconn(void);
92
static void ptransfer(const char *direction, long bytes,
93
                      const struct timeval *t0,
94
                      const struct timeval *t1);
95
static void tvsub(struct timeval *tdiff,
96
                  const struct timeval *t1,
97
                  const struct timeval *t0);
98
static void abort_remote(FILE *din);
99
 
100
FILE *cin, *cout;
101
static FILE *dataconn(const char *);
102
 
103
char *
104
hookup(char *host, int port)
105
{
106
        register struct hostent *hp = 0;
107
        int s, tos;
108
        socklen_t len;
109
        static char hostnamebuf[256];
110
 
111
        memset(&hisctladdr, 0, sizeof(hisctladdr));
112
        if (inet_aton(host, &hisctladdr.sin_addr)) {
113
                hisctladdr.sin_family = AF_INET;
114
                strncpy(hostnamebuf, host, sizeof(hostnamebuf));
115
                hostnamebuf[sizeof(hostnamebuf)-1]=0;
116
        }
117
        else {
118
                hp = gethostbyname(host);
119
                if (hp == NULL) {
120
                        fprintf(stderr, "ftp: %s: ", host);
121
#ifndef EMBED
122
                        herror((char *)NULL);
123
#endif
124
                        code = -1;
125
                        return((char *) 0);
126
                }
127
                hisctladdr.sin_family = hp->h_addrtype;
128
                if (hp->h_length > (int)sizeof(hisctladdr.sin_addr)) {
129
                        hp->h_length = sizeof(hisctladdr.sin_addr);
130
                }
131
                memcpy(&hisctladdr.sin_addr, hp->h_addr_list[0], hp->h_length);
132
                (void) strncpy(hostnamebuf, hp->h_name, sizeof(hostnamebuf));
133
                hostnamebuf[sizeof(hostnamebuf)-1] = 0;
134
        }
135
        hostname = hostnamebuf;
136
        s = socket(hisctladdr.sin_family, SOCK_STREAM, 0);
137
        if (s < 0) {
138
                perror("ftp: socket");
139
                code = -1;
140
                return (0);
141
        }
142
        hisctladdr.sin_port = port;
143
        while (connect(s, (struct sockaddr *)&hisctladdr, sizeof (hisctladdr)) < 0) {
144
                if (hp && hp->h_addr_list[1]) {
145
                        int oerrno = errno;
146
 
147
                        fprintf(stderr, "ftp: connect to address %s: ",
148
                                inet_ntoa(hisctladdr.sin_addr));
149
                        errno = oerrno;
150
                        perror((char *) 0);
151
                        hp->h_addr_list++;
152
                        memcpy(&hisctladdr.sin_addr, hp->h_addr_list[0],
153
                               hp->h_length);
154
                        fprintf(stdout, "Trying %s...\n",
155
                                inet_ntoa(hisctladdr.sin_addr));
156
                        (void) close(s);
157
                        s = socket(hisctladdr.sin_family, SOCK_STREAM, 0);
158
                        if (s < 0) {
159
                                perror("ftp: socket");
160
                                code = -1;
161
                                return (0);
162
                        }
163
                        continue;
164
                }
165
                perror("ftp: connect");
166
                code = -1;
167
                goto bad;
168
        }
169
        len = sizeof (myctladdr);
170
        if (getsockname(s, (struct sockaddr *)&myctladdr, &len) < 0) {
171
                perror("ftp: getsockname");
172
                code = -1;
173
                goto bad;
174
        }
175
#ifdef IP_TOS
176
        tos = IPTOS_LOWDELAY;
177
        if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0)
178
                perror("ftp: setsockopt TOS (ignored)");
179
#endif
180
        cin = fdopen(s, "r");
181
        cout = fdopen(s, "w");
182
        if (cin == NULL || cout == NULL) {
183
                fprintf(stderr, "ftp: fdopen failed.\n");
184
                if (cin)
185
                        (void) fclose(cin);
186
                if (cout)
187
                        (void) fclose(cout);
188
                code = -1;
189
                goto bad;
190
        }
191
        if (verbose)
192
                printf("Connected to %s.\n", hostname);
193
        if (getreply(0) > 2) {   /* read startup message from server */
194
                if (cin)
195
                        (void) fclose(cin);
196
                if (cout)
197
                        (void) fclose(cout);
198
                code = -1;
199
                goto bad;
200
        }
201
#ifdef SO_OOBINLINE
202
        {
203
        int on = 1;
204
 
205
        if (setsockopt(s, SOL_SOCKET, SO_OOBINLINE, (char *)&on, sizeof(on))
206
                < 0 && debug) {
207
                        perror("ftp: setsockopt");
208
                }
209
        }
210
#endif /* SO_OOBINLINE */
211
 
212
        return (hostname);
213
bad:
214
        (void) close(s);
215
        return ((char *)0);
216
}
217
 
218
int
219
dologin(const char *host)
220
{
221
        char tmp[80];
222
        char *luser, *pass, *zacct;
223
        int n, aflag = 0;
224
 
225
        luser = pass = zacct = 0;
226
        if (xruserpass(host, &luser, &pass, &zacct) < 0) {
227
                code = -1;
228
                return(0);
229
        }
230
        while (luser == NULL) {
231
                char *myname = getlogin();
232
 
233
                if (myname == NULL) {
234
                        struct passwd *pp = getpwuid(getuid());
235
 
236
                        if (pp != NULL)
237
                                myname = pp->pw_name;
238
                }
239
                if (myname)
240
                        printf("Name (%s:%s): ", host, myname);
241
                else
242
                        printf("Name (%s): ", host);
243
#ifdef EMBED
244
                fflush(stdout);
245
#endif
246
                if (fgets(tmp, sizeof(tmp) - 1, stdin)==NULL) {
247
                        fprintf(stderr, "\nLogin failed.\n");
248
                        return 0;
249
                }
250
                tmp[strlen(tmp) - 1] = '\0';
251
                if (*tmp == '\0')
252
                        luser = myname;
253
                else
254
                        luser = tmp;
255
        }
256
        n = command("USER %s", luser);
257
        if (n == CONTINUE) {
258
                if (pass == NULL) {
259
                        /* fflush(stdout); */
260
                        pass = getpass("Password:");
261
                }
262
                n = command("PASS %s", pass);
263
        }
264
        if (n == CONTINUE) {
265
                aflag++;
266
                /* fflush(stdout); */
267
                zacct = getpass("Account:");
268
                n = command("ACCT %s", zacct);
269
        }
270
        if (n != COMPLETE) {
271
                fprintf(stderr, "Login failed.\n");
272
                return (0);
273
        }
274
        if (!aflag && zacct != NULL)
275
                (void) command("ACCT %s", zacct);
276
        if (proxy)
277
                return(1);
278
        for (n = 0; n < macnum; ++n) {
279
                if (!strcmp("init", macros[n].mac_name)) {
280
                        int margc;
281
                        char **margv;
282
                        strcpy(line, "$init");
283
                        margv = makeargv(&margc, NULL);
284
                        domacro(margc, margv);
285
                        break;
286
                }
287
        }
288
        return (1);
289
}
290
 
291
 
292
static void
293
cmdabort(int ignore)
294
{
295
        (void)ignore;
296
 
297
        printf("\n");
298
        fflush(stdout);
299
        abrtflag++;
300
        if (ptflag) siglongjmp(ptabort,1);
301
}
302
 
303
int
304
command(const char *fmt, ...)
305
{
306
        va_list ap;
307
        int r;
308
        void (*oldintr)(int);
309
 
310
        abrtflag = 0;
311
        if (debug) {
312
                printf("---> ");
313
                va_start(ap, fmt);
314
                if (strncmp("PASS ", fmt, 5) == 0)
315
                        printf("PASS XXXX");
316
                else
317
                        vfprintf(stdout, fmt, ap);
318
                va_end(ap);
319
                printf("\n");
320
                (void) fflush(stdout);
321
        }
322
        if (cout == NULL) {
323
                perror ("No control connection for command");
324
                code = -1;
325
                return (0);
326
        }
327
        oldintr = signal(SIGINT, cmdabort);
328
        va_start(ap, fmt);
329
        vfprintf(cout, fmt, ap);
330
        va_end(ap);
331
        fprintf(cout, "\r\n");
332
        (void) fflush(cout);
333
        cpend = 1;
334
        r = getreply(!strcmp(fmt, "QUIT"));
335
        if (abrtflag && oldintr != SIG_IGN)
336
                (*oldintr)(SIGINT);
337
        (void) signal(SIGINT, oldintr);
338
        return(r);
339
}
340
 
341
char reply_string[BUFSIZ];              /* last line of previous reply */
342
 
343
#include <ctype.h>
344
 
345
int
346
getreply(int expecteof)
347
{
348
        register int c, n;
349
        register int dig;
350
        register char *cp;
351
        int originalcode = 0, continuation = 0;
352
        void (*oldintr)(int);
353
        int pflag = 0;
354
        size_t px = 0;
355
        size_t psize = sizeof(pasv);
356
 
357
        oldintr = signal(SIGINT, cmdabort);
358
        for (;;) {
359
                dig = n = code = 0;
360
                cp = reply_string;
361
                while ((c = getc(cin)) != '\n') {
362
                        if (c == IAC) {     /* handle telnet commands */
363
                                switch (c = getc(cin)) {
364
                                case WILL:
365
                                case WONT:
366
                                        c = getc(cin);
367
                                        fprintf(cout, "%c%c%c", IAC, DONT, c);
368
                                        (void) fflush(cout);
369
                                        break;
370
                                case DO:
371
                                case DONT:
372
                                        c = getc(cin);
373
                                        fprintf(cout, "%c%c%c", IAC, WONT, c);
374
                                        (void) fflush(cout);
375
                                        break;
376
                                default:
377
                                        break;
378
                                }
379
                                continue;
380
                        }
381
                        dig++;
382
                        if (c == EOF) {
383
                                if (expecteof) {
384
                                        (void) signal(SIGINT,oldintr);
385
                                        code = 221;
386
                                        return (0);
387
                                }
388
                                lostpeer(0);
389
                                if (verbose) {
390
                                        printf("421 Service not available, remote server has closed connection\n");
391
                                        (void) fflush(stdout);
392
                                }
393
                                code = 421;
394
                                return(4);
395
                        }
396
                        if (c != '\r' && (verbose > 0 ||
397
                            (verbose > -1 && n == '5' && dig > 4))) {
398
                                if (proxflag &&
399
                                   (dig == 1 || (dig == 5 && verbose == 0)))
400
                                        printf("%s:",hostname);
401
                                (void) putchar(c);
402
                        }
403
                        if (dig < 4 && isdigit(c))
404
                                code = code * 10 + (c - '0');
405
                        if (!pflag && code == 227)
406
                                pflag = 1;
407
                        if (dig > 4 && pflag == 1 && isdigit(c))
408
                                pflag = 2;
409
                        if (pflag == 2) {
410
                                if (c != '\r' && c != ')') {
411
                                        if (px < psize-1) pasv[px++] = c;
412
                                }
413
                                else {
414
                                        pasv[px] = '\0';
415
                                        pflag = 3;
416
                                }
417
                        }
418
                        if (dig == 4 && c == '-') {
419
                                if (continuation)
420
                                        code = 0;
421
                                continuation++;
422
                        }
423
                        if (n == 0)
424
                                n = c;
425
                        if (cp < &reply_string[sizeof(reply_string) - 1])
426
                                *cp++ = c;
427
                }
428
                if (verbose > 0 || (verbose > -1 && n == '5')) {
429
                        (void) putchar(c);
430
                        (void) fflush (stdout);
431
                }
432
                if (continuation && code != originalcode) {
433
                        if (originalcode == 0)
434
                                originalcode = code;
435
                        continue;
436
                }
437
                *cp = '\0';
438
                if (n != '1')
439
                        cpend = 0;
440
                (void) signal(SIGINT,oldintr);
441
                if (code == 421 || originalcode == 421)
442
                        lostpeer(0);
443
                if (abrtflag && oldintr != cmdabort && oldintr != SIG_IGN)
444
                        (*oldintr)(SIGINT);
445
                return (n - '0');
446
        }
447
}
448
 
449
static int
450
empty(fd_set *mask, int hifd, int sec)
451
{
452
        struct timeval t;
453
 
454
        t.tv_sec = (long) sec;
455
        t.tv_usec = 0;
456
        return(select(hifd+1, mask, (fd_set *) 0, (fd_set *) 0, &t));
457
}
458
 
459
static void
460
abortsend(int ignore)
461
{
462
        (void)ignore;
463
 
464
        mflag = 0;
465
        abrtflag = 0;
466
        printf("\nsend aborted\nwaiting for remote to finish abort\n");
467
        (void) fflush(stdout);
468
        siglongjmp(sendabort, 1);
469
}
470
 
471
#define HASHBYTES 1024
472
 
473
void
474
sendrequest(const char *cmd, char *local, char *remote, int printnames)
475
{
476
        struct stat st;
477
        struct timeval start, stop;
478
        register int c, d;
479
        FILE *volatile fin, *volatile dout = 0;
480
        int (*volatile closefunc)(FILE *);
481
        void (*volatile oldintr)(int);
482
        void (*volatile oldintp)(int);
483
        volatile long bytes = 0, hashbytes = HASHBYTES;
484
        char buf[BUFSIZ], *bufp;
485
        const char *volatile lmode;
486
 
487
        if (verbose && printnames) {
488
                if (local && *local != '-')
489
                        printf("local: %s ", local);
490
                if (remote)
491
                        printf("remote: %s\n", remote);
492
        }
493
        if (proxy) {
494
                proxtrans(cmd, local, remote);
495
                return;
496
        }
497
        if (curtype != type)
498
                changetype(type, 0);
499
        closefunc = NULL;
500
        oldintr = NULL;
501
        oldintp = NULL;
502
        lmode = "w";
503
        if (sigsetjmp(sendabort, 1)) {
504
                while (cpend) {
505
                        (void) getreply(0);
506
                }
507
                if (data >= 0) {
508
                        (void) close(data);
509
                        data = -1;
510
                }
511
                if (oldintr)
512
                        (void) signal(SIGINT,oldintr);
513
                if (oldintp)
514
                        (void) signal(SIGPIPE,oldintp);
515
                code = -1;
516
                return;
517
        }
518
        oldintr = signal(SIGINT, abortsend);
519
        if (strcmp(local, "-") == 0)
520
                fin = stdin;
521
        else if (*local == '|') {
522
                oldintp = signal(SIGPIPE,SIG_IGN);
523
                fin = popen(local + 1, "r");
524
                if (fin == NULL) {
525
                        perror(local + 1);
526
                        (void) signal(SIGINT, oldintr);
527
                        (void) signal(SIGPIPE, oldintp);
528
                        code = -1;
529
                        return;
530
                }
531
                closefunc = pclose;
532
        } else {
533
                fin = fopen(local, "r");
534
                if (fin == NULL) {
535
                        fprintf(stderr, "local: %s: %s\n", local,
536
                                strerror(errno));
537
                        (void) signal(SIGINT, oldintr);
538
                        code = -1;
539
                        return;
540
                }
541
                closefunc = fclose;
542
                if (fstat(fileno(fin), &st) < 0 ||
543
                    (st.st_mode&S_IFMT) != S_IFREG) {
544
                        fprintf(stdout, "%s: not a plain file.\n", local);
545
                        (void) signal(SIGINT, oldintr);
546
                        fclose(fin);
547
                        code = -1;
548
                        return;
549
                }
550
        }
551
        if (initconn()) {
552
                (void) signal(SIGINT, oldintr);
553
                if (oldintp)
554
                        (void) signal(SIGPIPE, oldintp);
555
                code = -1;
556
                if (closefunc != NULL)
557
                        (*closefunc)(fin);
558
                return;
559
        }
560
        if (sigsetjmp(sendabort, 1))
561
                goto abort;
562
 
563
        if (restart_point &&
564
            (strcmp(cmd, "STOR") == 0 || strcmp(cmd, "APPE") == 0)) {
565
                if (fseek(fin, (long) restart_point, 0) < 0) {
566
                        fprintf(stderr, "local: %s: %s\n", local,
567
                                strerror(errno));
568
                        restart_point = 0;
569
                        if (closefunc != NULL)
570
                                (*closefunc)(fin);
571
                        return;
572
                }
573
                if (command("REST %ld", (long) restart_point)
574
                        != CONTINUE) {
575
                        restart_point = 0;
576
                        if (closefunc != NULL)
577
                                (*closefunc)(fin);
578
                        return;
579
                }
580
                restart_point = 0;
581
                lmode = "r+w";
582
        }
583
        if (remote) {
584
                if (command("%s %s", cmd, remote) != PRELIM) {
585
                        (void) signal(SIGINT, oldintr);
586
                        if (oldintp)
587
                                (void) signal(SIGPIPE, oldintp);
588
                        if (closefunc != NULL)
589
                                (*closefunc)(fin);
590
                        return;
591
                }
592
        } else
593
                if (command("%s", cmd) != PRELIM) {
594
                        (void) signal(SIGINT, oldintr);
595
                        if (oldintp)
596
                                (void) signal(SIGPIPE, oldintp);
597
                        if (closefunc != NULL)
598
                                (*closefunc)(fin);
599
                        return;
600
                }
601
        dout = dataconn(lmode);
602
        if (dout == NULL)
603
                goto abort;
604
        (void) gettimeofday(&start, (struct timezone *)0);
605
        oldintp = signal(SIGPIPE, SIG_IGN);
606
        switch (curtype) {
607
 
608
        case TYPE_I:
609
        case TYPE_L:
610
                errno = d = 0;
611
                while ((c = read(fileno(fin), buf, sizeof (buf))) > 0) {
612
                        bytes += c;
613
                        for (bufp = buf; c > 0; c -= d, bufp += d)
614
                                if ((d = write(fileno(dout), bufp, c)) <= 0)
615
                                        break;
616
                        if (hash) {
617
                                while (bytes >= hashbytes) {
618
                                        (void) putchar('#');
619
                                        hashbytes += HASHBYTES;
620
                                }
621
                                (void) fflush(stdout);
622
                        }
623
                        if (tick && (bytes >= hashbytes)) {
624
                                printf("\rBytes transferred: %ld", bytes);
625
                                (void) fflush(stdout);
626
                                while (bytes >= hashbytes)
627
                                        hashbytes += TICKBYTES;
628
                        }
629
                }
630
                if (hash && (bytes > 0)) {
631
                        if (bytes < HASHBYTES)
632
                                (void) putchar('#');
633
                        (void) putchar('\n');
634
                        (void) fflush(stdout);
635
                }
636
                if (tick) {
637
                        (void) printf("\rBytes transferred: %ld\n", bytes);
638
                        (void) fflush(stdout);
639
                }
640
                if (c < 0)
641
                        fprintf(stderr, "local: %s: %s\n", local,
642
                                strerror(errno));
643
                if (d < 0) {
644
                        if (errno != EPIPE)
645
                                perror("netout");
646
                        bytes = -1;
647
                }
648
                break;
649
 
650
        case TYPE_A:
651
                while ((c = getc(fin)) != EOF) {
652
                        if (c == '\n') {
653
                                while (hash && (bytes >= hashbytes)) {
654
                                        (void) putchar('#');
655
                                        (void) fflush(stdout);
656
                                        hashbytes += HASHBYTES;
657
                                }
658
                                if (tick && (bytes >= hashbytes)) {
659
                                        (void) printf("\rBytes transferred: %ld",
660
                                                bytes);
661
                                        (void) fflush(stdout);
662
                                        while (bytes >= hashbytes)
663
                                                hashbytes += TICKBYTES;
664
                                }
665
                                if (ferror(dout))
666
                                        break;
667
                                (void) putc('\r', dout);
668
                                bytes++;
669
                        }
670
                        (void) putc(c, dout);
671
                        bytes++;
672
        /*              if (c == '\r') {                                */
673
        /*              (void)  putc('\0', dout);  (* this violates rfc */
674
        /*                      bytes++;                                */
675
        /*              }                                               */
676
                }
677
                if (hash) {
678
                        if (bytes < hashbytes)
679
                                (void) putchar('#');
680
                        (void) putchar('\n');
681
                        (void) fflush(stdout);
682
                }
683
                if (tick) {
684
                        (void) printf("\rBytes transferred: %ld\n", bytes);
685
                        (void) fflush(stdout);
686
                }
687
                if (ferror(fin))
688
                        fprintf(stderr, "local: %s: %s\n", local,
689
                                strerror(errno));
690
                if (ferror(dout)) {
691
                        if (errno != EPIPE)
692
                                perror("netout");
693
                        bytes = -1;
694
                }
695
                break;
696
        }
697
        (void) gettimeofday(&stop, (struct timezone *)0);
698
        if (closefunc != NULL)
699
                (*closefunc)(fin);
700
        (void) fclose(dout);
701
        /* closes data as well, so discard it */
702
        data = -1;
703
        (void) getreply(0);
704
        (void) signal(SIGINT, oldintr);
705
        if (oldintp)
706
                (void) signal(SIGPIPE, oldintp);
707
        if (bytes > 0)
708
                ptransfer("sent", bytes, &start, &stop);
709
        return;
710
abort:
711
        (void) gettimeofday(&stop, (struct timezone *)0);
712
        (void) signal(SIGINT, oldintr);
713
        if (oldintp)
714
                (void) signal(SIGPIPE, oldintp);
715
        if (!cpend) {
716
                code = -1;
717
                return;
718
        }
719
        if (dout) {
720
                (void) fclose(dout);
721
        }
722
        if (data >= 0) {
723
                /* if it just got closed with dout, again won't hurt */
724
                (void) close(data);
725
                data = -1;
726
        }
727
        (void) getreply(0);
728
        code = -1;
729
        if (closefunc != NULL && fin != NULL)
730
                (*closefunc)(fin);
731
        if (bytes > 0)
732
                ptransfer("sent", bytes, &start, &stop);
733
}
734
 
735
static void
736
abortrecv(int ignore)
737
{
738
        (void)ignore;
739
 
740
        mflag = 0;
741
        abrtflag = 0;
742
        printf("\nreceive aborted\nwaiting for remote to finish abort\n");
743
        (void) fflush(stdout);
744
        siglongjmp(recvabort, 1);
745
}
746
 
747
void
748
recvrequest(const char *cmd,
749
            char *volatile local, char *remote,
750
            const char *lmode, int printnames)
751
{
752
        FILE *volatile fout, *volatile din = 0;
753
        int (*volatile closefunc)(FILE *);
754
        void (*volatile oldintp)(int);
755
        void (*volatile oldintr)(int);
756
        volatile int is_retr, tcrflag, bare_lfs = 0;
757
        static unsigned bufsize;
758
        static char *buf;
759
        volatile long bytes = 0, hashbytes = HASHBYTES;
760
        register int c, d;
761
        struct timeval start, stop;
762
        struct stat st;
763
 
764
        is_retr = strcmp(cmd, "RETR") == 0;
765
        if (is_retr && verbose && printnames) {
766
                if (local && *local != '-')
767
                        printf("local: %s ", local);
768
                if (remote)
769
                        printf("remote: %s\n", remote);
770
        }
771
        if (proxy && is_retr) {
772
                proxtrans(cmd, local, remote);
773
                return;
774
        }
775
        closefunc = NULL;
776
        oldintr = NULL;
777
        oldintp = NULL;
778
        tcrflag = !crflag && is_retr;
779
        if (sigsetjmp(recvabort, 1)) {
780
                while (cpend) {
781
                        (void) getreply(0);
782
                }
783
                if (data >= 0) {
784
                        (void) close(data);
785
                        data = -1;
786
                }
787
                if (oldintr)
788
                        (void) signal(SIGINT, oldintr);
789
                code = -1;
790
                return;
791
        }
792
        oldintr = signal(SIGINT, abortrecv);
793
        if (strcmp(local, "-") && *local != '|') {
794
                if (access(local, W_OK) < 0) {
795
                        char *dir = rindex(local, '/');
796
 
797
                        if (errno != ENOENT && errno != EACCES) {
798
                                fprintf(stderr, "local: %s: %s\n", local,
799
                                        strerror(errno));
800
                                (void) signal(SIGINT, oldintr);
801
                                code = -1;
802
                                return;
803
                        }
804
                        if (dir != NULL)
805
                                *dir = 0;
806
                        d = access(dir ? local : ".", W_OK);
807
                        if (dir != NULL)
808
                                *dir = '/';
809
                        if (d < 0) {
810
                                fprintf(stderr, "local: %s: %s\n", local,
811
                                        strerror(errno));
812
                                (void) signal(SIGINT, oldintr);
813
                                code = -1;
814
                                return;
815
                        }
816
                        if (!runique && errno == EACCES &&
817
                            chmod(local, 0600) < 0) {
818
                                fprintf(stderr, "local: %s: %s\n", local,
819
                                        strerror(errno));
820
                                /*
821
                                 * Believe it or not, this was actually
822
                                 * repeated in the original source.
823
                                 */
824
                                (void) signal(SIGINT, oldintr);
825
                                /*(void) signal(SIGINT, oldintr);*/
826
                                code = -1;
827
                                return;
828
                        }
829
                        if (runique && errno == EACCES &&
830
                           (local = gunique(local)) == NULL) {
831
                                (void) signal(SIGINT, oldintr);
832
                                code = -1;
833
                                return;
834
                        }
835
                }
836
                else if (runique && (local = gunique(local)) == NULL) {
837
                        (void) signal(SIGINT, oldintr);
838
                        code = -1;
839
                        return;
840
                }
841
        }
842
        if (!is_retr) {
843
                if (curtype != TYPE_A)
844
                        changetype(TYPE_A, 0);
845
        }
846
        else if (curtype != type) {
847
                changetype(type, 0);
848
        }
849
        if (initconn()) {
850
                (void) signal(SIGINT, oldintr);
851
                code = -1;
852
                return;
853
        }
854
        if (sigsetjmp(recvabort, 1))
855
                goto abort;
856
        if (is_retr && restart_point &&
857
            command("REST %ld", (long) restart_point) != CONTINUE)
858
                return;
859
        if (remote) {
860
                if (command("%s %s", cmd, remote) != PRELIM) {
861
                        (void) signal(SIGINT, oldintr);
862
                        return;
863
                }
864
        }
865
        else {
866
                if (command("%s", cmd) != PRELIM) {
867
                        (void) signal(SIGINT, oldintr);
868
                        return;
869
                }
870
        }
871
        din = dataconn("r");
872
        if (din == NULL)
873
                goto abort;
874
        if (strcmp(local, "-") == 0)
875
                fout = stdout;
876
        else if (*local == '|') {
877
                oldintp = signal(SIGPIPE, SIG_IGN);
878
                fout = popen(local + 1, "w");
879
                if (fout == NULL) {
880
                        perror(local+1);
881
                        goto abort;
882
                }
883
                closefunc = pclose;
884
        }
885
        else {
886
                fout = fopen(local, lmode);
887
                if (fout == NULL) {
888
                        fprintf(stderr, "local: %s: %s\n", local,
889
                                strerror(errno));
890
                        goto abort;
891
                }
892
                closefunc = fclose;
893
        }
894
        if (fstat(fileno(fout), &st) < 0 || st.st_blksize == 0)
895
                st.st_blksize = BUFSIZ;
896
        if (st.st_blksize > bufsize) {
897
                if (buf)
898
                        (void) free(buf);
899
                buf = malloc((unsigned)st.st_blksize);
900
                if (buf == NULL) {
901
                        perror("malloc");
902
                        bufsize = 0;
903
                        goto abort;
904
                }
905
                bufsize = st.st_blksize;
906
        }
907
        (void) gettimeofday(&start, (struct timezone *)0);
908
        switch (curtype) {
909
 
910
        case TYPE_I:
911
        case TYPE_L:
912
                if (restart_point &&
913
                    lseek(fileno(fout), (long) restart_point, L_SET) < 0) {
914
                        fprintf(stderr, "local: %s: %s\n", local,
915
                                strerror(errno));
916
                        if (closefunc != NULL)
917
                                (*closefunc)(fout);
918
                        return;
919
                }
920
                errno = d = 0;
921
                while ((c = read(fileno(din), buf, bufsize)) > 0) {
922
                        if ((d = write(fileno(fout), buf, c)) != c)
923
                                break;
924
                        bytes += c;
925
                        if (hash && is_retr) {
926
                                while (bytes >= hashbytes) {
927
                                        (void) putchar('#');
928
                                        hashbytes += HASHBYTES;
929
                                }
930
                                (void) fflush(stdout);
931
                        }
932
                        if (tick && (bytes >= hashbytes) && is_retr) {
933
                                (void) printf("\rBytes transferred: %ld",
934
                                        bytes);
935
                                (void) fflush(stdout);
936
                                while (bytes >= hashbytes)
937
                                        hashbytes += TICKBYTES;
938
                        }
939
                }
940
                if (hash && bytes > 0) {
941
                        if (bytes < HASHBYTES)
942
                                (void) putchar('#');
943
                        (void) putchar('\n');
944
                        (void) fflush(stdout);
945
                }
946
                if (tick && is_retr) {
947
                        (void) printf("\rBytes transferred: %ld\n", bytes);
948
                        (void) fflush(stdout);
949
                }
950
                if (c < 0) {
951
                        if (errno != EPIPE)
952
                                perror("netin");
953
                        bytes = -1;
954
                }
955
                if (d < c) {
956
                        if (d < 0)
957
                                fprintf(stderr, "local: %s: %s\n", local,
958
                                        strerror(errno));
959
                        else
960
                                fprintf(stderr, "%s: short write\n", local);
961
                }
962
                break;
963
 
964
        case TYPE_A:
965
                if (restart_point) {
966
                        register int i, n, ch;
967
 
968
                        if (fseek(fout, 0L, L_SET) < 0)
969
                                goto done;
970
                        n = restart_point;
971
                        for (i = 0; i++ < n;) {
972
                                if ((ch = getc(fout)) == EOF)
973
                                        goto done;
974
                                if (ch == '\n')
975
                                        i++;
976
                        }
977
                        if (fseek(fout, 0L, L_INCR) < 0) {
978
done:
979
                                fprintf(stderr, "local: %s: %s\n", local,
980
                                        strerror(errno));
981
                                if (closefunc != NULL)
982
                                        (*closefunc)(fout);
983
                                return;
984
                        }
985
                }
986
                while ((c = getc(din)) != EOF) {
987
                        if (c == '\n')
988
                                bare_lfs++;
989
                        while (c == '\r') {
990
                                while (hash && (bytes >= hashbytes)
991
                                        && is_retr) {
992
                                        (void) putchar('#');
993
                                        (void) fflush(stdout);
994
                                        hashbytes += HASHBYTES;
995
                                }
996
                                if (tick && (bytes >= hashbytes) && is_retr) {
997
                                        printf("\rBytes transferred: %ld",
998
                                                bytes);
999
                                        fflush(stdout);
1000
                                        while (bytes >= hashbytes)
1001
                                                hashbytes += TICKBYTES;
1002
                                }
1003
                                bytes++;
1004
                                if ((c = getc(din)) != '\n' || tcrflag) {
1005
                                        if (ferror(fout))
1006
                                                goto break2;
1007
                                        (void) putc('\r', fout);
1008
                                        if (c == '\0') {
1009
                                                bytes++;
1010
                                                goto contin2;
1011
                                        }
1012
                                        if (c == EOF)
1013
                                                goto contin2;
1014
                                }
1015
                        }
1016
                        (void) putc(c, fout);
1017
                        bytes++;
1018
        contin2:        ;
1019
                }
1020
break2:
1021
                if (hash && is_retr) {
1022
                        if (bytes < hashbytes)
1023
                                (void) putchar('#');
1024
                        (void) putchar('\n');
1025
                        (void) fflush(stdout);
1026
                }
1027
                if (tick && is_retr) {
1028
                        (void) printf("\rBytes transferred: %ld\n", bytes);
1029
                        (void) fflush(stdout);
1030
                }
1031
                if (bare_lfs) {
1032
                        printf("WARNING! %d bare linefeeds received in ASCII mode\n", bare_lfs);
1033
                        printf("File may not have transferred correctly.\n");
1034
                }
1035
                if (ferror(din)) {
1036
                        if (errno != EPIPE)
1037
                                perror("netin");
1038
                        bytes = -1;
1039
                }
1040
                if (ferror(fout))
1041
                        fprintf(stderr, "local: %s: %s\n", local,
1042
                                strerror(errno));
1043
                break;
1044
        }
1045
        if (closefunc != NULL)
1046
                (*closefunc)(fout);
1047
        (void) signal(SIGINT, oldintr);
1048
        if (oldintp)
1049
                (void) signal(SIGPIPE, oldintp);
1050
        (void) gettimeofday(&stop, (struct timezone *)0);
1051
        (void) fclose(din);
1052
        /* closes data as well, so discard it */
1053
        data = -1;
1054
        (void) getreply(0);
1055
        if (bytes > 0 && is_retr)
1056
                ptransfer("received", bytes, &start, &stop);
1057
        return;
1058
abort:
1059
 
1060
/* abort using RFC959 recommended IP,SYNC sequence  */
1061
 
1062
        (void) gettimeofday(&stop, (struct timezone *)0);
1063
        if (oldintp)
1064
                (void) signal(SIGPIPE, oldintp);
1065
        (void) signal(SIGINT, SIG_IGN);
1066
        if (!cpend) {
1067
                code = -1;
1068
                (void) signal(SIGINT, oldintr);
1069
                return;
1070
        }
1071
 
1072
        abort_remote(din);
1073
        code = -1;
1074
        if (closefunc != NULL && fout != NULL)
1075
                (*closefunc)(fout);
1076
        if (din) {
1077
                (void) fclose(din);
1078
        }
1079
        if (data >= 0) {
1080
                /* if it just got closed with din, again won't hurt */
1081
                (void) close(data);
1082
                data = -1;
1083
        }
1084
        if (bytes > 0)
1085
                ptransfer("received", bytes, &start, &stop);
1086
        (void) signal(SIGINT, oldintr);
1087
}
1088
 
1089
/*
1090
 * Need to start a listen on the data channel before we send the command,
1091
 * otherwise the server's connect may fail.
1092
 */
1093
static int
1094
initconn(void)
1095
{
1096
        register char *p, *a;
1097
        int result, tmpno = 0;
1098
        socklen_t len;
1099
        int on = 1;
1100
        int tos;
1101
        u_long a1,a2,a3,a4,p1,p2;
1102
 
1103
        if (passivemode) {
1104
                data = socket(AF_INET, SOCK_STREAM, 0);
1105
                if (data < 0) {
1106
                        perror("ftp: socket");
1107
                        return(1);
1108
                }
1109
                if (options & SO_DEBUG &&
1110
                    setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on,
1111
                               sizeof (on)) < 0)
1112
                        perror("ftp: setsockopt (ignored)");
1113
                if (command("PASV") != COMPLETE) {
1114
                        printf("Passive mode refused.\n");
1115
                        return(1);
1116
                }
1117
 
1118
                /*
1119
                 * What we've got at this point is a string of comma separated
1120
                 * one-byte unsigned integer values, separated by commas.
1121
                 * The first four are the an IP address. The fifth is the MSB
1122
                 * of the port number, the sixth is the LSB. From that we'll
1123
                 * prepare a sockaddr_in.
1124
                 */
1125
 
1126
                if (sscanf(pasv,"%ld,%ld,%ld,%ld,%ld,%ld",
1127
                           &a1,&a2,&a3,&a4,&p1,&p2)
1128
                    != 6)
1129
                {
1130
                        printf("Passive mode address scan failure. Shouldn't happen!\n");
1131
                        return(1);
1132
                }
1133
 
1134
                data_addr.sin_family = AF_INET;
1135
                data_addr.sin_addr.s_addr = htonl((a1 << 24) | (a2 << 16) |
1136
                                                  (a3 << 8) | a4);
1137
                data_addr.sin_port = htons((p1 << 8) | p2);
1138
 
1139
                if (connect(data, (struct sockaddr *) &data_addr,
1140
                    sizeof(data_addr))<0) {
1141
                        perror("ftp: connect");
1142
                        return(1);
1143
                }
1144
#ifdef IP_TOS
1145
                tos = IPTOS_THROUGHPUT;
1146
                if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&tos,
1147
                    sizeof(tos)) < 0)
1148
                        perror("ftp: setsockopt TOS (ignored)");
1149
#endif
1150
                return(0);
1151
        }
1152
noport:
1153
        data_addr = myctladdr;
1154
        if (sendport)
1155
                data_addr.sin_port = 0;  /* let system pick one */
1156
        if (data != -1)
1157
                (void) close(data);
1158
        data = socket(AF_INET, SOCK_STREAM, 0);
1159
        if (data < 0) {
1160
                perror("ftp: socket");
1161
                if (tmpno)
1162
                        sendport = 1;
1163
                return (1);
1164
        }
1165
        if (!sendport)
1166
                if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof (on)) < 0) {
1167
                        perror("ftp: setsockopt (reuse address)");
1168
                        goto bad;
1169
                }
1170
        if (bind(data, (struct sockaddr *)&data_addr, sizeof (data_addr)) < 0) {
1171
                perror("ftp: bind");
1172
                goto bad;
1173
        }
1174
        if (options & SO_DEBUG &&
1175
            setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof (on)) < 0)
1176
                perror("ftp: setsockopt (ignored)");
1177
        len = sizeof (data_addr);
1178
        if (getsockname(data, (struct sockaddr *)&data_addr, &len) < 0) {
1179
                perror("ftp: getsockname");
1180
                goto bad;
1181
        }
1182
        if (listen(data, 1) < 0)
1183
                perror("ftp: listen");
1184
        if (sendport) {
1185
                a = (char *)&data_addr.sin_addr;
1186
                p = (char *)&data_addr.sin_port;
1187
#define UC(b)   (((int)b)&0xff)
1188
                result =
1189
                    command("PORT %d,%d,%d,%d,%d,%d",
1190
                      UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]),
1191
                      UC(p[0]), UC(p[1]));
1192
                if (result == ERROR && sendport == -1) {
1193
                        sendport = 0;
1194
                        tmpno = 1;
1195
                        goto noport;
1196
                }
1197
                return (result != COMPLETE);
1198
        }
1199
        if (tmpno)
1200
                sendport = 1;
1201
#ifdef IP_TOS
1202
        on = IPTOS_THROUGHPUT;
1203
        if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int)) < 0)
1204
                perror("ftp: setsockopt TOS (ignored)");
1205
#endif
1206
        return (0);
1207
bad:
1208
        (void) close(data), data = -1;
1209
        if (tmpno)
1210
                sendport = 1;
1211
        return (1);
1212
}
1213
 
1214
static FILE *
1215
dataconn(const char *lmode)
1216
{
1217
        struct sockaddr_in from;
1218
        int s, tos;
1219
        socklen_t fromlen = sizeof(from);
1220
 
1221
        if (passivemode)
1222
            return (fdopen(data, lmode));
1223
 
1224
        s = accept(data, (struct sockaddr *) &from, &fromlen);
1225
        if (s < 0) {
1226
                perror("ftp: accept");
1227
                (void) close(data), data = -1;
1228
                return (NULL);
1229
        }
1230
        (void) close(data);
1231
        data = s;
1232
#ifdef IP_TOS
1233
        tos = IPTOS_THROUGHPUT;
1234
        if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0)
1235
                perror("ftp: setsockopt TOS (ignored)");
1236
#endif
1237
        return (fdopen(data, lmode));
1238
}
1239
 
1240
static void
1241
ptransfer(const char *direction, long bytes,
1242
          const struct timeval *t0,
1243
          const struct timeval *t1)
1244
{
1245
        struct timeval td;
1246
#ifdef EMBED
1247
        /* Use all ints for embedded targets */
1248
        unsigned long s, bs;
1249
 
1250
        if (verbose) {
1251
                tvsub(&td, t1, t0);
1252
                s = (td.tv_sec * 1000) + (td.tv_usec / 1000);
1253
#define nz(x)   ((x) == 0 ? 1 : (x))
1254
                bs = bytes / nz(s);
1255
                printf("%ld bytes %s in %d secs (%d Kbytes/sec)\n",
1256
                    bytes, direction, (s/1000), bs);
1257
        }
1258
#else
1259
        float s, bs;
1260
 
1261
        if (verbose) {
1262
                tvsub(&td, t1, t0);
1263
                s = td.tv_sec + (td.tv_usec / 1000000.);
1264
#define nz(x)   ((x) == 0 ? 1 : (x))
1265
                bs = bytes / nz(s);
1266
                printf("%ld bytes %s in %.3g secs (%.2g Kbytes/sec)\n",
1267
                    bytes, direction, s, bs / 1024.0);
1268
        }
1269
#endif
1270
}
1271
 
1272
#if 0
1273
tvadd(tsum, t0)
1274
        struct timeval *tsum, *t0;
1275
{
1276
 
1277
        tsum->tv_sec += t0->tv_sec;
1278
        tsum->tv_usec += t0->tv_usec;
1279
        if (tsum->tv_usec > 1000000)
1280
                tsum->tv_sec++, tsum->tv_usec -= 1000000;
1281
}
1282
#endif
1283
 
1284
static void
1285
tvsub(struct timeval *tdiff,
1286
      const struct timeval *t1,
1287
      const struct timeval *t0)
1288
{
1289
 
1290
        tdiff->tv_sec = t1->tv_sec - t0->tv_sec;
1291
        tdiff->tv_usec = t1->tv_usec - t0->tv_usec;
1292
        if (tdiff->tv_usec < 0)
1293
                tdiff->tv_sec--, tdiff->tv_usec += 1000000;
1294
}
1295
 
1296
static
1297
void
1298
psabort(int ignore)
1299
{
1300
        (void)ignore;
1301
        abrtflag++;
1302
}
1303
 
1304
void
1305
pswitch(int flag)
1306
{
1307
        void (*oldintr)(int);
1308
        static struct comvars {
1309
                int connect;
1310
                char name[MAXHOSTNAMELEN];
1311
                struct sockaddr_in mctl;
1312
                struct sockaddr_in hctl;
1313
                FILE *in;
1314
                FILE *out;
1315
                int tpe;
1316
                int curtpe;
1317
                int cpnd;
1318
                int sunqe;
1319
                int runqe;
1320
                int mcse;
1321
                int ntflg;
1322
                char nti[17];
1323
                char nto[17];
1324
                int mapflg;
1325
                char mi[MAXPATHLEN];
1326
                char mo[MAXPATHLEN];
1327
        } proxstruct, tmpstruct;
1328
        struct comvars *ip, *op;
1329
 
1330
        abrtflag = 0;
1331
        oldintr = signal(SIGINT, psabort);
1332
        if (flag) {
1333
                if (proxy)
1334
                        return;
1335
                ip = &tmpstruct;
1336
                op = &proxstruct;
1337
                proxy++;
1338
        }
1339
        else {
1340
                if (!proxy)
1341
                        return;
1342
                ip = &proxstruct;
1343
                op = &tmpstruct;
1344
                proxy = 0;
1345
        }
1346
        ip->connect = connected;
1347
        connected = op->connect;
1348
        if (hostname) {
1349
                (void) strncpy(ip->name, hostname, sizeof(ip->name) - 1);
1350
                ip->name[strlen(ip->name)] = '\0';
1351
        }
1352
        else {
1353
                ip->name[0] = 0;
1354
        }
1355
        hostname = op->name;
1356
        ip->hctl = hisctladdr;
1357
        hisctladdr = op->hctl;
1358
        ip->mctl = myctladdr;
1359
        myctladdr = op->mctl;
1360
        ip->in = cin;
1361
        cin = op->in;
1362
        ip->out = cout;
1363
        cout = op->out;
1364
        ip->tpe = type;
1365
        type = op->tpe;
1366
        ip->curtpe = curtype;
1367
        curtype = op->curtpe;
1368
        ip->cpnd = cpend;
1369
        cpend = op->cpnd;
1370
        ip->sunqe = sunique;
1371
        sunique = op->sunqe;
1372
        ip->runqe = runique;
1373
        runique = op->runqe;
1374
        ip->mcse = mcase;
1375
        mcase = op->mcse;
1376
        ip->ntflg = ntflag;
1377
        ntflag = op->ntflg;
1378
        (void) strncpy(ip->nti, ntin, 16);
1379
        (ip->nti)[strlen(ip->nti)] = '\0';
1380
        (void) strcpy(ntin, op->nti);
1381
        (void) strncpy(ip->nto, ntout, 16);
1382
        (ip->nto)[strlen(ip->nto)] = '\0';
1383
        (void) strcpy(ntout, op->nto);
1384
        ip->mapflg = mapflag;
1385
        mapflag = op->mapflg;
1386
        (void) strncpy(ip->mi, mapin, MAXPATHLEN - 1);
1387
        (ip->mi)[strlen(ip->mi)] = '\0';
1388
        (void) strcpy(mapin, op->mi);
1389
        (void) strncpy(ip->mo, mapout, MAXPATHLEN - 1);
1390
        (ip->mo)[strlen(ip->mo)] = '\0';
1391
        (void) strcpy(mapout, op->mo);
1392
        (void) signal(SIGINT, oldintr);
1393
        if (abrtflag) {
1394
                abrtflag = 0;
1395
                (*oldintr)(SIGINT);
1396
        }
1397
}
1398
 
1399
static
1400
void
1401
abortpt(int ignore)
1402
{
1403
        (void)ignore;
1404
        printf("\n");
1405
        fflush(stdout);
1406
        ptabflg++;
1407
        mflag = 0;
1408
        abrtflag = 0;
1409
        siglongjmp(ptabort, 1);
1410
}
1411
 
1412
static void
1413
proxtrans(const char *cmd, char *local, char *remote)
1414
{
1415
        void (*volatile oldintr)(int);
1416
        volatile int secndflag = 0, prox_type, nfnd;
1417
        const char *volatile cmd2;
1418
        fd_set mask;
1419
 
1420
        if (strcmp(cmd, "RETR"))
1421
                cmd2 = "RETR";
1422
        else
1423
                cmd2 = runique ? "STOU" : "STOR";
1424
        if ((prox_type = type) == 0) {
1425
                if (unix_server && unix_proxy)
1426
                        prox_type = TYPE_I;
1427
                else
1428
                        prox_type = TYPE_A;
1429
        }
1430
        if (curtype != prox_type)
1431
                changetype(prox_type, 1);
1432
        if (command("PASV") != COMPLETE) {
1433
                printf("proxy server does not support third party transfers.\n");
1434
                return;
1435
        }
1436
        pswitch(0);
1437
        if (!connected) {
1438
                printf("No primary connection\n");
1439
                pswitch(1);
1440
                code = -1;
1441
                return;
1442
        }
1443
        if (curtype != prox_type)
1444
                changetype(prox_type, 1);
1445
        if (command("PORT %s", pasv) != COMPLETE) {
1446
                pswitch(1);
1447
                return;
1448
        }
1449
        if (sigsetjmp(ptabort, 1))
1450
                goto abort;
1451
        oldintr = signal(SIGINT, abortpt);
1452
        if (command("%s %s", cmd, remote) != PRELIM) {
1453
                (void) signal(SIGINT, oldintr);
1454
                pswitch(1);
1455
                return;
1456
        }
1457
        sleep(2);
1458
        pswitch(1);
1459
        secndflag++;
1460
        if (command("%s %s", cmd2, local) != PRELIM)
1461
                goto abort;
1462
        ptflag++;
1463
        (void) getreply(0);
1464
        pswitch(0);
1465
        (void) getreply(0);
1466
        (void) signal(SIGINT, oldintr);
1467
        pswitch(1);
1468
        ptflag = 0;
1469
        printf("local: %s remote: %s\n", local, remote);
1470
        return;
1471
abort:
1472
        (void) signal(SIGINT, SIG_IGN);
1473
        ptflag = 0;
1474
        if (strcmp(cmd, "RETR") && !proxy)
1475
                pswitch(1);
1476
        else if (!strcmp(cmd, "RETR") && proxy)
1477
                pswitch(0);
1478
        if (!cpend && !secndflag) {  /* only here if cmd = "STOR" (proxy=1) */
1479
                if (command("%s %s", cmd2, local) != PRELIM) {
1480
                        pswitch(0);
1481
                        if (cpend)
1482
                                abort_remote((FILE *) NULL);
1483
                }
1484
                pswitch(1);
1485
                if (ptabflg)
1486
                        code = -1;
1487
                (void) signal(SIGINT, oldintr);
1488
                return;
1489
        }
1490
        if (cpend)
1491
                abort_remote((FILE *) NULL);
1492
        pswitch(!proxy);
1493
        if (!cpend && !secndflag) {  /* only if cmd = "RETR" (proxy=1) */
1494
                if (command("%s %s", cmd2, local) != PRELIM) {
1495
                        pswitch(0);
1496
                        if (cpend)
1497
                                abort_remote((FILE *) NULL);
1498
                        pswitch(1);
1499
                        if (ptabflg)
1500
                                code = -1;
1501
                        (void) signal(SIGINT, oldintr);
1502
                        return;
1503
                }
1504
        }
1505
        if (cpend)
1506
                abort_remote((FILE *) NULL);
1507
        pswitch(!proxy);
1508
        if (cpend) {
1509
                FD_ZERO(&mask);
1510
                FD_SET(fileno(cin), &mask);
1511
                if ((nfnd = empty(&mask, fileno(cin), 10)) <= 0) {
1512
                        if (nfnd < 0) {
1513
                                perror("abort");
1514
                        }
1515
                        if (ptabflg)
1516
                                code = -1;
1517
                        lostpeer(0);
1518
                }
1519
                (void) getreply(0);
1520
                (void) getreply(0);
1521
        }
1522
        if (proxy)
1523
                pswitch(0);
1524
        pswitch(1);
1525
        if (ptabflg)
1526
                code = -1;
1527
        (void) signal(SIGINT, oldintr);
1528
}
1529
 
1530
void
1531
reset(void)
1532
{
1533
        fd_set mask;
1534
        int nfnd = 1;
1535
 
1536
        FD_ZERO(&mask);
1537
        while (nfnd > 0) {
1538
                FD_SET(fileno(cin), &mask);
1539
                if ((nfnd = empty(&mask, fileno(cin), 0)) < 0) {
1540
                        perror("reset");
1541
                        code = -1;
1542
                        lostpeer(0);
1543
                }
1544
                else if (nfnd) {
1545
                        (void) getreply(0);
1546
                }
1547
        }
1548
}
1549
 
1550
static char *
1551
gunique(char *local)
1552
{
1553
        static char new[MAXPATHLEN];
1554
        char *cp = rindex(local, '/');
1555
        int d, count=0;
1556
        char ext = '1';
1557
 
1558
        if (cp)
1559
                *cp = '\0';
1560
        d = access(cp ? local : ".", W_OK);
1561
        if (cp)
1562
                *cp = '/';
1563
        if (d < 0) {
1564
                fprintf(stderr, "local: %s: %s\n", local, strerror(errno));
1565
                return((char *) 0);
1566
        }
1567
        (void) strcpy(new, local);
1568
        cp = new + strlen(new);
1569
        *cp++ = '.';
1570
        while (!d) {
1571
                if (++count == 100) {
1572
                        printf("runique: can't find unique file name.\n");
1573
                        return((char *) 0);
1574
                }
1575
                *cp++ = ext;
1576
                *cp = '\0';
1577
                if (ext == '9')
1578
                        ext = '0';
1579
                else
1580
                        ext++;
1581
                if ((d = access(new, F_OK)) < 0)
1582
                        break;
1583
                if (ext != '0')
1584
                        cp--;
1585
                else if (*(cp - 2) == '.')
1586
                        *(cp - 1) = '1';
1587
                else {
1588
                        *(cp - 2) = *(cp - 2) + 1;
1589
                        cp--;
1590
                }
1591
        }
1592
        return(new);
1593
}
1594
 
1595
static void
1596
abort_remote(FILE *din)
1597
{
1598
        char buf[BUFSIZ];
1599
        int nfnd, hifd;
1600
        fd_set mask;
1601
 
1602
        /*
1603
         * send IAC in urgent mode instead of DM because 4.3BSD places oob mark
1604
         * after urgent byte rather than before as is protocol now
1605
         */
1606
        snprintf(buf, sizeof(buf), "%c%c%c", IAC, IP, IAC);
1607
        if (send(fileno(cout), buf, 3, MSG_OOB) != 3)
1608
                perror("abort");
1609
        fprintf(cout,"%cABOR\r\n", DM);
1610
        (void) fflush(cout);
1611
        FD_ZERO(&mask);
1612
        FD_SET(fileno(cin), &mask);
1613
        hifd = fileno(cin);
1614
        if (din) {
1615
                FD_SET(fileno(din), &mask);
1616
                if (hifd < fileno(din)) hifd = fileno(din);
1617
        }
1618
        if ((nfnd = empty(&mask, hifd, 10)) <= 0) {
1619
                if (nfnd < 0) {
1620
                        perror("abort");
1621
                }
1622
                if (ptabflg)
1623
                        code = -1;
1624
                lostpeer(0);
1625
        }
1626
        if (din && FD_ISSET(fileno(din), &mask)) {
1627
                while (read(fileno(din), buf, BUFSIZ) > 0)
1628
                        /* LOOP */;
1629
        }
1630
        if (getreply(0) == ERROR && code == 552) {
1631
                /* 552 needed for nic style abort */
1632
                (void) getreply(0);
1633
        }
1634
        (void) getreply(0);
1635
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.