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