/* $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 #include #include #include #include #include #include #include #include #include #include #include "lock.h" #include "util.h" // Where do lockfiles reside? #ifndef LOCK_DIR #define LOCK_DIR "/var/lock" #endif 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_DIR, W_OK) < 0) return -1; snprintf(path, sizeof(path), "%s/LCK..%s", LOCK_DIR, 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; } }