⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 expect.c

📁 linux集群服务器软件代码包
💻 C
字号:
/* $Id: expect.c,v 1.16 2005/02/03 20:07:07 msoffen Exp $ *//* * Simple expect module for the STONITH library * *	Copyright (c) 2000 Alan Robertson <alanr@unix.sh> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. *  * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * Lesser General Public License for more details. *  * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA * */#include <portability.h>#include <sys/types.h>#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <errno.h>#include <syslog.h>#include <sys/wait.h>#include <stdio.h>#include <stdlib.h>#include <stddef.h>#include <stdarg.h>#include <string.h>#include <unistd.h>#include <errno.h>#include <time.h>#include <sys/time.h>#include <sys/times.h>#include <sys/socket.h>#include <netdb.h>#include <netinet/in.h>#include <arpa/inet.h>#define ENABLE_PIL_DEFS_PRIVATE#include <pils/plugin.h>#ifdef _POSIX_PRIORITY_SCHEDULING#	include <sched.h>#endif#include <stonith/stonith.h>#include <stonith/stonith_plugin.h>extern 	PILPluginUniv*	StonithPIsys;#define	LOG(args...) PILCallLog(StonithPIsys->imports->log, args)#define DEBUG(args...) LOG(PIL_DEBUG, args)#undef DEBUG#define	DEBUG(args...) PILCallLog(StonithPIsys->imports->log, PIL_DEBUG, args)/* *	Look for ('expect') any of a series of tokens in the input *	Return the token type for the given token or -1 on error. */static intExpectToken(int	fd, struct Etoken * toklist, int to_secs, char * savebuf,	int maxline, int Debug){	/*	 * We use unsigned long instead of clock_t here because it's signed,	 * but the return value from times() is basically unsigned...	 * This is broken, but according to POSIX ;-)	 */	unsigned long	starttime;	unsigned long	endtime;	int		wraparound=0;	unsigned	hz =  sysconf(_SC_CLK_TCK);	int		tickstousec = (1000000/hz);	unsigned long	now;	unsigned long	ticks;	int		nchars = 1; /* reserve space for an EOS */	struct timeval	tv;	char *		buf = savebuf;	struct Etoken *	this;	/* Figure out when to give up.  Handle lbolt wraparound */	starttime = times(NULL);	ticks = (to_secs*hz);	endtime = starttime + ticks;	if (endtime < starttime) {		wraparound = 1;	}	if (buf) {		*buf = EOS;	}	for (this=toklist; this->string; ++this) {		this->matchto = 0;	}	while (now = times(NULL),		(wraparound && (now > starttime || now <= endtime))		||	(!wraparound && now <= endtime)) {		fd_set infds;		char	ch;		unsigned long	timeleft;		int		retval;		timeleft = endtime - now;		tv.tv_sec = timeleft / hz;		tv.tv_usec = (timeleft % hz) * tickstousec;		if (tv.tv_sec == 0 && tv.tv_usec < tickstousec) {			/* Give 'em a little chance */			tv.tv_usec = tickstousec;		}		/* Watch our FD to see when it has input. */           	FD_ZERO(&infds);           	FD_SET(fd, &infds);		retval = select(fd+1, &infds, NULL, NULL, &tv); 		if (retval <= 0) {			errno = ETIMEDOUT;			return(-1);		}		/* Whew!  All that work just to read one character! */				if (read(fd, &ch, sizeof(ch)) <= 0) {			return(-1);		}		/* Save the text, if we can */		if (buf && nchars < maxline-1) {			*buf = ch;			++buf;			*buf = EOS;			++nchars;		}		if (Debug) {			DEBUG("Got '%c'", ch);		}		/* See how this character matches our expect strings */		for (this=toklist; this->string; ++this) {			if (ch == this->string[this->matchto]) {				/* It matches the current token */			 	++this->matchto;				if (this->string[this->matchto] == EOS){					/* Hallelujah! We matched */					if (Debug) {						DEBUG("Matched [%s] [%d]"						,	this->string						,	this->toktype);						if (savebuf) {							DEBUG("Saved [%s]"							,	savebuf);						}					}					return(this->toktype);				}			}else{				/* It doesn't appear to match this token */				int	curlen;				int	nomatch=1;				/*				 * If we already had a match (matchto is				 * greater than zero), we look for a match				 * of the tail of the pattern matched so far				 * (with the current character) against the				 * head of the pattern.				 */				/*				 * This is to make the string "aab" match				 * the pattern "ab" correctly 				 * Painful, but nice to do it right.				 */				for (curlen = (this->matchto)				;	nomatch && curlen >= 0				;	--curlen) 			{					const char *	tail;					tail=(this->string)					+	this->matchto					-	curlen;					if (strncmp(this->string, tail					,	curlen) == 0					&&	this->string[curlen] == ch)  {												if (this->string[curlen+1]==EOS){							/* We matched!  */							/* (can't happen?) */							return(this->toktype);						}						this->matchto = curlen+1;						nomatch=0;					}				}				if (nomatch) {					this->matchto = 0;				}			}		}	}	errno = ETIMEDOUT;	return(-1);}/* * Start a process with its stdin and stdout redirected to pipes * so the parent process can talk to it. */static intStartProcess(const char * cmd, int * readfd, int * writefd){	pid_t	pid;	int	wrpipe[2];	/* The pipe the parent process writes to */				/* (which the child process reads from) */	int	rdpipe[2];	/* The pipe the parent process reads from */				/* (which the child process writes to) */	if (pipe(wrpipe) < 0) {		perror("cannot create pipe\n");		return(-1);	}	if (pipe(rdpipe) < 0) {		perror("cannot create pipe\n");		close(wrpipe[0]);		close(wrpipe[1]);		return(-1);	}	switch(pid=fork()) {		case -1:	perror("cannot StartProcess cmd");				close(rdpipe[0]);				close(wrpipe[1]);				close(wrpipe[0]);				close(rdpipe[1]);				return(-1);		case 0:		/* We are the child */				/* Redirect stdin */				close(0);				dup2(wrpipe[0], 0);				close(wrpipe[0]);				close(wrpipe[1]);				/* Redirect stdout */				close(1);				dup2(rdpipe[1], 1);				close(rdpipe[0]);				close(rdpipe[1]);#if defined(SCHED_OTHER)			{				/*				 * Try and (re)set our scheduling to "normal"				 * Sometimes our callers run in soft				 * real-time mode.  The program we exec might				 * not be very well behaved - this is bad for				 * operation in high-priority (soft real-time)				 * mode.  In particular, telnet is prone to				 * going into infinite loops when killed.				 */				struct sched_param	sp;				memset(&sp, 0, sizeof(sp));				sp.sched_priority = 0;				sched_setscheduler(0, SCHED_OTHER, &sp);			}#endif				execlp("/bin/sh", "sh", "-c", cmd, (const char *)NULL);				perror("cannot exec shell!");				exit(1);		default:	/* We are the parent */				*readfd = rdpipe[0];				close(rdpipe[1]);				*writefd = wrpipe[1];				close(wrpipe[0]);				return(pid);	}	/*NOTREACHED*/	return(-1);}static char **stonith_copy_hostlist(const char** hostlist){	int hlleng = 1;	const char ** here = hostlist;	char ** hret;	char **	ret;	for (here = hostlist; *here; ++here) {		++hlleng;	}	ret = (char**)malloc(hlleng * sizeof(char *));	if (ret == NULL) {		return ret;	}		hret = ret;	for (here = hostlist; *here; ++here,++hret) {		*hret = strdup(*here);		if (*hret == NULL) {			stonith_free_hostlist(hret);			return NULL; 		}	}	*hret = NULL;	return ret;}static char **StringToHostList(const char * s){	const char *	here;	int		hlleng = 0;	char **		ret;	char **		hret;	const char *	delims = " \t\n\f\r,";	/* Count the number of strings (words) in the result */	here = s;	while (*here != EOS) {		/* skip delimiters */		here += strspn(here, delims);		if (*here == EOS) {			break;		}		/* skip over substring proper... */		here += strcspn(here, delims);		++hlleng;	}	/* Malloc space for the result string pointers */	ret = (char**)malloc((hlleng+1) * sizeof(char *));	if (ret == NULL) {		return NULL;	}		hret = ret;	here = s;	/* Copy each substring into a separate string */	while (*here != EOS) {		int	slen;	/* substring length */		/* skip delimiters */		here += strspn(here, delims);		if (*here == EOS) {			break;		}		/* Compute substring length */		slen = strcspn(here, delims);		*hret = malloc((slen+1) * sizeof(char));		if (*hret == NULL) {			stonith_free_hostlist(hret);			return NULL; 		}		/* Copy string (w/o EOS) */		memcpy(*hret, here, slen);		/* Add EOS to result string */		(*hret)[slen] = EOS;		g_strdown(*hret);		here += slen;		++hret;	}	*hret = NULL;	return ret;}static const char *GetValue(StonithNVpair* parameters, const char * name){	while (parameters->s_name) {		if (strcmp(name, parameters->s_name) == 0) {			return parameters->s_value;		}		++parameters;	}	return NULL;}static intGetAllValues(StonithNamesToGet* output, StonithNVpair * input){	int	j;	int	rc;	for (j=0; output[j].s_name; ++j) {		const char * value = GetValue(input, output[j].s_name);		if (value == NULL) {			rc = S_INVAL;			goto fail;		}		if ((output[j].s_value = strdup(value)) == NULL) {			rc = S_OOPS;			goto fail;		}	}	return S_OK;fail:	for (j=0; output[j].s_value; ++j) {		free(output[j].s_value);		output[j].s_value = NULL;	}	return rc;}static intOpenStreamSocket(const char * host, int port, const char * service){	union s_un {		struct sockaddr_in	si4;		struct sockaddr_in6	si6;	}sockun;	int			sock;	int			addrlen = -1;	memset(&sockun, 0, sizeof(sockun));	if (inet_pton(AF_INET, host, (void*)&sockun.si4.sin_addr) < 0) {		sockun.si4.sin_family = AF_INET;	}else if (inet_pton(AF_INET6, host, (void*)&sockun.si6.sin6_addr)<0){		sockun.si6.sin6_family = AF_INET6;	}else{		struct hostent*	hostp = gethostbyname(host);		if (hostp == NULL) {			errno = EINVAL;			return -1;		}		sockun.si4.sin_family = hostp->h_addrtype;		memcpy(&sockun.si4.sin_addr, hostp->h_addr, hostp->h_length);	}	if ((sock = socket(sockun.si4.sin_family, SOCK_STREAM, 0)) < 0) {		return -1;	}	if (service != NULL) {		struct servent*	se = getservbyname(service, "tcp");		if (se != NULL) {			/* We convert it back later... */			port = ntohs(se->s_port);		}	}	if (port <= 0) {		errno = EINVAL;		return -1;	}	port = htons(port);	if (sockun.si6.sin6_family == AF_INET6) {		sockun.si6.sin6_port = port;		addrlen = sizeof(sockun.si6);	}else if (sockun.si4.sin_family == AF_INET) {		sockun.si4.sin_port = port;		addrlen = sizeof(sockun.si4);	}else{		errno = EINVAL;		return -1;	}			if (connect(sock, (struct sockaddr*)(&sockun), addrlen)< 0){		int	save = errno;		perror("connect() failed");		close(sock);		errno = save;		return -1;	}	return sock;}StonithImports		stonithimports = {	ExpectToken,	StartProcess,	OpenStreamSocket,	GetValue,	GetAllValues,	StringToHostList,	stonith_copy_hostlist,	stonith_free_hostlist,};

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -