| 62 | */ |
| 63 | |
| 64 | int |
| 65 | uu_lock(const char *tty_name) |
| 66 | { |
| 67 | int fd, tmpfd, i; |
| 68 | pid_t pid, pid_old; |
| 69 | char lckname[sizeof(_PATH_UUCPLOCK) + MAXNAMLEN], |
| 70 | lcktmpname[sizeof(_PATH_UUCPLOCK) + MAXNAMLEN]; |
| 71 | int err, uuerr; |
| 72 | |
| 73 | pid = getpid(); |
| 74 | (void)snprintf(lcktmpname, sizeof(lcktmpname), _PATH_UUCPLOCK LOCKTMP, |
| 75 | pid); |
| 76 | (void)snprintf(lckname, sizeof(lckname), _PATH_UUCPLOCK LOCKFMT, |
| 77 | tty_name); |
| 78 | if ((tmpfd = open(lcktmpname, O_CREAT | O_TRUNC | O_WRONLY | O_CLOEXEC, |
| 79 | 0664)) < 0) |
| 80 | GORET(0, UU_LOCK_CREAT_ERR); |
| 81 | |
| 82 | for (i = 0; i < MAXTRIES; i++) { |
| 83 | if (link (lcktmpname, lckname) < 0) { |
| 84 | if (errno != EEXIST) |
| 85 | GORET(1, UU_LOCK_LINK_ERR); |
| 86 | /* |
| 87 | * file is already locked |
| 88 | * check to see if the process holding the lock |
| 89 | * still exists |
| 90 | */ |
| 91 | if ((fd = open(lckname, O_RDONLY | O_CLOEXEC)) < 0) |
| 92 | GORET(1, UU_LOCK_OPEN_ERR); |
| 93 | |
| 94 | if ((pid_old = get_pid (fd, &err)) == -1) |
| 95 | GORET(2, UU_LOCK_READ_ERR); |
| 96 | |
| 97 | close(fd); |
| 98 | |
| 99 | if (kill(pid_old, 0) == 0 || errno != ESRCH) |
| 100 | GORET(1, UU_LOCK_INUSE); |
| 101 | /* |
| 102 | * The process that locked the file isn't running, so |
| 103 | * we'll lock it ourselves |
| 104 | */ |
| 105 | (void)unlink(lckname); |
| 106 | } else { |
| 107 | if (!put_pid (tmpfd, pid)) |
| 108 | GORET(3, UU_LOCK_WRITE_ERR); |
| 109 | break; |
| 110 | } |
| 111 | } |
| 112 | GORET(1, (i >= MAXTRIES) ? UU_LOCK_TRY_ERR : UU_LOCK_OK); |
| 113 | |
| 114 | ret3: |
| 115 | (void)unlink(lckname); |
| 116 | goto ret1; |
| 117 | ret2: |
| 118 | (void)close(fd); |
| 119 | ret1: |
| 120 | (void)close(tmpfd); |
| 121 | (void)unlink(lcktmpname); |