physical.c revision 42452
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.6 1998/08/25 17:48:43 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_IsSync(struct physical *phys) {
58   return phys->cfg.speed == 0;
59}
60
61const char *physical_GetDevice(struct physical *phys)
62{
63   return phys->name.full;
64}
65
66void
67physical_SetDeviceList(struct physical *p, int argc, const char *const *argv)
68{
69  int f, pos;
70
71  p->cfg.devlist[sizeof p->cfg.devlist - 1] = '\0';
72  for (f = 0, pos = 0; f < argc && pos < sizeof p->cfg.devlist - 1; f++) {
73    if (pos)
74      p->cfg.devlist[pos++] = ' ';
75    strncpy(p->cfg.devlist + pos, argv[f], sizeof p->cfg.devlist - pos - 1);
76    pos += strlen(p->cfg.devlist + pos);
77  }
78}
79
80
81int
82physical_SetSpeed(struct physical *phys, int speed) {
83   if (IntToSpeed(speed) != B0) {
84      phys->cfg.speed = speed;
85      return 1;
86   } else {
87      return 0;
88   }
89}
90
91void
92physical_SetSync(struct physical *phys) {
93   phys->cfg.speed = 0;
94}
95
96
97int
98physical_SetRtsCts(struct physical *phys, int enable) {
99   phys->cfg.rts_cts = enable ? 1 : 0;
100   return 1;
101}
102
103/* Encapsulation for a read on the FD.  Avoids some exposure, and
104   concentrates control. */
105ssize_t
106physical_Read(struct physical *phys, void *buf, size_t nbytes) {
107   return read(phys->fd, buf, nbytes);
108}
109
110ssize_t
111physical_Write(struct physical *phys, const void *buf, size_t nbytes) {
112   return write(phys->fd, buf, nbytes);
113}
114
115int
116physical_UpdateSet(struct descriptor *d, fd_set *r, fd_set *w, fd_set *e,
117                   int *n, int force)
118{
119  struct physical *p = descriptor2physical(d);
120  int sets;
121
122  sets = 0;
123  if (p->fd >= 0) {
124    if (r) {
125      FD_SET(p->fd, r);
126      log_Printf(LogTIMER, "%s: fdset(r) %d\n", p->link.name, p->fd);
127      sets++;
128    }
129    if (e) {
130      FD_SET(p->fd, e);
131      log_Printf(LogTIMER, "%s: fdset(e) %d\n", p->link.name, p->fd);
132      sets++;
133    }
134    if (w && (force || link_QueueLen(&p->link) || p->out)) {
135      FD_SET(p->fd, w);
136      log_Printf(LogTIMER, "%s: fdset(w) %d\n", p->link.name, p->fd);
137      sets++;
138    }
139    if (sets && *n < p->fd + 1)
140      *n = p->fd + 1;
141  }
142
143  return sets;
144}
145
146int
147physical_RemoveFromSet(struct physical *p, fd_set *r, fd_set *w, fd_set *e)
148{
149  int sets;
150
151  sets = 0;
152  if (p->fd >= 0) {
153    if (r && FD_ISSET(p->fd, r)) {
154      FD_CLR(p->fd, r);
155      log_Printf(LogTIMER, "%s: fdunset(r) %d\n", p->link.name, p->fd);
156      sets++;
157    }
158    if (e && FD_ISSET(p->fd, e)) {
159      FD_CLR(p->fd, e);
160      log_Printf(LogTIMER, "%s: fdunset(e) %d\n", p->link.name, p->fd);
161      sets++;
162    }
163    if (w && FD_ISSET(p->fd, w)) {
164      FD_CLR(p->fd, w);
165      log_Printf(LogTIMER, "%s: fdunset(w) %d\n", p->link.name, p->fd);
166      sets++;
167    }
168  }
169
170  return sets;
171}
172
173int
174physical_IsSet(struct descriptor *d, const fd_set *fdset)
175{
176  struct physical *p = descriptor2physical(d);
177  return p->fd >= 0 && FD_ISSET(p->fd, fdset);
178}
179
180void
181physical_Login(struct physical *phys, const char *name)
182{
183  if (phys->type == PHYS_DIRECT && phys->isatty) {
184    if (phys->Utmp)
185      log_Printf(LogERROR, "Oops, already logged in on %s\n", phys->name.base);
186    else {
187      struct utmp ut;
188      const char *connstr;
189
190      memset(&ut, 0, sizeof ut);
191      time(&ut.ut_time);
192      strncpy(ut.ut_name, name, sizeof ut.ut_name);
193      strncpy(ut.ut_line, phys->name.base, sizeof ut.ut_line);
194      if ((connstr = getenv("CONNECT")))
195        /* mgetty sets this to the connection speed */
196        strncpy(ut.ut_host, connstr, sizeof ut.ut_host);
197      ID0login(&ut);
198      phys->Utmp = 1;
199    }
200  }
201}
202
203void
204physical_Logout(struct physical *phys)
205{
206  if (phys->Utmp) {
207    ID0logout(phys->name.base);
208    phys->Utmp = 0;
209  }
210}
211
212int
213physical_SetMode(struct physical *p, int mode)
214{
215  if ((p->type & (PHYS_DIRECT|PHYS_DEDICATED) ||
216       mode & (PHYS_DIRECT|PHYS_DEDICATED)) &&
217      (!(p->type & PHYS_DIRECT) || !(mode & PHYS_BACKGROUND))) {
218    log_Printf(LogWARN, "%s: Cannot change mode %s to %s\n", p->link.name,
219               mode2Nam(p->type), mode2Nam(mode));
220    return 0;
221  }
222  p->type = mode;
223  return 1;
224}
225
226void
227physical_DeleteQueue(struct physical *p)
228{
229  if (p->out) {
230    mbuf_Free(p->out);
231    p->out = NULL;
232  }
233  link_DeleteQueue(&p->link);
234}
235