uucplock.c revision 36451
185909Simp/* 285909Simp * Copyright (c) 1988, 1993 385909Simp * The Regents of the University of California. All rights reserved. 485909Simp * 585909Simp * Redistribution and use in source and binary forms, with or without 685909Simp * modification, are permitted provided that the following conditions 785909Simp * are met: 885909Simp * 1. Redistributions of source code must retain the above copyright 985909Simp * notice, this list of conditions and the following disclaimer. 1085909Simp * 2. Redistributions in binary form must reproduce the above copyright 1185909Simp * notice, this list of conditions and the following disclaimer in the 1285909Simp * documentation and/or other materials provided with the distribution. 1385909Simp * 3. All advertising materials mentioning features or use of this software 1485909Simp * must display the following acknowledgement: 1585909Simp * This product includes software developed by the University of 1685909Simp * California, Berkeley and its contributors. 1785909Simp * 4. Neither the name of the University nor the names of its contributors 1885909Simp * may be used to endorse or promote products derived from this software 1985909Simp * without specific prior written permission. 2085909Simp * 2185909Simp * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2285909Simp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2385909Simp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2485909Simp * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2585909Simp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2685909Simp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2785909Simp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2885909Simp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2985909Simp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3085909Simp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3185909Simp * SUCH DAMAGE. 3285909Simp * 3385909Simp * $Id: uucplock.c,v 1.8 1997/08/10 18:42:39 ache Exp $ 3485909Simp * 3585909Simp */ 3685909Simp 3785909Simp#ifndef lint 3885909Simpstatic const char sccsid[] = "@(#)uucplock.c 8.1 (Berkeley) 6/6/93"; 3985909Simp#endif /* not lint */ 4085909Simp 4185909Simp#include <sys/types.h> 4285909Simp#include <sys/file.h> 4385909Simp#include <dirent.h> 4485909Simp#include <errno.h> 4585909Simp#include <unistd.h> 4685909Simp#include <signal.h> 4785909Simp#include <stdio.h> 4885909Simp#include <stdlib.h> 4985909Simp#include <paths.h> 5085909Simp#include <string.h> 5185909Simp#include "libutil.h" 5285909Simp 5385909Simp#define MAXTRIES 5 5485909Simp 5585909Simp#define LOCKTMP "LCKTMP..%d" 5685909Simp#define LOCKFMT "LCK..%s" 5785909Simp 5885909Simp#define GORET(level, val) { err = errno; uuerr = (val); \ 5985909Simp goto __CONCAT(ret, level); } 6085909Simp 6185909Simp/* Forward declarations */ 6285909Simpstatic int put_pid (int fd, pid_t pid); 6385909Simpstatic pid_t get_pid (int fd,int *err); 6485909Simp 6585909Simp/* 6685909Simp * uucp style locking routines 6785909Simp */ 6885909Simp 6985909Simpint 7085909Simpuu_lock(const char *ttyname) 7185909Simp{ 7285909Simp int fd, tmpfd, i; 7385909Simp pid_t pid; 7485909Simp char lckname[sizeof(_PATH_UUCPLOCK) + MAXNAMLEN], 7585909Simp lcktmpname[sizeof(_PATH_UUCPLOCK) + MAXNAMLEN]; 7685909Simp int err, uuerr; 7785909Simp 7885909Simp pid = getpid(); 7985909Simp (void)snprintf(lcktmpname, sizeof(lcktmpname), _PATH_UUCPLOCK LOCKTMP, 8085909Simp pid); 8185909Simp (void)snprintf(lckname, sizeof(lckname), _PATH_UUCPLOCK LOCKFMT, 8285909Simp ttyname); 8385909Simp if ((tmpfd = creat(lcktmpname, 0664)) < 0) 8485909Simp GORET(0, UU_LOCK_CREAT_ERR); 8585909Simp 8685909Simp for (i = 0; i < MAXTRIES; i++) { 8785909Simp if (link (lcktmpname, lckname) < 0) { 8885909Simp if (errno != EEXIST) 8985909Simp GORET(1, UU_LOCK_LINK_ERR); 9085909Simp /* 9185909Simp * file is already locked 9285909Simp * check to see if the process holding the lock 9385909Simp * still exists 9485909Simp */ 9585909Simp if ((fd = open(lckname, O_RDONLY)) < 0) 9685909Simp GORET(1, UU_LOCK_OPEN_ERR); 9785909Simp 9885909Simp if ((pid = get_pid (fd, &err)) == -1) 9985909Simp GORET(2, UU_LOCK_READ_ERR); 10085909Simp 10185909Simp close(fd); 10285909Simp 10385909Simp if (kill(pid, 0) == 0 || errno != ESRCH) 10485909Simp GORET(1, UU_LOCK_INUSE); 10585909Simp /* 10685909Simp * The process that locked the file isn't running, so 10785909Simp * we'll lock it ourselves 10885909Simp */ 10985909Simp (void)unlink(lckname); 11085909Simp } else { 11185909Simp if (!put_pid (tmpfd, pid)) 11285909Simp GORET(3, UU_LOCK_WRITE_ERR); 11385909Simp break; 11485909Simp } 11585909Simp } 11685909Simp GORET(1, (i >= MAXTRIES) ? UU_LOCK_TRY_ERR : UU_LOCK_OK); 11785909Simp 11885909Simpret3: 11985909Simp (void)unlink(lckname); 12085909Simp goto ret1; 12185909Simpret2: 12285909Simp (void)close(fd); 12385909Simpret1: 12485909Simp (void)close(tmpfd); 12585909Simp (void)unlink(lcktmpname); 12685909Simpret0: 12785909Simp errno = err; 12885909Simp return uuerr; 12985909Simp} 13085909Simp 13185909Simpint 13285909Simpuu_lock_txfr(const char *ttyname, pid_t pid) 13385909Simp{ 13485909Simp int fd, err; 13585909Simp char lckname[sizeof(_PATH_UUCPLOCK) + MAXNAMLEN]; 13685909Simp 13785909Simp snprintf(lckname, sizeof(lckname), _PATH_UUCPLOCK LOCKFMT, ttyname); 13885909Simp 13985909Simp if ((fd = open(lckname, O_RDWR)) < 0) 14085909Simp return UU_LOCK_OWNER_ERR; 14185909Simp if (get_pid(fd, &err) != getpid()) 14285909Simp return UU_LOCK_OWNER_ERR; 14385909Simp lseek(fd, 0, SEEK_SET); 14485909Simp if (put_pid(fd, pid)) 14585909Simp return UU_LOCK_WRITE_ERR; 14685909Simp close(fd); 14785909Simp 14885909Simp return UU_LOCK_OK; 14985909Simp} 15085909Simp 15185909Simpint 15285909Simpuu_unlock(const char *ttyname) 15385909Simp{ 15485909Simp char tbuf[sizeof(_PATH_UUCPLOCK) + MAXNAMLEN]; 15585909Simp 15685909Simp (void)snprintf(tbuf, sizeof(tbuf), _PATH_UUCPLOCK LOCKFMT, ttyname); 15785909Simp return unlink(tbuf); 15885909Simp} 15985909Simp 16085909Simpconst char * 16185909Simpuu_lockerr(int uu_lockresult) 16285909Simp{ 16385909Simp static char errbuf[128]; 16485909Simp char *fmt; 16585909Simp 16685909Simp switch (uu_lockresult) { 16785909Simp case UU_LOCK_INUSE: 16885909Simp return "device in use"; 16985909Simp case UU_LOCK_OK: 17085909Simp return ""; 17185909Simp case UU_LOCK_OPEN_ERR: 17285909Simp fmt = "open error: %s"; 17385909Simp break; 17485909Simp case UU_LOCK_READ_ERR: 17585909Simp fmt = "read error: %s"; 17685909Simp break; 17785909Simp case UU_LOCK_CREAT_ERR: 17885909Simp fmt = "creat error: %s"; 17985909Simp break; 18085909Simp case UU_LOCK_WRITE_ERR: 18185909Simp fmt = "write error: %s"; 18285909Simp break; 18385909Simp case UU_LOCK_LINK_ERR: 18485909Simp fmt = "link error: %s"; 18585909Simp break; 18685909Simp case UU_LOCK_TRY_ERR: 18785909Simp fmt = "too many tries: %s"; 18885909Simp break; 18985909Simp case UU_LOCK_OWNER_ERR: 19085909Simp fmt = "not locking process: %s"; 19185909Simp break; 19285909Simp default: 19385909Simp fmt = "undefined error: %s"; 19485909Simp break; 19585909Simp } 19685909Simp 19785909Simp (void)snprintf(errbuf, sizeof(errbuf), fmt, strerror(errno)); 19885909Simp return errbuf; 19985909Simp} 20085909Simp 20185909Simpstatic int 20285909Simpput_pid(int fd, pid_t pid) 20385909Simp{ 20485909Simp char buf[32]; 20585909Simp int len; 20685909Simp 20785909Simp len = sprintf (buf, "%10d\n", pid); 20885909Simp return write (fd, buf, len) == len; 20985909Simp} 21085909Simp 21185909Simpstatic pid_t 21285909Simpget_pid(int fd, int *err) 21385909Simp{ 21485909Simp int bytes_read; 21585909Simp char buf[32]; 21685909Simp pid_t pid; 21785909Simp 21885909Simp bytes_read = read (fd, buf, sizeof (buf) - 1); 21985909Simp if (bytes_read > 0) { 22085909Simp buf[bytes_read] = '\0'; 22185909Simp pid = strtol (buf, (char **) NULL, 10); 22285909Simp } else { 22385909Simp pid = -1; 22485909Simp *err = bytes_read ? errno : EINVAL; 22585909Simp } 22685909Simp return pid; 22785909Simp} 22885909Simp 22985909Simp/* end of uucplock.c */ 23085909Simp