1 #ifndef lint 2 static char sccsid[] = "@(#)ulockf.c 5.7 (Berkeley) 4/24/88"; 3 #endif 4 5 #include "uucp.h" 6 #include <sys/stat.h> 7 #include <errno.h> 8 9 #define LCKMODE 0444 /* File mode for lock files */ 10 #define MAXLOCKS 16 /* Maximum number of lock files */ 11 12 char *Lockfile[MAXLOCKS]; 13 char *LockDirectory = LOCKDIR; 14 int Nlocks = 0; 15 extern int errno; 16 17 /*LINTLIBRARY*/ 18 19 /* 20 * This routine will attempt to create a lock file (file). 21 * It makes sure that the lock file is valid if it already exists. 22 * 23 * return codes: SUCCESS | FAIL 24 */ 25 ulockf(hfile, atime) 26 char *hfile; 27 time_t atime; 28 { 29 register char *p; 30 register int i; 31 static char tempfile[NAMESIZE]; 32 char file[NAMESIZE]; 33 static int pid = -1; 34 35 if (pid < 0) { 36 pid = getpid(); 37 sprintf(tempfile, "%s/LTMP.%d", LockDirectory, pid); 38 } 39 sprintf(file, "%s/LCK..%s", LockDirectory, hfile); 40 i = 0; 41 while (onelock(pid, tempfile, file) == -1) { /* lock file exists */ 42 #if !defined(BSD4_2) && !defined(USG) 43 struct stat stbuf; 44 time_t ptime; 45 /* get status to check age of the lock file */ 46 if (stat(file, &stbuf) == 0) { 47 (void) time(&ptime); 48 if ((ptime - stbuf.st_ctime) < atime) 49 return FAIL; /* file not old enough to delete */ 50 } 51 #else BSD4_2 || USG 52 register int fd; 53 fd = open(file, 0); 54 if (fd >= 0) { 55 int upid, ret; 56 ret = read(fd, &upid, sizeof upid); 57 close(fd); 58 if (ret == sizeof upid && (kill(upid, 0) == 0 59 || errno != ESRCH)) 60 return FAIL; /* process is still running */ 61 } 62 #endif BSD4_2 || USG 63 syslog(LOG_WARNING, "%s: dead lock %s", Rmtname, file); 64 logent(file, "DEAD LOCK"); 65 (void) unlink(file); 66 sleep(5); /* avoid a possible race */ 67 if (i++ >= 5) { 68 syslog(LOG_ERR, "%s: can't get lockfile %s: %m", 69 Rmtname, tempfile); 70 cleanup(FAIL); 71 } 72 } 73 74 for (i = 0; i < Nlocks; i++) { 75 if (Lockfile[i] == NULL) 76 break; 77 } 78 if (i >= MAXLOCKS) { 79 syslog(LOG_ERR, "Too many locks"); 80 cleanup(FAIL); 81 } 82 if (i >= Nlocks) 83 i = Nlocks++; 84 p = malloc((unsigned)(strlen(file)+1)); 85 if (p == NULL) { 86 syslog(LOG_ERR, "malloc failed: %m"); 87 cleanup(FAIL); 88 } 89 strcpy(p, file); 90 Lockfile[i] = p; 91 92 return SUCCESS; 93 } 94 95 /* 96 * remove all lock files in list or name 97 */ 98 rmlock(name) 99 register char *name; 100 { 101 register int i; 102 char file[MAXFULLNAME]; 103 104 if (name != NULL) { 105 sprintf(file, "%s/LCK..%s", LockDirectory, name); 106 name = file; 107 } 108 for (i = 0; i < Nlocks; i++) { 109 if (Lockfile[i] == NULL) 110 continue; 111 if (name == NULL || strcmp(name, Lockfile[i]) == SAME) { 112 unlink(Lockfile[i]); 113 free(Lockfile[i]); 114 Lockfile[i] = NULL; 115 } 116 } 117 } 118 119 /* 120 * makes lock a name on behalf of pid. Tempfile must be in the same 121 * file system as name. 122 */ 123 onelock(pid, tempfile, name) 124 int pid; 125 char *tempfile, *name; 126 { 127 register int fd, ret; 128 #ifdef VMS 129 fd = creat(name, LCKMODE, "1version"); 130 #else !VMS 131 fd = creat(tempfile, LCKMODE); 132 #endif !VMS 133 if (fd < 0) { 134 DEBUG(1,"Can't creat temp file %s ", tempfile); 135 DEBUG(1,"-- errno %d", errno); 136 return FAIL; 137 } 138 ret = write(fd, (char *)&pid, sizeof(int)); 139 (void) close(fd); 140 141 if (ret != sizeof(int)) { 142 DEBUG(1,"Temp file write failed -- errno %d\n", errno); 143 #ifdef VMS 144 (void) unlink(name); 145 #else !VMS 146 (void) unlink(tempfile); 147 #endif !VMS 148 return FAIL; 149 } 150 #ifndef VMS 151 if (link(tempfile, name) < 0) { 152 (void) unlink(tempfile); 153 return FAIL; 154 } 155 unlink(tempfile); 156 #endif !VMS 157 return SUCCESS; 158 } 159 160 #if !defined(BSD4_2) && !defined(USG) 161 /* 162 * update 'change' time for lock files 163 * 164 * Only update ctime, not mtime or atime. 165 * The 'chmod' method permits cu(I)-like programs 166 * to determine how long uucp has been on the line. 167 * The old "change access, mod, and change time" method 168 * can be had by defining OLDTOUCH 169 * 170 * return code - none 171 */ 172 173 ultouch() 174 { 175 static time_t lasttouch = 0; 176 register int i; 177 struct ut { 178 time_t actime; 179 time_t modtime; 180 } ut; 181 182 #ifdef USG 183 time(&Now.time); 184 t1.millitm = 0; 185 #else !USG 186 ftime(&Now); 187 #endif !USG 188 ut.actime = ut.modtime = Now.time; 189 /* Do not waste time touching locking files too often */ 190 /* (But, defend against backward time changes) */ 191 if (ut.actime >= lasttouch && ut.actime < lasttouch+60) 192 return; 193 lasttouch = ut.actime; 194 DEBUG(4, "ultouch\n", 0); 195 196 for (i = 0; i < Nlocks; i++) { 197 if (Lockfile[i] == NULL) 198 continue; 199 #ifdef OLDTOUCH 200 utime(Lockfile[i], &ut); 201 #else !OLDTOUCH 202 chmod(Lockfile[i], LCKMODE); 203 #endif !OLDTOUCH 204 } 205 } 206 #endif !BSD4_2 && ! USG 207