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

📄 ttylock.c

📁 linux集群服务器软件代码包
💻 C
字号:
/* $Id: ttylock.c,v 1.2 2005/01/05 06:54:27 alan Exp $ */#include <portability.h>#include <stdio.h>#include <unistd.h>#include <fcntl.h>#include <errno.h>#include <sys/types.h>#include <sys/stat.h>#include <ctype.h>#include <clplumbing/cl_signal.h>#include <clplumbing/ttylock.h>#ifndef TTY_LOCK_D#	define TTY_LOCK_D	"/var/lock"#endif/* * The following information is from the Filesystem Hierarchy Standard * version 2.1 dated 12 April, 2000. * * 5.6 /var/lock : Lock files * Lock files should be stored within the /var/lock directory structure. * Device lock files, such as the serial device lock files that were originally * found in either /usr/spool/locks or /usr/spool/uucp, must now be stored in * /var/lock. The naming convention which must be used is LCK.. followed by * the base name of the device file. For example, to lock /dev/cua0 the file * LCK..cua0 would be created. *  * The format used for device lock files must be the HDB UUCP lock file format. * The HDB format is to store the process identifier (PID) as a ten byte * ASCII decimal number, with a trailing newline. For example, if process 1230 * holds a lock file, it would contain the eleven characters: space, space, * space, space, space, space, one, two, three, zero, and newline. * Then, anything wishing to use /dev/cua0 can read the lock file and act * accordingly (all locks in /var/lock should be world-readable). * * * PERMISSIONS NOTE: * Different linux distributions set the mode of the lock directory differently * Any process which wants to create lock files must have write permissions * on TTY_LOCK_D (probably /var/lock).  For things like the heartbeat API * code, this may mean allowing the uid of the processes that use this API * to join group uucp, or making the binaries setgid to uucp. */#define	DEVDIR	"/dev/"#define	DEVLEN	(sizeof(DEVDIR)-1)static void raw_device (const char *dev, char *dest_name, size_t size);static int DoLock(const char * prefix, const char *lockname);static int DoUnlock(const char * prefix, const char *lockname);/* The code in this file originally written by Guenther Thomsen *//* Somewhat mangled by Alan Robertson *//* * Lock a tty (using lock files, see linux `man 2 open` close to O_EXCL)  * serial_device has to be _the complete path_, i.e. including '/dev/' to the * special file, which denotes the tty to lock -tho * return 0 on success,  * -1 if device is locked (lockfile exists and isn't stale), * -2 for temporarily failure, try again, * other negative value, if something unexpected happend (failure anyway) */static voidraw_device (const char *serial_device, char *dest_name, size_t size){	char*		dp	= dest_name;	const char*	sp	= serial_device+DEVLEN;	const char* 	dpend	= dp + size - 1;	while (*sp != '\0' && dp < dpend) {		if (isalnum((unsigned int)*sp))			*dp++ = *sp;		sp++;	}	*dp = EOS;}intttylock(const char *serial_device){	char rawname[64];	raw_device (serial_device, rawname, sizeof(rawname));	return(DoLock("LCK..", rawname));}/* * Unlock a tty (remove its lockfile)  * do we need to check, if its (still) ours? No, IMHO, if someone else * locked our line, it's his fault  -tho * returns 0 on success * <0 if some failure occured */ intttyunlock(const char *serial_device){	char rawname[64];	raw_device (serial_device, rawname, sizeof(rawname));	return(DoUnlock("LCK..", rawname));}/* This is what the FHS standard specifies for the size of our lock file */#define	LOCKSTRLEN	11static intDoLock(const char * prefix, const char *lockname){	char lf_name[256], tf_name[256], buf[LOCKSTRLEN+1];	int fd;	unsigned long pid, mypid;	int rc;	struct stat sbuf;	mypid = (unsigned long) getpid();	snprintf(lf_name, sizeof(lf_name), "%s/%s%s"	,	TTY_LOCK_D, prefix, lockname);	snprintf(tf_name, sizeof(tf_name), "%s/tmp%lu-%s"	,	TTY_LOCK_D, mypid, lockname);	if ((fd = open(lf_name, O_RDONLY)) >= 0) {		if (fstat(fd, &sbuf) >= 0 && sbuf.st_size < LOCKSTRLEN) {			sleep(1); /* if someone was about to create one,			   	   * give'm a sec to do so				   * Though if they follow our protocol,				   * this won't happen.  They should really				   * put the pid in, then link, not the				   * other way around.				   */		}		if (read(fd, buf, sizeof(buf)) < 1) {			/* lockfile empty -> rm it and go on */;		} else {			if (sscanf(buf, "%lu", &pid) < 1) {				/* lockfile screwed up -> rm it and go on */			} else {				if (CL_KILL((pid_t)pid, 0) < 0 				&&	errno != ESRCH) {					/* tty is locked by existing (not					 * necessarily running) process					 * -> give up */					close(fd);					return -1;				} else {					/* stale lockfile -> rm it and go on */				}			}		}		unlink(lf_name);	}	if ((fd = open(tf_name, O_CREAT | O_WRONLY | O_EXCL, 0644)) < 0) {		/* Hmmh, why did we fail? Anyway, nothing we can do about it */		return -3;	}	/* Slight overkill with the %*d format ;-) */	snprintf(buf, sizeof(buf), "%*lu\n", LOCKSTRLEN-1, mypid);	if (write(fd, buf, LOCKSTRLEN) != LOCKSTRLEN) {		/* Again, nothing we can do about this */		return -3;	}	close(fd);	switch (link(tf_name, lf_name)) {	case 0:		if (stat(tf_name, &sbuf) < 0) {			/* something weird happened */			rc = -3;			break;		}		if (sbuf.st_nlink < 2) {			/* somehow, it didn't get through - NFS trouble? */			rc = -2;			break;		}		rc = 0;		break;	case EEXIST:		rc = -1;		break;	default:		rc = -3;	}	unlink(tf_name);	return rc;}static intDoUnlock(const char * prefix, const char *lockname){	char lf_name[256];		snprintf(lf_name, sizeof(lf_name), "%s/%s%s", TTY_LOCK_D	,	prefix, lockname);	return unlink(lf_name);}

⌨️ 快捷键说明

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