uucplock.c revision 121193
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. 3224417Sbrian */ 3324417Sbrian 3484225Sdillon#include <sys/cdefs.h> 3584225Sdillon__FBSDID("$FreeBSD: head/lib/libutil/uucplock.c 121193 2003-10-18 10:04:16Z markm $"); 3684225Sdillon 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> 45116344Smarkm#include <paths.h> 4624417Sbrian#include <signal.h> 4724417Sbrian#include <stdio.h> 4824417Sbrian#include <stdlib.h> 4924461Sbrian#include <string.h> 50116344Smarkm#include <unistd.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 6936451Sbrianint 70121193Smarkmuu_lock(const char *tty_name) 7124417Sbrian{ 7228040Sache int fd, tmpfd, i; 7344652Sbrian pid_t pid, pid_old; 7428040Sache char lckname[sizeof(_PATH_UUCPLOCK) + MAXNAMLEN], 7528040Sache lcktmpname[sizeof(_PATH_UUCPLOCK) + MAXNAMLEN]; 7628040Sache int err, uuerr; 7724417Sbrian 7828040Sache pid = getpid(); 7928040Sache (void)snprintf(lcktmpname, sizeof(lcktmpname), _PATH_UUCPLOCK LOCKTMP, 8028040Sache pid); 8128040Sache (void)snprintf(lckname, sizeof(lckname), _PATH_UUCPLOCK LOCKFMT, 82121193Smarkm tty_name); 8328040Sache if ((tmpfd = creat(lcktmpname, 0664)) < 0) 8428040Sache GORET(0, UU_LOCK_CREAT_ERR); 8524461Sbrian 8628040Sache for (i = 0; i < MAXTRIES; i++) { 8728040Sache if (link (lcktmpname, lckname) < 0) { 8828040Sache if (errno != EEXIST) 8928040Sache GORET(1, UU_LOCK_LINK_ERR); 9028040Sache /* 9128040Sache * file is already locked 9228040Sache * check to see if the process holding the lock 9328040Sache * still exists 9428040Sache */ 9528040Sache if ((fd = open(lckname, O_RDONLY)) < 0) 9628040Sache GORET(1, UU_LOCK_OPEN_ERR); 9724417Sbrian 9844652Sbrian if ((pid_old = get_pid (fd, &err)) == -1) 9928040Sache GORET(2, UU_LOCK_READ_ERR); 10028040Sache 10128040Sache close(fd); 10228040Sache 10344652Sbrian if (kill(pid_old, 0) == 0 || errno != ESRCH) 10428040Sache GORET(1, UU_LOCK_INUSE); 10528040Sache /* 10628040Sache * The process that locked the file isn't running, so 10728040Sache * we'll lock it ourselves 10828040Sache */ 10928040Sache (void)unlink(lckname); 11028040Sache } else { 11128040Sache if (!put_pid (tmpfd, pid)) 11228040Sache GORET(3, UU_LOCK_WRITE_ERR); 11328040Sache break; 11424417Sbrian } 11524417Sbrian } 11628040Sache GORET(1, (i >= MAXTRIES) ? UU_LOCK_TRY_ERR : UU_LOCK_OK); 11728040Sache 11828040Sacheret3: 11928040Sache (void)unlink(lckname); 12028040Sache goto ret1; 12128040Sacheret2: 12224417Sbrian (void)close(fd); 12328040Sacheret1: 12428040Sache (void)close(tmpfd); 12528040Sache (void)unlink(lcktmpname); 12628040Sacheret0: 12728040Sache errno = err; 12828040Sache return uuerr; 12924417Sbrian} 13024417Sbrian 13136451Sbrianint 132121193Smarkmuu_lock_txfr(const char *tty_name, pid_t pid) 13324417Sbrian{ 13436451Sbrian int fd, err; 13536451Sbrian char lckname[sizeof(_PATH_UUCPLOCK) + MAXNAMLEN]; 13636451Sbrian 137121193Smarkm snprintf(lckname, sizeof(lckname), _PATH_UUCPLOCK LOCKFMT, tty_name); 13836451Sbrian 13936451Sbrian if ((fd = open(lckname, O_RDWR)) < 0) 14036451Sbrian return UU_LOCK_OWNER_ERR; 14136451Sbrian if (get_pid(fd, &err) != getpid()) 14266558Sbrian err = UU_LOCK_OWNER_ERR; 14366558Sbrian else { 144121193Smarkm lseek(fd, (off_t)0, SEEK_SET); 14566558Sbrian err = put_pid(fd, pid) ? 0 : UU_LOCK_WRITE_ERR; 14666558Sbrian } 14736451Sbrian close(fd); 14836451Sbrian 14966558Sbrian return err; 15036451Sbrian} 15136451Sbrian 15236451Sbrianint 153121193Smarkmuu_unlock(const char *tty_name) 15436451Sbrian{ 15524417Sbrian char tbuf[sizeof(_PATH_UUCPLOCK) + MAXNAMLEN]; 15624417Sbrian 157121193Smarkm (void)snprintf(tbuf, sizeof(tbuf), _PATH_UUCPLOCK LOCKFMT, tty_name); 15824461Sbrian return unlink(tbuf); 15924417Sbrian} 16024417Sbrian 16136451Sbrianconst char * 16236451Sbrianuu_lockerr(int uu_lockresult) 16324461Sbrian{ 16424531Sache static char errbuf[128]; 165121193Smarkm const char *fmt; 16624461Sbrian 16724461Sbrian switch (uu_lockresult) { 16824461Sbrian case UU_LOCK_INUSE: 16924529Sache return "device in use"; 17024529Sache case UU_LOCK_OK: 17124461Sbrian return ""; 17224461Sbrian case UU_LOCK_OPEN_ERR: 17324530Sache fmt = "open error: %s"; 17424461Sbrian break; 17524461Sbrian case UU_LOCK_READ_ERR: 17624530Sache fmt = "read error: %s"; 17724461Sbrian break; 17828040Sache case UU_LOCK_CREAT_ERR: 17928040Sache fmt = "creat error: %s"; 18024461Sbrian break; 18124461Sbrian case UU_LOCK_WRITE_ERR: 18224530Sache fmt = "write error: %s"; 18324461Sbrian break; 18428040Sache case UU_LOCK_LINK_ERR: 18528040Sache fmt = "link error: %s"; 18628040Sache break; 18728040Sache case UU_LOCK_TRY_ERR: 18828040Sache fmt = "too many tries: %s"; 18928040Sache break; 19036451Sbrian case UU_LOCK_OWNER_ERR: 19136451Sbrian fmt = "not locking process: %s"; 19236451Sbrian break; 19324461Sbrian default: 19424530Sache fmt = "undefined error: %s"; 19524461Sbrian break; 19624461Sbrian } 19724461Sbrian 19824530Sache (void)snprintf(errbuf, sizeof(errbuf), fmt, strerror(errno)); 19924461Sbrian return errbuf; 20024461Sbrian} 20124461Sbrian 20236451Sbrianstatic int 20336451Sbrianput_pid(int fd, pid_t pid) 20424417Sbrian{ 20524417Sbrian char buf[32]; 20624417Sbrian int len; 20724417Sbrian 20836833Sbrian len = sprintf (buf, "%10d\n", (int)pid); 209121193Smarkm return write (fd, buf, (size_t)len) == len; 21024417Sbrian} 21124417Sbrian 21236451Sbrianstatic pid_t 21336451Sbrianget_pid(int fd, int *err) 21424417Sbrian{ 21524417Sbrian int bytes_read; 21624417Sbrian char buf[32]; 21724417Sbrian pid_t pid; 21824417Sbrian 21924417Sbrian bytes_read = read (fd, buf, sizeof (buf) - 1); 22024417Sbrian if (bytes_read > 0) { 22124417Sbrian buf[bytes_read] = '\0'; 222121193Smarkm pid = (pid_t)strtol (buf, (char **) NULL, 10); 22324461Sbrian } else { 22424417Sbrian pid = -1; 22524461Sbrian *err = bytes_read ? errno : EINVAL; 22624461Sbrian } 22724417Sbrian return pid; 22824417Sbrian} 22924417Sbrian 23024417Sbrian/* end of uucplock.c */ 231