www.pudn.com > socks5.zip > main.c


/* 
 * Copyright (c) 1985, 1989 Regents of the University of California. 
 * All rights reserved. 
 * 
 * Redistribution and use in source and binary forms, with or without 
 * modification, are permitted provided that the following conditions 
 * are met: 
 * 1. Redistributions of source code must retain the above copyright 
 *    notice, this list of conditions and the following disclaimer. 
 * 2. Redistributions in binary form must reproduce the above copyright 
 *    notice, this list of conditions and the following disclaimer in the 
 *    documentation and/or other materials provided with the distribution. 
 * 3. All advertising materials mentioning features or use of this software 
 *    must display the following acknowledgement: 
 *	This product includes software developed by the University of 
 *	California, Berkeley and its contributors. 
 * 4. Neither the name of the University nor the names of its contributors 
 *    may be used to endorse or promote products derived from this software 
 *    without specific prior written permission. 
 * 
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
 * SUCH DAMAGE. 
 */ 
 
#ifndef lint 
char copyright[] =  
"@(#) Copyright (c) 1985, 1989 Regents of the University of California.\n\ 
 All rights reserved.\n"; 
#endif /* not lint */ 
 
/* 
 * FTP User Program -- Command Interface. 
 */ 
 
#include "ftp_var.h" 
 
#define DONT_NEED_SIGBLOCK 
#define DONT_NEED_SIGPAUSE 
#define DONT_NEED_SIGUNBLOCK 
#define DONT_NEED_SIGPENDING 
#include "sigfix.h" 
 
#include  
#include  
#include  
#include  
 
uid_t	getuid(); 
void	intr(), lostpeer(); 
extern	char *home; 
char	*getlogin(); 
 
#define HELPINDENT (sizeof ("directory")) 
 
struct cmd *getcmd(register char *name) { 
    extern struct cmd cmdtab[]; 
    register char *p, *q; 
    register struct cmd *c, *found; 
    register int nmatches, longest; 
     
    longest = 0; 
    nmatches = 0; 
    found = 0; 
    for (c = cmdtab; (p = c->c_name); c++) { 
	for (q = name; *q == *p++; q++) 
	    if (*q == 0)		/* exact match? */ 
		return (c); 
	if (!*q) {			/* the name was a prefix */ 
	    if (q - name > longest) { 
		longest = q - name; 
		nmatches = 1; 
		found = c; 
	    } else if (q - name == longest) 
		nmatches++; 
	} 
    } 
     
    if (nmatches > 1) return ((struct cmd *)-1); 
    return (found); 
} 
 
/* 
 * Help command. 
 * Call each command handler with argc == 0 and argv[0] == name. 
 */ 
void help(int argc, char *argv[]) { 
    extern struct cmd cmdtab[]; 
    register struct cmd *c; 
     
    if (argc == 1) { 
	register int i, j, w, k; 
	int columns, width = 0, lines; 
	extern int NCMDS; 
	 
	printf("Commands may be abbreviated.  Commands are:\n\n"); 
	for (c = cmdtab; c < &cmdtab[NCMDS]; c++) { 
	    int len = strlen(c->c_name); 
	     
	    if (len > width) 
		width = len; 
	} 
	width = (width + 8) &~ 7; 
	columns = 80 / width; 
	if (columns == 0) 
	    columns = 1; 
	lines = (NCMDS + columns - 1) / columns; 
	for (i = 0; i < lines; i++) { 
	    for (j = 0; j < columns; j++) { 
		c = cmdtab + j * lines + i; 
		if (c->c_name && (!proxy || c->c_proxy))  
		    printf("%s", c->c_name); 
		else if (c->c_name)  
		    for (k=0; k < strlen(c->c_name); k++) 
			putchar(' '); 
		 
		if (c + lines >= &cmdtab[NCMDS]) { 
		    printf("\n"); 
		    break; 
		} 
		w = strlen(c->c_name); 
		while (w < width) { 
		    w = (w + 8) &~ 7; 
		    putchar('\t'); 
		} 
	    } 
	} 
	return; 
    } 
    while (--argc > 0) { 
	register char *arg; 
	arg = *++argv; 
	c = getcmd(arg); 
	if (c == (struct cmd *)-1) 
	    printf("?Ambiguous help command %s\n", arg); 
	else if (c == (struct cmd *)0) 
	    printf("?Invalid help command %s\n", arg); 
	else 
	    printf("%-*s\t%s\n", HELPINDENT, 
		   c->c_name, c->c_help); 
    } 
} 
 
