1*13673Ssam #ifndef lint 2*13673Ssam static char sccsid[] = "@(#)ulockf.c 5.1 (Berkeley) 07/02/83"; 3*13673Ssam #endif 4*13673Ssam 5*13673Ssam #include "uucp.h" 6*13673Ssam #include <sys/types.h> 7*13673Ssam #include <sys/stat.h> 8*13673Ssam 9*13673Ssam 10*13673Ssam extern time_t time(); 11*13673Ssam 12*13673Ssam /* File mode for lock files */ 13*13673Ssam #define LCKMODE 0444 14*13673Ssam 15*13673Ssam /******* 16*13673Ssam * ulockf(file, atime) 17*13673Ssam * char *file; 18*13673Ssam * time_t atime; 19*13673Ssam * 20*13673Ssam * ulockf - this routine will create a lock file (file). 21*13673Ssam * If one already exists, the create time is checked for 22*13673Ssam * older than the age time (atime). 23*13673Ssam * If it is older, an attempt will be made to unlink it 24*13673Ssam * and create a new one. 25*13673Ssam * 26*13673Ssam * return codes: 0 | FAIL 27*13673Ssam */ 28*13673Ssam 29*13673Ssam ulockf(file, atime) 30*13673Ssam register char *file; 31*13673Ssam time_t atime; 32*13673Ssam { 33*13673Ssam struct stat stbuf; 34*13673Ssam time_t ptime; 35*13673Ssam register int ret; 36*13673Ssam static int pid = -1; 37*13673Ssam static char tempfile[NAMESIZE]; 38*13673Ssam 39*13673Ssam if (pid < 0) { 40*13673Ssam pid = getpid(); 41*13673Ssam sprintf(tempfile, "LTMP.%d", pid); 42*13673Ssam } 43*13673Ssam if (onelock(pid, tempfile, file) == -1) { 44*13673Ssam /* lock file exists */ 45*13673Ssam /* get status to check age of the lock file */ 46*13673Ssam ret = stat(file, &stbuf); 47*13673Ssam if (ret != -1) { 48*13673Ssam time(&ptime); 49*13673Ssam if ((ptime - stbuf.st_ctime) < atime) { 50*13673Ssam /* file not old enough to delete */ 51*13673Ssam return(FAIL); 52*13673Ssam } 53*13673Ssam } 54*13673Ssam ret = unlink(file); 55*13673Ssam ret = onelock(pid, tempfile, file); 56*13673Ssam if (ret != 0) 57*13673Ssam return(FAIL); 58*13673Ssam } 59*13673Ssam stlock(file); 60*13673Ssam return(0); 61*13673Ssam } 62*13673Ssam 63*13673Ssam 64*13673Ssam #define MAXLOCKS 10 /* maximum number of lock files */ 65*13673Ssam char *Lockfile[MAXLOCKS]; 66*13673Ssam int Nlocks = 0; 67*13673Ssam 68*13673Ssam /*** 69*13673Ssam * stlock(name) put name in list of lock files 70*13673Ssam * char *name; 71*13673Ssam * 72*13673Ssam * return codes: none 73*13673Ssam */ 74*13673Ssam 75*13673Ssam stlock(name) 76*13673Ssam register char *name; 77*13673Ssam { 78*13673Ssam register char *p; 79*13673Ssam register int i; 80*13673Ssam 81*13673Ssam for (i = 0; i < Nlocks; i++) { 82*13673Ssam if (Lockfile[i] == NULL) 83*13673Ssam break; 84*13673Ssam } 85*13673Ssam ASSERT(i < MAXLOCKS, "TOO MANY LOCKS", "", i); 86*13673Ssam if (i >= Nlocks) 87*13673Ssam i = Nlocks++; 88*13673Ssam p = calloc((unsigned)(strlen(name)+1), sizeof (char)); 89*13673Ssam ASSERT(p != NULL, "CAN NOT ALLOCATE FOR", name, 0); 90*13673Ssam strcpy(p, name); 91*13673Ssam Lockfile[i] = p; 92*13673Ssam return; 93*13673Ssam } 94*13673Ssam 95*13673Ssam 96*13673Ssam /*** 97*13673Ssam * rmlock(name) remove all lock files in list 98*13673Ssam * char *name; or name 99*13673Ssam * 100*13673Ssam * return codes: none 101*13673Ssam */ 102*13673Ssam 103*13673Ssam rmlock(name) 104*13673Ssam register char *name; 105*13673Ssam { 106*13673Ssam register int i; 107*13673Ssam 108*13673Ssam for (i = 0; i < Nlocks; i++) { 109*13673Ssam if (Lockfile[i] == NULL) 110*13673Ssam continue; 111*13673Ssam if (name == NULL 112*13673Ssam || strcmp(name, Lockfile[i]) == SAME) { 113*13673Ssam unlink(Lockfile[i]); 114*13673Ssam free(Lockfile[i]); 115*13673Ssam Lockfile[i] = NULL; 116*13673Ssam } 117*13673Ssam } 118*13673Ssam return; 119*13673Ssam } 120*13673Ssam 121*13673Ssam 122*13673Ssam /* 123*13673Ssam * this stuff from pjw 124*13673Ssam * /usr/pjw/bin/recover - Check pids to remove unnecessary locks. 125*13673Ssam * isalock(name) returns 0 if the name is a lock. 126*13673Ssam * unlock(name) unlocks name if it is a lock. 127*13673Ssam * onelock(pid,tempfile,name) makes lock a name 128*13673Ssam * on behalf of pid. Tempfile must be in the same 129*13673Ssam * file system as name. 130*13673Ssam * lock(pid,tempfile,names) either locks all the 131*13673Ssam * names or none of them. 132*13673Ssam */ 133*13673Ssam isalock(name) char *name; 134*13673Ssam { 135*13673Ssam struct stat xstat; 136*13673Ssam if(stat(name,&xstat)<0) return(0); 137*13673Ssam if(xstat.st_size!=sizeof(int)) return(0); 138*13673Ssam return(1); 139*13673Ssam } 140*13673Ssam unlock(name) char *name; 141*13673Ssam { 142*13673Ssam if(isalock(name)) return(unlink(name)); 143*13673Ssam else return(-1); 144*13673Ssam } 145*13673Ssam onelock(pid,tempfile,name) char *tempfile,*name; 146*13673Ssam { register int fd; 147*13673Ssam fd=creat(tempfile,LCKMODE); 148*13673Ssam if(fd<0) return(-1); 149*13673Ssam write(fd,(char *) &pid,sizeof(int)); 150*13673Ssam close(fd); 151*13673Ssam if(link(tempfile,name)<0) 152*13673Ssam { unlink(tempfile); 153*13673Ssam return(-1); 154*13673Ssam } 155*13673Ssam unlink(tempfile); 156*13673Ssam return(0); 157*13673Ssam } 158*13673Ssam lock(pid,tempfile,names) char *tempfile; 159*13673Ssam register char **names; 160*13673Ssam { register int i,j; 161*13673Ssam for(i=0;names[i]!=0;i++) 162*13673Ssam { if(onelock(pid,tempfile,names[i])==0) continue; 163*13673Ssam for(j=0;j<i;j++) unlink(names[j]); 164*13673Ssam return(-1); 165*13673Ssam } 166*13673Ssam return(0); 167*13673Ssam } 168*13673Ssam 169*13673Ssam #define LOCKPRE "LCK." 170*13673Ssam 171*13673Ssam /*** 172*13673Ssam * delock(s) remove a lock file 173*13673Ssam * char *s; 174*13673Ssam * 175*13673Ssam * return codes: 0 | FAIL 176*13673Ssam */ 177*13673Ssam 178*13673Ssam delock(s) 179*13673Ssam char *s; 180*13673Ssam { 181*13673Ssam char ln[30]; 182*13673Ssam 183*13673Ssam sprintf(ln, "%s.%s", LOCKPRE, s); 184*13673Ssam rmlock(ln); 185*13673Ssam } 186*13673Ssam 187*13673Ssam 188*13673Ssam /*** 189*13673Ssam * mlock(sys) create system lock 190*13673Ssam * char *sys; 191*13673Ssam * 192*13673Ssam * return codes: 0 | FAIL 193*13673Ssam */ 194*13673Ssam 195*13673Ssam mlock(sys) 196*13673Ssam char *sys; 197*13673Ssam { 198*13673Ssam char lname[30]; 199*13673Ssam sprintf(lname, "%s.%s", LOCKPRE, sys); 200*13673Ssam return(ulockf(lname, (time_t) SLCKTIME ) < 0 ? FAIL : 0); 201*13673Ssam } 202*13673Ssam 203*13673Ssam 204*13673Ssam /*** 205*13673Ssam * ultouch() update 'change' time for lock files 206*13673Ssam * 207*13673Ssam * -- mod by rti!trt -- 208*13673Ssam * Only update ctime, not mtime or atime. 209*13673Ssam * The 'chmod' method permits cu(I)-like programs 210*13673Ssam * to determine how long uucp has been on the line. 211*13673Ssam * The old "change access, mod, and change time" method 212*13673Ssam * can be had by defining OLDTOUCH 213*13673Ssam * 214*13673Ssam * return code - none 215*13673Ssam */ 216*13673Ssam 217*13673Ssam ultouch() 218*13673Ssam { 219*13673Ssam time_t time(); 220*13673Ssam static time_t lasttouch = 0; 221*13673Ssam register int i; 222*13673Ssam struct ut { 223*13673Ssam time_t actime; 224*13673Ssam time_t modtime; 225*13673Ssam } ut; 226*13673Ssam 227*13673Ssam ut.actime = time(&ut.modtime); 228*13673Ssam /* Do not waste time touching locking files too often */ 229*13673Ssam /* (But, defend against backward time changes) */ 230*13673Ssam if (ut.actime >= lasttouch && ut.actime < lasttouch+60) 231*13673Ssam return; 232*13673Ssam lasttouch = ut.actime; 233*13673Ssam DEBUG(4, "ultouch\n", 0); 234*13673Ssam 235*13673Ssam for (i = 0; i < Nlocks; i++) { 236*13673Ssam if (Lockfile[i] == NULL) 237*13673Ssam continue; 238*13673Ssam #ifdef OLDTOUCH 239*13673Ssam utime(Lockfile[i], &ut); 240*13673Ssam #else 241*13673Ssam chmod(Lockfile[i], LCKMODE); 242*13673Ssam #endif 243*13673Ssam } 244*13673Ssam } 245