diff options
author | stevel@tonic-gate <none@none> | 2005-06-14 00:00:00 -0700 |
---|---|---|
committer | stevel@tonic-gate <none@none> | 2005-06-14 00:00:00 -0700 |
commit | 7c478bd95313f5f23a4c958a745db2134aa03244 (patch) | |
tree | c871e58545497667cbb4b0a4f2daf204743e1fe7 /usr/src/lib/libmail/common/maillock.c | |
download | illumos-joyent-7c478bd95313f5f23a4c958a745db2134aa03244.tar.gz |
OpenSolaris Launch
Diffstat (limited to 'usr/src/lib/libmail/common/maillock.c')
-rw-r--r-- | usr/src/lib/libmail/common/maillock.c | 187 |
1 files changed, 187 insertions, 0 deletions
diff --git a/usr/src/lib/libmail/common/maillock.c b/usr/src/lib/libmail/common/maillock.c new file mode 100644 index 0000000000..aaaccbcce5 --- /dev/null +++ b/usr/src/lib/libmail/common/maillock.c @@ -0,0 +1,187 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ +/* All Rights Reserved */ + + +/* + * Copyright (c) 1999, by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" +/*LINTLIBRARY*/ + +#include "synonyms.h" +#include "maillock.h" +#include <sys/types.h> +#include <fcntl.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include <stdlib.h> +#include <utime.h> + +#include <sys/stat.h> + +static char *lockext = ".lock"; /* Lock suffix for mailname */ +static char curlock[PATHSIZE]; /* Last used name of lock */ +static int locked; /* To note that we locked it */ +static time_t locktime; /* time lock file was touched */ +static time_t lock1(char *, char *); + +/* + * Lock the specified mail file by setting the file mailfile.lock. + * We must, of course, be careful to remove the lock file by a call + * to unlock before we stop. The algorithm used here is to see if + * the lock exists, and if it does, to check its modify time. If it + * is older than 5 minutes, we assume error and set our own file. + * Otherwise, we wait for 5 seconds and try again. + */ + +/*ARGSUSED*/ +int +maillock(char *user, int retrycnt) +{ + time_t t; + struct stat sbuf; + int statfailed; + char locktmp[PATHSIZE]; /* Usable lock temporary */ + char file[PATHSIZE]; + + if (locked) + return (0); + (void) strcpy(file, MAILDIR); + (void) strcat(file, user); + (void) strcpy(curlock, file); + (void) strcat(curlock, lockext); + (void) strcpy(locktmp, file); + (void) strcat(locktmp, "XXXXXX"); + (void) mktemp(locktmp); + (void) remove(locktmp); + statfailed = 0; + for (;;) { + t = lock1(locktmp, curlock); + if (t == (time_t)0) { + locked = 1; + locktime = time(0); + return (0); + } + if (stat(curlock, &sbuf) < 0) { + if (statfailed++ > 5) + return (-1); + (void) sleep(5); + continue; + } + statfailed = 0; + + /* + * Compare the time of the temp file with the time + * of the lock file, rather than with the current + * time of day, since the files may reside on + * another machine whose time of day differs from + * ours. If the lock file is less than 5 minutes + * old, keep trying. + */ + if (t < sbuf.st_ctime + 300) { + (void) sleep(5); + continue; + } + (void) remove(curlock); + } +} + +/* + * Remove the mail lock, and note that we no longer + * have it locked. + */ +void +mailunlock(void) +{ + (void) remove(curlock); + locked = 0; +} + +/* + * Attempt to set the lock by creating the temporary file, + * then doing a link/unlink. If it succeeds, return 0, + * else return a guess of the current time on the machine + * holding the file. + */ +static time_t +lock1(char tempfile[], char name[]) +{ + int fd; + struct stat sbuf; + + fd = open(tempfile, O_RDWR|O_CREAT|O_EXCL, 0600); + if (fd < 0) + return (time(0)); + (void) fstat(fd, &sbuf); + /* + * Write the string "0" into the lock file to give us some + * interoperability with SVR4 mailers. SVR4 mailers expect + * a process ID to be written into the lock file and then + * use kill() to see if the process is alive or not. We write + * 0 into it so that SVR4 mailers will always think our lock file + * is valid. + */ + (void) write(fd, "0", 2); + (void) close(fd); + if (link(tempfile, name) < 0) { + (void) remove(tempfile); + return (sbuf.st_ctime); + } + (void) remove(tempfile); + return ((time_t)0); +} + +/* + * Update the change time on the lock file so + * others will know we're still using it. + */ +void +touchlock(void) +{ + struct stat sbuf; + time_t t; + struct utimbuf tp; + + if (!locked) + return; + + /* if it hasn't been at least 3 minutes, don't bother */ + if (time(&t) < locktime + 180) + return; + locktime = t; + + if (stat(curlock, &sbuf) < 0) + return; + /* + * Don't actually change the times, we just want the + * side effect that utime causes st_ctime to be set + * to the current time. + */ + tp.actime = sbuf.st_atime; + tp.modtime = sbuf.st_mtime; + (void) utime(curlock, &tp); +} |