Exemplo n.º 1
0
void * pop3pchild(void * data) {
#define param ((struct clientparam*)data)
 int i=0, res;
 unsigned char buf[320];
 unsigned char *se;

 if(socksend(param->clisock, (unsigned char *)"+OK Proxy\r\n", 11, conf.timeouts[STRING_S])!=11) {RETURN (611);}
 i = sockgetlinebuf(param, CLIENT, buf, sizeof(buf) - 10, '\n', conf.timeouts[STRING_S]);
 while(i > 4 && strncasecmp((char *)buf, "USER", 4)){
	if(!strncasecmp((char *)buf, "QUIT", 4)){
		socksend(param->clisock, (unsigned char *)"+OK\r\n", 5,conf.timeouts[STRING_S]);	
		RETURN(0);
	}
	socksend(param->clisock, (unsigned char *)"-ERR need USER first\r\n", 22, conf.timeouts[STRING_S]);	
	i = sockgetlinebuf(param, CLIENT, buf, sizeof(buf) - 10, '\n', conf.timeouts[STRING_S]);
 }
 if(i<6) {RETURN(612);}
 
 buf[i] = 0;
 if ((se=(unsigned char *)strchr((char *)buf, '\r'))) *se = 0;
 if (strncasecmp((char *)buf, "USER ", 5)){RETURN (614);}
 if(!param->hostname && param->remsock == INVALID_SOCKET) {
	if(parseconnusername((char *)buf +5, param, 0, 110)){RETURN(615);}
 }
 else if(parseusername((char *)buf + 5, param, 0)) {RETURN(616);}
 param->operation = CONNECT;
 res = (*param->authfunc)(param);
 if(res) {RETURN(res);}
 i = sockgetlinebuf(param, SERVER, buf, sizeof(buf) - 1, '\n', conf.timeouts[STRING_L]);
 param->statssrv+=i;
 if( i < 3 ) {RETURN(621);}
 buf[i] = 0;
 if(strncasecmp((char *)buf, "+OK", 3)||!strncasecmp((char *)buf+4, "PROXY", 5)){RETURN(622);}
 if( socksend(param->remsock, (unsigned char *)"USER ", 5, conf.timeouts[STRING_S])!= 5 || 
	socksend(param->remsock, param->extusername, strlen((char *)param->extusername), conf.timeouts[STRING_S]) <= 0 ||
	socksend(param->remsock, (unsigned char *)"\r\n", 2, conf.timeouts[STRING_S])!=2)
		{RETURN(623);}
 param->statscli += (strlen((char *)param->extusername) + 7);
 RETURN (sockmap(param, 180));
CLEANRET:

 if(param->hostname&&param->extusername) {
	sprintf((char *)buf, "%.64s@%.128s%c%hu", param->extusername, param->hostname, (ntohs(param->sins.sin_port)==110)?0:':', ntohs(param->sins.sin_port));
	 (*param->logfunc)(param, buf);
 }
 else (*param->logfunc)(param, NULL);
 if(param->clisock != INVALID_SOCKET) {
	if ((param->res > 0 && param->res < 100) || (param->res > 611 && param->res <700)) socksend(param->clisock, (unsigned char *)"-ERR\r\n", 6,conf.timeouts[STRING_S]);
 }
 freeparam(param);
 return (NULL);
}
Exemplo n.º 2
0
void * tcppmchild(void * data) {
#define param ((struct clientparam*)data)
 int res;

 param->hostname = param->target;
 param->sins.sin_port = param->targetport;
 param->operation = CONNECT;
 res = (*param->authfunc)(param);
 param->hostname = NULL;
 if(res) {RETURN(res);}
 RETURN (sockmap(param, conf.timeouts[CONNECTION_L]));
CLEANRET:
 
 (*param->logfunc)(param, NULL);
 freeparam(param);
 return (NULL);
}
Exemplo n.º 3
0
static void
setparam(int argc, char **argv)
{
	char **newparam;
	char **ap;

	ap = newparam = ckmalloc((argc + 1) * sizeof *ap);
	while (*argv) {
		*ap++ = savestr(*argv++);
	}
	*ap = NULL;
	freeparam(&shellparam);
	shellparam.malloc = 1;
	shellparam.nparam = argc;
	shellparam.p = newparam;
	shellparam.optp = NULL;
	shellparam.reset = 1;
	shellparam.optnext = NULL;
}
Exemplo n.º 4
0
void
setparam(char **argv)
{
	char **newparam;
	char **ap;
	int nparam;

	for (nparam = 0 ; argv[nparam] ; nparam++);
	ap = newparam = ckmalloc((nparam + 1) * sizeof *ap);
	while (*argv) {
		*ap++ = savestr(*argv++);
	}
	*ap = NULL;
	freeparam(&shellparam);
	shellparam.malloc = 1;
	shellparam.nparam = nparam;
	shellparam.p = newparam;
	shellparam.optnext = NULL;
}
Exemplo n.º 5
0
void * sockschild(struct clientparam* param) {
 int res;
 unsigned i=0;
 SOCKET s;
 unsigned size;
 SASIZETYPE sasize;
 unsigned char * buf=NULL;
 unsigned char c;
 unsigned char command=0;
 struct pollfd fds[3];
 int ver=0;
 int havepass = 0;
 struct sockaddr_in sin;
 int len;


 param->req.sin_addr.s_addr = 0;
 param->service = S_SOCKS;

 if(!(buf = myalloc(BUFSIZE))) {RETURN(21);}
 memset(buf, 0, BUFSIZE);
 if ((ver = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_L], 0)) != 5 && ver != 4) {
	RETURN(401);
 } /* version */
 param->service = ver;
 if(ver == 5){
	 if ((i = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(441);} /* nmethods */
	 for (; i; i--) {
		if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(442);}
		if (res == 2 && !param->srv->nouser) {
			havepass = res;
		}
	 }
	 buf[0] = 5;
	 buf[1] = havepass;
	 if(socksend(param->clisock, buf, 2, conf.timeouts[STRING_S])!=2){RETURN(402);}
	 if (havepass) {
		if (((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_L], 0))) != 1) {
			RETURN(412);
		}
		if ((i = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(443);}
		if (i && (unsigned)(res = sockgetlinebuf(param, CLIENT, buf, i, 0, conf.timeouts[STRING_S])) != i){RETURN(444);};
		buf[i] = 0;
		if(!param->username)param->username = (unsigned char *)mystrdup((char *)buf);
		if ((i = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(445);}
		if (i && (unsigned)(res = sockgetlinebuf(param, CLIENT, buf, i, 0, conf.timeouts[STRING_S])) != i){RETURN(446);};
		buf[i] = 0;
		if(!param->password)param->password = (unsigned char *)mystrdup((char *)buf);
		buf[0] = 1;
		buf[1] = 0;
		if(socksend(param->clisock, buf, 2, conf.timeouts[STRING_S])!=2){RETURN(402);}
	 }
	 if ((c = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_L], 0)) != 5) {
		RETURN(421);
         } /* version */
 }
 if( (command = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) < 1 || command > 3){command = 0; RETURN(407);} /* command */
 if(ver == 5){
	 if (sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0) == EOF) {RETURN(447);} /* reserved */
	 c = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0); /* atype */
 }
 else {
	if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(448);}
	buf[0] = (unsigned char) res;
	if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(449);}
	buf[1] = (unsigned char) res;
	param->sins.sin_port = param->req.sin_port = *(unsigned short*)buf;
	c = 1;
 }
 
 switch(c) {
	case 1:
		for (i = 0; i<4; i++){
			if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(450);}
			buf[i] = (unsigned char)res;
		}
		param->sins.sin_addr.s_addr = param->req.sin_addr.s_addr = *(unsigned long *)buf;
		if(command==1 && !param->req.sin_addr.s_addr) {
			RETURN(422);
		}
		myinet_ntoa(param->sins.sin_addr, (char *)buf);
		break;
	case 3:
		if ((size = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(451);} /* nmethods */
		for (i=0; i<size; i++){ /* size < 256 */
			if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(452);}
			buf[i] = (unsigned char)res;
		}
		buf[i] = 0;
		param->sins.sin_addr.s_addr = param->req.sin_addr.s_addr = getip(buf);
		if(command==1 && !param->req.sin_addr.s_addr) {
			RETURN(100);
		}
		break;
	default:
		RETURN(998);
 }
 if(param->hostname)myfree(param->hostname);
 param->hostname = (unsigned char *)mystrdup((char *)buf);
 if (ver == 5) {
	 if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(453);}
	 buf[0] = (unsigned char) res;
	 if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(454);}
	 buf[1] = (unsigned char) res;
	 param->sins.sin_port = param->req.sin_port = *(unsigned short*)buf;
 }
 else {
	sockgetlinebuf(param, CLIENT, buf, BUFSIZE - 1, 0, conf.timeouts[STRING_S]);
	buf[127] = 0;
	if(!param->srv->nouser && *buf && !param->username)param->username = (unsigned char *)mystrdup((char *)buf);
	if(param->sins.sin_addr.s_addr && ntohl(param->sins.sin_addr.s_addr)<256){
		param->service = S_SOCKS45;
		sockgetlinebuf(param, CLIENT, buf, BUFSIZE - 1, 0, conf.timeouts[STRING_S]);
		buf[127] = 0;
		if(param->hostname)myfree(param->hostname);
		param->hostname = (unsigned char *)mystrdup((char *)buf);
		param->sins.sin_addr.s_addr = param->req.sin_addr.s_addr = getip(buf);
	}
 }
 if(command == 1 && !param->req.sin_port) {RETURN(424);}
 param->sins.sin_family = AF_INET;
 switch(command) { 
	case 1:
	 param->operation = CONNECT;
	 break;
 	case 2:
	 param->sins.sin_addr.s_addr = param->extip;
	 param->sins.sin_port = param->extport?param->extport:param->req.sin_port;
	 if ((param->remsock=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) {RETURN (11);}
	 param->operation = BIND;
	 break;
	case 3:
	 param->sins.sin_port = param->extport?param->extport:param->req.sin_port;
	 param->sins.sin_addr.s_addr = param->extip;
	 if ((param->remsock=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) {RETURN (11);}
	 param->operation = UDPASSOC;
	 break;
	default:
	 RETURN(997);
 }

 if((res = (*param->srv->authfunc)(param))) {RETURN(res);}

 if(command > 1) {
	if(bind(param->remsock,(struct sockaddr *)&param->sins,sizeof(param->sins))) {
		param->sins.sin_port = 0;
		if(bind(param->remsock,(struct sockaddr *)&param->sins,sizeof(param->sins)))RETURN (12);
#if SOCKSTRACE > 0
fprintf(stderr, "%s:%hu binded to communicate with server\n",
			inet_ntoa(param->sins.sin_addr),
			ntohs(param->sins.sin_port)
	);
fflush(stderr);
#endif
	}
	sasize = sizeof(struct sockaddr_in);
	getsockname(param->remsock, (struct sockaddr *)&param->sins,  &sasize);
	if(command == 3) {
		param->ctrlsock = param->clisock;
		param->clisock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
		if(param->clisock == INVALID_SOCKET) {RETURN(11);}
		sin.sin_family = AF_INET;
		sin.sin_addr.s_addr = param->srv->intip;
		sin.sin_port = htons(0);
		if(bind(param->clisock,(struct sockaddr *)&sin,sizeof(struct sockaddr_in))) {RETURN (12);}
#if SOCKSTRACE > 0
fprintf(stderr, "%s:%hu binded to communicate with client\n",
			inet_ntoa(sin.sin_addr),
			ntohs(sin.sin_port)
	);
fflush(stderr);
#endif
	}
 }
 param->res = 0;

CLEANRET:

 if(param->clisock != INVALID_SOCKET){
	sasize = sizeof(struct sockaddr_in);
	if(command != 3) getsockname(param->remsock, (struct sockaddr *)&sin,  &sasize);
	else getsockname(param->clisock, (struct sockaddr *)&sin,  &sasize);
#if SOCKSTRACE > 0
fprintf(stderr, "Sending confirmation to client with code %d for %s with %s:%hu\n",
			param->res,
			commands[command],
			inet_ntoa(sin.sin_addr),
			ntohs(sin.sin_port)
	);
fflush(stderr);
#endif
	if(ver == 5){
		buf[0] = 5;
		buf[1] = param->res%10;
		buf[2] = 0;
		buf[3] = 1;
		memcpy(buf+4, &sin.sin_addr.s_addr, 4);
		memcpy(buf+8, &sin.sin_port, 2);
		socksend((command == 3)?param->ctrlsock:param->clisock, buf, 10, conf.timeouts[STRING_S]);
	}
	else{
		buf[0] = 0;
		buf[1] = 90 + (param->res%10);
		memcpy(buf+2, &sin.sin_port, 2);
		memcpy(buf+4, &sin.sin_addr.s_addr, 4);
		socksend(param->clisock, buf, 8, conf.timeouts[STRING_S]);
	}

	if (param->res == 0) {
		switch(command) {
			case 1:
				if(param->redirectfunc){
					if(buf)myfree(buf);
					return (*param->redirectfunc)(param);
				}
				param->res = sockmap(param, conf.timeouts[CONNECTION_L]);
				break;
			case 2:
				listen (param->remsock, 1);
				
				fds[0].fd = param->remsock;
				fds[1].fd = param->clisock;
				fds[0].events = fds[1].events = POLLIN;
				res = poll(fds, 2, conf.timeouts[(param->req.sin_addr.s_addr)?CONNECTION_S:CONNECTION_L] * 1000);
				if (res < 1 || fds[1].revents) {
					res = 460;
					break;
				}
				sasize = sizeof(param->sins);
				s = accept(param->remsock, (struct sockaddr *)&param->sins, &sasize);
				closesocket(param->remsock);
				param->remsock = s;
				if(s == INVALID_SOCKET) {
					param->res = 462;
					break;
				}
				if(param->req.sin_addr.s_addr && param->req.sin_addr.s_addr != param->sins.sin_addr.s_addr) {
					param->res = 470;
					break;
				}
#if SOCKSTRACE > 0
fprintf(stderr, "Sending incoming connection to client with code %d for %s with %s:%hu\n",
			param->res,
			commands[command],
			inet_ntoa(param->sins.sin_addr),
			ntohs(param->sins.sin_port)
	);
fflush(stderr);
#endif
				if(ver == 5){
					memcpy (buf+4, &param->sins.sin_addr, 4);
					memcpy (buf+8, &param->sins.sin_port, 2);
					socksend(param->clisock, buf, 10, conf.timeouts[STRING_S]);
				}
				else {
					memcpy (buf+2, &param->sins.sin_port, 2);
					memcpy (buf+4, &param->sins.sin_addr, 4);
					socksend(param->clisock, buf, 8, conf.timeouts[STRING_S]);
				}

				param->res = sockmap(param, conf.timeouts[CONNECTION_S]);
				break;
			case 3:
				param->sins.sin_addr.s_addr = param->req.sin_addr.s_addr;
				param->sins.sin_port = param->req.sin_port;
				myfree(buf);
				if(!(buf = myalloc(LARGEBUFSIZE))) {RETURN(21);}

				for(;;){
					fds[0].fd = param->remsock;
					fds[1].fd = param->clisock;
					fds[2].fd = param->ctrlsock;
					fds[2].events = fds[1].events = fds[0].events = POLLIN;

					res = poll(fds, 3, conf.timeouts[CONNECTION_L]*1000);
					if(res <= 0) {
						param->res = 463;
						break;
					}
					if (fds[2].revents) {
						param->res = 0;
						break;
					}
					if (fds[1].revents) {
						sasize = sizeof(struct sockaddr_in);
						if((len = recvfrom(param->clisock, buf, 65535, 0, (struct sockaddr *)&sin, &sasize)) <= 10) {
							param->res = 464;
							break;
						}
						if(sin.sin_addr.s_addr != param->sinc.sin_addr.s_addr){
							param->res = 465;
							break;
						}
						if(buf[0] || buf[1] || buf[2]) {
							param->res = 466;
							break;
						}
						switch(buf[3]) {
							case 1:
								i = 8;
								memcpy(&param->sins.sin_addr.s_addr, buf+4, 4);
								break;
							case 3:
								size = buf[4];
								for (i=4; size; i++, size--){
									buf[i] = buf[i+1];
								}
								buf[i++] = 0;
								param->sins.sin_addr.s_addr = getip(buf+4);
								break;
							default:
								RETURN(996);
						 }

						memcpy(&param->sins.sin_port, buf+i, 2);
						i+=2;

						sasize = sizeof(param->sins);
						if(len > (int)i){
							if(socksendto(param->remsock, &param->sins, buf+i, len - i, conf.timeouts[SINGLEBYTE_L]*1000) <= 0){
								param->res = 467;
								break;
							}
							param->statscli+=(len - i);
							param->nwrites++;
#if SOCKSTRACE > 1
fprintf(stderr, "UDP packet relayed from client to %s:%hu size %d, header %d\n",
			inet_ntoa(param->sins.sin_addr),
			ntohs(param->sins.sin_port),
			(len - i),
			i
	);
fprintf(stderr, "client address is assumed to be %s:%hu\n",
			inet_ntoa(sin.sin_addr),
			ntohs(sin.sin_port)
	);
fflush(stderr);
#endif
						}

					}
					if (fds[0].revents) {
						struct sockaddr_in tsin;
						sasize = sizeof(tsin);
						buf[0]=buf[1]=buf[2]=0;
						buf[3]=1;
						if((len = recvfrom(param->remsock, buf+10, 65535 - 10, 0, (struct sockaddr *)&tsin, &sasize)) <= 0) {
							param->res = 468;
							break;
						}
						param->statssrv+=len;
						param->nreads++;
						memcpy(buf+4, &tsin.sin_addr.s_addr, 4);
						memcpy(buf+8, &tsin.sin_port, 2);
						sasize = sizeof(param->sins);
						if(socksendto(param->clisock, &sin, buf, len + 10, conf.timeouts[SINGLEBYTE_L]*1000) <=0){
							param->res = 469;
							break;
						}
#if SOCKSTRACE > 1
fprintf(stderr, "UDP packet relayed to client from %s:%hu size %d\n",
			inet_ntoa(tsin.sin_addr),
			ntohs(tsin.sin_port),
			len
	);
fflush(stderr);
#endif

					}
				}
				break;
			default:
				param->res = 417;
				break;
		}
	}
 }
 
 if(command > 3) command = 0;
 if(buf){
	 sprintf((char *)buf, "%s ", commands[command]);
	 if(param->hostname){
	  sprintf((char *)buf + strlen((char *)buf), "%.265s", param->hostname);
	 }
	 else myinet_ntoa(param->req.sin_addr, (char *)buf+strlen((char *)buf));
         sprintf((char *)buf+strlen((char *)buf), ":%hu", ntohs(param->req.sin_port));
	 (*param->srv->logfunc)(param, buf);
	 myfree(buf);
 }
 freeparam(param);
 return (NULL);
}
Exemplo n.º 6
0
Arquivo: eval.c Projeto: dpl0/soc2013
static void
evalcommand(union node *cmd, int flags, struct backcmd *backcmd)
{
	union node *argp;
	struct arglist arglist;
	struct arglist varlist;
	char **argv;
	int argc;
	char **envp;
	int varflag;
	struct strlist *sp;
	int mode;
	int pip[2];
	struct cmdentry cmdentry;
	struct job *jp;
	struct jmploc jmploc;
	struct jmploc *savehandler;
	char *savecmdname;
	struct shparam saveparam;
	struct localvar *savelocalvars;
	struct parsefile *savetopfile;
	volatile int e;
	char *lastarg;
	int realstatus;
	int do_clearcmdentry;
	const char *path = pathval();

	/* First expand the arguments. */
	TRACE(("evalcommand(%p, %d) called\n", (void *)cmd, flags));
	arglist.lastp = &arglist.list;
	varlist.lastp = &varlist.list;
	varflag = 1;
	jp = NULL;
	do_clearcmdentry = 0;
	oexitstatus = exitstatus;
	exitstatus = 0;
	for (argp = cmd->ncmd.args ; argp ; argp = argp->narg.next) {
		if (varflag && isassignment(argp->narg.text)) {
			expandarg(argp, varflag == 1 ? &varlist : &arglist,
			    EXP_VARTILDE);
			continue;
		} else if (varflag == 1)
			varflag = isdeclarationcmd(&argp->narg) ? 2 : 0;
		expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
	}
	*arglist.lastp = NULL;
	*varlist.lastp = NULL;
	expredir(cmd->ncmd.redirect);
	argc = 0;
	for (sp = arglist.list ; sp ; sp = sp->next)
		argc++;
	/* Add one slot at the beginning for tryexec(). */
	argv = stalloc(sizeof (char *) * (argc + 2));
	argv++;

	for (sp = arglist.list ; sp ; sp = sp->next) {
		TRACE(("evalcommand arg: %s\n", sp->text));
		*argv++ = sp->text;
	}
	*argv = NULL;
	lastarg = NULL;
	if (iflag && funcnest == 0 && argc > 0)
		lastarg = argv[-1];
	argv -= argc;

	/* Print the command if xflag is set. */
	if (xflag) {
		char sep = 0;
		const char *p, *ps4;
		ps4 = expandstr(ps4val());
		out2str(ps4 != NULL ? ps4 : ps4val());
		for (sp = varlist.list ; sp ; sp = sp->next) {
			if (sep != 0)
				out2c(' ');
			p = strchr(sp->text, '=');
			if (p != NULL) {
				p++;
				outbin(sp->text, p - sp->text, out2);
				out2qstr(p);
			} else
				out2qstr(sp->text);
			sep = ' ';
		}
		for (sp = arglist.list ; sp ; sp = sp->next) {
			if (sep != 0)
				out2c(' ');
			/* Disambiguate command looking like assignment. */
			if (sp == arglist.list &&
					strchr(sp->text, '=') != NULL &&
					strchr(sp->text, '\'') == NULL) {
				out2c('\'');
				out2str(sp->text);
				out2c('\'');
			} else
				out2qstr(sp->text);
			sep = ' ';
		}
		out2c('\n');
		flushout(&errout);
	}

	/* Now locate the command. */
	if (argc == 0) {
		/* Variable assignment(s) without command */
		cmdentry.cmdtype = CMDBUILTIN;
		cmdentry.u.index = BLTINCMD;
		cmdentry.special = 0;
	} else {
		static const char PATH[] = "PATH=";
		int cmd_flags = 0, bltinonly = 0;

		/*
		 * Modify the command lookup path, if a PATH= assignment
		 * is present
		 */
		for (sp = varlist.list ; sp ; sp = sp->next)
			if (strncmp(sp->text, PATH, sizeof(PATH) - 1) == 0) {
				path = sp->text + sizeof(PATH) - 1;
				/*
				 * On `PATH=... command`, we need to make
				 * sure that the command isn't using the
				 * non-updated hash table of the outer PATH
				 * setting and we need to make sure that
				 * the hash table isn't filled with items
				 * from the temporary setting.
				 *
				 * It would be better to forbit using and
				 * updating the table while this command
				 * runs, by the command finding mechanism
				 * is heavily integrated with hash handling,
				 * so we just delete the hash before and after
				 * the command runs. Partly deleting like
				 * changepatch() does doesn't seem worth the
				 * bookinging effort, since most such runs add
				 * directories in front of the new PATH.
				 */
				clearcmdentry();
				do_clearcmdentry = 1;
			}

		for (;;) {
			if (bltinonly) {
				cmdentry.u.index = find_builtin(*argv, &cmdentry.special);
				if (cmdentry.u.index < 0) {
					cmdentry.u.index = BLTINCMD;
					argv--;
					argc++;
					break;
				}
			} else
				find_command(argv[0], &cmdentry, cmd_flags, path);
			/* implement the bltin and command builtins here */
			if (cmdentry.cmdtype != CMDBUILTIN)
				break;
			if (cmdentry.u.index == BLTINCMD) {
				if (argc == 1)
					break;
				argv++;
				argc--;
				bltinonly = 1;
			} else if (cmdentry.u.index == COMMANDCMD) {
				if (argc == 1)
					break;
				if (!strcmp(argv[1], "-p")) {
					if (argc == 2)
						break;
					if (argv[2][0] == '-') {
						if (strcmp(argv[2], "--"))
							break;
						if (argc == 3)
							break;
						argv += 3;
						argc -= 3;
					} else {
						argv += 2;
						argc -= 2;
					}
					path = _PATH_STDPATH;
					clearcmdentry();
					do_clearcmdentry = 1;
				} else if (!strcmp(argv[1], "--")) {
					if (argc == 2)
						break;
					argv += 2;
					argc -= 2;
				} else if (argv[1][0] == '-')
					break;
				else {
					argv++;
					argc--;
				}
				cmd_flags |= DO_NOFUNC;
				bltinonly = 0;
			} else
				break;
		}
		/*
		 * Special builtins lose their special properties when
		 * called via 'command'.
		 */
		if (cmd_flags & DO_NOFUNC)
			cmdentry.special = 0;
	}

	/* Fork off a child process if necessary. */
	if (((cmdentry.cmdtype == CMDNORMAL || cmdentry.cmdtype == CMDUNKNOWN)
	    && ((flags & EV_EXIT) == 0 || have_traps()))
	 || ((flags & EV_BACKCMD) != 0
	    && (cmdentry.cmdtype != CMDBUILTIN ||
		 !safe_builtin(cmdentry.u.index, argc, argv)))) {
		jp = makejob(cmd, 1);
		mode = FORK_FG;
		if (flags & EV_BACKCMD) {
			mode = FORK_NOJOB;
			if (pipe(pip) < 0)
				error("Pipe call failed: %s", strerror(errno));
		}
		if (cmdentry.cmdtype == CMDNORMAL &&
		    cmd->ncmd.redirect == NULL &&
		    varlist.list == NULL &&
		    (mode == FORK_FG || mode == FORK_NOJOB) &&
		    !disvforkset() && !iflag && !mflag) {
			vforkexecshell(jp, argv, environment(), path,
			    cmdentry.u.index, flags & EV_BACKCMD ? pip : NULL);
			goto parent;
		}
		if (forkshell(jp, cmd, mode) != 0)
			goto parent;	/* at end of routine */
		if (flags & EV_BACKCMD) {
			FORCEINTON;
			close(pip[0]);
			if (pip[1] != 1) {
				dup2(pip[1], 1);
				close(pip[1]);
			}
			flags &= ~EV_BACKCMD;
		}
		flags |= EV_EXIT;
	}

	/* This is the child process if a fork occurred. */
	/* Execute the command. */
	if (cmdentry.cmdtype == CMDFUNCTION) {
#ifdef DEBUG
		trputs("Shell function:  ");  trargs(argv);
#endif
		saveparam = shellparam;
		shellparam.malloc = 0;
		shellparam.reset = 1;
		shellparam.nparam = argc - 1;
		shellparam.p = argv + 1;
		shellparam.optnext = NULL;
		INTOFF;
		savelocalvars = localvars;
		localvars = NULL;
		reffunc(cmdentry.u.func);
		savehandler = handler;
		if (setjmp(jmploc.loc)) {
			freeparam(&shellparam);
			shellparam = saveparam;
			popredir();
			unreffunc(cmdentry.u.func);
			poplocalvars();
			localvars = savelocalvars;
			funcnest--;
			handler = savehandler;
			longjmp(handler->loc, 1);
		}
		handler = &jmploc;
		funcnest++;
		redirect(cmd->ncmd.redirect, REDIR_PUSH);
		INTON;
		for (sp = varlist.list ; sp ; sp = sp->next)
			mklocal(sp->text);
		exitstatus = oexitstatus;
		evaltree(getfuncnode(cmdentry.u.func),
		    flags & (EV_TESTED | EV_EXIT));
		INTOFF;
		unreffunc(cmdentry.u.func);
		poplocalvars();
		localvars = savelocalvars;
		freeparam(&shellparam);
		shellparam = saveparam;
		handler = savehandler;
		funcnest--;
		popredir();
		INTON;
		if (evalskip == SKIPFUNC) {
			evalskip = 0;
			skipcount = 0;
		}
		if (jp)
			exitshell(exitstatus);
	} else if (cmdentry.cmdtype == CMDBUILTIN) {
#ifdef DEBUG
		trputs("builtin command:  ");  trargs(argv);
#endif
		mode = (cmdentry.u.index == EXECCMD)? 0 : REDIR_PUSH;
		if (flags == EV_BACKCMD) {
			memout.nleft = 0;
			memout.nextc = memout.buf;
			memout.bufsize = 64;
			mode |= REDIR_BACKQ;
		}
		savecmdname = commandname;
		savetopfile = getcurrentfile();
		cmdenviron = varlist.list;
		e = -1;
		savehandler = handler;
		if (setjmp(jmploc.loc)) {
			e = exception;
			if (e == EXINT)
				exitstatus = SIGINT+128;
			else if (e != EXEXIT)
				exitstatus = 2;
			goto cmddone;
		}
		handler = &jmploc;
		redirect(cmd->ncmd.redirect, mode);
		outclearerror(out1);
		/*
		 * If there is no command word, redirection errors should
		 * not be fatal but assignment errors should.
		 */
		if (argc == 0)
			cmdentry.special = 1;
		listsetvar(cmdenviron, cmdentry.special ? 0 : VNOSET);
		if (argc > 0)
			bltinsetlocale();
		commandname = argv[0];
		argptr = argv + 1;
		nextopt_optptr = NULL;		/* initialize nextopt */
		builtin_flags = flags;
		exitstatus = (*builtinfunc[cmdentry.u.index])(argc, argv);
		flushall();
		if (outiserror(out1)) {
			warning("write error on stdout");
			if (exitstatus == 0 || exitstatus == 1)
				exitstatus = 2;
		}
cmddone:
		if (argc > 0)
			bltinunsetlocale();
		cmdenviron = NULL;
		out1 = &output;
		out2 = &errout;
		freestdout();
		handler = savehandler;
		commandname = savecmdname;
		if (jp)
			exitshell(exitstatus);
		if (flags == EV_BACKCMD) {
			backcmd->buf = memout.buf;
			backcmd->nleft = memout.nextc - memout.buf;
			memout.buf = NULL;
		}
		if (cmdentry.u.index != EXECCMD)
			popredir();
		if (e != -1) {
			if ((e != EXERROR && e != EXEXEC)
			    || cmdentry.special)
				exraise(e);
			popfilesupto(savetopfile);
			if (flags != EV_BACKCMD)
				FORCEINTON;
		}
	} else {
#ifdef DEBUG
		trputs("normal command:  ");  trargs(argv);
#endif
		redirect(cmd->ncmd.redirect, 0);
		for (sp = varlist.list ; sp ; sp = sp->next)
			setvareq(sp->text, VEXPORT|VSTACK);
		envp = environment();
		shellexec(argv, envp, path, cmdentry.u.index);
		/*NOTREACHED*/
	}
	goto out;

parent:	/* parent process gets here (if we forked) */
	if (mode == FORK_FG) {	/* argument to fork */
		INTOFF;
		exitstatus = waitforjob(jp, &realstatus);
		INTON;
		if (iflag && loopnest > 0 && WIFSIGNALED(realstatus)) {
			evalskip = SKIPBREAK;
			skipcount = loopnest;
		}
	} else if (mode == FORK_NOJOB) {
		backcmd->fd = pip[0];
		close(pip[1]);
		backcmd->jp = jp;
	}

out:
	if (lastarg)
		setvar("_", lastarg, 0);
	if (do_clearcmdentry)
		clearcmdentry();
}
Exemplo n.º 7
0
static void
evalcommand(union node *cmd, int flags, struct backcmd *backcmd)
{
	struct stackmark smark;
	union node *argp;
	struct arglist arglist;
	struct arglist varlist;
	char **argv;
	int argc;
	char **envp;
	int varflag;
	struct strlist *sp;
	int mode;
	int pip[2];
	struct cmdentry cmdentry;
	struct job *jp;
	struct jmploc jmploc;
	struct jmploc *savehandler;
	char *savecmdname;
	struct shparam saveparam;
	struct localvar *savelocalvars;
	volatile int e;
	char *lastarg;
	int realstatus;
	int do_clearcmdentry;

	/* First expand the arguments. */
	TRACE(("evalcommand(%p, %d) called\n", (void *)cmd, flags));
	setstackmark(&smark);
	arglist.lastp = &arglist.list;
	varlist.lastp = &varlist.list;
	varflag = 1;
	do_clearcmdentry = 0;
	oexitstatus = exitstatus;
	exitstatus = 0;
	for (argp = cmd->ncmd.args ; argp ; argp = argp->narg.next) {
		char *p = argp->narg.text;
		if (varflag && is_name(*p)) {
			do {
				p++;
			} while (is_in_name(*p));
			if (*p == '=') {
				expandarg(argp, &varlist, EXP_VARTILDE);
				continue;
			}
		}
		expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
		varflag = 0;
	}
	*arglist.lastp = NULL;
	*varlist.lastp = NULL;
	expredir(cmd->ncmd.redirect);
	argc = 0;
	for (sp = arglist.list ; sp ; sp = sp->next)
		argc++;
	argv = stalloc(sizeof (char *) * (argc + 1));

	for (sp = arglist.list ; sp ; sp = sp->next) {
		TRACE(("evalcommand arg: %s\n", sp->text));
		*argv++ = sp->text;
	}
	*argv = NULL;
	lastarg = NULL;
	if (iflag && funcnest == 0 && argc > 0)
		lastarg = argv[-1];
	argv -= argc;

	/* Print the command if xflag is set. */
	if (xflag) {
		char sep = 0;
		const char *p;
		out2str(ps4val());
		for (sp = varlist.list ; sp ; sp = sp->next) {
			if (sep != 0)
				outc(' ', &errout);
			p = sp->text;
			while (*p != '=' && *p != '\0')
				out2c(*p++);
			if (*p != '\0') {
				out2c(*p++);
				out2qstr(p);
			}
			sep = ' ';
		}
		for (sp = arglist.list ; sp ; sp = sp->next) {
			if (sep != 0)
				outc(' ', &errout);
			/* Disambiguate command looking like assignment. */
			if (sp == arglist.list &&
					strchr(sp->text, '=') != NULL &&
					strchr(sp->text, '\'') == NULL) {
				out2c('\'');
				out2str(sp->text);
				out2c('\'');
			} else
				out2qstr(sp->text);
			sep = ' ';
		}
		outc('\n', &errout);
		flushout(&errout);
	}

	/* Now locate the command. */
	if (argc == 0) {
		/* Variable assignment(s) without command */
		cmdentry.cmdtype = CMDBUILTIN;
		cmdentry.u.index = BLTINCMD;
		cmdentry.special = 1;
	} else {
		static const char PATH[] = "PATH=";
		char *path = pathval();

		/*
		 * Modify the command lookup path, if a PATH= assignment
		 * is present
		 */
		for (sp = varlist.list ; sp ; sp = sp->next)
			if (strncmp(sp->text, PATH, sizeof(PATH) - 1) == 0) {
				path = sp->text + sizeof(PATH) - 1;
				/*
				 * On `PATH=... command`, we need to make
				 * sure that the command isn't using the
				 * non-updated hash table of the outer PATH
				 * setting and we need to make sure that
				 * the hash table isn't filled with items
				 * from the temporary setting.
				 *
				 * It would be better to forbit using and
				 * updating the table while this command
				 * runs, by the command finding mechanism
				 * is heavily integrated with hash handling,
				 * so we just delete the hash before and after
				 * the command runs. Partly deleting like
				 * changepatch() does doesn't seem worth the
				 * bookinging effort, since most such runs add
				 * directories in front of the new PATH.
				 */
				clearcmdentry(0);
				do_clearcmdentry = 1;
			}

		find_command(argv[0], &cmdentry, 1, path);
		if (cmdentry.cmdtype == CMDUNKNOWN) {	/* command not found */
			exitstatus = 127;
			flushout(&errout);
			return;
		}
		/* implement the bltin builtin here */
		if (cmdentry.cmdtype == CMDBUILTIN && cmdentry.u.index == BLTINCMD) {
			for (;;) {
				argv++;
				if (--argc == 0)
					break;
				if ((cmdentry.u.index = find_builtin(*argv,
				    &cmdentry.special)) < 0) {
					outfmt(&errout, "%s: not found\n", *argv);
					exitstatus = 127;
					flushout(&errout);
					return;
				}
				if (cmdentry.u.index != BLTINCMD)
					break;
			}
		}
	}

	/* Fork off a child process if necessary. */
	if (cmd->ncmd.backgnd
	 || (cmdentry.cmdtype == CMDNORMAL
	    && ((flags & EV_EXIT) == 0 || have_traps()))
	 || ((flags & EV_BACKCMD) != 0
	    && (cmdentry.cmdtype != CMDBUILTIN
		 || cmdentry.u.index == CDCMD
		 || cmdentry.u.index == DOTCMD
		 || cmdentry.u.index == EVALCMD))
	 || (cmdentry.cmdtype == CMDBUILTIN &&
	    cmdentry.u.index == COMMANDCMD)) {
		jp = makejob(cmd, 1);
		mode = cmd->ncmd.backgnd;
		if (flags & EV_BACKCMD) {
			mode = FORK_NOJOB;
			if (pipe(pip) < 0)
				error("Pipe call failed: %s", strerror(errno));
		}
		if (forkshell(jp, cmd, mode) != 0)
			goto parent;	/* at end of routine */
		if (flags & EV_BACKCMD) {
			FORCEINTON;
			close(pip[0]);
			if (pip[1] != 1) {
				dup2(pip[1], 1);
				close(pip[1]);
			}
		}
		flags |= EV_EXIT;
	}

	/* This is the child process if a fork occurred. */
	/* Execute the command. */
	if (cmdentry.cmdtype == CMDFUNCTION) {
#ifdef DEBUG
		trputs("Shell function:  ");  trargs(argv);
#endif
		redirect(cmd->ncmd.redirect, REDIR_PUSH);
		saveparam = shellparam;
		shellparam.malloc = 0;
		shellparam.reset = 1;
		shellparam.nparam = argc - 1;
		shellparam.p = argv + 1;
		shellparam.optnext = NULL;
		INTOFF;
		savelocalvars = localvars;
		localvars = NULL;
		reffunc(cmdentry.u.func);
		INTON;
		savehandler = handler;
		if (setjmp(jmploc.loc)) {
			if (exception == EXSHELLPROC)
				freeparam(&saveparam);
			else {
				freeparam(&shellparam);
				shellparam = saveparam;
			}
			unreffunc(cmdentry.u.func);
			poplocalvars();
			localvars = savelocalvars;
			handler = savehandler;
			longjmp(handler->loc, 1);
		}
		handler = &jmploc;
		for (sp = varlist.list ; sp ; sp = sp->next)
			mklocal(sp->text);
		funcnest++;
		exitstatus = oexitstatus;
		if (flags & EV_TESTED)
			evaltree(getfuncnode(cmdentry.u.func), EV_TESTED);
		else
			evaltree(getfuncnode(cmdentry.u.func), 0);
		funcnest--;
		INTOFF;
		unreffunc(cmdentry.u.func);
		poplocalvars();
		localvars = savelocalvars;
		freeparam(&shellparam);
		shellparam = saveparam;
		handler = savehandler;
		popredir();
		INTON;
		if (evalskip == SKIPFUNC) {
			evalskip = 0;
			skipcount = 0;
		}
		if (flags & EV_EXIT)
			exitshell(exitstatus);
	} else if (cmdentry.cmdtype == CMDBUILTIN) {
#ifdef DEBUG
		trputs("builtin command:  ");  trargs(argv);
#endif
		mode = (cmdentry.u.index == EXECCMD)? 0 : REDIR_PUSH;
		if (flags == EV_BACKCMD) {
			memout.nleft = 0;
			memout.nextc = memout.buf;
			memout.bufsize = 64;
			mode |= REDIR_BACKQ;
		}
		savecmdname = commandname;
		cmdenviron = varlist.list;
		e = -1;
		savehandler = handler;
		if (setjmp(jmploc.loc)) {
			e = exception;
			exitstatus = (e == EXINT)? SIGINT+128 : 2;
			goto cmddone;
		}
		handler = &jmploc;
		redirect(cmd->ncmd.redirect, mode);
		if (cmdentry.special)
			listsetvar(cmdenviron);
		commandname = argv[0];
		argptr = argv + 1;
		nextopt_optptr = NULL;		/* initialize nextopt */
		builtin_flags = flags;
		exitstatus = (*builtinfunc[cmdentry.u.index])(argc, argv);
		flushall();
cmddone:
		cmdenviron = NULL;
		out1 = &output;
		out2 = &errout;
		freestdout();
		if (e != EXSHELLPROC) {
			commandname = savecmdname;
			if (flags & EV_EXIT) {
				exitshell(exitstatus);
			}
		}
		handler = savehandler;
		if (e != -1) {
			if ((e != EXERROR && e != EXEXEC)
			    || cmdentry.special)
				exraise(e);
			FORCEINTON;
		}
		if (cmdentry.u.index != EXECCMD)
			popredir();
		if (flags == EV_BACKCMD) {
			backcmd->buf = memout.buf;
			backcmd->nleft = memout.nextc - memout.buf;
			memout.buf = NULL;
		}
	} else {
#ifdef DEBUG
		trputs("normal command:  ");  trargs(argv);
#endif
		clearredir();
		redirect(cmd->ncmd.redirect, 0);
		for (sp = varlist.list ; sp ; sp = sp->next)
			setvareq(sp->text, VEXPORT|VSTACK);
		envp = environment();
		shellexec(argv, envp, pathval(), cmdentry.u.index);
		/*NOTREACHED*/
	}
	goto out;

parent:	/* parent process gets here (if we forked) */
	if (mode == FORK_FG) {	/* argument to fork */
		INTOFF;
		exitstatus = waitforjob(jp, &realstatus);
		INTON;
		if (iflag && loopnest > 0 && WIFSIGNALED(realstatus)) {
			evalskip = SKIPBREAK;
			skipcount = loopnest;
		}
	} else if (mode == FORK_NOJOB) {
		backcmd->fd = pip[0];
		close(pip[1]);
		backcmd->jp = jp;
	}

out:
	if (lastarg)
		setvar("_", lastarg, 0);
	if (do_clearcmdentry)
		clearcmdentry(0);
	popstackmark(&smark);
}
Exemplo n.º 8
0
int MODULEMAINFUNC (int argc, char** argv){

 SOCKET sock = INVALID_SOCKET;
 int i=0;
 SASIZETYPE size;
 pthread_t thread;
 struct clientparam defparam;
 int demon=0;
 struct clientparam * newparam;
 char *s;
 int error = 0;
 unsigned sleeptime;
 struct extparam myconf;
 unsigned char buf[256];
 struct pollfd fds;
 int opt = 1;
 PROXYFUNC pf;
 FILE *fp = NULL;
 int maxchild;
 int silent = 0;
 int nlog = 5000;
 char loghelp[] =
#ifdef STDMAIN
	" -d go to background (daemon)\n"
#endif
	" -fFORMAT logging format (see documentation)\n"
	" -l log to stderr\n"
	" -lFILENAME log to FILENAME\n"
	" -bBUFSIZE size of network buffer (default 4096 for TCP, 16384 for UDP)\n"
	" -l@IDENT log to syslog IDENT\n"
	" -t be silenT (do not log service start/stop)\n"
	" -iIP ip address or internal interface (clients are expected to connect)\n"
	" -eIP ip address or external interface (outgoing connection will have this)\n";

 int childcount=0;
 pthread_mutex_t counter_mutex;


 int new_sock = INVALID_SOCKET;
 struct linger lg;

#ifdef STDMAIN
 signal(SIGPIPE, SIG_IGN);

 pthread_attr_init(&pa);
 pthread_attr_setstacksize(&pa,PTHREAD_STACK_MIN + 16384);
 pthread_attr_setdetachstate(&pa,PTHREAD_CREATE_DETACHED);
#endif


 pf = childdef.pf;
 memcpy(&myconf, &conf, sizeof(myconf));
 memset(&defparam, 0, sizeof(struct clientparam));
 defparam.version = paused;
 defparam.childcount = &childcount;
 defparam.logfunc = myconf.logfunc;
 defparam.authfunc = myconf.authfunc;
 defparam.aclnum = myconf.aclnum;
 defparam.service = childdef.service;
 defparam.usentlm = 1;
 defparam.stdlog = NULL;
 defparam.time_start = time(NULL);
 maxchild = myconf.maxchild;

#ifndef STDMAIN
 if(!conf.services){
	conf.services = &defparam;
 }
 else {
	defparam.next = conf.services;
	conf.services = conf.services->prev = &defparam;
 }
#endif

 pthread_mutex_init(defparam.counter_mutex = &counter_mutex, NULL);

 for (i=1; i<argc; i++) {
	if(*argv[i]=='-') {
		switch(argv[i][1]) {
		 case 'd': 
			if(!demon)daemonize();
			demon = 1;
			break;
		 case 'l':
			defparam.logfunc = logstdout;
			defparam.logtarget = (unsigned char*)mystrdup(argv[i]);
			if(argv[i][2]) {
#ifdef STDMAIN
				if(argv[i][2]=='@'){
					openlog(argv[i]+3, LOG_PID, LOG_DAEMON);
					defparam.logfunc = logsyslog;
				}
				else 
#endif
				{
					fp = fopen(argv[i] + 2, "a");
					if (fp) {
						defparam.stdlog = fp;
						fseek(fp, 0L, SEEK_END);
					}
				}

			}
			break;
		 case 'i':
			myconf.intip = getip((unsigned char *)argv[i]+2);
			break;
		 case 'e':
			myconf.extip = getip((unsigned char *)argv[i]+2);
			break;
		 case 'p':
			myconf.intport = atoi(argv[i]+2);
			break;
		 case 'b':
			myconf.bufsize = atoi(argv[i]+2);
			break;
		 case 'n':
			defparam.usentlm = 0;
			break;
		 case 'f':
			defparam.logformat = (unsigned char *)argv[i] + 2;
			break;
		 case 't':
			silent = 1;
			break;
		case 's':
		case 'a':
			myconf.singlepacket = 1 + atoi(argv[i]+2);
			break;
		 default:
			error = 1;
			break;
		}
	}
	else break;
 }


#ifndef STDMAIN
 if(childdef.port) {
#endif
#ifndef PORTMAP
	if (error || i!=argc) {
#ifndef STDMAIN
		haveerror = 1;
		conf.threadinit = 0;
#endif
		fprintf(stderr, "Usage: %s options\n"
			"Available options are:\n"
			"%s"
			" -pPORT - service port to accept connections\n"
			"%s"
			"\tExample: %s -i127.0.0.1\n\n"
			"%s", 
			argv[0], loghelp, childdef.helpmessage, argv[0],
#ifdef STDMAIN
			copyright
#else
			""
#endif
		);

		return (1);
	}
#endif
#ifndef STDMAIN
 }
 else {
#endif
#ifndef NOPORTMAP
	if (error || argc != i+3 || *argv[i]=='-'|| (myconf.intport = atoi(argv[i]))==0 || (defparam.targetport = htons((unsigned short)atoi(argv[i+2])))==0) {
#ifndef STDMAIN
		haveerror = 1;
		conf.threadinit = 0;
#endif
		fprintf(stderr, "Usage: %s options"
			" [-e<external_ip>] <port_to_bind>"
			" <target_hostname> <target_port>\n"
			"Available options are:\n"
			"%s"
			"%s"
			"\tExample: %s -d -i127.0.0.1 6666 serv.somehost.ru 6666\n\n"
			"%s", 
			argv[0], loghelp, childdef.helpmessage, argv[0],
#ifdef STDMAIN
			copyright
#else
			""
#endif
		);
		return (1);
	}
	defparam.target = (unsigned char *)mystrdup(argv[i+1]);
#endif
#ifndef STDMAIN
 }
#endif
 if(!defparam.logformat){
	defparam.logformat = myconf.logformat;
 }
 if(defparam.logformat){
	if(*defparam.logformat == '-' && (s = strchr((char *)defparam.logformat + 1, '+')) && s[1]){
		*s = 0;
		defparam.nonprintable = (unsigned char *)mystrdup((char *)defparam.logformat + 1);
		defparam.replace = s[1];
		defparam.logformat = (unsigned char *)mystrdup(s + 2);
		*s = '+';
	}
	else defparam.logformat = (unsigned char *)mystrdup((char *)defparam.logformat);
 }
 defparam.sinc.sin_addr.s_addr = defparam.intip = myconf.intip;
 if(!myconf.intport)myconf.intport = childdef.port;
 defparam.sinc.sin_port = defparam.intport = htons(myconf.intport);
 defparam.sins.sin_addr.s_addr = defparam.extip = myconf.extip;
 defparam.sins.sin_port = defparam.extport = htons(myconf.extport);
 defparam.remsock = defparam.clisock = defparam.ctrlsock = INVALID_SOCKET;
 defparam.sins.sin_family = defparam.sinc.sin_family = AF_INET;
 defparam.singlepacket = myconf.singlepacket;
 defparam.bufsize = myconf.bufsize;
#ifndef STDMAIN
 conf.threadinit = 0;
#endif


 lg.l_onoff = 1;
 lg.l_linger = conf.timeouts[STRING_L];
 if( (sock=socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) {
	perror("socket()");
	return -2;
 }

	fcntl(sock,F_SETFL,O_NONBLOCK);

 defparam.srvsock = sock;
 if(setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (unsigned char *)&opt, sizeof(int)))perror("setsockopt()");

 size = sizeof(defparam.sinc);
 for(sleeptime = SLEEPTIME * 100; bind(sock, (struct sockaddr*)&defparam.sinc, size)==-1; usleep(sleeptime)) {
	sprintf((char *)buf, "bind(): %s", strerror(errno));
	(*defparam.logfunc)(&defparam, buf);	
	sleeptime = (sleeptime<<1);	
	if(!sleeptime) {
		closesocket(sock);
		return -3;
	}
 }
 if(listen (sock, 1 + (maxchild>>4))==-1) {
	sprintf((char *)buf, "listen(): %s", strerror(errno));
	(*defparam.logfunc)(&defparam, buf);
	return -4;
 }


 defparam.threadid = (unsigned)pthread_self();
 if(!silent){
	sprintf((char *)buf, "Accepting connections [%u/%u]", (unsigned)getpid(), (unsigned)pthread_self());
	(*defparam.logfunc)(&defparam, buf);
 }
 defparam.sinc.sin_addr.s_addr = defparam.sins.sin_addr.s_addr = 0;
 defparam.sinc.sin_port = defparam.sins.sin_port = 0;

 fds.fd = sock;
 fds.events = POLLIN;
 

 for (;;) {
	for(;;){
		while((paused == defparam.version && childcount >= myconf.maxchild)){
			nlog++;			
			if(nlog > 5000) {
				sprintf((char *)buf, "Warning: too many connected clients (%d/%d)", childcount, myconf.maxchild);
				(*defparam.logfunc)(&defparam, buf);
				nlog = 0;
			}
			usleep(SLEEPTIME);
		}
		if (paused != defparam.version) break;
		if (fds.events & POLLIN) {
			error = poll(&fds, 1, 1000);
		}
		else {
			usleep(SLEEPTIME);
			continue;
		}
		if (error >= 1) break;
		if (error == 0) continue;
		sprintf((char *)buf, "poll(): %s/%d", strerror(errno), errno);
		(*defparam.logfunc)(&defparam, buf);
		if(errno != EAGAIN) break;
		continue;
	}
	if(paused != defparam.version) break;
	size = sizeof(defparam.sinc);
	new_sock = accept(sock, (struct sockaddr*)&defparam.sinc, &size);
	if(new_sock == INVALID_SOCKET){
		sprintf((char *)buf, "accept(): %s", strerror(errno));
		(*defparam.logfunc)(&defparam, buf);
		continue;
	}
	fcntl(new_sock,F_SETFL,O_NONBLOCK);

	setsockopt(new_sock, SOL_SOCKET, SO_LINGER, (unsigned char *)&lg, sizeof(lg));
	setsockopt(new_sock, SOL_SOCKET, SO_OOBINLINE, (unsigned char *)&opt, sizeof(int));

	if(! (newparam = myalloc (sizeof(defparam)))){
		closesocket(new_sock);
		defparam.res = 21;
		(*defparam.logfunc)(&defparam, (unsigned char *)"Memory Allocation Failed");
		usleep(SLEEPTIME);
		continue;
	};
	memcpy(newparam, &defparam, sizeof(defparam));
	clearstat(newparam);
	newparam->clisock = new_sock;
	newparam->child = newparam->prev = newparam->next = NULL;
	newparam->parent = &defparam;
	pthread_mutex_lock(&counter_mutex);
	if(!defparam.child)defparam.child = newparam;
	else {
		newparam->next = defparam.child;
		defparam.child = defparam.child->prev = newparam;
	}

	if((error = pthread_create(&thread, &pa, pf, (void *)newparam))){
		sprintf((char *)buf, "pthread_create(): %s", strerror(error));
		(*defparam.logfunc)(&defparam, buf);
		freeparam(newparam);
	}
	else {
		childcount++;
		newparam->threadid = (unsigned)thread;
	}

	pthread_mutex_unlock(&counter_mutex);
	memset(&defparam.sinc, 0, sizeof(defparam.sinc));
	while(!fds.events)usleep(SLEEPTIME);
 }
 if(defparam.srvsock != INVALID_SOCKET) closesocket(defparam.srvsock);
 if(!silent) defparam.logfunc(&defparam, (unsigned char *)"Exiting thread");
 defparam.service = S_ZOMBIE;
 while(defparam.child) usleep(SLEEPTIME * 100);
 defparam.threadid = 0;
 if(fp) fclose(fp);
 if(defparam.target) myfree(defparam.target);
 if(defparam.logtarget) myfree(defparam.logtarget);
 if(defparam.logformat) myfree(defparam.logformat);
 if(defparam.nonprintable) myfree(defparam.nonprintable);
#ifndef STDMAIN
 if(defparam.next)defparam.next->prev = defparam.prev;
 if(defparam.prev)defparam.prev->next = defparam.next;
 else conf.services = defparam.next;
#endif
 pthread_mutex_destroy(&counter_mutex);
 return 0;
}
Exemplo n.º 9
0
void * ftpprchild(struct clientparam* param) {
 int i=0, res;
 unsigned char *buf;
 unsigned char *se;
 int status = 0;
 int inbuf;
 int pasv = 0;
 SOCKET sc = INVALID_SOCKET, ss = INVALID_SOCKET, clidatasock = INVALID_SOCKET;
 SASIZETYPE sasize;
 char * req = NULL;
 struct linger lg;
 struct pollfd fds;

 if(!(buf = myalloc(BUFSIZE))) RETURN(876);
 param->ctrlsock = param->clisock;
 param->operation = CONNECT;
 lg.l_onoff = 1;
 lg.l_linger = conf.timeouts[STRING_L];;
 if(socksend(param->ctrlsock, (unsigned char *)"220 Ready\r\n", 11, conf.timeouts[STRING_S])!=11) {RETURN (801);}
 for(;;){
	i = sockgetlinebuf(param, CLIENT, buf, BUFSIZE - 10, '\n', conf.timeouts[CONNECTION_S]);
	if(!i) {
		RETURN(0);
	}
	if(i<4) {RETURN(802);}
	buf[i] = 0;
	if ((se=(unsigned char *)strchr((char *)buf, '\r'))) *se = 0;
	if (req) myfree (req);
	req = NULL;

	if (!strncasecmp((char *)buf, "OPEN ", 5)){
		if(parsehostname((char *)buf+5, param, 21)){RETURN(803);}
		if(param->remsock != INVALID_SOCKET) {
			so._shutdown(param->remsock, SHUT_RDWR);
			so._closesocket(param->remsock);
			param->remsock = INVALID_SOCKET;
		}
		if((res = (*param->srv->authfunc)(param))) {RETURN(res);}
		param->ctrlsocksrv = param->remsock;
		if(socksend(param->ctrlsock, (unsigned char *)"220 Ready\r\n", 11, conf.timeouts[STRING_S])!=11) {RETURN (801);}
		status = 1;
	}
	else if (!strncasecmp((char *)buf, "USER ", 5)){
		if(parseconnusername((char *)buf +5, param, 0, 21)){RETURN(804);}
		if(!status){
			if((res = (*param->srv->authfunc)(param))) {RETURN(res);}
			param->ctrlsocksrv = param->remsock;
		}
		if(socksend(param->ctrlsock, (unsigned char *)"331 ok\r\n", 8, conf.timeouts[STRING_S])!=8) {RETURN (807);}
		status = 2;

	}
	else if (!strncasecmp((char *)buf, "PASS ", 5)){
		param->extpassword = (unsigned char *)mystrdup((char *)buf+5);
		inbuf = BUFSIZE;
		res = ftplogin(param, (char *)buf, &inbuf);
		param->res = res;
		if(inbuf && inbuf != BUFSIZE && socksend(param->ctrlsock, buf, inbuf, conf.timeouts[STRING_S])!=inbuf) {RETURN (807);}
		if(!res) status = 3;
		sprintf((char *)buf, "%.64s@%.128s%c%hu", param->extusername, param->hostname, (ntohs(param->sins.sin_port)==21)?0:':', ntohs(param->sins.sin_port));
		req = mystrdup((char *)buf);
#ifndef WITHMAIN
		{
			int action, reqbufsize, reqsize;
			reqbufsize = BUFSIZE;
			reqsize = (int)strlen(buf) + 1;
			
			action = handlereqfilters(param, &buf, &reqbufsize, 0, &reqsize);
			if(action == HANDLED){
				RETURN(0);
			}
			if(action != PASS) RETURN(877);
		}
#endif
	}
	else if (status >= 3 && (
			(!strncasecmp((char *)buf, "PASV", 4) && (pasv = 1)) ||
			(!strncasecmp((char *)buf, "PORT ", 5) && !(pasv = 0))
		)){
#ifndef WITHMAIN
		{
			int action, reqbufsize, reqsize;
			reqbufsize = BUFSIZE;
			reqsize = (int)strlen(buf) + 1;
			
			action = handlehdrfilterscli(param, &buf, &reqbufsize, 0, &reqsize);
			if(action == HANDLED){
				RETURN(0);
			}
			if(action != PASS) RETURN(878);
		}
#endif
		if(sc != INVALID_SOCKET) {
			so._shutdown(sc, SHUT_RDWR);
			so._closesocket(sc);
			sc = INVALID_SOCKET;
		}
		if(ss != INVALID_SOCKET) {
			so._shutdown(ss, SHUT_RDWR);
			so._closesocket(ss);
			ss = INVALID_SOCKET;
		}
		if(clidatasock != INVALID_SOCKET) {
			so._shutdown(clidatasock, SHUT_RDWR);
			so._closesocket(clidatasock);
			clidatasock = INVALID_SOCKET;
		}
		if ((clidatasock=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) {RETURN(821);}
		sasize = sizeof(struct sockaddr_in);
		if(so._getsockname(param->ctrlsock, (struct sockaddr *)&param->sinc, &sasize)){RETURN(824);}
		param->sinc.sin_port = 0;
		if(so._bind(clidatasock, (struct sockaddr *)&param->sinc, sasize)){RETURN(822);}
		if (pasv) {
			if(so._listen(clidatasock, 1)) {RETURN(823);}
			if(so._getsockname(clidatasock, (struct sockaddr *)&param->sinc, &sasize)){RETURN(824);}
			sprintf((char *)buf, "227 OK (%u,%u,%u,%u,%u,%u)\r\n",
				 (unsigned)(((unsigned char *)(&param->sinc.sin_addr.s_addr))[0]),
				 (unsigned)(((unsigned char *)(&param->sinc.sin_addr.s_addr))[1]),
				 (unsigned)(((unsigned char *)(&param->sinc.sin_addr.s_addr))[2]),
				 (unsigned)(((unsigned char *)(&param->sinc.sin_addr.s_addr))[3]),
				 (unsigned)(((unsigned char *)(&param->sinc.sin_port))[0]),
				 (unsigned)(((unsigned char *)(&param->sinc.sin_port))[1])
				);
		}
		else {
			unsigned long b1, b2, b3, b4;
			unsigned short b5, b6;

			if(sscanf((char *)buf+5, "%lu,%lu,%lu,%lu,%hu,%hu", &b1, &b2, &b3, &b4, &b5, &b6)!=6) {RETURN(828);}
			param->sinc.sin_family = AF_INET;
			param->sinc.sin_port = htons((unsigned short)((b5<<8)^b6));
			param->sinc.sin_addr.s_addr = htonl((b1<<24)^(b2<<16)^(b3<<8)^b4);
			if(so._connect(clidatasock, (struct sockaddr *)&param->sinc, sasize)) {
				so._closesocket(clidatasock);
				clidatasock = INVALID_SOCKET;
				RETURN(826);
			}
			sprintf(buf, "200 OK\r\n");
		}
#ifndef WITHMAIN
		{
			int action, reqbufsize, reqsize;
			reqbufsize = BUFSIZE;
			reqsize = (int)strlen(buf) + 1;
			
			action = handlehdrfilterssrv(param, &buf, &reqbufsize, 0, &reqsize);
			if(action == HANDLED){
				RETURN(0);
			}
			if(action != PASS) RETURN(879);
		}
#endif
		if(socksend(param->ctrlsock, buf, (int)strlen((char *)buf), conf.timeouts[STRING_S])!=(int)strlen((char *)buf)) {RETURN (825);}
		status = 4;
	}
	else if (status == 4 && (
		!(strncasecmp((char *)buf, "RETR ", 5) && (param->operation = FTP_GET)) ||
		!(strncasecmp((char *)buf, "LIST", 4) && (param->operation = FTP_LIST))||
		!(strncasecmp((char *)buf, "NLST ", 5) && (param->operation = FTP_LIST)) ||
		!(strncasecmp((char *)buf, "MLSD", 4) && (param->operation = FTP_LIST)) ||
		!(strncasecmp((char *)buf, "APPE ", 5) && (param->operation = FTP_PUT)) ||
		!(strncasecmp((char *)buf, "STOR ", 5) && (param->operation = FTP_PUT))
	)){
		int arg = (buf[4] && buf[5])? 1:0;
		int ressent = 0;


#ifndef WITHMAIN
		{
			int action, reqbufsize, reqsize;
			reqbufsize = BUFSIZE;
			reqsize = (int)strlen(buf) + 1;
			
			action = handlehdrfilterscli(param, &buf, &reqbufsize, 0, &reqsize);
			if(action == HANDLED){
				RETURN(0);
			}
			if(action != PASS) RETURN(880);
		}
#endif
		if(clidatasock == INVALID_SOCKET) { RETURN (829);}
		if(pasv){

			memset(&fds, 0, sizeof(fds));
			fds.fd = clidatasock;
			fds.events = POLLIN;

			res = so._poll (&fds, 1, conf.timeouts[STRING_L]*1000);
			if(res != 1) {
				RETURN(857);
			}
			sasize = sizeof(struct sockaddr_in);
			ss = so._accept(clidatasock, (struct sockaddr *)&param->sinc, &sasize);
			if (ss == INVALID_SOCKET) { RETURN (858);}
			so._shutdown(clidatasock, SHUT_RDWR);
			so._closesocket(clidatasock);
			clidatasock = ss;
			ss = INVALID_SOCKET;
		}
		if(clidatasock == INVALID_SOCKET){RETURN(828);}
		req = mystrdup((char *)buf);
		buf[4] = 0;
		status = 3;
		ss = ftpcommand(param, buf, arg? buf+5 : NULL);
		if (ss == INVALID_SOCKET) {
			so._shutdown(clidatasock, SHUT_RDWR);
			so._closesocket(clidatasock);
			clidatasock = INVALID_SOCKET;
			
			if(socksend(param->ctrlsock, (unsigned char *)"550 err\r\n", 9, conf.timeouts[STRING_S])!=9) {RETURN (831);}
			continue;
		}

		if(socksend(param->ctrlsock, (unsigned char *)"125 data\r\n", 10, conf.timeouts[STRING_S]) != 10) {
			param->remsock = INVALID_SOCKET;
			RETURN (832);
		}
		if(param->srvoffset < param->srvinbuf)while((i = sockgetlinebuf(param, SERVER, buf, BUFSIZE, '\n', 0)) > 3){
			if(socksend(param->ctrlsock, buf, i, conf.timeouts[STRING_S])!=i) {RETURN(833);}
			if(isnumber(*buf) && buf[3] != '-') {
				ressent = 1;
				break;
			}
		}
		sc = param->remsock;
		param->remsock = ss;
		so._setsockopt(param->remsock, SOL_SOCKET, SO_LINGER, (unsigned char *)&lg, sizeof(lg));
		so._setsockopt(clidatasock, SOL_SOCKET, SO_LINGER, (unsigned char *)&lg, sizeof(lg));
		param->clisock = clidatasock;
		res = sockmap(param, conf.timeouts[CONNECTION_S]);
		if(param->remsock != INVALID_SOCKET) {
			so._shutdown (param->remsock, SHUT_RDWR);
			so._closesocket(param->remsock);
		}
		if(param->clisock != INVALID_SOCKET) {
			so._shutdown (param->clisock, SHUT_RDWR);
			so._closesocket(param->clisock);
		}
		param->clisock = param->ctrlsock;
		param->remsock = sc;
		sc = INVALID_SOCKET;
		ss = INVALID_SOCKET;
		clidatasock = INVALID_SOCKET;
		if(!ressent){
			while((i = sockgetlinebuf(param, SERVER, buf, BUFSIZE, '\n', conf.timeouts[STRING_L])) > 3){
				if(socksend(param->ctrlsock, buf, i, conf.timeouts[STRING_S])!=i) {RETURN(833);}
				if(isnumber(*buf) && buf[3] != '-') break;
			}
			if(i < 3) {RETURN(834);}
		}
	}
	else {
		if(status < 3) {
			if(socksend(param->remsock, (unsigned char *)"530 login\r\n", 11, conf.timeouts[STRING_S])!=1) {RETURN (810);}
			continue;
		}
		if(!strncasecmp((char *)buf, "QUIT", 4)) status = 5;
		if(!strncasecmp((char *)buf, "CWD ", 4)) req = mystrdup((char *)buf);
		i = (int)strlen((char *)buf);
		buf[i++] = '\r';
		buf[i++] = '\n';
		if(socksend(param->remsock, buf, i, conf.timeouts[STRING_S])!=i) {RETURN (811);}
		param->statscli += i;
		param->nwrites++;
		while((i = sockgetlinebuf(param, SERVER, buf, BUFSIZE, '\n', conf.timeouts[STRING_L])) > 0){
			if(socksend(param->ctrlsock, buf, i, conf.timeouts[STRING_S])!=i) {RETURN (812);}
			if(i > 4 && isnumber(*buf) && buf[3] != '-') break;
		}
		if(status == 5) {RETURN (0);}
		if(i < 3) {RETURN (813);}
	}
	sasize = sizeof(struct sockaddr_in);
	if(so._getpeername(param->ctrlsock, (struct sockaddr *)&param->sinc, &sasize)){RETURN(819);}
	if(req && (param->statscli || param->statssrv)){
		(*param->srv->logfunc)(param, (unsigned char *)req);
	}
 }

CLEANRET:

 if(sc != INVALID_SOCKET) {
	so._shutdown(sc, SHUT_RDWR);
	so._closesocket(sc);
 }
 if(ss != INVALID_SOCKET) {
	so._shutdown(ss, SHUT_RDWR);
	so._closesocket(ss);
 }
 if(clidatasock != INVALID_SOCKET) {
	so._shutdown(clidatasock, SHUT_RDWR);
	so._closesocket(clidatasock);
 }
 sasize = sizeof(struct sockaddr_in);
 so._getpeername(param->ctrlsock, (struct sockaddr *)&param->sinc, &sasize);
 if(param->res != 0 || param->statscli || param->statssrv ){
	(*param->srv->logfunc)(param, (unsigned char *)((req && (param->res > 802))? req:NULL));
 }
 if(req) myfree(req);
 if(buf) myfree(buf);
 freeparam(param);
 return (NULL);
}
Exemplo n.º 10
0
STATIC void
evalcommand(shinstance *psh, union node *cmd, int flags, struct backcmd *backcmd)
{
	struct stackmark smark;
	union node *argp;
	struct arglist arglist;
	struct arglist varlist;
	char **argv;
	int argc;
	char **envp;
	int varflag;
	struct strlist *sp;
	int mode;
	int pip[2];
	struct cmdentry cmdentry;
	struct job *jp;
	struct jmploc jmploc;
	struct jmploc *volatile savehandler;
	char *volatile savecmdname;
	volatile struct shparam saveparam;
	struct localvar *volatile savelocalvars;
	volatile int e;
	char *lastarg;
	const char *path = pathval(psh);
	volatile int temp_path;
#if __GNUC__
	/* Avoid longjmp clobbering */
	(void) &argv;
	(void) &argc;
	(void) &lastarg;
	(void) &flags;
#endif

	psh->vforked = 0;
	/* First expand the arguments. */
	TRACE((psh, "evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
	setstackmark(psh, &smark);
	psh->back_exitstatus = 0;

	arglist.lastp = &arglist.list;
	varflag = 1;
	/* Expand arguments, ignoring the initial 'name=value' ones */
	for (argp = cmd->ncmd.args ; argp ; argp = argp->narg.next) {
		char *p = argp->narg.text;
		if (varflag && is_name(*p)) {
			do {
				p++;
			} while (is_in_name(*p));
			if (*p == '=')
				continue;
		}
		expandarg(psh, argp, &arglist, EXP_FULL | EXP_TILDE);
		varflag = 0;
	}
	*arglist.lastp = NULL;

	expredir(psh, cmd->ncmd.redirect);

	/* Now do the initial 'name=value' ones we skipped above */
	varlist.lastp = &varlist.list;
	for (argp = cmd->ncmd.args ; argp ; argp = argp->narg.next) {
		char *p = argp->narg.text;
		if (!is_name(*p))
			break;
		do
			p++;
		while (is_in_name(*p));
		if (*p != '=')
			break;
		expandarg(psh, argp, &varlist, EXP_VARTILDE);
	}
	*varlist.lastp = NULL;

	argc = 0;
	for (sp = arglist.list ; sp ; sp = sp->next)
		argc++;
	argv = stalloc(psh, sizeof (char *) * (argc + 1));

	for (sp = arglist.list ; sp ; sp = sp->next) {
		TRACE((psh, "evalcommand arg: %s\n", sp->text));
		*argv++ = sp->text;
	}
	*argv = NULL;
	lastarg = NULL;
	if (iflag(psh) && psh->funcnest == 0 && argc > 0)
		lastarg = argv[-1];
	argv -= argc;

	/* Print the command if xflag is set. */
	if (xflag(psh)) {
		char sep = 0;
		out2str(psh, ps4val(psh));
		for (sp = varlist.list ; sp ; sp = sp->next) {
			if (sep != 0)
				outc(sep, &psh->errout);
			out2str(psh, sp->text);
			sep = ' ';
		}
		for (sp = arglist.list ; sp ; sp = sp->next) {
			if (sep != 0)
				outc(sep, &psh->errout);
			out2str(psh, sp->text);
			sep = ' ';
		}
		outc('\n', &psh->errout);
		flushout(&psh->errout);
	}

	/* Now locate the command. */
	if (argc == 0) {
		cmdentry.cmdtype = CMDSPLBLTIN;
		cmdentry.u.bltin = bltincmd;
	} else {
		static const char PATH[] = "PATH=";
		int cmd_flags = DO_ERR;

		/*
		 * Modify the command lookup path, if a PATH= assignment
		 * is present
		 */
		for (sp = varlist.list; sp; sp = sp->next)
			if (strncmp(sp->text, PATH, sizeof(PATH) - 1) == 0)
				path = sp->text + sizeof(PATH) - 1;

		do {
			int argsused, use_syspath;
			find_command(psh, argv[0], &cmdentry, cmd_flags, path);
			if (cmdentry.cmdtype == CMDUNKNOWN) {
				psh->exitstatus = 127;
				flushout(&psh->errout);
				goto out;
			}

			/* implement the 'command' builtin here */
			if (cmdentry.cmdtype != CMDBUILTIN ||
			    cmdentry.u.bltin != bltincmd)
				break;
			cmd_flags |= DO_NOFUNC;
			argsused = parse_command_args(psh, argc, argv, &use_syspath);
			if (argsused == 0) {
				/* use 'type' builting to display info */
				cmdentry.u.bltin = typecmd;
				break;
			}
			argc -= argsused;
			argv += argsused;
			if (use_syspath)
				path = syspath(psh) + 5;
		} while (argc != 0);
		if (cmdentry.cmdtype == CMDSPLBLTIN && cmd_flags & DO_NOFUNC)
			/* posix mandates that 'command <splbltin>' act as if
			   <splbltin> was a normal builtin */
			cmdentry.cmdtype = CMDBUILTIN;
	}

	/* Fork off a child process if necessary. */
	if (cmd->ncmd.backgnd
	 || (cmdentry.cmdtype == CMDNORMAL && (flags & EV_EXIT) == 0)
	 || ((flags & EV_BACKCMD) != 0
	    && ((cmdentry.cmdtype != CMDBUILTIN && cmdentry.cmdtype != CMDSPLBLTIN)
		 || cmdentry.u.bltin == dotcmd
		 || cmdentry.u.bltin == evalcmd))) {
		INTOFF;
		jp = makejob(psh, cmd, 1);
		mode = cmd->ncmd.backgnd;
		if (flags & EV_BACKCMD) {
			mode = FORK_NOJOB;
			if (sh_pipe(psh, pip) < 0)
				error(psh, "Pipe call failed");
		}
#ifdef DO_SHAREDVFORK
		/* It is essential that if DO_SHAREDVFORK is defined that the
		 * child's address space is actually shared with the parent as
		 * we rely on this.
		 */
		if (cmdentry.cmdtype == CMDNORMAL) {
			pid_t	pid;

			savelocalvars = psh->localvars;
			psh->localvars = NULL;
			psh->vforked = 1;
			switch (pid = vfork()) {
			case -1:
				TRACE((psh, "Vfork failed, errno=%d\n", errno));
				INTON;
				error(psh, "Cannot vfork");
				break;
			case 0:
				/* Make sure that exceptions only unwind to
				 * after the vfork(2)
				 */
				if (setjmp(jmploc.loc)) {
					if (psh->exception == EXSHELLPROC) {
						/* We can't progress with the vfork,
						 * so, set vforked = 2 so the parent
						 * knows, and _exit();
						 */
						psh->vforked = 2;
						sh__exit(psh, 0);
					} else {
						sh__exit(psh, psh->exerrno);
					}
				}
				savehandler = psh->handler;
				psh->handler = &jmploc;
				listmklocal(psh, varlist.list, VEXPORT | VNOFUNC);
				forkchild(psh, jp, cmd, mode, psh->vforked);
				break;
			default:
				psh->handler = savehandler;	/* restore from vfork(2) */
				poplocalvars(psh);
				psh->localvars = savelocalvars;
				if (psh->vforked == 2) {
					psh->vforked = 0;

					(void)sh_waitpid(psh, pid, NULL, 0);
					/* We need to progress in a normal fork fashion */
					goto normal_fork;
				}
				psh->vforked = 0;
				forkparent(psh, jp, cmd, mode, pid);
				goto parent;
			}
		} else {
normal_fork:
#endif
			if (forkshell(psh, jp, cmd, mode) != 0)
				goto parent;	/* at end of routine */
			FORCEINTON;
#ifdef DO_SHAREDVFORK
		}
#endif
		if (flags & EV_BACKCMD) {
			if (!psh->vforked) {
				FORCEINTON;
			}
			shfile_close(&psh->fdtab, pip[0]);
			if (pip[1] != 1) {
				movefd(psh, pip[1], 1);
			}
		}
		flags |= EV_EXIT;
	}

	/* This is the child process if a fork occurred. */
	/* Execute the command. */
	switch (cmdentry.cmdtype) {
	case CMDFUNCTION:
#ifdef DEBUG
		trputs(psh, "Shell function:  ");  trargs(psh, argv);
#endif
		redirect(psh, cmd->ncmd.redirect, REDIR_PUSH);
		saveparam = psh->shellparam;
		psh->shellparam.malloc = 0;
		psh->shellparam.reset = 1;
		psh->shellparam.nparam = argc - 1;
		psh->shellparam.p = argv + 1;
		psh->shellparam.optnext = NULL;
		INTOFF;
		savelocalvars = psh->localvars;
		psh->localvars = NULL;
		INTON;
		if (setjmp(jmploc.loc)) {
			if (psh->exception == EXSHELLPROC) {
				freeparam(psh, (volatile struct shparam *)
				    &saveparam);
			} else {
				freeparam(psh, &psh->shellparam);
				psh->shellparam = saveparam;
			}
			poplocalvars(psh);
			psh->localvars = savelocalvars;
			psh->handler = savehandler;
			longjmp(psh->handler->loc, 1);
		}
		savehandler = psh->handler;
		psh->handler = &jmploc;
		listmklocal(psh, varlist.list, 0);
		/* stop shell blowing its stack */
		if (++psh->funcnest > 1000)
			error(psh, "too many nested function calls");
		evaltree(psh, cmdentry.u.func, flags & EV_TESTED);
		psh->funcnest--;
		INTOFF;
		poplocalvars(psh);
		psh->localvars = savelocalvars;
		freeparam(psh, &psh->shellparam);
		psh->shellparam = saveparam;
		psh->handler = savehandler;
		popredir(psh);
		INTON;
		if (psh->evalskip == SKIPFUNC) {
			psh->evalskip = 0;
			psh->skipcount = 0;
		}
		if (flags & EV_EXIT)
			exitshell(psh, psh->exitstatus);
		break;

	case CMDBUILTIN:
	case CMDSPLBLTIN:
#ifdef DEBUG
		trputs(psh, "builtin command:  ");  trargs(psh, argv);
#endif
		mode = (cmdentry.u.bltin == execcmd) ? 0 : REDIR_PUSH;
		if (flags == EV_BACKCMD) {
			psh->memout.nleft = 0;
			psh->memout.nextc = psh->memout.buf;
			psh->memout.bufsize = 64;
			mode |= REDIR_BACKQ;
		}
		e = -1;
		savehandler = psh->handler;
		savecmdname = psh->commandname;
		psh->handler = &jmploc;
		if (!setjmp(jmploc.loc)) {
			/* We need to ensure the command hash table isn't
			 * corruped by temporary PATH assignments.
			 * However we must ensure the 'local' command works!
			 */
			if (path != pathval(psh) && (cmdentry.u.bltin == hashcmd ||
			    cmdentry.u.bltin == typecmd)) {
				savelocalvars = psh->localvars;
				psh->localvars = 0;
				mklocal(psh, path - 5 /* PATH= */, 0);
				temp_path = 1;
			} else
				temp_path = 0;
			redirect(psh, cmd->ncmd.redirect, mode);

			/* exec is a special builtin, but needs this list... */
			psh->cmdenviron = varlist.list;
			/* we must check 'readonly' flag for all builtins */
			listsetvar(psh, varlist.list,
				cmdentry.cmdtype == CMDSPLBLTIN ? 0 : VNOSET);
			psh->commandname = argv[0];
			/* initialize nextopt */
			psh->argptr = argv + 1;
			psh->optptr = NULL;
			/* and getopt */
#if 0 /** @todo fix getop usage! */
#if defined(__FreeBSD__) || defined(__EMX__) || defined(__APPLE__)
			optreset = 1;
			optind = 1;
#else
			optind = 0; /* init */
#endif
#endif

			psh->exitstatus = cmdentry.u.bltin(psh, argc, argv);
		} else {
			e = psh->exception;
			psh->exitstatus = e == EXINT ? SIGINT + 128 :
					e == EXEXEC ? psh->exerrno : 2;
		}
		psh->handler = savehandler;
		output_flushall(psh);
		psh->out1 = &psh->output;
		psh->out2 = &psh->errout;
		freestdout(psh);
		if (temp_path) {
			poplocalvars(psh);
			psh->localvars = savelocalvars;
		}
		psh->cmdenviron = NULL;
		if (e != EXSHELLPROC) {
			psh->commandname = savecmdname;
			if (flags & EV_EXIT)
				exitshell(psh, psh->exitstatus);
		}
		if (e != -1) {
			if ((e != EXERROR && e != EXEXEC)
			    || cmdentry.cmdtype == CMDSPLBLTIN)
				exraise(psh, e);
			FORCEINTON;
		}
		if (cmdentry.u.bltin != execcmd)
			popredir(psh);
		if (flags == EV_BACKCMD) {
			backcmd->buf = psh->memout.buf;
			backcmd->nleft = (int)(psh->memout.nextc - psh->memout.buf);
			psh->memout.buf = NULL;
		}
		break;

	default:
#ifdef DEBUG
		trputs(psh, "normal command:  ");  trargs(psh, argv);
#endif
		clearredir(psh, psh->vforked);
		redirect(psh, cmd->ncmd.redirect, psh->vforked ? REDIR_VFORK : 0);
		if (!psh->vforked)
			for (sp = varlist.list ; sp ; sp = sp->next)
				setvareq(psh, sp->text, VEXPORT|VSTACK);
		envp = environment(psh);
		shellexec(psh, argv, envp, path, cmdentry.u.index, psh->vforked);
		break;
	}
	goto out;

parent:	/* parent process gets here (if we forked) */
	if (mode == FORK_FG) {	/* argument to fork */
		psh->exitstatus = waitforjob(psh, jp);
	} else if (mode == FORK_NOJOB) {
		backcmd->fd = pip[0];
		shfile_close(&psh->fdtab, pip[1]);
		backcmd->jp = jp;
	}
	FORCEINTON;

out:
	if (lastarg)
		/* dsl: I think this is intended to be used to support
		 * '_' in 'vi' command mode during line editing...
		 * However I implemented that within libedit itself.
		 */
		setvar(psh, "_", lastarg, 0);
	popstackmark(psh, &smark);

	if (eflag(psh) && psh->exitstatus && !(flags & EV_TESTED))
		exitshell(psh, psh->exitstatus);
}
Exemplo n.º 11
0
void * adminchild(struct clientparam* param) {
 int i, res;
 char * buf;
 char username[256];
 char *sb;
 char *req = NULL;
 struct printparam pp;
 int contentlen = 0;
 int isform = 0;

 pp.inbuf = 0;
 pp.cp = param;

 buf = myalloc(LINESIZE);
 if(!buf) {RETURN(555);}
 i = sockgetlinebuf(param, CLIENT, (unsigned char *)buf, LINESIZE - 1, '\n', conf.timeouts[STRING_S]);
 if(i<5 || ((buf[0]!='G' || buf[1]!='E' || buf[2]!='T' || buf[3]!=' ' || buf[4]!='/') && 
	   (buf[0]!='P' || buf[1]!='O' || buf[2]!='S' || buf[3]!='T' || buf[4]!=' ' || buf[5]!='/')))
 {
	RETURN(701);
 }
 buf[i] = 0;
 sb = strchr(buf+5, ' ');
 if(!sb){
	RETURN(702);
 }
 *sb = 0;
 req = mystrdup(buf + ((*buf == 'P')? 6 : 5));
 while((i = sockgetlinebuf(param, CLIENT, (unsigned char *)buf, LINESIZE - 1, '\n', conf.timeouts[STRING_S])) > 2){
	buf[i] = 0;
	if(i > 19 && (!strncasecmp(buf, "authorization", 13))){
		sb = strchr(buf, ':');
		if(!sb)continue;
		++sb;
		while(isspace(*sb))sb++;
		if(!*sb || strncasecmp(sb, "basic", 5)){
			continue;
		}
		sb+=5;
		while(isspace(*sb))sb++;
		i = de64((unsigned char *)sb, (unsigned char *)username, 255);
		if(i<=0)continue;
		username[i] = 0;
		sb = strchr((char *)username, ':');
		if(sb){
			*sb = 0;
			if(param->password)myfree(param->password);
			param->password = (unsigned char *)mystrdup(sb+1);
		}
		if(param->username) myfree(param->username);
		param->username = (unsigned char *)mystrdup(username);
		continue;
	}
	else if(i > 15 && (!strncasecmp(buf, "content-length:", 15))){
		sb = buf + 15;
		while(isspace(*sb))sb++;
		contentlen = atoi(sb);
	}
	else if(i > 13 && (!strncasecmp(buf, "content-type:", 13))){
		sb = buf + 13;
		while(isspace(*sb))sb++;
		if(!strncasecmp(sb, "x-www-form-urlencoded", 21)) isform = 1;
	}
 }
 param->operation = ADMIN;
 if(isform && contentlen) {
	printstr(&pp, "HTTP/1.0 100 Continue\r\n\r\n");
	stdpr(&pp, NULL, 0);
 }
 res = (*param->srv->authfunc)(param);
 if(res && res != 10) {
	printstr(&pp, authreq);
	RETURN(res);
 }
 if(param->srv->singlepacket || param->redirected){
	if(*req == 'C') req[1] = 0;
	else *req = 0;
 }
 sprintf(buf, ok, conf.stringtable?(char *)conf.stringtable[2]:"3proxy", conf.stringtable?(char *)conf.stringtable[2]:"3[APA3A] tiny proxy", conf.stringtable?(char *)conf.stringtable[3]:"");
 if(*req != 'S') printstr(&pp, buf);
 switch(*req){
	case 'C':
		printstr(&pp, counters);
		{
			struct trafcount *cp; 
			int num = 0;
			for(cp = conf.trafcounter; cp; cp = cp->next, num++){
			 int inbuf = 0;

			 if(cp->ace && (param->srv->singlepacket || param->redirected)){
				if(!ACLmatches(cp->ace, param))continue;
			 }
			 if(req[1] == 'S' && atoi(req+2) == num) cp->disabled=0;
			 if(req[1] == 'D' && atoi(req+2) == num) cp->disabled=1;
			 inbuf += sprintf(buf,	"<tr>"
						"<td>%s</td><td><A HREF=\'/C%c%d\'>%s</A></td><td>",
						(cp->comment)?cp->comment:"&nbsp;",
						(cp->disabled)?'S':'D',
						num,
						(cp->disabled)?"NO":"YES"
					);
			 if(!cp->ace || !cp->ace->users){
				inbuf += sprintf(buf+inbuf, "<center>ANY</center>");
			 }
			 else {
				inbuf += printuserlist(buf+inbuf, LINESIZE-800, cp->ace->users, ",<br />\r\n");
			 }
			 inbuf += sprintf(buf+inbuf, "</td><td>");
			 if(!cp->ace || !cp->ace->src){
				inbuf += sprintf(buf+inbuf, "<center>ANY</center>");
			 }
			 else {
				inbuf += printiplist(buf+inbuf, LINESIZE-512, cp->ace->src, ",<br />\r\n");
			 }
			 inbuf += sprintf(buf+inbuf, "</td><td>");
			 if(!cp->ace || !cp->ace->dst){
				inbuf += sprintf(buf+inbuf, "<center>ANY</center>");
			 }
			 else {
				inbuf += printiplist(buf+inbuf, LINESIZE-512, cp->ace->dst, ",<br />\r\n");
			 }
			 inbuf += sprintf(buf+inbuf, "</td><td>");
			 if(!cp->ace || !cp->ace->ports){
				inbuf += sprintf(buf+inbuf, "<center>ANY</center>");
			 }
			 else {
				inbuf += printportlist(buf+inbuf, LINESIZE-128, cp->ace->ports, ",<br />\r\n");
			 }
			 if(cp->type == NONE) {
			  inbuf += sprintf(buf+inbuf,	
					"</td><td colspan=\'6\' align=\'center\'>exclude from limitation</td></tr>\r\n"
				 );
			 }
			 else {
			  inbuf += sprintf(buf+inbuf,	
					"</td><td>%.3f</td>"
					"<td>MB%s</td>"
					"<td>%.3f MB</td>"
					"<td>%s</td>",
				 (1024.0 * (float)cp->traflimgb) + (float)cp->traflim/1048576.0,
				 rotations[cp->type],
				 (1024.0 * (float)cp->trafgb) + (float)cp->traf/1048576.0,
				 cp->cleared?ctime(&cp->cleared):"never"
				);
			 inbuf += sprintf(buf + inbuf,
					"<td>%s</td>"
					"<td>%i</td>"
					"</tr>\r\n",

				 cp->updated?ctime(&cp->updated):"never",
				 cp->number
				);
			 }
			 printstr(&pp, buf);
			}

		}
		printstr(&pp, counterstail);
		break;
		
	case 'R':
		conf.needreload = 1;
		printstr(&pp, "<h3>Reload scheduled</h3>");
		break;
	case 'S':
		{
			if(req[1] == 'X'){
				printstr(&pp, style);
				break;
			}
			printstr(&pp, xml);
			printval(conf.services, TYPE_SERVER, 0, &pp);
			printstr(&pp, postxml);
		}
			break;
	case 'F':
		{
			FILE *fp;
			char buf[256];

			fp = confopen();
			if(!fp){
				printstr(&pp, "<h3><font color=\"red\">Failed to open config file</font></h3>");
				break;
			}
				printstr(&pp, "<h3>Please be careful editing config file remotely</h3>");
				printstr(&pp, "<form method=\"POST\" action=\"/U\"><textarea cols=\"80\" rows=\"30\" name=\"conffile\">");
				while(fgets(buf, 256, fp)){
					printstr(&pp, buf);
				}
				if(!writable) fclose(fp);
				printstr(&pp, "</textarea><br><input type=\"Submit\"></form>");
			break;
		}
	case 'U':
		{
			int l=0;
			int error = 0;

			if(!writable || fseek(writable, 0, 0)){
				error = 1;
			}
			while((i = sockgetlinebuf(param, CLIENT, (unsigned char *)buf, LINESIZE - 1, '+', conf.timeouts[STRING_S])) > 0){
				if(i > (contentlen - l)) i = (contentlen - l);
				buf[i] = 0;
				if(!l){
					if(strncasecmp(buf, "conffile=", 9)) error = 1;
				}
				if(!error){
					decodeurl((unsigned char *)buf, 1);
					fprintf(writable, "%s", l? buf : buf + 9);
				}
				l += i;
				if(l >= contentlen) break;
			}
			if(writable && !error){
				fflush(writable);
#ifndef _WINCE
				ftruncate(fileno(writable), ftell(writable));
#endif
			}
			printstr(&pp, error?    "<h3><font color=\"red\">Config file is not writable</font></h3>Make sure you have \"writable\" command in configuration file":
						"<h3>Configuration updated</h3>");

		}
		break;
	default:
		printstr(&pp, (char *)conf.stringtable[WEBBANNERS]);
		break;
 }
 if(*req != 'S') printstr(&pp, tail);

CLEANRET:


 printstr(&pp, NULL);
 if(buf) myfree(buf);
 (*param->srv->logfunc)(param, (unsigned char *)req);
 if(req)myfree(req);
 freeparam(param);
 return (NULL);
}
Exemplo n.º 12
0
void * udppmchild(struct clientparam* param) {
 unsigned char *buf = NULL;
 int res, i;
#ifdef _WIN32
 SASIZETYPE size;
 unsigned long ul = 1;
#endif
 struct udpmap *udpmappings = NULL;
 struct pollfd fds[256];


 if(!param->hostname)parsehostname((char *)param->srv->target, param, ntohs(param->srv->targetport));
 if (!param->req.sin_addr.s_addr) {
	param->srv->fds.events = POLLIN;
	RETURN (100);
 }
 if(!param->clibuf && (!(param->clibuf=myalloc(UDPBUFSIZE)) || !(param->clibufsize = UDPBUFSIZE))){
	param->srv->fds.events = POLLIN;
	RETURN (21);
 }
 param->cliinbuf = param->clioffset = 0;
 i = sockrecvfrom(param->srv->srvsock, &param->sinc, param->clibuf, param->clibufsize, 0);
 if(i<=0){
	param->srv->fds.events = POLLIN;
	RETURN (214);
 }
 param->cliinbuf = i;

#ifdef _WIN32
	if((param->clisock=so._socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) {
		RETURN(818);
	}
	if(so._setsockopt(param->clisock, SOL_SOCKET, SO_REUSEADDR, (unsigned char *)&ul, sizeof(int))) {RETURN(820);};
	ioctlsocket(param->clisock, FIONBIO, &ul);
	size = sizeof(struct sockaddr_in);
	if(so._getsockname(param->srv->srvsock, (struct sockaddr *)&param->sins, &size)) {RETURN(21);};
	if(so._bind(param->clisock,(struct sockaddr *)&param->sins,sizeof(struct sockaddr_in))) {
		RETURN(822);
	}
#else
	param->clisock = param->srv->srvsock;
#endif

 param->sins.sin_family = AF_INET;
 param->sins.sin_port = htons(0);
 param->sins.sin_addr.s_addr = param->extip;
 if ((param->remsock=so._socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) {RETURN (11);}
 if(so._bind(param->remsock,(struct sockaddr *)&param->sins,sizeof(param->sins))) {RETURN (12);}
#ifdef _WIN32
	ioctlsocket(param->remsock, FIONBIO, &ul);
#else
	fcntl(param->remsock,F_SETFL,O_NONBLOCK);
#endif
 param->sins.sin_addr.s_addr = param->req.sin_addr.s_addr;
 param->sins.sin_port = param->req.sin_port;

 param->operation = UDPASSOC;
 if((res = (*param->srv->authfunc)(param))) {RETURN(res);}
 if(param->srv->singlepacket) {
	param->srv->fds.events = POLLIN;
 }

 param->res = sockmap(param, conf.timeouts[(param->srv->singlepacket)?SINGLEBYTE_L:STRING_L]);
 if(!param->srv->singlepacket) {
	param->srv->fds.events = POLLIN;
 }

CLEANRET:

 if(buf)myfree(buf);
 (*param->srv->logfunc)(param, NULL);
#ifndef _WIN32
 param->clisock = INVALID_SOCKET;
#endif
 freeparam(param);
 return (NULL);
}
Exemplo n.º 13
0
void * dnsprchild(struct clientparam* param) {
 unsigned long ip = 0;
 unsigned char *bbuf;
 unsigned char *buf, *s1, *s2;
 char * host = NULL;
 unsigned char c;
 SASIZETYPE size;
 int res, i;
 int len;
 unsigned type=0;
 unsigned ttl;
 unsigned char addr[16];
#ifdef _WIN32
	unsigned long ul = 1;
#endif


 if(!(bbuf = myalloc(BUFSIZE+2))){
	param->srv->fds.events = POLLIN;
	RETURN (21);
 }
 buf = bbuf+2;
 size = sizeof(param->sincr);
 i = so._recvfrom(param->srv->srvsock, buf, BUFSIZE, 0, (struct sockaddr *)&param->sincr, &size); 
 size = sizeof(param->sinsl);
 getsockname(param->srv->srvsock, (struct sockaddr *)&param->sincl, &size);
#ifdef _WIN32
	if((param->clisock=so._socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) {
		RETURN(818);
	}
	ioctlsocket(param->clisock, FIONBIO, &ul);
	if(so._setsockopt(param->clisock, SOL_SOCKET, SO_REUSEADDR, (unsigned char *)&ul, sizeof(int))) {RETURN(820);};
	if(so._bind(param->clisock,(struct sockaddr *)&param->sincl,sizeof(param->sincl))) {
		RETURN(822);
	}

#else
	param->clisock = param->srv->srvsock;
#endif
 param->srv->fds.events = POLLIN;

 if(i < 0) {
	RETURN(813);
 }
 buf[BUFSIZE - 1] = 0;
 if(i<=13 || i>1000){
	RETURN (814);
 }
 param->operation = DNSRESOLVE;
 if((res = (*param->srv->authfunc)(param))) {RETURN(res);}
 
 if(buf[4]!=0 || buf[5]!=1) RETURN(816);
 for(len = 12; len<i; len+=(c+1)){
	c = buf[len];
	if(!c)break;
	buf[len] = '.';
 }
 if(len > (i-4)) {RETURN(817);}

 host = mystrdup((char *)buf+13);
 if(!host) {RETURN(21);}

 for(s2 = buf + 12; (s1 = (unsigned char *)strchr((char *)s2 + 1, '.')); s2 = s1)*s2 = (unsigned char)((s1 - s2) - 1); 
 *s2 = (len - (int)(s2 - buf)) - 1;

 type = ((unsigned)buf[len+1])*256 + (unsigned)buf[len+2];
 if((type==0x01 || type==0x1c) && !param->srv->singlepacket){
 	ip = udpresolve((type==0x1c)?AF_INET6:AF_INET, (unsigned char *)host, addr, &ttl, param, 0);
 }

 len+=5;

 if(ip){
	buf[2] = 0x85;
	buf[3] = 0x80;
	buf[6] = 0;
	buf[7] = 1;
	buf[8] = buf[9] = buf[10] = buf[11] = 0;
 	memset(buf+len, 0, 16);
	buf[len] = 0xc0;
	buf[len+1] = 0x0c;
	buf[len+3] = type;
	buf[len+5] = 1;
	ttl = htonl(ttl);
	memcpy(buf + len + 6, &ttl, 4);
	buf[len+11] = type==1? 4:16;
	memcpy(buf+len+12,(void *)&addr,type==1? 4:16);
	len+=(type==1?16:28);
 }
 else if(type == 0x0c) {
	unsigned a, b, c, d;
	sscanf(host, "%u.%u.%u.%u", &a, &b, &c, &d);
	ip = htonl((d<<24) ^ (c<<16) ^ (b<<8) ^ a);
	if(*SAFAMILY(&param->sincl) == AF_INET &&  ip == *(unsigned long*)SAADDR(&param->sincl)){
		buf[2] = 0x85;
		buf[3] = 0x80;
		buf[6] = 0;
		buf[7] = 1;
		buf[8] = buf[9] = buf[10] = buf[11] = 0;
	 	memset(buf+len, 0, 20);
		buf[len] = 0xc0;
		buf[len+1] = 0x0c;
		buf[len+3] = 0x0c;
		buf[len+5] = 1;
		ttl = htonl(3600);
		memcpy(buf + len + 6, &ttl, 4);
		buf[len+11] = 7;
		buf[len+12] = 6;
		memcpy(buf+len+13,(void *)"3proxy",6);
		len+=20;
	}
	else ip = 0;
 }
 if(!ip && numservers){
	if((param->remsock=so._socket(SASOCK(&nservers[0].addr), nservers[0].usetcp? SOCK_STREAM:SOCK_DGRAM, nservers[0].usetcp?IPPROTO_TCP:IPPROTO_UDP)) == INVALID_SOCKET) {
		RETURN(818);
	}
	memset(&param->sinsl, 0, sizeof(param->sinsl));
	*SAFAMILY(&param->sinsl) = *SAFAMILY(&nservers[0].addr);
	if(so._bind(param->remsock,(struct sockaddr *)&param->sinsl,sizeof(param->sinsl))) {
		RETURN(819);
	}
	memcpy(&param->sinsr, &nservers[0].addr, sizeof(param->sinsr));
	if(nservers[0].usetcp) {
		if(so._connect(param->remsock,(struct sockaddr *)&param->sinsr,sizeof(param->sinsr))) RETURN(830);
		buf-=2;
		*(unsigned short*)buf = htons(i);
		i+=2;
	}
	else {
#ifdef _WIN32
/*		ioctlsocket(param->remsock, FIONBIO, &ul); */
#else
/*		fcntl(param->remsock,F_SETFL,O_NONBLOCK);  */
#endif
	}

	if(socksendto(param->remsock, (struct sockaddr *)&param->sinsr, buf, i, conf.timeouts[SINGLEBYTE_L]*1000) != i){
		RETURN(820);
	}
	param->statscli64 += i;
	param->nwrites++;
	len = sockrecvfrom(param->remsock, (struct sockaddr *)&param->sinsr, buf, BUFSIZE, 15000);
	if(len <= 13) {
		RETURN(821);
	}
	param->statssrv64 += len;
	param->nreads++;
	if(nservers[0].usetcp) {
		unsigned short us;
		us = ntohs(*(unsigned short *)buf);
		if(us > 4096) RETURN(833);
		buf += 2;
		len -= 2;
		if(len < us) len += sockgetlinebuf(param, SERVER, buf+len, us - len, 0, conf.timeouts[SINGLEBYTE_L]);
		if(len != us) RETURN(832);
	}
	if(buf[6] || buf[7]){
		if(socksendto(param->clisock, (struct sockaddr *)&param->sincr, buf, len, conf.timeouts[SINGLEBYTE_L]*1000) != len){
			RETURN(822);
		}
		RETURN(0);
	}

 }
 if(!ip) {
	buf[2] = 0x85;
	buf[3] = 0x83;
 }
 res = socksendto(param->clisock, (struct sockaddr *)&param->sincr, buf, len, conf.timeouts[SINGLEBYTE_L]*1000); 
 if(res != len){RETURN(819);}
 if(!ip) {RETURN(888);}

CLEANRET:

 if(param->res!=813){
	sprintf((char *)buf, "%04x/%s/", 
			(unsigned)type,
			host?host:"");
	if(ip && type == 0x01 || type == 0x1c){
		myinet_ntop(type == 0x01? AF_INET:AF_INET6, addr, buf+strlen(buf), 64);
	}
	(*param->srv->logfunc)(param, buf);
 }
 if(bbuf)myfree(bbuf);
 if(host)myfree(host);
#ifndef _WIN32
 param->clisock = INVALID_SOCKET;
#endif
 freeparam(param);
 return (NULL);
}