1 /* 2 * Copyright 2006 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) snprintf(pid, sizeof (pid), "%*d\n", SIZEOFPID, 89 (int)getpid()); 90 (void) snprintf(tempfile, sizeof (tempfile), 91 "%s/LTMP.%d", LOCKDIR, getpid()); 92 } 93 if (onelock(pid, tempfile, file) == -1) { 94 /* lock file exists */ 95 (void) unlink(tempfile); 96 if (checkLock(file)) 97 return (FAIL); 98 else { 99 if (onelock(pid, tempfile, file)) { 100 (void) unlink(tempfile); 101 return (FAIL); 102 } 103 } 104 } 105 stlock(file); 106 return (0); 107 } 108 109 /* 110 * check to see if the lock file exists and is still active 111 * - use kill(pid, 0) - (this only works on ATTSV and some hacked 112 * BSD systems at this time) 113 * return: 114 * 0 -> success (lock file removed - no longer active) 115 * FAIL -> lock file still active 116 */ 117 static int 118 checkLock(char *file) 119 { 120 int ret; 121 int lpid = -1; 122 char alpid[SIZEOFPID+2]; /* +2 for '\n' and NULL */ 123 int fd; 124 125 fd = open(file, 0); 126 if (fd == -1) { 127 if (errno == ENOENT) /* file does not exist -- OK */ 128 return (0); 129 goto unlk; 130 } 131 ret = read(fd, (char *)alpid, SIZEOFPID+1); /* +1 for '\n' */ 132 (void) close(fd); 133 if (ret != (SIZEOFPID+1)) 134 goto unlk; 135 lpid = atoi(alpid); 136 if ((ret = kill(lpid, 0)) == 0 || errno == EPERM) 137 return (FAIL); 138 139 unlk: 140 if (unlink(file) != 0) 141 return (FAIL); 142 return (0); 143 } 144 145 #define MAXLOCKS 10 /* maximum number of lock files */ 146 char *Lockfile[MAXLOCKS]; 147 int Nlocks = 0; 148 149 /* 150 * stlock(name) put name in list of lock files 151 * char *name; 152 * 153 * return codes: none 154 */ 155 156 static void 157 stlock(char *name) 158 { 159 char *p; 160 int i; 161 162 for (i = 0; i < Nlocks; i++) { 163 if (Lockfile[i] == NULL) 164 break; 165 } 166 ASSERT(i < MAXLOCKS, "TOO MANY LOCKS %d", i); 167 if (i >= Nlocks) 168 i = Nlocks++; 169 p = calloc(strlen(name) + 1, sizeof (char)); 170 ASSERT(p != NULL, "CAN NOT ALLOCATE FOR %s", name); 171 (void) strcpy(p, name); 172 Lockfile[i] = p; 173 } 174 175 /* 176 * rmlock(name) remove all lock files in list 177 * char *name; or name 178 * 179 * return codes: none 180 */ 181 182 static void 183 rmlock(char *name) 184 { 185 int i; 186 187 for (i = 0; i < Nlocks; i++) { 188 if (Lockfile[i] == NULL) 189 continue; 190 if (name == NULL || strcmp(name, Lockfile[i]) == SAME) { 191 (void) unlink(Lockfile[i]); 192 free(Lockfile[i]); 193 Lockfile[i] = NULL; 194 } 195 } 196 } 197 198 static int 199 onelock(char *pid, char *tempfile, char *name) 200 { 201 int fd; 202 static int first = 1; 203 204 fd = creat(tempfile, 0444); 205 if (fd < 0) { 206 if (first) { 207 if (errno == EACCES) { 208 (void) fprintf(stderr, 209 "tip: can't create files in lock file directory %s\n", 210 LOCKDIR); 211 } else if (access(LOCKDIR, 0) < 0) { 212 (void) fprintf(stderr, 213 "tip: lock file directory %s: ", 214 LOCKDIR); 215 perror(""); 216 } 217 first = 0; 218 } 219 if (errno == EMFILE || errno == ENFILE) 220 (void) unlink(tempfile); 221 return (-1); 222 } 223 /* +1 for '\n' */ 224 if (write(fd, pid, SIZEOFPID+1) != (SIZEOFPID+1)) { 225 (void) fprintf(stderr, 226 "tip: can't write to files in lock file directory %s: %s\n", 227 LOCKDIR, strerror(errno)); 228 (void) unlink(tempfile); 229 return (-1); 230 } 231 (void) fchmod(fd, 0444); 232 (void) close(fd); 233 if (link(tempfile, name) < 0) { 234 (void) unlink(tempfile); 235 return (-1); 236 } 237 (void) unlink(tempfile); 238 return (0); 239 } 240 241 /* 242 * delock(sys) remove a lock file 243 * char *sys; 244 */ 245 246 void 247 delock(char *sys) 248 { 249 struct stat sb; 250 char lname[NAMESIZE]; 251 252 if (stat(sys, &sb) < 0) 253 return; 254 (void) snprintf(lname, sizeof (lname), "%s/%s.%3.3lu.%3.3lu.%3.3lu", 255 LOCKDIR, LOCKPRE, 256 (unsigned long)major(sb.st_dev), 257 (unsigned long)major(sb.st_rdev), 258 (unsigned long)minor(sb.st_rdev)); 259 rmlock(lname); 260 } 261 262 /* 263 * tip_mlock(sys) create system lock 264 * char *sys; 265 * 266 * return codes: 0 | FAIL 267 */ 268 269 int 270 tip_mlock(char *sys) 271 { 272 struct stat sb; 273 char lname[NAMESIZE]; 274 275 if (stat(sys, &sb) < 0) 276 return (FAIL); 277 (void) snprintf(lname, sizeof (lname), "%s/%s.%3.3lu.%3.3lu.%3.3lu", 278 LOCKDIR, LOCKPRE, 279 (unsigned long)major(sb.st_dev), 280 (unsigned long)major(sb.st_rdev), 281 (unsigned long)minor(sb.st_rdev)); 282 return (ulockf(lname, (time_t)SLCKTIME) < 0 ? FAIL : 0); 283 } 284