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