diff options
| author | Richard M. Stallman | 1999-02-19 01:36:29 +0000 |
|---|---|---|
| committer | Richard M. Stallman | 1999-02-19 01:36:29 +0000 |
| commit | 9177d97852ed4594d49224c12e9a6bbbce7c0946 (patch) | |
| tree | 48686bf7b5c0b1c8b2bbce1de20a2ffa3b96d218 /src | |
| parent | 5bda49c640132d7eb25c4aa047b895622f3a4ff0 (diff) | |
| download | emacs-9177d97852ed4594d49224c12e9a6bbbce7c0946.tar.gz emacs-9177d97852ed4594d49224c12e9a6bbbce7c0946.zip | |
(within_one_second): New function.
(current_lock_owner): Use that.
(get_boot_time): Use /proc/uptime if available.
Otherwise, if nothing found in wtmp, try wtmp.1.gz and so on.
(get_boot_time_1): New subroutine taken from get_boot_time.
Diffstat (limited to 'src')
| -rw-r--r-- | src/filelock.c | 114 |
1 files changed, 106 insertions, 8 deletions
diff --git a/src/filelock.c b/src/filelock.c index 6876cbdb5c1..39cfe68c8fd 100644 --- a/src/filelock.c +++ b/src/filelock.c | |||
| @@ -43,6 +43,7 @@ Boston, MA 02111-1307, USA. */ | |||
| 43 | #include "buffer.h" | 43 | #include "buffer.h" |
| 44 | #include "charset.h" | 44 | #include "charset.h" |
| 45 | #include "coding.h" | 45 | #include "coding.h" |
| 46 | #include "systime.h" | ||
| 46 | 47 | ||
| 47 | #include <time.h> | 48 | #include <time.h> |
| 48 | #include <errno.h> | 49 | #include <errno.h> |
| @@ -94,18 +95,113 @@ extern int errno; | |||
| 94 | 95 | ||
| 95 | static time_t boot_time; | 96 | static time_t boot_time; |
| 96 | 97 | ||
| 98 | extern Lisp_Object Vshell_file_name; | ||
| 99 | |||
| 97 | static time_t | 100 | static time_t |
| 98 | get_boot_time () | 101 | get_boot_time () |
| 99 | { | 102 | { |
| 100 | #ifdef BOOT_TIME | 103 | #ifdef BOOT_TIME |
| 101 | struct utmp ut, *utp; | 104 | struct utmp ut, *utp; |
| 105 | int fd; | ||
| 106 | EMACS_TIME time_before, after; | ||
| 107 | int counter; | ||
| 102 | 108 | ||
| 103 | if (boot_time) | 109 | if (boot_time) |
| 104 | return boot_time; | 110 | return boot_time; |
| 105 | 111 | ||
| 106 | utmpname ("/var/log/wtmp"); | 112 | EMACS_GET_TIME (time_before); |
| 113 | |||
| 114 | /* Try calculating the last boot time | ||
| 115 | from the uptime as obtained from /proc/uptime. */ | ||
| 116 | |||
| 117 | while ((fd = open ("/proc/uptime", O_RDONLY)) >= 0) | ||
| 118 | { | ||
| 119 | char buf[BUFSIZ]; | ||
| 120 | int res; | ||
| 121 | double upsecs; | ||
| 122 | time_t uptime; | ||
| 123 | |||
| 124 | read (fd, buf, BUFSIZ); | ||
| 125 | close (fd); | ||
| 126 | |||
| 127 | res = sscanf (buf, "%lf", &upsecs); | ||
| 128 | |||
| 129 | /* If the current time did not tick while we were getting the | ||
| 130 | uptime, we have a valid result. */ | ||
| 131 | EMACS_GET_TIME (after); | ||
| 132 | if (res == 1 && EMACS_SECS (after) == EMACS_SECS (time_before)) | ||
| 133 | { | ||
| 134 | boot_time = EMACS_SECS (time_before) - (time_t) upsecs; | ||
| 135 | return boot_time; | ||
| 136 | } | ||
| 137 | |||
| 138 | /* Otherwise, try again to read the uptime. */ | ||
| 139 | time_before = after; | ||
| 140 | } | ||
| 141 | |||
| 142 | /* Try to get boot time from the current wtmp file. */ | ||
| 143 | get_boot_time_1 ("/var/log/wtmp"); | ||
| 144 | |||
| 145 | /* If we did not find a boot time in wtmp, look at wtmp, and so on. */ | ||
| 146 | for (counter = 0; counter < 20 && boot_time == 1; counter++) | ||
| 147 | { | ||
| 148 | char cmd_string[100]; | ||
| 149 | Lisp_Object tempname, filename; | ||
| 150 | int delete_flag = 0; | ||
| 151 | |||
| 152 | filename = Qnil; | ||
| 153 | |||
| 154 | sprintf (cmd_string, "/var/log/wtmp.%d", counter); | ||
| 155 | tempname = build_string (cmd_string); | ||
| 156 | if (! NILP (Ffile_exists_p (filename))) | ||
| 157 | filename = tempname; | ||
| 158 | else | ||
| 159 | { | ||
| 160 | sprintf (cmd_string, "/var/log/wtmp.%d.gz", counter); | ||
| 161 | tempname = build_string (cmd_string); | ||
| 162 | if (! NILP (Ffile_exists_p (tempname))) | ||
| 163 | { | ||
| 164 | Lisp_Object args[6]; | ||
| 165 | tempname = Fmake_temp_name (build_string ("wtmp")); | ||
| 166 | args[0] = Vshell_file_name; | ||
| 167 | args[1] = Qnil; | ||
| 168 | args[2] = Qnil; | ||
| 169 | args[3] = Qnil; | ||
| 170 | args[4] = build_string ("-c"); | ||
| 171 | sprintf (cmd_string, "gunzip < /var/log/wtmp.%d.gz > %s", | ||
| 172 | counter, XSTRING (tempname)->data); | ||
| 173 | args[5] = build_string (cmd_string); | ||
| 174 | Fcall_process (6, args); | ||
| 175 | filename = tempname; | ||
| 176 | delete_flag = 1; | ||
| 177 | } | ||
| 178 | } | ||
| 179 | |||
| 180 | if (! NILP (filename)) | ||
| 181 | { | ||
| 182 | get_boot_time_1 (XSTRING (filename)->data); | ||
| 183 | if (delete_flag) | ||
| 184 | unlink (XSTRING (filename)->data); | ||
| 185 | } | ||
| 186 | } | ||
| 187 | |||
| 188 | return boot_time; | ||
| 189 | #else | ||
| 190 | return 0; | ||
| 191 | #endif | ||
| 192 | } | ||
| 193 | |||
| 194 | /* Try to get the boot time from wtmp file FILENAME. | ||
| 195 | This succeeds if that file contains a reboot record. | ||
| 196 | Success is indicated by setting BOOT_TIME. */ | ||
| 197 | |||
| 198 | get_boot_time_1 (filename) | ||
| 199 | char *filename; | ||
| 200 | { | ||
| 201 | struct utmp ut, *utp; | ||
| 202 | |||
| 203 | utmpname (filename); | ||
| 107 | setutent (); | 204 | setutent (); |
| 108 | boot_time = 1; | ||
| 109 | while (1) | 205 | while (1) |
| 110 | { | 206 | { |
| 111 | /* Find the next reboot record. */ | 207 | /* Find the next reboot record. */ |
| @@ -123,11 +219,6 @@ get_boot_time () | |||
| 123 | break; | 219 | break; |
| 124 | } | 220 | } |
| 125 | endutent (); | 221 | endutent (); |
| 126 | |||
| 127 | return boot_time; | ||
| 128 | #else | ||
| 129 | return 0; | ||
| 130 | #endif | ||
| 131 | } | 222 | } |
| 132 | 223 | ||
| 133 | /* Here is the structure that stores information about a lock. */ | 224 | /* Here is the structure that stores information about a lock. */ |
| @@ -218,7 +309,14 @@ lock_file_1 (lfname, force) | |||
| 218 | return err == 0; | 309 | return err == 0; |
| 219 | } | 310 | } |
| 220 | 311 | ||
| 312 | /* Return 1 if times A and B are no more than one second apart. */ | ||
| 221 | 313 | ||
| 314 | int | ||
| 315 | within_one_second (a, b) | ||
| 316 | time_t a, b; | ||
| 317 | { | ||
| 318 | return (a - b >= -1 && a - b <= 1); | ||
| 319 | } | ||
| 222 | 320 | ||
| 223 | /* Return 0 if nobody owns the lock file LFNAME or the lock is obsolete, | 321 | /* Return 0 if nobody owns the lock file LFNAME or the lock is obsolete, |
| 224 | 1 if another process owns it (and set OWNER (if non-null) to info), | 322 | 1 if another process owns it (and set OWNER (if non-null) to info), |
| @@ -309,7 +407,7 @@ current_lock_owner (owner, lfname) | |||
| 309 | else if (owner->pid > 0 | 407 | else if (owner->pid > 0 |
| 310 | && (kill (owner->pid, 0) >= 0 || errno == EPERM) | 408 | && (kill (owner->pid, 0) >= 0 || errno == EPERM) |
| 311 | && (owner->boot_time == 0 | 409 | && (owner->boot_time == 0 |
| 312 | || owner->boot_time == get_boot_time ())) | 410 | || within_one_second (owner->boot_time, get_boot_time ()))) |
| 313 | ret = 1; /* An existing process on this machine owns it. */ | 411 | ret = 1; /* An existing process on this machine owns it. */ |
| 314 | /* The owner process is dead or has a strange pid (<=0), so try to | 412 | /* The owner process is dead or has a strange pid (<=0), so try to |
| 315 | zap the lockfile. */ | 413 | zap the lockfile. */ |