* Makefile.in (DLL_OFILES): Add rexec.o.
* autoload.cc (inet_network): Drop definition. (rexec): Ditto. * net.cc (rexec): Drop extern declaration. (inet_network): Ditto. (cygwin_inet_network): Implement using inet_addr. (cygwin_rexec): Remove. * libc/rexec.cc: New file.
This commit is contained in:
		
							
								
								
									
										416
									
								
								winsup/cygwin/libc/rexec.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										416
									
								
								winsup/cygwin/libc/rexec.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,416 @@ | ||||
| /* | ||||
|  * Copyright (c) 1980, 1993 | ||||
|  *	The 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. | ||||
|  * | ||||
|  * $FreeBSD$ | ||||
|  */ | ||||
|  | ||||
| /* CV 2006-07-04: Tweaked for inclusion into Cygwin. */ | ||||
|  | ||||
| #if defined(LIBC_SCCS) && !defined(lint) | ||||
| static char sccsid[] = "@(#)rexec.c	8.1 (Berkeley) 6/4/93"; | ||||
| #endif /* LIBC_SCCS and not lint */ | ||||
|  | ||||
| #ifdef __CYGWIN__ | ||||
| #include "winsup.h" | ||||
| #include "sigproc.h" | ||||
| #include "cygtls.h" | ||||
| #include <wininet.h> | ||||
| #endif | ||||
|  | ||||
| #include <sys/types.h> | ||||
| #include <sys/uio.h> | ||||
| #include <sys/socket.h> | ||||
| #include <sys/param.h> | ||||
| #include <sys/stat.h> | ||||
|  | ||||
| #include <netinet/in.h> | ||||
|  | ||||
| #include <stdio.h> | ||||
| #include <unistd.h> | ||||
| #include <string.h> | ||||
| #include <netdb.h> | ||||
| #include <errno.h> | ||||
| #include <ctype.h> | ||||
| #include <err.h> | ||||
| #include <stdlib.h> | ||||
| #include <unistd.h> | ||||
|  | ||||
| extern "C" { | ||||
|   int cygwin_accept (int, struct sockaddr *, socklen_t *); | ||||
|   int cygwin_connect (int, const struct sockaddr *, socklen_t); | ||||
|   int cygwin_getsockname (int, struct sockaddr *, socklen_t *); | ||||
|   void cygwin_herror (const char *); | ||||
|   int cygwin_listen (int, int); | ||||
|   int cygwin_socket (int, int, int); | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * Options and other state info. | ||||
|  */ | ||||
| struct macel { | ||||
| 	char mac_name[9];	/* macro name */ | ||||
| 	char *mac_start;	/* start of macro in macbuf */ | ||||
| 	char *mac_end;		/* end of macro in macbuf */ | ||||
| }; | ||||
|  | ||||
| int macnum;			/* number of defined macros */ | ||||
| struct macel macros[16]; | ||||
| char macbuf[4096]; | ||||
|  | ||||
| static	FILE *cfile; | ||||
|  | ||||
| #define	DEFAULT	1 | ||||
| #define	LOGIN	2 | ||||
| #define	PASSWD	3 | ||||
| #define	ACCOUNT 4 | ||||
| #define MACDEF  5 | ||||
| #define	ID	10 | ||||
| #define	MACH	11 | ||||
|  | ||||
| static char tokval[100]; | ||||
|  | ||||
| static struct toktab { | ||||
| 	const char *tokstr; | ||||
| 	int tval; | ||||
| } toktab[]= { | ||||
| 	{ "default",	DEFAULT }, | ||||
| 	{ "login",	LOGIN }, | ||||
| 	{ "password",	PASSWD }, | ||||
| 	{ "passwd",	PASSWD }, | ||||
| 	{ "account",	ACCOUNT }, | ||||
| 	{ "machine",	MACH }, | ||||
| 	{ "macdef",	MACDEF }, | ||||
| 	{ NULL,		0 } | ||||
| }; | ||||
|  | ||||
| static int | ||||
| token() | ||||
| { | ||||
| 	char *cp; | ||||
| 	int c; | ||||
| 	struct toktab *t; | ||||
|  | ||||
| 	if (feof(cfile) || ferror(cfile)) | ||||
| 		return (0); | ||||
| 	while ((c = getc(cfile)) != EOF && | ||||
| 	    (c == '\n' || c == '\t' || c == ' ' || c == ',')) | ||||
| 		continue; | ||||
| 	if (c == EOF) | ||||
| 		return (0); | ||||
| 	cp = tokval; | ||||
| 	if (c == '"') { | ||||
| 		while ((c = getc(cfile)) != EOF && c != '"') { | ||||
| 			if (c == '\\') | ||||
| 				c = getc(cfile); | ||||
| 			*cp++ = c; | ||||
| 		} | ||||
| 	} else { | ||||
| 		*cp++ = c; | ||||
| 		while ((c = getc(cfile)) != EOF | ||||
| 		    && c != '\n' && c != '\t' && c != ' ' && c != ',') { | ||||
| 			if (c == '\\') | ||||
| 				c = getc(cfile); | ||||
| 			*cp++ = c; | ||||
| 		} | ||||
| 	} | ||||
| 	*cp = 0; | ||||
| 	if (tokval[0] == 0) | ||||
| 		return (0); | ||||
| 	for (t = toktab; t->tokstr; t++) | ||||
| 		if (!strcmp(t->tokstr, tokval)) | ||||
| 			return (t->tval); | ||||
| 	return (ID); | ||||
| } | ||||
|  | ||||
| static int | ||||
| ruserpass(const char *host, char **aname, char **apass, char **aacct) | ||||
| { | ||||
| 	const char *hdir; | ||||
| 	char buf[BUFSIZ], *tmp; | ||||
| 	char myname[INTERNET_MAX_HOST_NAME_LENGTH + 1]; | ||||
| 	const char *mydomain; | ||||
| 	int t, i, c, usedefault = 0; | ||||
| 	struct stat stb; | ||||
|  | ||||
| 	hdir = getenv("HOME"); | ||||
| 	if (hdir == NULL) | ||||
| 		hdir = "."; | ||||
| 	if (strlen(hdir) + 8 > sizeof(buf)) | ||||
| 		return (0); | ||||
| 	(void) sprintf(buf, "%s/.netrc", hdir); | ||||
| 	cfile = fopen(buf, "r"); | ||||
| 	if (cfile == NULL) { | ||||
| 		if (errno != ENOENT) | ||||
| 			warn("%s", buf); | ||||
| 		return (0); | ||||
| 	} | ||||
| 	if (cygwin_gethostname(myname, sizeof(myname)) < 0) | ||||
| 		myname[0] = '\0'; | ||||
| 	if ((mydomain = strchr(myname, '.')) == NULL) | ||||
| 		mydomain = ""; | ||||
| next: | ||||
| 	while ((t = token())) switch(t) { | ||||
|  | ||||
| 	case DEFAULT: | ||||
| 		usedefault = 1; | ||||
| 		/* FALL THROUGH */ | ||||
|  | ||||
| 	case MACH: | ||||
| 		if (!usedefault) { | ||||
| 			if (token() != ID) | ||||
| 				continue; | ||||
| 			/* | ||||
| 			 * Allow match either for user's input host name | ||||
| 			 * or official hostname.  Also allow match of | ||||
| 			 * incompletely-specified host in local domain. | ||||
| 			 */ | ||||
| 			if (strcasecmp(host, tokval) == 0) | ||||
| 				goto match; | ||||
| 			if ((tmp = strchr(host, '.')) != NULL && | ||||
| 			    strcasecmp(tmp, mydomain) == 0 && | ||||
| 			    strncasecmp(host, tokval, tmp - host) == 0 && | ||||
| 			    tokval[tmp - host] == '\0') | ||||
| 				goto match; | ||||
| 			continue; | ||||
| 		} | ||||
| 	match: | ||||
| 		while ((t = token()) && t != MACH && t != DEFAULT) switch(t) { | ||||
|  | ||||
| 		case LOGIN: | ||||
| 			if (token()) | ||||
| 				if (*aname == 0) { | ||||
| 					*aname = (char *) malloc((unsigned) strlen(tokval) + 1); | ||||
| 					(void) strcpy(*aname, tokval); | ||||
| 				} else { | ||||
| 					if (strcmp(*aname, tokval)) | ||||
| 						goto next; | ||||
| 				} | ||||
| 			break; | ||||
| 		case PASSWD: | ||||
| 			if ((*aname == 0 || strcmp(*aname, "anonymous")) && | ||||
| 			    fstat(fileno(cfile), &stb) >= 0 && | ||||
| 			    (stb.st_mode & 077) != 0) { | ||||
| 	warnx("Error: .netrc file is readable by others."); | ||||
| 	warnx("Remove password or make file unreadable by others."); | ||||
| 				goto bad; | ||||
| 			} | ||||
| 			if (token() && *apass == 0) { | ||||
| 				*apass = (char *) malloc((unsigned) strlen(tokval) + 1); | ||||
| 				(void) strcpy(*apass, tokval); | ||||
| 			} | ||||
| 			break; | ||||
| 		case ACCOUNT: | ||||
| 			if (fstat(fileno(cfile), &stb) >= 0 | ||||
| 			    && (stb.st_mode & 077) != 0) { | ||||
| 	warnx("Error: .netrc file is readable by others."); | ||||
| 	warnx("Remove account or make file unreadable by others."); | ||||
| 				goto bad; | ||||
| 			} | ||||
| 			if (token() && aacct && *aacct == 0) { | ||||
| 				*aacct = (char *) malloc((unsigned) strlen(tokval) + 1); | ||||
| 				(void) strcpy(*aacct, tokval); | ||||
| 			} | ||||
| 			break; | ||||
| 		case MACDEF: | ||||
| 			while ((c=getc(cfile)) != EOF && | ||||
| 						(c == ' ' || c == '\t')) | ||||
| 				; | ||||
| 			if (c == EOF || c == '\n') { | ||||
| 				printf("Missing macdef name argument.\n"); | ||||
| 				goto bad; | ||||
| 			} | ||||
| 			if (macnum == 16) { | ||||
| 				printf("Limit of 16 macros have already been defined\n"); | ||||
| 				goto bad; | ||||
| 			} | ||||
| 			tmp = macros[macnum].mac_name; | ||||
| 			*tmp++ = c; | ||||
| 			for (i=0; i < 8 && (c=getc(cfile)) != EOF && | ||||
| 			    !isspace(c); ++i) { | ||||
| 				*tmp++ = c; | ||||
| 			} | ||||
| 			if (c == EOF) { | ||||
| 				printf("Macro definition missing null line terminator.\n"); | ||||
| 				goto bad; | ||||
| 			} | ||||
| 			*tmp = '\0'; | ||||
| 			if (c != '\n') { | ||||
| 				while ((c=getc(cfile)) != EOF && c != '\n'); | ||||
| 			} | ||||
| 			if (c == EOF) { | ||||
| 				printf("Macro definition missing null line terminator.\n"); | ||||
| 				goto bad; | ||||
| 			} | ||||
| 			if (macnum == 0) { | ||||
| 				macros[macnum].mac_start = macbuf; | ||||
| 			} | ||||
| 			else { | ||||
| 				macros[macnum].mac_start = macros[macnum-1].mac_end + 1; | ||||
| 			} | ||||
| 			tmp = macros[macnum].mac_start; | ||||
| 			while (tmp != macbuf + 4096) { | ||||
| 				if ((c=getc(cfile)) == EOF) { | ||||
| 				printf("Macro definition missing null line terminator.\n"); | ||||
| 					goto bad; | ||||
| 				} | ||||
| 				*tmp = c; | ||||
| 				if (*tmp == '\n') { | ||||
| 					if (*(tmp-1) == '\0') { | ||||
| 					   macros[macnum++].mac_end = tmp - 1; | ||||
| 					   break; | ||||
| 					} | ||||
| 					*tmp = '\0'; | ||||
| 				} | ||||
| 				tmp++; | ||||
| 			} | ||||
| 			if (tmp == macbuf + 4096) { | ||||
| 				printf("4K macro buffer exceeded\n"); | ||||
| 				goto bad; | ||||
| 			} | ||||
| 			break; | ||||
| 		default: | ||||
| 			warnx("Unknown .netrc keyword %s", tokval); | ||||
| 			break; | ||||
| 		} | ||||
| 		goto done; | ||||
| 	} | ||||
| done: | ||||
| 	(void) fclose(cfile); | ||||
| 	return (0); | ||||
| bad: | ||||
| 	(void) fclose(cfile); | ||||
| 	return (-1); | ||||
| } | ||||
|  | ||||
| extern "C" int | ||||
| cygwin_rexec (char **ahost, unsigned short rport, char *name, char *pass, | ||||
| 	      char *cmd, int *fd2p) | ||||
| { | ||||
| 	struct sockaddr_in sin, sin2, from; | ||||
| 	struct hostent *hp; | ||||
| 	u_short port; | ||||
| 	int s, timo = 1, s3; | ||||
| 	char c; | ||||
| 	char ahostbuf[INTERNET_MAX_HOST_NAME_LENGTH + 1]; | ||||
|  | ||||
| 	sig_dispatch_pending (); | ||||
| 	myfault efault; | ||||
| 	if (efault.faulted (EFAULT)) | ||||
| 		return -1; | ||||
|  | ||||
| 	hp = cygwin_gethostbyname(*ahost); | ||||
| 	if (hp == 0) { | ||||
| 		cygwin_herror(*ahost); | ||||
| 		return (-1); | ||||
| 	} | ||||
| 	*ahost = strcpy (ahostbuf, hp->h_name); | ||||
| 	ruserpass(hp->h_name, &name, &pass, NULL); | ||||
| 	if (!name) | ||||
| 		name = getlogin (); | ||||
| 	if (!pass) | ||||
| 		pass = almost_null; | ||||
| retry: | ||||
| 	s = cygwin_socket(AF_INET, SOCK_STREAM, 0); | ||||
| 	if (s < 0) { | ||||
| 		perror("rexec: socket"); | ||||
| 		return (-1); | ||||
| 	} | ||||
| 	sin.sin_family = hp->h_addrtype; | ||||
| 	sin.sin_port = rport; | ||||
| 	bcopy(hp->h_addr, (caddr_t)&sin.sin_addr, hp->h_length); | ||||
| 	if (cygwin_connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) { | ||||
| 		if (errno == ECONNREFUSED && timo <= 16) { | ||||
| 			(void) close(s); | ||||
| 			sleep(timo); | ||||
| 			timo *= 2; | ||||
| 			goto retry; | ||||
| 		} | ||||
| 		perror(hp->h_name); | ||||
| 		return (-1); | ||||
| 	} | ||||
| 	if (fd2p == 0) { | ||||
| 		(void) write(s, "", 1); | ||||
| 		port = 0; | ||||
| 	} else { | ||||
| 		char num[8]; | ||||
| 		int s2, sin2len; | ||||
|  | ||||
| 		s2 = cygwin_socket(AF_INET, SOCK_STREAM, 0); | ||||
| 		if (s2 < 0) { | ||||
| 			(void) close(s); | ||||
| 			return (-1); | ||||
| 		} | ||||
| 		cygwin_listen(s2, 1); | ||||
| 		sin2len = sizeof (sin2); | ||||
| 		if (cygwin_getsockname(s2, (struct sockaddr *)&sin2, &sin2len) < 0 || | ||||
| 		  sin2len != sizeof (sin2)) { | ||||
| 			perror("getsockname"); | ||||
| 			(void) close(s2); | ||||
| 			goto bad; | ||||
| 		} | ||||
| 		port = ntohs((u_short)sin2.sin_port); | ||||
| 		(void) sprintf(num, "%u", port); | ||||
| 		(void) write(s, num, strlen(num)+1); | ||||
| 		{ int len = sizeof (from); | ||||
| 		  s3 = cygwin_accept(s2, (struct sockaddr *)&from, &len); | ||||
| 		  close(s2); | ||||
| 		  if (s3 < 0) { | ||||
| 			perror("accept"); | ||||
| 			port = 0; | ||||
| 			goto bad; | ||||
| 		  } | ||||
| 		} | ||||
| 		*fd2p = s3; | ||||
| 	} | ||||
| 	(void) write(s, name, strlen(name) + 1); | ||||
| 	/* should public key encypt the password here */ | ||||
| 	(void) write(s, pass, strlen(pass) + 1); | ||||
| 	(void) write(s, cmd, strlen(cmd) + 1); | ||||
| 	if (read(s, &c, 1) != 1) { | ||||
| 		perror(*ahost); | ||||
| 		goto bad; | ||||
| 	} | ||||
| 	if (c != 0) { | ||||
| 		while (read(s, &c, 1) == 1) { | ||||
| 			(void) write(2, &c, 1); | ||||
| 			if (c == '\n') | ||||
| 				break; | ||||
| 		} | ||||
| 		goto bad; | ||||
| 	} | ||||
| 	return (s); | ||||
| bad: | ||||
| 	if (port) | ||||
| 		(void) close(*fd2p); | ||||
| 	(void) close(s); | ||||
| 	return (-1); | ||||
| } | ||||
		Reference in New Issue
	
	Block a user