uucplock.c revision 28040
124417Sbrian/* 224417Sbrian * Copyright (c) 1988, 1993 324417Sbrian * The Regents of the University of California. All rights reserved. 424417Sbrian * 524417Sbrian * Redistribution and use in source and binary forms, with or without 624417Sbrian * modification, are permitted provided that the following conditions 724417Sbrian * are met: 824417Sbrian * 1. Redistributions of source code must retain the above copyright 924417Sbrian * notice, this list of conditions and the following disclaimer. 1024417Sbrian * 2. Redistributions in binary form must reproduce the above copyright 1124417Sbrian * notice, this list of conditions and the following disclaimer in the 1224417Sbrian * documentation and/or other materials provided with the distribution. 1324417Sbrian * 3. All advertising materials mentioning features or use of this software 1424417Sbrian * must display the following acknowledgement: 1524417Sbrian * This product includes software developed by the University of 1624417Sbrian * California, Berkeley and its contributors. 1724417Sbrian * 4. Neither the name of the University nor the names of its contributors 1824417Sbrian * may be used to endorse or promote products derived from this software 1924417Sbrian * without specific prior written permission. 2024417Sbrian * 2124417Sbrian * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2224417Sbrian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2324417Sbrian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2424417Sbrian * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2524417Sbrian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2624417Sbrian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2724417Sbrian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2824417Sbrian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2924417Sbrian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3024417Sbrian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3124417Sbrian * SUCH DAMAGE. 3224531Sache * 3328040Sache * $Id: uucplock.c,v 1.7 1997/08/05 12:58:02 ache Exp $ 3424531Sache * 3524417Sbrian */ 3624417Sbrian 3724417Sbrian#ifndef lint 3824417Sbrianstatic const char sccsid[] = "@(#)uucplock.c 8.1 (Berkeley) 6/6/93"; 3924417Sbrian#endif /* not lint */ 4024417Sbrian 4124417Sbrian#include <sys/types.h> 4224417Sbrian#include <sys/file.h> 4324417Sbrian#include <dirent.h> 4424417Sbrian#include <errno.h> 4524417Sbrian#include <unistd.h> 4624417Sbrian#include <signal.h> 4724417Sbrian#include <stdio.h> 4824417Sbrian#include <stdlib.h> 4924417Sbrian#include <paths.h> 5024461Sbrian#include <string.h> 5124461Sbrian#include "libutil.h" 5224417Sbrian 5328040Sache#define MAXTRIES 5 5428040Sache 5528040Sache#define LOCKTMP "LCKTMP..%d" 5624417Sbrian#define LOCKFMT "LCK..%s" 5724417Sbrian 5828040Sache#define GORET(level, val) { err = errno; uuerr = (val); \ 5928040Sache goto __CONCAT(ret, level); } 6028040Sache 6124417Sbrian/* Forward declarations */ 6224417Sbrianstatic int put_pid (int fd, pid_t pid); 6324461Sbrianstatic pid_t get_pid (int fd,int *err); 6424417Sbrian 6524417Sbrian/* 6624417Sbrian * uucp style locking routines 6724417Sbrian */ 6824417Sbrian 6925740Sbrianint uu_lock (const char *ttyname) 7024417Sbrian{ 7128040Sache int fd, tmpfd, i; 7224417Sbrian pid_t pid; 7328040Sache char lckname[sizeof(_PATH_UUCPLOCK) + MAXNAMLEN], 7428040Sache lcktmpname[sizeof(_PATH_UUCPLOCK) + MAXNAMLEN]; 7528040Sache int err, uuerr; 7624417Sbrian 7728040Sache pid = getpid(); 7828040Sache (void)snprintf(lcktmpname, sizeof(lcktmpname), _PATH_UUCPLOCK LOCKTMP, 7928040Sache pid); 8028040Sache (void)snprintf(lckname, sizeof(lckname), _PATH_UUCPLOCK LOCKFMT, 8128040Sache ttyname); 8228040Sache if ((tmpfd = creat(lcktmpname, 0664)) < 0) 8328040Sache GORET(0, UU_LOCK_CREAT_ERR); 8424461Sbrian 8528040Sache for (i = 0; i < MAXTRIES; i++) { 8628040Sache if (link (lcktmpname, lckname) < 0) { 8728040Sache if (errno != EEXIST) 8828040Sache GORET(1, UU_LOCK_LINK_ERR); 8928040Sache /* 9028040Sache * file is already locked 9128040Sache * check to see if the process holding the lock 9228040Sache * still exists 9328040Sache */ 9428040Sache if ((fd = open(lckname, O_RDONLY)) < 0) 9528040Sache GORET(1, UU_LOCK_OPEN_ERR); 9624417Sbrian 9728040Sache if ((pid = get_pid (fd, &err)) == -1) 9828040Sache GORET(2, UU_LOCK_READ_ERR); 9928040Sache 10028040Sache close(fd); 10128040Sache 10228040Sache if (kill(pid, 0) == 0 || errno != ESRCH) 10328040Sache GORET(1, UU_LOCK_INUSE); 10428040Sache /* 10528040Sache * The process that locked the file isn't running, so 10628040Sache * we'll lock it ourselves 10728040Sache */ 10828040Sache (void)unlink(lckname); 10928040Sache } else { 11028040Sache if (!put_pid (tmpfd, pid)) 11128040Sache GORET(3, UU_LOCK_WRITE_ERR); 11228040Sache break; 11324417Sbrian } 11424417Sbrian } 11528040Sache GORET(1, (i >= MAXTRIES) ? UU_LOCK_TRY_ERR : UU_LOCK_OK); 11628040Sache 11728040Sacheret3: 11828040Sache (void)unlink(lckname); 11928040Sache goto ret1; 12028040Sacheret2: 12124417Sbrian (void)close(fd); 12228040Sacheret1: 12328040Sache (void)close(tmpfd); 12428040Sache (void)unlink(lcktmpname); 12528040Sacheret0: 12628040Sache errno = err; 12728040Sache return uuerr; 12824417Sbrian} 12924417Sbrian 13025740Sbrianint uu_unlock (const char *ttyname) 13124417Sbrian{ 13224417Sbrian char tbuf[sizeof(_PATH_UUCPLOCK) + MAXNAMLEN]; 13324417Sbrian 13424529Sache (void)snprintf(tbuf, sizeof(tbuf), _PATH_UUCPLOCK LOCKFMT, ttyname); 13524461Sbrian return unlink(tbuf); 13624417Sbrian} 13724417Sbrian 13825740Sbrianconst char *uu_lockerr (int uu_lockresult) 13924461Sbrian{ 14024531Sache static char errbuf[128]; 14124530Sache char *fmt; 14224461Sbrian 14324461Sbrian switch (uu_lockresult) { 14424461Sbrian case UU_LOCK_INUSE: 14524529Sache return "device in use"; 14624529Sache case UU_LOCK_OK: 14724461Sbrian return ""; 14824461Sbrian case UU_LOCK_OPEN_ERR: 14924530Sache fmt = "open error: %s"; 15024461Sbrian break; 15124461Sbrian case UU_LOCK_READ_ERR: 15224530Sache fmt = "read error: %s"; 15324461Sbrian break; 15428040Sache case UU_LOCK_CREAT_ERR: 15528040Sache fmt = "creat error: %s"; 15624461Sbrian break; 15724461Sbrian case UU_LOCK_WRITE_ERR: 15824530Sache fmt = "write error: %s"; 15924461Sbrian break; 16028040Sache case UU_LOCK_LINK_ERR: 16128040Sache fmt = "link error: %s"; 16228040Sache break; 16328040Sache case UU_LOCK_TRY_ERR: 16428040Sache fmt = "too many tries: %s"; 16528040Sache break; 16624461Sbrian default: 16724530Sache fmt = "undefined error: %s"; 16824461Sbrian break; 16924461Sbrian } 17024461Sbrian 17124530Sache (void)snprintf(errbuf, sizeof(errbuf), fmt, strerror(errno)); 17224461Sbrian return errbuf; 17324461Sbrian} 17424461Sbrian 17524417Sbrianstatic int put_pid (int fd, pid_t pid) 17624417Sbrian{ 17724417Sbrian char buf[32]; 17824417Sbrian int len; 17924417Sbrian 18024417Sbrian len = sprintf (buf, "%10d\n", pid); 18124417Sbrian return write (fd, buf, len) == len; 18224417Sbrian} 18324417Sbrian 18428040Sachestatic pid_t get_pid (int fd, int *err) 18524417Sbrian{ 18624417Sbrian int bytes_read; 18724417Sbrian char buf[32]; 18824417Sbrian pid_t pid; 18924417Sbrian 19024417Sbrian bytes_read = read (fd, buf, sizeof (buf) - 1); 19124417Sbrian if (bytes_read > 0) { 19224417Sbrian buf[bytes_read] = '\0'; 19324417Sbrian pid = strtol (buf, (char **) NULL, 10); 19424461Sbrian } else { 19524417Sbrian pid = -1; 19624461Sbrian *err = bytes_read ? errno : EINVAL; 19724461Sbrian } 19824417Sbrian return pid; 19924417Sbrian} 20024417Sbrian 20124417Sbrian/* end of uucplock.c */ 202