physical.c revision 36314
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.2 1998/05/21 21:47:37 brian Exp $
20 *
21 */
22
23#include <sys/types.h>
24
25#include <stdio.h>
26#include <stdlib.h>
27#include <string.h>
28#include <time.h>
29#include <unistd.h>
30#include <utmp.h>
31#include <sys/tty.h>
32
33#include "defs.h"
34#include "mbuf.h"
35#include "timer.h"
36#include "lqr.h"
37#include "hdlc.h"
38#include "throughput.h"
39#include "fsm.h"
40#include "lcp.h"
41#include "async.h"
42#include "ccp.h"
43#include "link.h"
44#include "descriptor.h"
45#include "physical.h"
46#include "log.h"
47#include "id.h"
48
49/* External calls - should possibly be moved inline */
50extern int IntToSpeed(int);
51
52
53int
54physical_GetFD(struct physical *phys) {
55   return phys->fd;
56}
57
58int
59physical_IsATTY(struct physical *phys) {
60   return isatty(phys->fd);
61}
62
63int
64physical_IsSync(struct physical *phys) {
65   return phys->cfg.speed == 0;
66}
67
68const char *physical_GetDevice(struct physical *phys)
69{
70   return phys->name.full;
71}
72
73void
74physical_SetDeviceList(struct physical *p, int argc, const char *const *argv)
75{
76  int f, pos;
77
78  p->cfg.devlist[sizeof p->cfg.devlist - 1] = '\0';
79  for (f = 0, pos = 0; f < argc && pos < sizeof p->cfg.devlist - 1; f++) {
80    if (pos)
81      p->cfg.devlist[pos++] = ' ';
82    strncpy(p->cfg.devlist + pos, argv[f], sizeof p->cfg.devlist - pos - 1);
83    pos += strlen(p->cfg.devlist + pos);
84  }
85}
86
87
88int
89physical_SetSpeed(struct physical *phys, int speed) {
90   if (IntToSpeed(speed) != B0) {
91      phys->cfg.speed = speed;
92      return 1;
93   } else {
94      return 0;
95   }
96}
97
98void
99physical_SetSync(struct physical *phys) {
100   phys->cfg.speed = 0;
101}
102
103
104int
105physical_SetRtsCts(struct physical *phys, int enable) {
106   phys->cfg.rts_cts = enable ? 1 : 0;
107   return 1;
108}
109
110/* Encapsulation for a read on the FD.  Avoids some exposure, and
111   concentrates control. */
112ssize_t
113physical_Read(struct physical *phys, void *buf, size_t nbytes) {
114   return read(phys->fd, buf, nbytes);
115}
116
117ssize_t
118physical_Write(struct physical *phys, const void *buf, size_t nbytes) {
119   return write(phys->fd, buf, nbytes);
120}
121
122int
123physical_UpdateSet(struct descriptor *d, fd_set *r, fd_set *w, fd_set *e,
124                   int *n, int force)
125{
126  struct physical *p = descriptor2physical(d);
127  int sets;
128
129  sets = 0;
130  if (p->fd >= 0) {
131    if (r) {
132      FD_SET(p->fd, r);
133      log_Printf(LogTIMER, "%s: fdset(r) %d\n", p->link.name, p->fd);
134      sets++;
135    }
136    if (e) {
137      FD_SET(p->fd, e);
138      log_Printf(LogTIMER, "%s: fdset(e) %d\n", p->link.name, p->fd);
139      sets++;
140    }
141    if (w && (force || link_QueueLen(&p->link) || p->out)) {
142      FD_SET(p->fd, w);
143      log_Printf(LogTIMER, "%s: fdset(w) %d\n", p->link.name, p->fd);
144      sets++;
145    }
146    if (sets && *n < p->fd + 1)
147      *n = p->fd + 1;
148  }
149
150  return sets;
151}
152
153int
154physical_RemoveFromSet(struct physical *p, fd_set *r, fd_set *w, fd_set *e)
155{
156  int sets;
157
158  sets = 0;
159  if (p->fd >= 0) {
160    if (r && FD_ISSET(p->fd, r)) {
161      FD_CLR(p->fd, r);
162      log_Printf(LogTIMER, "%s: fdunset(r) %d\n", p->link.name, p->fd);
163      sets++;
164    }
165    if (e && FD_ISSET(p->fd, e)) {
166      FD_CLR(p->fd, e);
167      log_Printf(LogTIMER, "%s: fdunset(e) %d\n", p->link.name, p->fd);
168      sets++;
169    }
170    if (w && FD_ISSET(p->fd, w)) {
171      FD_CLR(p->fd, w);
172      log_Printf(LogTIMER, "%s: fdunset(w) %d\n", p->link.name, p->fd);
173      sets++;
174    }
175  }
176
177  return sets;
178}
179
180int
181physical_IsSet(struct descriptor *d, const fd_set *fdset)
182{
183  struct physical *p = descriptor2physical(d);
184  return p->fd >= 0 && FD_ISSET(p->fd, fdset);
185}
186
187void
188physical_Login(struct physical *phys, const char *name)
189{
190  if (phys->type == PHYS_DIRECT && physical_IsATTY(phys)) {
191    if (phys->Utmp)
192      log_Printf(LogERROR, "Oops, already logged in on %s\n", phys->name.base);
193    else {
194      struct utmp ut;
195      const char *connstr;
196
197      memset(&ut, 0, sizeof ut);
198      time(&ut.ut_time);
199      strncpy(ut.ut_name, name, sizeof ut.ut_name);
200      strncpy(ut.ut_line, phys->name.base, sizeof ut.ut_line);
201      if ((connstr = getenv("CONNECT")))
202        /* mgetty sets this to the connection speed */
203        strncpy(ut.ut_host, connstr, sizeof ut.ut_host);
204      ID0login(&ut);
205      phys->Utmp = 1;
206    }
207  }
208}
209
210void
211physical_Logout(struct physical *phys)
212{
213  if (phys->Utmp) {
214    ID0logout(phys->name.base);
215    phys->Utmp = 0;
216  }
217}
218
219int
220physical_SetMode(struct physical *p, int mode)
221{
222  if (p->type & (PHYS_DIRECT|PHYS_DEDICATED)
223      || mode & (PHYS_DIRECT|PHYS_DEDICATED)) {
224    log_Printf(LogWARN, "%s: Cannot change mode %s to %s\n", p->link.name,
225               mode2Nam(p->type), mode2Nam(mode));
226    return 0;
227  }
228  p->type = mode;
229  return 1;
230}
231