diff options
Diffstat (limited to 'src/lock.c')
-rw-r--r-- | src/lock.c | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/src/lock.c b/src/lock.c new file mode 100644 index 0000000..465736c --- /dev/null +++ b/src/lock.c @@ -0,0 +1,130 @@ +/* $Id$ */ + +/* + * This file is part of ivcall. + * + * ivcall is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * ivcall is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ivcall; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include <unistd.h> +#include <sys/stat.h> +#include <stdio.h> +#include <limits.h> +#include <fcntl.h> +#include <errno.h> +#include <signal.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> +#include <pwd.h> + +#include "lock.h" +#include "util.h" + +// Where do lockfiles reside? +#define LOCK_PATH "/var/lock" + +static char* lockfile = NULL; + +// Tries to lock a TTY-device, returns 0 on success +int device_lock(char *dev, char *appname) { + char buf[256], u[16]; + char path[PATH_MAX]; + int fd; + struct passwd *pwd; + char *username; + + assert(dev && !lockfile); + + if (access(LOCK_PATH, W_OK) < 0) + return -1; + + snprintf(path, sizeof(path), "%s/LCK..%s", LOCK_PATH, basename(dev)); + + if ((fd = open(path, O_RDONLY)) >= 0) { + int n = loop_read(fd, buf, sizeof(buf) - 1); + close(fd); + + if (n > 0) { + int pid; + + if (n == 4) + pid = *(int*) buf; + else { + buf[n] = 0; + sscanf(buf, "%d", &pid); + } + + if (pid > 0) { + if (kill((pid_t) pid, 0) < 0 && errno == ESRCH) { + fprintf(stderr, "Lockfile is stale. Overriding it.\n"); + unlink(path); + } else + return -1; + } + } + } + + if ((fd = open(path, O_WRONLY | O_CREAT | O_EXCL, 0666)) < 0) + return -1; + + if ((pwd = getpwuid(getuid()))) + username = pwd->pw_name; + else + snprintf(username = u, sizeof(u), "%u", getuid()); + + snprintf(buf, sizeof(buf), "%10ld %s %.20s\n", (long)getpid(), appname, username); + + if (loop_write(fd, buf, strlen(buf)) < 0) { + close(fd); + return -1; + } + + close(fd); + + lockfile = strdup(path); + + return 0; +} + +// Tries to lock the first free device, returns 0 on success +int device_lock_first(char *appname, char *dev, size_t l) { + int i, found = 0; + + for (i = 2; i <= 20; i++) { + snprintf(dev, l, "/dev/ttyI%i", i); + + if (!device_lock(dev, appname)) { + found = 1; + break; + } + } + + if (found) + return 0; + else { + fprintf(stderr, "Could not find free device.\n"); + return -1; + } +} + +// Deletes the lockfile +void device_unlock(void) { + if (lockfile) { + unlink(lockfile); + free (lockfile); + lockfile = NULL; + } +} |