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 * 4. Neither the name of the University nor the names of its contributors 1424417Sbrian * may be used to endorse or promote products derived from this software 1524417Sbrian * without specific prior written permission. 1624417Sbrian * 1724417Sbrian * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 1824417Sbrian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1924417Sbrian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2024417Sbrian * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2124417Sbrian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2224417Sbrian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2324417Sbrian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2424417Sbrian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2524417Sbrian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2624417Sbrian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2724417Sbrian * SUCH DAMAGE. 2824417Sbrian */ 2924417Sbrian 3084225Sdillon#include <sys/cdefs.h> 3184225Sdillon__FBSDID("$FreeBSD$"); 3284225Sdillon 3324417Sbrian#ifndef lint 3424417Sbrianstatic const char sccsid[] = "@(#)uucplock.c 8.1 (Berkeley) 6/6/93"; 3524417Sbrian#endif /* not lint */ 3624417Sbrian 3724417Sbrian#include <sys/types.h> 3824417Sbrian#include <sys/file.h> 3924417Sbrian#include <dirent.h> 4024417Sbrian#include <errno.h> 41116344Smarkm#include <paths.h> 4224417Sbrian#include <signal.h> 4324417Sbrian#include <stdio.h> 4424417Sbrian#include <stdlib.h> 4524461Sbrian#include <string.h> 46116344Smarkm#include <unistd.h> 4724461Sbrian#include "libutil.h" 4824417Sbrian 4928040Sache#define MAXTRIES 5 5028040Sache 5128040Sache#define LOCKTMP "LCKTMP..%d" 5224417Sbrian#define LOCKFMT "LCK..%s" 5324417Sbrian 5428040Sache#define GORET(level, val) { err = errno; uuerr = (val); \ 5528040Sache goto __CONCAT(ret, level); } 5628040Sache 5724417Sbrian/* Forward declarations */ 5824417Sbrianstatic int put_pid (int fd, pid_t pid); 5924461Sbrianstatic pid_t get_pid (int fd,int *err); 6024417Sbrian 6124417Sbrian/* 6224417Sbrian * uucp style locking routines 6324417Sbrian */ 6424417Sbrian 6536451Sbrianint 66121193Smarkmuu_lock(const char *tty_name) 6724417Sbrian{ 6828040Sache int fd, tmpfd, i; 6944652Sbrian pid_t pid, pid_old; 7028040Sache char lckname[sizeof(_PATH_UUCPLOCK) + MAXNAMLEN], 7128040Sache lcktmpname[sizeof(_PATH_UUCPLOCK) + MAXNAMLEN]; 7228040Sache int err, uuerr; 7324417Sbrian 7428040Sache pid = getpid(); 7528040Sache (void)snprintf(lcktmpname, sizeof(lcktmpname), _PATH_UUCPLOCK LOCKTMP, 7628040Sache pid); 7728040Sache (void)snprintf(lckname, sizeof(lckname), _PATH_UUCPLOCK LOCKFMT, 78121193Smarkm tty_name); 7928040Sache if ((tmpfd = creat(lcktmpname, 0664)) < 0) 8028040Sache GORET(0, UU_LOCK_CREAT_ERR); 8124461Sbrian 8228040Sache for (i = 0; i < MAXTRIES; i++) { 8328040Sache if (link (lcktmpname, lckname) < 0) { 8428040Sache if (errno != EEXIST) 8528040Sache GORET(1, UU_LOCK_LINK_ERR); 8628040Sache /* 8728040Sache * file is already locked 8828040Sache * check to see if the process holding the lock 8928040Sache * still exists 9028040Sache */ 9128040Sache if ((fd = open(lckname, O_RDONLY)) < 0) 9228040Sache GORET(1, UU_LOCK_OPEN_ERR); 9324417Sbrian 9444652Sbrian if ((pid_old = get_pid (fd, &err)) == -1) 9528040Sache GORET(2, UU_LOCK_READ_ERR); 9628040Sache 9728040Sache close(fd); 9828040Sache 9944652Sbrian if (kill(pid_old, 0) == 0 || errno != ESRCH) 10028040Sache GORET(1, UU_LOCK_INUSE); 10128040Sache /* 10228040Sache * The process that locked the file isn't running, so 10328040Sache * we'll lock it ourselves 10428040Sache */ 10528040Sache (void)unlink(lckname); 10628040Sache } else { 10728040Sache if (!put_pid (tmpfd, pid)) 10828040Sache GORET(3, UU_LOCK_WRITE_ERR); 10928040Sache break; 11024417Sbrian } 11124417Sbrian } 11228040Sache GORET(1, (i >= MAXTRIES) ? UU_LOCK_TRY_ERR : UU_LOCK_OK); 11328040Sache 11428040Sacheret3: 11528040Sache (void)unlink(lckname); 11628040Sache goto ret1; 11728040Sacheret2: 11824417Sbrian (void)close(fd); 11928040Sacheret1: 12028040Sache (void)close(tmpfd); 12128040Sache (void)unlink(lcktmpname); 12228040Sacheret0: 12328040Sache errno = err; 12428040Sache return uuerr; 12524417Sbrian} 12624417Sbrian 12736451Sbrianint 128121193Smarkmuu_lock_txfr(const char *tty_name, pid_t pid) 12924417Sbrian{ 13036451Sbrian int fd, err; 13136451Sbrian char lckname[sizeof(_PATH_UUCPLOCK) + MAXNAMLEN]; 13236451Sbrian 133121193Smarkm snprintf(lckname, sizeof(lckname), _PATH_UUCPLOCK LOCKFMT, tty_name); 13436451Sbrian 13536451Sbrian if ((fd = open(lckname, O_RDWR)) < 0) 13636451Sbrian return UU_LOCK_OWNER_ERR; 13736451Sbrian if (get_pid(fd, &err) != getpid()) 13866558Sbrian err = UU_LOCK_OWNER_ERR; 13966558Sbrian else { 140121193Smarkm lseek(fd, (off_t)0, SEEK_SET); 14166558Sbrian err = put_pid(fd, pid) ? 0 : UU_LOCK_WRITE_ERR; 14266558Sbrian } 14336451Sbrian close(fd); 14436451Sbrian 14566558Sbrian return err; 14636451Sbrian} 14736451Sbrian 14836451Sbrianint 149121193Smarkmuu_unlock(const char *tty_name) 15036451Sbrian{ 15124417Sbrian char tbuf[sizeof(_PATH_UUCPLOCK) + MAXNAMLEN]; 15224417Sbrian 153121193Smarkm (void)snprintf(tbuf, sizeof(tbuf), _PATH_UUCPLOCK LOCKFMT, tty_name); 15424461Sbrian return unlink(tbuf); 15524417Sbrian} 15624417Sbrian 15736451Sbrianconst char * 15836451Sbrianuu_lockerr(int uu_lockresult) 15924461Sbrian{ 16024531Sache static char errbuf[128]; 161121193Smarkm const char *fmt; 16224461Sbrian 16324461Sbrian switch (uu_lockresult) { 16424461Sbrian case UU_LOCK_INUSE: 16524529Sache return "device in use"; 16624529Sache case UU_LOCK_OK: 16724461Sbrian return ""; 16824461Sbrian case UU_LOCK_OPEN_ERR: 16924530Sache fmt = "open error: %s"; 17024461Sbrian break; 17124461Sbrian case UU_LOCK_READ_ERR: 17224530Sache fmt = "read error: %s"; 17324461Sbrian break; 17428040Sache case UU_LOCK_CREAT_ERR: 17528040Sache fmt = "creat error: %s"; 17624461Sbrian break; 17724461Sbrian case UU_LOCK_WRITE_ERR: 17824530Sache fmt = "write error: %s"; 17924461Sbrian break; 18028040Sache case UU_LOCK_LINK_ERR: 18128040Sache fmt = "link error: %s"; 18228040Sache break; 18328040Sache case UU_LOCK_TRY_ERR: 18428040Sache fmt = "too many tries: %s"; 18528040Sache break; 18636451Sbrian case UU_LOCK_OWNER_ERR: 18736451Sbrian fmt = "not locking process: %s"; 18836451Sbrian break; 18924461Sbrian default: 19024530Sache fmt = "undefined error: %s"; 19124461Sbrian break; 19224461Sbrian } 19324461Sbrian 19424530Sache (void)snprintf(errbuf, sizeof(errbuf), fmt, strerror(errno)); 19524461Sbrian return errbuf; 19624461Sbrian} 19724461Sbrian 19836451Sbrianstatic int 19936451Sbrianput_pid(int fd, pid_t pid) 20024417Sbrian{ 20124417Sbrian char buf[32]; 20224417Sbrian int len; 20324417Sbrian 20436833Sbrian len = sprintf (buf, "%10d\n", (int)pid); 205121193Smarkm return write (fd, buf, (size_t)len) == len; 20624417Sbrian} 20724417Sbrian 20836451Sbrianstatic pid_t 20936451Sbrianget_pid(int fd, int *err) 21024417Sbrian{ 21124417Sbrian int bytes_read; 21224417Sbrian char buf[32]; 21324417Sbrian pid_t pid; 21424417Sbrian 21524417Sbrian bytes_read = read (fd, buf, sizeof (buf) - 1); 21624417Sbrian if (bytes_read > 0) { 21724417Sbrian buf[bytes_read] = '\0'; 218121193Smarkm pid = (pid_t)strtol (buf, (char **) NULL, 10); 21924461Sbrian } else { 22024417Sbrian pid = -1; 22124461Sbrian *err = bytes_read ? errno : EINVAL; 22224461Sbrian } 22324417Sbrian return pid; 22424417Sbrian} 22524417Sbrian 22624417Sbrian/* end of uucplock.c */ 227