physical.c revision 37192
1/*
2 * Written by Eivind Eklund <eivind@yes.no>
3 *    for Yes Interactive
4 *
5 * Copyright (C) 1998, Yes Interactive.  All rights reserved.
6 *
7 * Redistribution and use in any form is permitted.  Redistribution in
8 * source form should include the above copyright and this set of
9 * conditions, because large sections american law seems to have been
10 * created by a bunch of jerks on drugs that are now illegal, forcing
11 * me to include this copyright-stuff instead of placing this in the
12 * public domain.  The name of of 'Yes Interactive' or 'Eivind Eklund'
13 * may not be used to endorse or promote products derived from this
14 * software without specific prior written permission.
15 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
17 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
18 *
19 *  $Id: physical.c,v 1.3 1998/05/23 22:24:47 brian Exp $
20 *
21 */
22
23#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#include <time.h>
27#include <unistd.h>
28#include <utmp.h>
29#include <sys/tty.h>
30
31#include "defs.h"
32#include "mbuf.h"
33#include "timer.h"
34#include "lqr.h"
35#include "hdlc.h"
36#include "throughput.h"
37#include "fsm.h"
38#include "lcp.h"
39#include "async.h"
40#include "ccp.h"
41#include "link.h"
42#include "descriptor.h"
43#include "physical.h"
44#include "log.h"
45#include "id.h"
46
47/* External calls - should possibly be moved inline */
48extern int IntToSpeed(int);
49
50
51int
52physical_GetFD(struct physical *phys) {
53   return phys->fd;
54}
55
56int
57physical_IsATTY(struct physical *phys) {
58   return isatty(phys->fd);
59}
60
61int
62physical_IsSync(struct physical *phys) {
63   return phys->cfg.speed == 0;
64}
65
66const char *physical_GetDevice(struct physical *phys)
67{
68   return phys->name.full;
69}
70
71void
72physical_SetDeviceList(struct physical *p, int argc, const char *const *argv)
73{
74  int f, pos;
75
76  p->cfg.devlist[sizeof p->cfg.devlist - 1] = '\0';
77  for (f = 0, pos = 0; f < argc && pos < sizeof p->cfg.devlist - 1; f++) {
78    if (pos)
79      p->cfg.devlist[pos++] = ' ';
80    strncpy(p->cfg.devlist + pos, argv[f], sizeof p->cfg.devlist - pos - 1);
81    pos += strlen(p->cfg.devlist + pos);
82  }
83}
84
85
86int
87physical_SetSpeed(struct physical *phys, int speed) {
88   if (IntToSpeed(speed) != B0) {
89      phys->cfg.speed = speed;
90      return 1;
91   } else {
92      return 0;
93   }
94}
95
96void
97physical_SetSync(struct physical *phys) {
98   phys->cfg.speed = 0;
99}
100
101
102int
103physical_SetRtsCts(struct physical *phys, int enable) {
104   phys->cfg.rts_cts = enable ? 1 : 0;
105   return 1;
106}
107
108/* Encapsulation for a read on the FD.  Avoids some exposure, and
109   concentrates control. */
110ssize_t
111physical_Read(struct physical *phys, void *buf, size_t nbytes) {
112   return read(phys->fd, buf, nbytes);
113}
114
115ssize_t
116physical_Write(struct physical *phys, const void *buf, size_t nbytes) {
117   return write(phys->fd, buf, nbytes);
118}
119
120int
121physical_UpdateSet(struct descriptor *d, fd_set *r, fd_set *w, fd_set *e,
122                   int *n, int force)
123{
124  struct physical *p = descriptor2physical(d);
125  int sets;
126
127  sets = 0;
128  if (p->fd >= 0) {
129    if (r) {
130      FD_SET(p->fd, r);
131      log_Printf(LogTIMER, "%s: fdset(r) %d\n", p->link.name, p->fd);
132      sets++;
133    }
134    if (e) {
135      FD_SET(p->fd, e);
136      log_Printf(LogTIMER, "%s: fdset(e) %d\n", p->link.name, p->fd);
137      sets++;
138    }
139    if (w && (force || link_QueueLen(&p->link) || p->out)) {
140      FD_SET(p->fd, w);
141      log_Printf(LogTIMER, "%s: fdset(w) %d\n", p->link.name, p->fd);
142      sets++;
143    }
144    if (sets && *n < p->fd + 1)
145      *n = p->fd + 1;
146  }
147
148  return sets;
149}
150
151int
152physical_RemoveFromSet(struct physical *p, fd_set *r, fd_set *w, fd_set *e)
153{
154  int sets;
155
156  sets = 0;
157  if (p->fd >= 0) {
158    if (r && FD_ISSET(p->fd, r)) {
159      FD_CLR(p->fd, r);
160      log_Printf(LogTIMER, "%s: fdunset(r) %d\n", p->link.name, p->fd);
161      sets++;
162    }
163    if (e && FD_ISSET(p->fd, e)) {
164      FD_CLR(p->fd, e);
165      log_Printf(LogTIMER, "%s: fdunset(e) %d\n", p->link.name, p->fd);
166      sets++;
167    }
168    if (w && FD_ISSET(p->fd, w)) {
169      FD_CLR(p->fd, w);
170      log_Printf(LogTIMER, "%s: fdunset(w) %d\n", p->link.name, p->fd);
171      sets++;
172    }
173  }
174
175  return sets;
176}
177
178int
179physical_IsSet(struct descriptor *d, const fd_set *fdset)
180{
181  struct physical *p = descriptor2physical(d);
182  return p->fd >= 0 && FD_ISSET(p->fd, fdset);
183}
184
185void
186physical_Login(struct physical *phys, const char *name)
187{
188  if (phys->type == PHYS_DIRECT && physical_IsATTY(phys)) {
189    if (phys->Utmp)
190      log_Printf(LogERROR, "Oops, already logged in on %s\n", phys->name.base);
191    else {
192      struct utmp ut;
193      const char *connstr;
194
195      memset(&ut, 0, sizeof ut);
196      time(&ut.ut_time);
197      strncpy(ut.ut_name, name, sizeof ut.ut_name);
198      strncpy(ut.ut_line, phys->name.base, sizeof ut.ut_line);
199      if ((connstr = getenv("CONNECT")))
200        /* mgetty sets this to the connection speed */
201        strncpy(ut.ut_host, connstr, sizeof ut.ut_host);
202      ID0login(&ut);
203      phys->Utmp = 1;
204    }
205  }
206}
207
208void
209physical_Logout(struct physical *phys)
210{
211  if (phys->Utmp) {
212    ID0logout(phys->name.base);
213    phys->Utmp = 0;
214  }
215}
216
217int
218physical_SetMode(struct physical *p, int mode)
219{
220  if (p->type & (PHYS_DIRECT|PHYS_DEDICATED)
221      || mode & (PHYS_DIRECT|PHYS_DEDICATED)) {
222    log_Printf(LogWARN, "%s: Cannot change mode %s to %s\n", p->link.name,
223               mode2Nam(p->type), mode2Nam(mode));
224    return 0;
225  }
226  p->type = mode;
227  return 1;
228}
229