/* 
 * Command parser. 
 */ 
void cmdscanner(int top) { 
    register struct cmd *c; 
    register int l; 
     
    if (!top) 
	putchar('\n'); 
    for (;;) { 
	if (fromatty) { 
	    printf("ftp> "); 
	    fflush(stdout); 
	} 
	if (fgets(line, sizeof line, stdin) == NULL) 
	    quit(); 
	l = strlen(line); 
	if (l == 0) 
	    break; 
	if (line[--l] == '\n') { 
	    if (l == 0) 
		break; 
	    line[l] = '\0'; 
	} else if (l == sizeof(line) - 2) { 
	    printf("sorry, input line too long\n"); 
	    while ((l = getchar()) != '\n' && l != EOF) 
		/* void */; 
	    break; 
	} /* else it was a line without a newline */ 
	makeargv(); 
	if (margc == 0) { 
	    continue; 
	} 
	c = getcmd(margv[0]); 
	if (c == (struct cmd *)-1) { 
	    printf("?Ambiguous command\n"); 
	    continue; 
	} 
	if (c == 0) { 
	    printf("?Invalid command\n"); 
	    continue; 
	} 
	if (c->c_conn && !connected) { 
	    printf("Not connected.\n"); 
	    continue; 
	} 
	(*c->c_handler)(margc, margv); 
	if (bell && c->c_bell) 
	    putchar('\007'); 
	if (c->c_handler != (int (*)())help) 
	    break; 
    } 
 
    Signal(SIGINT,  intr); 
    Signal(SIGPIPE, lostpeer); 
} 
 
void intr() { 
    longjmp(toplevel, 1); 
} 
 
void lostpeer() { 
    extern FILE *cout; 
    extern int data; 
 
    if (connected) { 
	if (cout != NULL) { 
	    shutdown(fileno(cout), 1+1); 
	    fclose(cout); 
	    cout = NULL; 
	} 
 
	if (data >= 0) { 
	    shutdown(data, 1+1); 
	    close(data); 
	    data = -1; 
	} 
 
	connected = 0; 
    } 
 
    pswitch(1); 
 
    if (connected) { 
	if (cout != NULL) { 
	    shutdown(fileno(cout), 1+1); 
	    fclose(cout); 
	    cout = NULL; 
	} 
 
	connected = 0; 
    } 
 
    proxflag = 0; 
    pswitch(0); 
} 
 
/* 
 * Slice a string up into argc/argv. 
 */ 
 
int slrflag; 
 
/* 
 * Parse string into argbuf; 
 * implemented with FSM to 
 * handle quoting and strings 
 */ 
char *slurpstring() { 
    int got_one = 0; 
    register char *sb = stringbase; 
    register char *ap = argbase; 
    char *tmp = argbase;		/* will return this if token found */ 
     
    if (*sb == '!' || *sb == '$') {	/* recognize ! as a token for shell */ 
	switch (slrflag) {	         /* and $ as token for macro invoke */ 
	    case 0: 
		slrflag++; 
		stringbase++; 
		return ((*sb == '!') ? "!" : "$"); 
		/* NOTREACHED */ 
	    case 1: 
		slrflag++; 
		altarg = stringbase; 
		break; 
	    default: 
		break; 
	} 
    } 
     
  S0: 
    switch (*sb) { 
	case '\0': 
	    goto OUT; 
	     
	case ' ': 
	case '\t': 
	    sb++; goto S0; 
 
	default: 
	    switch (slrflag) { 
		case 0: 
		    slrflag++; 
		    break; 
		case 1: 
		    slrflag++; 
		    altarg = sb; 
		    break; 
		default: 
		    break; 
	    } 
 
		    goto S1; 
    } 
     
  S1: 
    switch (*sb) { 
	case ' ': 
	case '\t': 
	case '\0': 
	    goto OUT;	/* end of token */ 
	     
	case '\\': 
	    sb++; goto S2;	/* slurp next character */ 
	     
	case '"': 
	    sb++; goto S3;	/* slurp quoted string */ 
	     
	default: 
	    *ap++ = *sb++;	/* add character to token */ 
	    got_one = 1; 
	    goto S1; 
    } 
     
  S2: 
    switch (*sb) { 
	case '\0': 
	    goto OUT; 
	     
	default: 
	    *ap++ = *sb++; 
	    got_one = 1; 
	    goto S1; 
    } 
     
  S3: 
    switch (*sb) { 
	case '\0': 
	    goto OUT; 
	     
	case '"': 
	    sb++; goto S1; 
	     
	default: 
	    *ap++ = *sb++; 
	    got_one = 1; 
	    goto S3; 
	} 
 
  OUT: 
    if (got_one) { 
	*ap++ = '\0'; 
    } 
 
    argbase = ap;			/* update storage pointer */ 
    stringbase = sb;		        /* update scan pointer */ 
    if (got_one) { 
	return(tmp); 
    } 
 
    switch (slrflag) { 
	case 0: 
	    slrflag++; 
	    break; 
	case 1: 
	    slrflag++; 
	    altarg = (char *) 0; 
	    break; 
	default: 
	    break; 
    } 
 
    return((char *)0); 
} 
 
