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