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