void makeargv() { 
    char **argp; 
     
    margc = 0; 
    argp = margv; 
    stringbase = line;		/* scan from first of buffer */ 
    argbase = argbuf;		/* store from first of buffer */ 
    slrflag = 0; 
 
    while ((*argp++ = slurpstring())) margc++; 
} 
 
int main(int argc, char *argv[]) { 
    register char *cp; 
    struct passwd *pw = NULL; 
    char homedir[MAXPATHLEN]; 
    int top; 
     
#ifdef SOCKS 
    LIBPREFIX2(init)(argv[0]); 
#endif 
     
#ifdef FASCIST 
    fprintf(stderr,"***NOTE: Names of all files transferred will be recorded! \n"); 
#endif 
     
    if ((sp = getservbyname("ftp", "tcp")) == 0) { 
	fprintf(stderr, "ftp: ftp/tcp: unknown service\n"); 
	exit(1); 
    } 
 
    /* save ftp's s_port value so it won't be clobbered by by another call   */ 
    /* to getserbyname()                                                     */ 
    ftp_s_port = sp->s_port; 
    doglob = 1; 
    interactive = 1; 
    autologin = 1; 
    argc--, argv++; 
 
    while (argc > 0 && **argv == '-') { 
	for (cp = *argv + 1; *cp; cp++) 
	    switch (*cp) { 
		case 'd': 
		    options |= SO_DEBUG; 
		    debug++; 
		    break; 
			 
		case 'v': 
		    verbose++; 
		    break; 
		     
		case 't': 
		    trace++; 
		    break; 
		     
		case 'i': 
		    interactive = 0; 
		    break; 
		     
		case 'n': 
		    autologin = 0; 
		    break; 
		     
		case 'g': 
		    doglob = 0; 
		    break; 
		     
		default: 
		    fprintf(stdout, "ftp: %c: unknown option\n", *cp); 
		    exit(1); 
	    } 
 
	argc--, argv++; 
    } 
 
    fromatty = isatty(fileno(stdin)); 
    if (fromatty) verbose++; 
 
    cpend = 0;	/* no pending replies */ 
    proxy = 0;	/* proxy not active */ 
    crflag = 1;	/* strip c.r. on ascii gets */ 
    sendport = -1;	/* not using ports */ 
 
    /*  Set up the home directory in case we're globbing.                    */ 
    if ((cp = getlogin()) != NULL) { 
	pw = getpwnam(cp); 
    } 
 
    if (pw == NULL) { 
	pw = getpwuid(getuid()); 
    } 
 
    if (pw != NULL) { 
	home = homedir; 
	strcpy(home, pw->pw_dir); 
    } 
 
    if (argc > 0) { 
	if (setjmp(toplevel)) exit(0); 
	Signal(SIGINT, intr); 
	Signal(SIGPIPE, lostpeer); 
	setpeer(argc + 1, argv - 1); 
    } 
 
    top = setjmp(toplevel) == 0; 
 
    if (top) { 
	Signal(SIGINT, intr); 
	Signal(SIGPIPE, lostpeer); 
    } 
 
    for (;;) { 
	cmdscanner(top); 
	top = 1; 
    } 
}