From cb7f5ad55578fad7245152f0f9b7647830a53a2b Mon Sep 17 00:00:00 2001 From: brian Date: Mon, 31 Mar 1997 22:51:00 +0000 Subject: Remove the syslog stuff, and allow various return values in uu_lock(). Add uu_lockerr() for turning the results of uu_lock into something printable. Remove bogus section in man page about race conditions allowing both processes to get the lock. Include libutil.h and use uu_lock() correctly where it should. Suggested by: ache@freebsd.org --- lib/libutil/libutil.h | 10 +++++- lib/libutil/uucplock.3 | 91 +++++++++++++++++++++++++++++++++++++++++-------- lib/libutil/uucplock.c | 92 ++++++++++++++++++++++++++++++++------------------ 3 files changed, 145 insertions(+), 48 deletions(-) (limited to 'lib/libutil') diff --git a/lib/libutil/libutil.h b/lib/libutil/libutil.h index 695a8cb..35c1163 100644 --- a/lib/libutil/libutil.h +++ b/lib/libutil/libutil.h @@ -18,7 +18,7 @@ * 5. Modifications may be freely made to this file providing the above * conditions are met. * - * $Id: libutil.h,v 1.4 1997/02/22 15:08:14 peter Exp $ + * $Id: libutil.h,v 1.5 1997/03/30 12:11:27 brian Exp $ */ #ifndef _LIBUTIL_H_ @@ -41,8 +41,16 @@ int openpty __P((int *amaster, int *aslave, char *name, struct termios *termp, struct winsize *winp)); int forkpty __P((int *amaster, char *name, struct termios *termp, struct winsize *winp)); +char *uu_lockerr __P((int uu_lockresult)); int uu_lock __P((char *ttyname)); int uu_unlock __P((char *ttyname)); __END_DECLS +#define UU_LOCK_INUSE (1) +#define UU_LOCK_OK (0) +#define UU_LOCK_OPEN_ERR (-1) +#define UU_LOCK_READ_ERR (-2) +#define UU_LOCK_SEEK_ERR (-3) +#define UU_LOCK_WRITE_ERR (-4) + #endif /* !_LIBUTIL_H_ */ diff --git a/lib/libutil/uucplock.3 b/lib/libutil/uucplock.3 index a8b5df8..0c1ae7e 100644 --- a/lib/libutil/uucplock.3 +++ b/lib/libutil/uucplock.3 @@ -23,7 +23,7 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.\" $Id$ +.\" $Id: uucplock.3,v 1.1 1997/03/30 12:11:29 brian Exp $ .\" " .Dd March 30, 1997 .Os @@ -38,6 +38,8 @@ .Fn uu_lock "char *ttyname" .Ft int .Fn uu_unlock "char *ttyname" +.Ft char * +.Fn uu_lockerr "int uu_lockresult" .Pp Link with .Va -lutil @@ -68,23 +70,70 @@ Care should be taken that .Fn uu_lock was successful before calling .Fn uu_unlock . +.Pp +.Fn uu_lockerr +returns an error string representing the error +.Fa uu_lockresult , +as returned from +.Fn uu_lock . .Sh RETURN VALUES -Both +.Fn uu_unlock +returns 0 on success and -1 on failure. +.Pp +.Fn uu_lock +may return any of the following values: +.Pp +.Dv UU_LOCK_INUSE: +The lock is in use by another process. +.Pp +.Dv UU_LOCK_OK: +The lock was successfully created. +.Pp +.Dv UU_LOCK_OPEN_ERR: +The lock file could not be opened via +.Xr open 2 . +.Pp +.Dv UU_LOCK_READ_ERR: +The lock file could not be read via +.Xr read 2 . +.Pp +.Dv UU_LOCK_SEEK_ERR: +The lock file was +.Dq stale , +but the call to +.Xr lseek 2 +necessary to write the current process id failed. +.Pp +.Dv UU_LOCK_WRITE_ERR: +The current process id could not be written to the lock file via a call to +.Xr write 2 . +.Pp +If a value of +.Dv UU_LOCK_OK +is passed to +.Fn uu_lockerr , +a +.Dv NULL +pointer is returned. If a value of +.Dv UU_LOCK_INUSE +is passed, an empty string is returned. Otherwise, a string specifying +the reason for failure is returned. +.Fn uu_lockerr +uses the current value of +.Dv errno +to determine the exact error. Care should be made not to allow +.Dv errno +to be changed between calls to .Fn uu_lock and -.Fn uu_unlock -return 0 on success and -1 on failure. +.Fn uu_lockerr . .Sh ERRORS -On failure, -.Fn uu_lock -will log any unexpected errors using -.Xr syslog 2 . -If the lock already exists and contains the process id of a running -process, +If .Fn uu_lock -will silently fail. The value of +returns one of the four error values above, the global value .Dv errno -can not be used to determine the cause of failure. +can be used to determine the cause. Refer to the respective manual pages +for further details. .Pp .Fn uu_unlock will set the global variable @@ -93,9 +142,23 @@ to reflect the reason that the lock file could not be removed. Refer to the description of .Xr unlink 2 for further details. +.Sh SEE ALSO +.Xr open 2 , +.Xr read 2 , +.Xr lseek 2 , +.Xr write 2 .Sh BUGS -Locking is not atomic. Should a race condition occur, it's entirely -possible that both processes obtain the lock. +Locking is not atomic. Should a race condition occur, it's +possible that the +.Dq losing +process fails to identify the +.Dq winning +process. If this happens, +.Fn uu_lock +returns +.Dv UU_LOCK_READ_ERR +and errno is set to +.Dv EINVAL . .Pp It is possible that a stale lock is not recognised as such if a new processes is assigned the same processes id as the program that left diff --git a/lib/libutil/uucplock.c b/lib/libutil/uucplock.c index 20eafe4..0f08646 100644 --- a/lib/libutil/uucplock.c +++ b/lib/libutil/uucplock.c @@ -47,12 +47,14 @@ static const char sccsid[] = "@(#)uucplock.c 8.1 (Berkeley) 6/6/93"; #include #include #include +#include +#include "libutil.h" #define LOCKFMT "LCK..%s" /* Forward declarations */ static int put_pid (int fd, pid_t pid); -static pid_t get_pid (int fd); +static pid_t get_pid (int fd,int *err); /* * uucp style locking routines @@ -65,6 +67,7 @@ int uu_lock (char *ttyname) int fd; pid_t pid; char tbuf[sizeof(_PATH_UUCPLOCK) + MAXNAMLEN]; + int err; (void)sprintf(tbuf, _PATH_UUCPLOCK LOCKFMT, ttyname); fd = open(tbuf, O_RDWR|O_CREAT|O_EXCL, 0660); @@ -74,56 +77,41 @@ int uu_lock (char *ttyname) * check to see if the process holding the lock still exists */ fd = open(tbuf, O_RDWR, 0); - if (fd < 0) { -#ifndef USE_PERROR - syslog(LOG_ERR, "lock open: %m"); -#else - perror("lock open"); -#endif - return(-1); - } - if ((pid = get_pid (fd)) == -1) { -#ifndef USE_PERROR - syslog(LOG_ERR, "lock read: %m"); -#else - perror("lock read"); -#endif + if (fd < 0) + return UU_LOCK_OPEN_ERR; + + if ((pid = get_pid (fd, &err)) == -1) { (void)close(fd); - return(-1); + errno = err; + return UU_LOCK_READ_ERR; } if (kill(pid, 0) == 0 || errno != ESRCH) { (void)close(fd); /* process is still running */ - return(-1); + return UU_LOCK_INUSE; } /* * The process that locked the file isn't running, so * we'll lock it ourselves */ if (lseek(fd, (off_t) 0, L_SET) < 0) { -#ifndef USE_PERROR - syslog(LOG_ERR, "lock lseek: %m"); -#else - perror("lock lseek"); -#endif + err = errno; (void)close(fd); - return(-1); + errno = err; + return UU_LOCK_SEEK_ERR; } /* fall out and finish the locking process */ } pid = getpid(); if (!put_pid (fd, pid)) { -#ifndef USE_PERROR - syslog(LOG_ERR, "lock write: %m"); -#else - perror("lock write"); -#endif + err = errno; (void)close(fd); (void)unlink(tbuf); - return(-1); + errno = err; + return UU_LOCK_WRITE_ERR; } (void)close(fd); - return(0); + return UU_LOCK_OK; } int uu_unlock (char *ttyname) @@ -131,7 +119,43 @@ int uu_unlock (char *ttyname) char tbuf[sizeof(_PATH_UUCPLOCK) + MAXNAMLEN]; (void)sprintf(tbuf, _PATH_UUCPLOCK LOCKFMT, ttyname); - return(unlink(tbuf)); + return unlink(tbuf); +} + +char *uu_lockerr (int uu_lockresult) +{ + static char errbuf[512]; + int len; + + switch (uu_lockresult) { + case UU_LOCK_INUSE: + return ""; + case UU_LOCK_OK: + return 0; + case UU_LOCK_OPEN_ERR: + strcpy(errbuf,"open error: "); + len = 12; + break; + case UU_LOCK_READ_ERR: + strcpy(errbuf,"read error: "); + len = 12; + break; + case UU_LOCK_SEEK_ERR: + strcpy(errbuf,"seek error: "); + len = 12; + break; + case UU_LOCK_WRITE_ERR: + strcpy(errbuf,"write error: "); + len = 13; + break; + default: + strcpy(errbuf,"Undefined error: "); + len = 17; + break; + } + + strncpy(errbuf+len,strerror(errno),sizeof(errbuf)-len-1); + return errbuf; } static int put_pid (int fd, pid_t pid) @@ -143,7 +167,7 @@ static int put_pid (int fd, pid_t pid) return write (fd, buf, len) == len; } -static pid_t get_pid (int fd) +static pid_t get_pid (int fd,int *err) { int bytes_read; char buf[32]; @@ -153,8 +177,10 @@ static pid_t get_pid (int fd) if (bytes_read > 0) { buf[bytes_read] = '\0'; pid = strtol (buf, (char **) NULL, 10); - } else + } else { pid = -1; + *err = bytes_read ? errno : EINVAL; + } return pid; } -- cgit v1.1