/* * findtty: find a tty we can call a system with. */ #include "locktty.h" #include #include #include #include #include #include #include #include /* LOCKTYPE describes how lockfiles work: * 0 = no locking * 1 = LCK.. * 2 = LK.. */ #define LOCKTYPE 1 /* if ASCII_PID is defined, the lockfile will contain * the pid of the locking process as a newline-terminated * ascii string, otherwise it that pid will be written * out as a binary field. */ #define ASCII_PID /* LOCKDIR is where these locks live. */ #define LOCKDIR "/var/spool/uucp" #ifndef LOCKTYPE # define LOCKTYPE 0 #endif #if LOCKTYPE # include /* utmp has pid_t definition */ # if LOCKTYPE == 3 # include # include # endif # ifdef ASCII_PID # define PID_SIZE 10 /* 10 bytes should be enough for a pid_t */ # else # define PID_SIZE sizeof(pid_t) # endif # ifndef LOCKDIR # define LOCKDIR "/usr/spool/uucp" # endif #endif /* we keep an array of locks (a'la stdio) and only allow a certain number * of them to be defined. */ static struct tty_lock locks[NR_TTY_LOCKS]; static int last_lock = 0; static int unlock_registered = 0; /* * speedok() is a local procedure for speedmatch */ static speedok(p, speed) char* p; int speed; { register char *dash; if (dash=strchr(p,'-')) { *dash++ = 0; if (speed >= atol(p) && speed <= atol(dash)) { return speed; } } else if (speed == atol(p)) return speed; return 0; } /* * speedmatch() checks a tty speed against a list of valid speeds */ static speedmatch(speed, validstring) char *speed; char *validstring; { register char *p, *q; int spd; if (strcasecmp(speed, "any") == 0) return 1; for (p = validstring; q=strchr(p, ','); p=q) { *q++ = 0; if (speedok(p, atoi(speed))) return 1; } return speedok(p, atoi(speed)); } /* speedmatch */ /* * lockdata() populates a lockfile with the pid of the current process */ static int lockdata(char *lock, int pid) { #if LOCKTYPE int lockfile; # ifdef ASCII_PID char pid_string[PID_SIZE+1]; # endif if ((lockfile = creat(lock, 0666)) < 0) return -1; # ifdef ASCII_PID sprintf(pid_string, "%*d\n", PID_SIZE, pid); if (write(lockfile, pid_string, PID_SIZE+1) != PID_SIZE+1) return -1; # else if (write(lockfile, (char *) &pid, PID_SIZE) != PID_SIZE) return -1; # endif close(lockfile); #endif/* LOCKTYPE */ return 0; } /* lockdata */ /* * buildlock() builds the lock without fuss or bother */ static int buildlock(char *port, char *lock) { #if LOCKTYPE char *s, buf[12]; strcpy(buf, (s = strrchr(port, '/')) ? (1+s) : port); # if LOCKTYPE == 2 /* Attempt to build a LK lock */ struct stat stat_buf; if (stat(port, &stat_buf) == 0) { sprintf(lock, "%s/LK.%03d.%03d.%03d", LOCKDIR, major(stat_buf.st_dev), major(stat_buf.st_rdev), minor(stat_buf.st_rdev)); } else # endif /* LOCK_TYPE == 2*/ sprintf(lock, "%s/LCK..%s", LOCKDIR, buf); if (clearlock(lock, (int*)0) != 0) return -1; return lockdata(lock, getpid()); #endif /* LOCK_TYPE */ return 0; } /* buildlock */ /* * clearlock() quietly checks to see if the lock is there and tries to * remove stale ones */ int clearlock(char *lock) { #if LOCKTYPE int rc; FILE *fd; pid_t pid; if ((fd = fopen(lock, "r")) == (FILE*)0) { if (errno == ENOENT) return 0; /* lock file doesn't exist */ goto unlock; } # ifdef ASCII_PID rc = fscanf(fd, "%d", &pid); # else rc = fread(&pid, PID_SIZE, 1, fd); # endif close(fd); if (rc != 1) return (unlink(lock) != 0) ? 2 : 1; /* now, send a bogus 'kill' and check the results */ if (kill(pid, 0) == 0 || errno == EPERM) return 3; unlock: return (unlink(lock) != 0) ? 2 : 0; #endif return 0; } /* clearlock */ /* * unlock_at_exit() is a local that unlocks all the locked ttys (called * from atexit()) */ static int unlock_at_exit() { int i; for (i=0; i= NR_TTY_LOCKS) return (TTY_LOCK *)0; if (cfg=fopen("/usr/lib/uucp/Devices", "r")) { while (rdline(cfg, arg, sizeof arg)) { cnt = sscanf(arg, "%s %s %*s %s", teltyp, tty, telspeed, telopt); if (cnt < 3) continue; /* not appropriate call-unit or device */ if (strcasecmp(teltyp, call_unit) && strcasecmp(tty, call_unit)) continue; /* wrong speed */ if (speedmatch(callspeed, telspeed) == 0) continue; if (buildlock(tty, arg) == 0) { fclose(cfg); if ((locks[lockidx].tty = strdup(tty)) == (char*)0) break; if ((locks[lockidx].lock= strdup(arg)) == (char*)0) { free(locks[lockidx].tty); break; } if (lockidx >= last_lock) last_lock++; if (!unlock_registered) { atexit(unlock_at_exit); unlock_registered++; } return &locks[lockidx]; } } } return (TTY_LOCK*)0; } /* findtty */