Mercurial > emacs
comparison src/filelock.c @ 21217:18acb2723ec5
(current_lock_owner): If lock file data doesn't include
the uptime, assume the lock is from this system boot.
(get_boot_time): New function.
(lock_file_1): Include boot time in the lock text.
(current_lock_owner): Parse and compare the boot time.
author | Richard M. Stallman <rms@gnu.org> |
---|---|
date | Thu, 19 Mar 1998 06:32:34 +0000 |
parents | d1699afbc43e |
children | 7f00d0edbd29 |
comparison
equal
deleted
inserted
replaced
21216:54c89f745c5d | 21217:18acb2723ec5 |
---|---|
35 #endif /* USG */ | 35 #endif /* USG */ |
36 | 36 |
37 #include "lisp.h" | 37 #include "lisp.h" |
38 #include "buffer.h" | 38 #include "buffer.h" |
39 | 39 |
40 #include <time.h> | |
41 #include <utmp.h> | |
40 #include <errno.h> | 42 #include <errno.h> |
41 #ifndef errno | 43 #ifndef errno |
42 extern int errno; | 44 extern int errno; |
43 #endif | 45 #endif |
44 | 46 |
78 Ethan Jacobson, Kimbo Mundy, and others. | 80 Ethan Jacobson, Kimbo Mundy, and others. |
79 | 81 |
80 --karl@cs.umb.edu/karl@hq.ileaf.com. */ | 82 --karl@cs.umb.edu/karl@hq.ileaf.com. */ |
81 | 83 |
82 | 84 |
85 /* Return the time of the last system boot. */ | |
86 | |
87 static time_t boot_time; | |
88 | |
89 static time_t | |
90 get_boot_time () | |
91 { | |
92 struct utmp ut, *utp; | |
93 | |
94 if (boot_time) | |
95 return boot_time; | |
96 | |
97 utmpname ("/var/log/wtmp"); | |
98 ut.ut_type = BOOT_TIME; | |
99 utp = getutid (&ut); | |
100 endutent (); | |
101 | |
102 if (!utp) | |
103 return boot_time = 1; | |
104 return boot_time = utp->ut_time; | |
105 } | |
106 | |
83 /* Here is the structure that stores information about a lock. */ | 107 /* Here is the structure that stores information about a lock. */ |
84 | 108 |
85 typedef struct | 109 typedef struct |
86 { | 110 { |
87 char *user; | 111 char *user; |
88 char *host; | 112 char *host; |
89 unsigned long pid; | 113 unsigned long pid; |
114 time_t boot_time; | |
90 } lock_info_type; | 115 } lock_info_type; |
91 | 116 |
92 /* When we read the info back, we might need this much more, | 117 /* When we read the info back, we might need this much more, |
93 enough for decimal representation plus null. */ | 118 enough for decimal representation plus null. */ |
94 #define LOCK_PID_MAX (4 * sizeof (unsigned long)) | 119 #define LOCK_PID_MAX (4 * sizeof (unsigned long)) |
144 if (STRINGP (Fsystem_name ())) | 169 if (STRINGP (Fsystem_name ())) |
145 host_name = (char *)XSTRING (Fsystem_name ())->data; | 170 host_name = (char *)XSTRING (Fsystem_name ())->data; |
146 else | 171 else |
147 host_name = ""; | 172 host_name = ""; |
148 lock_info_str = (char *)alloca (strlen (user_name) + strlen (host_name) | 173 lock_info_str = (char *)alloca (strlen (user_name) + strlen (host_name) |
149 + LOCK_PID_MAX + 5); | 174 + LOCK_PID_MAX + 5); |
150 | 175 |
151 sprintf (lock_info_str, "%s@%s.%lu", user_name, host_name, | 176 sprintf (lock_info_str, "%s@%s.%lu:%lu", user_name, host_name, |
152 (unsigned long) getpid ()); | 177 (unsigned long) getpid (), (unsigned long) get_boot_time ()); |
153 | 178 |
154 err = symlink (lock_info_str, lfname); | 179 err = symlink (lock_info_str, lfname); |
155 if (errno == EEXIST && force) | 180 if (errno == EEXIST && force) |
156 { | 181 { |
157 unlink (lfname); | 182 unlink (lfname); |
176 #ifndef index | 201 #ifndef index |
177 extern char *rindex (), *index (); | 202 extern char *rindex (), *index (); |
178 #endif | 203 #endif |
179 int o, p, len, ret; | 204 int o, p, len, ret; |
180 int local_owner = 0; | 205 int local_owner = 0; |
181 char *at, *dot; | 206 char *at, *dot, *colon; |
182 char *lfinfo = 0; | 207 char *lfinfo = 0; |
183 int bufsize = 50; | 208 int bufsize = 50; |
184 /* Read arbitrarily-long contents of symlink. Similar code in | 209 /* Read arbitrarily-long contents of symlink. Similar code in |
185 file-symlink-p in fileio.c. */ | 210 file-symlink-p in fileio.c. */ |
186 do | 211 do |
207 { | 232 { |
208 owner = (lock_info_type *) alloca (sizeof (lock_info_type)); | 233 owner = (lock_info_type *) alloca (sizeof (lock_info_type)); |
209 local_owner = 1; | 234 local_owner = 1; |
210 } | 235 } |
211 | 236 |
212 /* Parse USER@HOST.PID. If can't parse, return -1. */ | 237 /* Parse USER@HOST.PID:BOOT_TIME. If can't parse, return -1. */ |
213 /* The USER is everything before the first @. */ | 238 /* The USER is everything before the first @. */ |
214 at = index (lfinfo, '@'); | 239 at = index (lfinfo, '@'); |
215 dot = rindex (lfinfo, '.'); | 240 dot = rindex (lfinfo, '.'); |
216 if (!at || !dot) { | 241 if (!at || !dot) |
217 xfree (lfinfo); | 242 { |
218 return -1; | 243 xfree (lfinfo); |
219 } | 244 return -1; |
245 } | |
220 len = at - lfinfo; | 246 len = at - lfinfo; |
221 owner->user = (char *) xmalloc (len + 1); | 247 owner->user = (char *) xmalloc (len + 1); |
222 strncpy (owner->user, lfinfo, len); | 248 strncpy (owner->user, lfinfo, len); |
223 owner->user[len] = 0; | 249 owner->user[len] = 0; |
224 | 250 |
225 /* The PID is everything after the last `.'. */ | 251 /* The PID is everything from the last `.' to the `:'. */ |
226 owner->pid = atoi (dot + 1); | 252 owner->pid = atoi (dot + 1); |
253 colon = dot; | |
254 while (*colon && *colon != ':') | |
255 colon++; | |
256 /* After the `:', if there is one, comes the boot time. */ | |
257 if (*colon == ':') | |
258 owner->boot_time = atoi (colon + 1); | |
259 else | |
260 owner->boot_time = 0; | |
227 | 261 |
228 /* The host is everything in between. */ | 262 /* The host is everything in between. */ |
229 len = dot - at - 1; | 263 len = dot - at - 1; |
230 owner->host = (char *) xmalloc (len + 1); | 264 owner->host = (char *) xmalloc (len + 1); |
231 strncpy (owner->host, at + 1, len); | 265 strncpy (owner->host, at + 1, len); |
239 && strcmp (owner->host, XSTRING (Fsystem_name ())->data) == 0) | 273 && strcmp (owner->host, XSTRING (Fsystem_name ())->data) == 0) |
240 { | 274 { |
241 if (owner->pid == getpid ()) | 275 if (owner->pid == getpid ()) |
242 ret = 2; /* We own it. */ | 276 ret = 2; /* We own it. */ |
243 else if (owner->pid > 0 | 277 else if (owner->pid > 0 |
244 && (kill (owner->pid, 0) >= 0 || errno == EPERM)) | 278 && (kill (owner->pid, 0) >= 0 || errno == EPERM) |
279 && (owner->boot_time == 0 | |
280 || owner->boot_time == get_boot_time ())) | |
245 ret = 1; /* An existing process on this machine owns it. */ | 281 ret = 1; /* An existing process on this machine owns it. */ |
246 /* The owner process is dead or has a strange pid (<=0), so try to | 282 /* The owner process is dead or has a strange pid (<=0), so try to |
247 zap the lockfile. */ | 283 zap the lockfile. */ |
248 else if (unlink (lfname) < 0) | 284 else if (unlink (lfname) < 0) |
249 ret = -1; | 285 ret = -1; |
463 if (owner > 0) | 499 if (owner > 0) |
464 FREE_LOCK_INFO (locker); | 500 FREE_LOCK_INFO (locker); |
465 | 501 |
466 return ret; | 502 return ret; |
467 } | 503 } |
468 | |
469 | 504 |
470 /* Initialization functions. */ | 505 /* Initialization functions. */ |
471 | 506 |
472 syms_of_filelock () | 507 syms_of_filelock () |
473 { | 508 { |