Move the tty locking stuff back out to physical.c so

that we lock the device *before* we open it.
We still open the device only once - and then ask all
our handlers if they know how to handle it.
This commit is contained in:
Brian Somers 1999-05-18 01:37:46 +00:00
parent 4ee02f4bb8
commit 9950fb2a00
2 changed files with 154 additions and 150 deletions

View File

@ -16,7 +16,7 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
* *
* $Id: physical.c,v 1.11 1999/05/12 09:48:56 brian Exp $ * $Id: physical.c,v 1.12 1999/05/13 19:29:40 brian Exp $
* *
*/ */
@ -256,13 +256,47 @@ physical_Offline(struct physical *p)
log_Printf(LogPHASE, "%s: Disconnected!\n", p->link.name); log_Printf(LogPHASE, "%s: Disconnected!\n", p->link.name);
} }
static int
physical_Lock(struct physical *p)
{
int res;
if (*p->name.full == '/' && p->type != PHYS_DIRECT &&
(res = ID0uu_lock(p->name.base)) != UU_LOCK_OK) {
if (res == UU_LOCK_INUSE)
log_Printf(LogPHASE, "%s: %s is in use\n", p->link.name, p->name.full);
else
log_Printf(LogPHASE, "%s: %s is in use: uu_lock: %s\n",
p->link.name, p->name.full, uu_lockerr(res));
return 0;
}
return 1;
}
static void static void
physical_ReallyClose(struct physical *p) physical_Unlock(struct physical *p)
{
char fn[MAXPATHLEN];
if (*p->name.full == '/' && p->type != PHYS_DIRECT &&
ID0uu_unlock(p->name.base) == -1)
log_Printf(LogALERT, "%s: Can't uu_unlock %s\n", p->link.name, fn);
}
void
physical_Close(struct physical *p)
{ {
int newsid; int newsid;
char fn[MAXPATHLEN];
if (p->fd < 0)
return;
log_Printf(LogDEBUG, "%s: Close\n", p->link.name);
if (p->handler && p->handler->cooked)
(*p->handler->cooked)(p);
log_Printf(LogDEBUG, "%s: Really close %d\n", p->link.name, p->fd);
if (p->fd >= 0) {
physical_StopDeviceTimer(p); physical_StopDeviceTimer(p);
if (p->Utmp) { if (p->Utmp) {
ID0logout(p->name.base); ID0logout(p->name.base);
@ -272,34 +306,34 @@ physical_ReallyClose(struct physical *p)
close(p->fd); close(p->fd);
p->fd = -1; p->fd = -1;
log_SetTtyCommandMode(p->dl); log_SetTtyCommandMode(p->dl);
throughput_stop(&p->link.throughput); throughput_stop(&p->link.throughput);
throughput_log(&p->link.throughput, LogPHASE, p->link.name); throughput_log(&p->link.throughput, LogPHASE, p->link.name);
if (p->session_owner != (pid_t)-1) { if (p->session_owner != (pid_t)-1) {
ID0kill(p->session_owner, SIGHUP); ID0kill(p->session_owner, SIGHUP);
p->session_owner = (pid_t)-1; p->session_owner = (pid_t)-1;
} }
if (newsid) if (newsid)
bundle_setsid(p->dl->bundle, 0); bundle_setsid(p->dl->bundle, 0);
if (*p->name.full == '/') {
snprintf(fn, sizeof fn, "%s%s.if", _PATH_VARRUN, p->name.base);
#ifndef RELEASE_CRUNCH
if (ID0unlink(fn) == -1)
log_Printf(LogALERT, "%s: Can't remove %s: %s\n",
p->link.name, fn, strerror(errno));
#else
ID0unlink(fn);
#endif
}
physical_Unlock(p);
if (p->handler && p->handler->destroy) if (p->handler && p->handler->destroy)
(*p->handler->destroy)(p); (*p->handler->destroy)(p);
p->handler = NULL; p->handler = NULL;
}
*p->name.full = '\0';
p->name.base = p->name.full; p->name.base = p->name.full;
} *p->name.full = '\0';
void
physical_Close(struct physical *p)
{
if (p->fd < 0)
return;
log_Printf(LogDEBUG, "%s: Close\n", p->link.name);
if (p->handler && p->handler->cooked)
(*p->handler->cooked)(p);
physical_ReallyClose(p);
} }
void void
@ -780,6 +814,23 @@ physical_SetDevice(struct physical *p, const char *name)
static void static void
physical_Found(struct physical *p) physical_Found(struct physical *p)
{ {
FILE *lockfile;
char fn[MAXPATHLEN];
if (*p->name.full == '/') {
snprintf(fn, sizeof fn, "%s%s.if", _PATH_VARRUN, p->name.base);
lockfile = ID0fopen(fn, "w");
if (lockfile != NULL) {
fprintf(lockfile, "%s%d\n", TUN_NAME, p->dl->bundle->unit);
fclose(lockfile);
}
#ifndef RELEASE_CRUNCH
else
log_Printf(LogALERT, "%s: Can't create %s: %s\n",
p->link.name, fn, strerror(errno));
#endif
}
throughput_start(&p->link.throughput, "physical throughput", throughput_start(&p->link.throughput, "physical throughput",
Enabled(p->dl->bundle, OPT_THROUGHPUT)); Enabled(p->dl->bundle, OPT_THROUGHPUT));
p->connect_count++; p->connect_count++;
@ -791,7 +842,7 @@ physical_Found(struct physical *p)
int int
physical_Open(struct physical *p, struct bundle *bundle) physical_Open(struct physical *p, struct bundle *bundle)
{ {
int devno, h; int devno, h, wasopen;
char *dev; char *dev;
if (p->fd >= 0) if (p->fd >= 0)
@ -814,19 +865,25 @@ physical_Open(struct physical *p, struct bundle *bundle)
devno = 0; devno = 0;
while (devno < p->cfg.ndev && p->fd < 0) { while (devno < p->cfg.ndev && p->fd < 0) {
physical_SetDevice(p, dev); physical_SetDevice(p, dev);
if (physical_Lock(p)) {
if (*p->name.full == '/') if (*p->name.full == '/')
p->fd = ID0open(p->name.full, O_RDWR | O_NONBLOCK); p->fd = ID0open(p->name.full, O_RDWR | O_NONBLOCK);
wasopen = p->fd >= 0;
for (h = 0; h < NDEVICES && p->handler == NULL; h++) for (h = 0; h < NDEVICES && p->handler == NULL; h++)
p->handler = (*devices[h].create)(p); if ((p->handler = (*devices[h].create)(p)) == NULL &&
wasopen && p->fd == -1)
break;
if (p->fd < 0) if (p->fd < 0) {
if (h == NDEVICES)
log_Printf(LogWARN, "%s: Device (%s) must begin with a '/'," log_Printf(LogWARN, "%s: Device (%s) must begin with a '/',"
" a '!' or be a host:port pair\n", p->link.name, " a '!' or be a host:port pair\n", p->link.name,
p->name.full); p->name.full);
else physical_Unlock(p);
} else
physical_Found(p); physical_Found(p);
}
dev += strlen(dev) + 1; dev += strlen(dev) + 1;
devno++; devno++;
} }

View File

@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* $Id: tty.c,v 1.4 1999/05/13 19:29:40 brian Exp $ * $Id: tty.c,v 1.5 1999/05/16 11:58:48 brian Exp $
*/ */
#include <sys/param.h> #include <sys/param.h>
@ -98,62 +98,6 @@ struct ttydevice {
#define device2tty(d) ((d)->type == TTY_DEVICE ? (struct ttydevice *)d : NULL) #define device2tty(d) ((d)->type == TTY_DEVICE ? (struct ttydevice *)d : NULL)
static int
tty_Lock(struct physical *p, int tunno)
{
int res;
FILE *lockfile;
char fn[MAXPATHLEN];
if (*p->name.full != '/')
return 0;
if (p->type != PHYS_DIRECT &&
(res = ID0uu_lock(p->name.base)) != UU_LOCK_OK) {
if (res == UU_LOCK_INUSE)
log_Printf(LogPHASE, "%s: %s is in use\n", p->link.name, p->name.full);
else
log_Printf(LogPHASE, "%s: %s is in use: uu_lock: %s\n",
p->link.name, p->name.full, uu_lockerr(res));
return (-1);
}
snprintf(fn, sizeof fn, "%s%s.if", _PATH_VARRUN, p->name.base);
lockfile = ID0fopen(fn, "w");
if (lockfile != NULL) {
fprintf(lockfile, "%s%d\n", TUN_NAME, tunno);
fclose(lockfile);
}
#ifndef RELEASE_CRUNCH
else
log_Printf(LogALERT, "%s: Can't create %s: %s\n",
p->link.name, fn, strerror(errno));
#endif
return 0;
}
static void
tty_Unlock(struct physical *p)
{
char fn[MAXPATHLEN];
if (*p->name.full != '/')
return;
snprintf(fn, sizeof fn, "%s%s.if", _PATH_VARRUN, p->name.base);
#ifndef RELEASE_CRUNCH
if (ID0unlink(fn) == -1)
log_Printf(LogALERT, "%s: Can't remove %s: %s\n",
p->link.name, fn, strerror(errno));
#else
ID0unlink(fn);
#endif
if (p->type != PHYS_DIRECT && ID0uu_unlock(p->name.base) == -1)
log_Printf(LogALERT, "%s: Can't uu_unlock %s\n", p->link.name, fn);
}
/* /*
* tty_Timeout() watches the DCD signal and mentions it if it's status * tty_Timeout() watches the DCD signal and mentions it if it's status
* changes. * changes.
@ -316,7 +260,6 @@ tty_Free(struct physical *p)
{ {
struct ttydevice *dev = device2tty(p->handler); struct ttydevice *dev = device2tty(p->handler);
tty_Unlock(p);
free(dev); free(dev);
} }
@ -376,22 +319,63 @@ static struct device basettydevice = {
tty_OpenInfo tty_OpenInfo
}; };
static struct device * struct device *
tty_SetupDevice(struct physical *p) tty_iov2device(int type, struct physical *p, struct iovec *iov, int *niov,
int maxiov)
{
if (type == TTY_DEVICE) {
struct ttydevice *dev;
/* It's one of ours ! Let's create the device */
dev = (struct ttydevice *)iov[(*niov)++].iov_base;
/* Refresh function pointers etc */
memcpy(&dev->dev, &basettydevice, sizeof dev->dev);
physical_SetupStack(p, PHYSICAL_NOFORCE);
if (dev->Timer.state != TIMER_STOPPED) {
dev->Timer.state = TIMER_STOPPED;
tty_StartTimer(p);
}
return &dev->dev;
}
return NULL;
}
struct device *
tty_Create(struct physical *p)
{ {
struct ttydevice *dev; struct ttydevice *dev;
struct termios ios; struct termios ios;
int oldflag; int oldflag;
if ((dev = malloc(sizeof *dev)) == NULL) if (p->fd < 0 || !isatty(p->fd))
/* Don't want this */
return NULL; return NULL;
if (*p->name.full == '\0') {
physical_SetDevice(p, ttyname(p->fd));
log_Printf(LogDEBUG, "%s: Input is a tty (%s)\n",
p->link.name, p->name.full);
} else
log_Printf(LogDEBUG, "%s: Opened %s\n", p->link.name, p->name.full);
/* We're gonna return a ttydevice (unless something goes horribly wrong) */
if ((dev = malloc(sizeof *dev)) == NULL) {
/* Complete failure - parent doesn't continue trying to ``create'' */
close(p->fd);
p->fd = -1;
return NULL;
}
memcpy(&dev->dev, &basettydevice, sizeof dev->dev); memcpy(&dev->dev, &basettydevice, sizeof dev->dev);
memset(&dev->Timer, '\0', sizeof dev->Timer); memset(&dev->Timer, '\0', sizeof dev->Timer);
tcgetattr(p->fd, &ios); tcgetattr(p->fd, &ios);
dev->ios = ios; dev->ios = ios;
log_Printf(LogDEBUG, "%s: tty_SetupDevice: physical (get): fd = %d," log_Printf(LogDEBUG, "%s: tty_Create: physical (get): fd = %d,"
" iflag = %lx, oflag = %lx, cflag = %lx\n", p->link.name, p->fd, " iflag = %lx, oflag = %lx, cflag = %lx\n", p->link.name, p->fd,
(u_long)ios.c_iflag, (u_long)ios.c_oflag, (u_long)ios.c_cflag); (u_long)ios.c_iflag, (u_long)ios.c_oflag, (u_long)ios.c_cflag);
@ -421,9 +405,13 @@ tty_SetupDevice(struct physical *p)
if (ioctl(p->fd, TIOCMGET, &dev->mbits) == -1) { if (ioctl(p->fd, TIOCMGET, &dev->mbits) == -1) {
if (p->type != PHYS_DIRECT) { if (p->type != PHYS_DIRECT) {
/* Complete failure - parent doesn't continue trying to ``create'' */
log_Printf(LogWARN, "%s: Open: Cannot get physical status: %s\n", log_Printf(LogWARN, "%s: Open: Cannot get physical status: %s\n",
p->link.name, strerror(errno)); p->link.name, strerror(errno));
physical_Close(p); tty_Cooked(p);
close(p->fd);
p->fd = -1;
return NULL; return NULL;
} else } else
dev->mbits = TIOCM_CD; dev->mbits = TIOCM_CD;
@ -433,9 +421,13 @@ tty_SetupDevice(struct physical *p)
oldflag = fcntl(p->fd, F_GETFL, 0); oldflag = fcntl(p->fd, F_GETFL, 0);
if (oldflag < 0) { if (oldflag < 0) {
/* Complete failure - parent doesn't continue trying to ``create'' */
log_Printf(LogWARN, "%s: Open: Cannot get physical flags: %s\n", log_Printf(LogWARN, "%s: Open: Cannot get physical flags: %s\n",
p->link.name, strerror(errno)); p->link.name, strerror(errno));
physical_Close(p); tty_Cooked(p);
close(p->fd);
p->fd = -1;
return NULL; return NULL;
} else } else
fcntl(p->fd, F_SETFL, oldflag & ~O_NONBLOCK); fcntl(p->fd, F_SETFL, oldflag & ~O_NONBLOCK);
@ -444,48 +436,3 @@ tty_SetupDevice(struct physical *p)
return &dev->dev; return &dev->dev;
} }
struct device *
tty_iov2device(int type, struct physical *p, struct iovec *iov, int *niov,
int maxiov)
{
if (type == TTY_DEVICE) {
struct ttydevice *dev;
/* It's one of ours ! Let's create the device */
dev = (struct ttydevice *)iov[(*niov)++].iov_base;
/* Refresh function pointers etc */
memcpy(&dev->dev, &basettydevice, sizeof dev->dev);
physical_SetupStack(p, PHYSICAL_NOFORCE);
if (dev->Timer.state != TIMER_STOPPED) {
dev->Timer.state = TIMER_STOPPED;
tty_StartTimer(p);
}
return &dev->dev;
}
return NULL;
}
struct device *
tty_Create(struct physical *p)
{
if (p->fd >= 0 && isatty(p->fd)) {
if (*p->name.full == '\0') {
log_Printf(LogDEBUG, "%s: Input is a tty\n", p->link.name);
physical_SetDevice(p, ttyname(p->fd));
if (tty_Lock(p, p->dl->bundle->unit) == -1) {
close(p->fd);
p->fd = -1;
} else
return tty_SetupDevice(p);
} else if (tty_Lock(p, p->dl->bundle->unit) != -1) {
log_Printf(LogDEBUG, "%s: Opened %s\n", p->link.name, p->name.full);
return tty_SetupDevice(p);
}
}
return NULL;
}