1 /* 2 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 /* 7 * Copyright (c) 1983 Regents of the University of California. 8 * All rights reserved. The Berkeley software License Agreement 9 * specifies the terms and conditions for redistribution. 10 */ 11 12 #pragma ident "%Z%%M% %I% %E% SMI" 13 14 /* 15 * defs that come from uucp.h 16 */ 17 #define NAMESIZE 40 18 #define FAIL -1 19 #define SAME 0 20 #define SLCKTIME (8*60*60) /* device timeout (LCK.. files) in seconds */ 21 #ifdef __STDC__ 22 #define ASSERT(e, f, v) if (!(e)) {\ 23 (void) fprintf(stderr, "AERROR - (%s) ", #e); \ 24 (void) fprintf(stderr, f, v); \ 25 finish(FAIL); \ 26 } 27 #else 28 #define ASSERT(e, f, v) if (!(e)) {\ 29 (void) fprintf(stderr, "AERROR - (%s) ", "e"); \ 30 (void) fprintf(stderr, f, v); \ 31 finish(FAIL); \ 32 } 33 #endif 34 #define SIZEOFPID 10 /* maximum number of digits in a pid */ 35 36 #define LOCKDIR "/var/spool/locks" 37 #define LOCKPRE "LK" 38 39 /* 40 * This code is taken almost directly from uucp and follows the same 41 * conventions. This is important since uucp and tip should 42 * respect each others locks. 43 */ 44 45 #include <sys/types.h> 46 #include <sys/stat.h> 47 #include <sys/mkdev.h> 48 #include <stdio.h> 49 #include <errno.h> 50 #include <string.h> 51 #include <stdlib.h> 52 #include <time.h> 53 #include <unistd.h> 54 #include <fcntl.h> 55 #include <signal.h> 56 #include <utime.h> 57 58 static void stlock(char *); 59 static int onelock(char *, char *, char *); 60 static int checkLock(char *); 61 62 extern void finish(int); 63 64 /* 65 * ulockf(file, atime) 66 * char *file; 67 * time_t atime; 68 * 69 * ulockf - this routine will create a lock file (file). 70 * If one already exists, send a signal 0 to the process--if 71 * it fails, then unlink it and make a new one. 72 * 73 * input: 74 * file - name of the lock file 75 * atime - is unused, but we keep it for lint compatibility 76 * with non-ATTSVKILL 77 * 78 * return codes: 0 | FAIL 79 */ 80 /* ARGSUSED */ 81 static int 82 ulockf(char *file, time_t atime) 83 { 84 static char pid[SIZEOFPID+2] = { '\0' }; /* +2 for '\n' and NULL */ 85 static char tempfile[NAMESIZE]; 86 87 if (pid[0] == '\0') { 88 (void) sprintf(pid, "%*d\n", SIZEOFPID, (int)getpid()); 89 (void) snprintf(tempfile, sizeof (tempfile), 90 "%s/LTMP.%d", LOCKDIR, getpid()); 91 } 92 if (onelock(pid, tempfile, file) == -1) { 93 /* lock file exists */ 94 (void) unlink(tempfile); 95 if (checkLock(file)) 96 return (FAIL); 97 else { 98 if (onelock(pid, tempfile, file)) { 99 (void) unlink(tempfile); 100 return (FAIL); 101 } 102 } 103 } 104 stlock(file); 105 return (0); 106 } 107 108 /* 109 * check to see if the lock file exists and is still active 110 * - use kill(pid, 0) - (this only works on ATTSV and some hacked 111 * BSD systems at this time) 112 * return: 113 * 0 -> success (lock file removed - no longer active) 114 * FAIL -> lock file still active 115 */ 116 static int 117 checkLock(char *file) 118 { 119 int ret; 120 int lpid = -1; 121 char alpid[SIZEOFPID+2]; /* +2 for '\n' and NULL */ 122 int fd; 123 124 fd = open(file, 0); 125 if (fd == -1) { 126 if (errno == ENOENT) /* file does not exist -- OK */ 127 return (0); 128 goto unlk; 129 } 130 ret = read(fd, (char *)alpid, SIZEOFPID+1); /* +1 for '\n' */ 131 (void) close(fd); 132 if (ret != (SIZEOFPID+1)) 133 goto unlk; 134 lpid = atoi(alpid); 135 if ((ret = kill(lpid, 0)) == 0 || errno == EPERM) 136 return (FAIL); 137 138 unlk: 139 if (unlink(file) != 0) 140 return (FAIL); 141 return (0); 142 } 143 144 #define MAXLOCKS 10 /* maximum number of lock files */ 145 char *Lockfile[MAXLOCKS]; 146 int Nlocks = 0; 147 148 /* 149 * stlock(name) put name in list of lock files 150 * char *name; 151 * 152 * return codes: none 153 */ 154 155 static void 156 stlock(char *name) 157 { 158 char *p; 159 int i; 160 161 for (i = 0; i < Nlocks; i++) { 162 if (Lockfile[i] == NULL) 163 break; 164 } 165 ASSERT(i < MAXLOCKS, "TOO MANY LOCKS %d", i); 166 if (i >= Nlocks) 167 i = Nlocks++; 168 p = calloc(strlen(name) + 1, sizeof (char)); 169 ASSERT(p != NULL, "CAN NOT ALLOCATE FOR %s", name); 170 (void) strcpy(p, name); 171 Lockfile[i] = p; 172 } 173 174 /* 175 * rmlock(name) remove all lock files in list 176 * char *name; or name 177 * 178 * return codes: none 179 */ 180 181 static void 182 rmlock(char *name) 183 { 184 int i; 185 186 for (i = 0; i < Nlocks; i++) { 187 if (Lockfile[i] == NULL) 188 continue; 189 if (name == NULL || strcmp(name, Lockfile[i]) == SAME) { 190 (void) unlink(Lockfile[i]); 191 free(Lockfile[i]); 192 Lockfile[i] = NULL; 193 } 194 } 195 } 196 197 static int 198 onelock(char *pid, char *tempfile, char *name) 199 { 200 int fd; 201 static int first = 1; 202 203 fd = creat(tempfile, 0444); 204 if (fd < 0) { 205 if (first) { 206 if (errno == EACCES) { 207 (void) fprintf(stderr, 208 "tip: can't create files in lock file directory %s\n", 209 LOCKDIR); 210 } else if (access(LOCKDIR, 0) < 0) { 211 (void) fprintf(stderr, 212 "tip: lock file directory %s: ", 213 LOCKDIR); 214 perror(""); 215 } 216 first = 0; 217 } 218 if (errno == EMFILE || errno == ENFILE) 219 (void) unlink(tempfile); 220 return (-1); 221 } 222 /* +1 for '\n' */ 223 if (write(fd, pid, SIZEOFPID+1) != (SIZEOFPID+1)) { 224 (void) fprintf(stderr, 225 "tip: can't write to files in lock file directory %s: %s\n", 226 LOCKDIR, strerror(errno)); 227 (void) unlink(tempfile); 228 return (-1); 229 } 230 (void) fchmod(fd, 0444); 231 (void) close(fd); 232 if (link(tempfile, name) < 0) { 233 (void) unlink(tempfile); 234 return (-1); 235 } 236 (void) unlink(tempfile); 237 return (0); 238 } 239 240 /* 241 * delock(sys) remove a lock file 242 * char *sys; 243 */ 244 245 void 246 delock(char *sys) 247 { 248 struct stat sb; 249 char lname[NAMESIZE]; 250 251 if (stat(sys, &sb) < 0) 252 return; 253 (void) snprintf(lname, sizeof (lname), "%s/%s.%3.3lu.%3.3lu.%3.3lu", 254 LOCKDIR, LOCKPRE, 255 (unsigned long)major(sb.st_dev), 256 (unsigned long)major(sb.st_rdev), 257 (unsigned long)minor(sb.st_rdev)); 258 rmlock(lname); 259 } 260 261 /* 262 * tip_mlock(sys) create system lock 263 * char *sys; 264 * 265 * return codes: 0 | FAIL 266 */ 267 268 int 269 tip_mlock(char *sys) 270 { 271 struct stat sb; 272 char lname[NAMESIZE]; 273 274 if (stat(sys, &sb) < 0) 275 return (FAIL); 276 (void) snprintf(lname, sizeof (lname), "%s/%s.%3.3lu.%3.3lu.%3.3lu", 277 LOCKDIR, LOCKPRE, 278 (unsigned long)major(sb.st_dev), 279 (unsigned long)major(sb.st_rdev), 280 (unsigned long)minor(sb.st_rdev)); 281 return (ulockf(lname, (time_t)SLCKTIME) < 0 ? FAIL : 0); 282 } 283