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

📄 expect.c

📁 在LINUX下实现HA的源代码
💻 C
字号:
/* $Id: expect.c,v 1.11.2.1 2004/04/20 09:08:51 lars 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 <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <errno.h>#include <syslog.h>#include <libintl.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>#ifdef _POSIX_PRIORITY_SCHEDULING#	include <sched.h>#endif#include <stonith/stonith.h>/* *	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 * buf,	int maxline){	/*	 * 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;	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 0		fprintf(stderr, "%c", ch);#endif		/* 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 */					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);}StonithImports		stonithimports = {	ExpectToken,	StartProcess,};

⌨️ 快捷键说明

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