1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* Copyright (c) 1988 AT&T */ 28 /* All Rights Reserved */ 29 30 #include "lint.h" 31 #include <sys/types.h> 32 #include <stdio.h> 33 #include <signal.h> 34 #include <fcntl.h> 35 #include <unistd.h> 36 #include <shadow.h> 37 #include <errno.h> 38 #include <thread.h> 39 #include "mtlib.h" 40 41 #define LOCKFILE "/etc/.pwd.lock" 42 #define S_WAITTIME 15 43 44 static struct flock flock = { 45 0, /* l_type */ 46 0, /* l_whence */ 47 0, /* l_start */ 48 0, /* l_len */ 49 0, /* l_sysid */ 50 0 /* l_pid */ 51 }; 52 53 /* 54 * lckpwdf() returns a 0 for a successful lock within W_WAITTIME 55 * seconds and -1 otherwise. We stand on our head to make it MT-safe. 56 */ 57 58 static pid_t lck_pid = 0; /* process's pid at last lock */ 59 static thread_t lck_tid = 0; /* thread that holds the lock */ 60 static int fildes = -1; 61 static mutex_t lck_lock = DEFAULTMUTEX; 62 63 int 64 lckpwdf(void) 65 { 66 int seconds = 0; 67 68 lmutex_lock(&lck_lock); 69 for (;;) { 70 if (lck_pid != 0 && lck_pid != getpid()) { 71 /* somebody forked */ 72 lck_pid = 0; 73 lck_tid = 0; 74 } 75 if (lck_tid == 0) { 76 if ((fildes = creat(LOCKFILE, 0600)) == -1) 77 break; 78 flock.l_type = F_WRLCK; 79 if (fcntl(fildes, F_SETLK, &flock) != -1) { 80 lck_pid = getpid(); 81 lck_tid = thr_self(); 82 lmutex_unlock(&lck_lock); 83 return (0); 84 } 85 (void) close(fildes); 86 fildes = -1; 87 } 88 if (seconds++ >= S_WAITTIME) { 89 /* 90 * For compatibility with the past, pretend 91 * that we were interrupted by SIGALRM. 92 */ 93 errno = EINTR; 94 break; 95 } 96 lmutex_unlock(&lck_lock); 97 (void) sleep(1); 98 lmutex_lock(&lck_lock); 99 } 100 lmutex_unlock(&lck_lock); 101 return (-1); 102 } 103 104 /* 105 * ulckpwdf() returns 0 for a successful unlock and -1 otherwise 106 */ 107 int 108 ulckpwdf(void) 109 { 110 lmutex_lock(&lck_lock); 111 if (lck_tid == thr_self() && fildes >= 0) { 112 flock.l_type = F_UNLCK; 113 (void) fcntl(fildes, F_SETLK, &flock); 114 (void) close(fildes); 115 fildes = -1; 116 lck_pid = 0; 117 lck_tid = 0; 118 lmutex_unlock(&lck_lock); 119 return (0); 120 } 121 lmutex_unlock(&lck_lock); 122 return (-1); 123 } 124