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