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.5 1998/08/07 18:42:50 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 */ 48 extern int IntToSpeed(int); 49 50 51 int 52 physical_GetFD(struct physical *phys) { 53 return phys->fd; 54 } 55 56 int 57 physical_IsATTY(struct physical *phys) { 58 return isatty(phys->fd); 59 } 60 61 int 62 physical_IsSync(struct physical *phys) { 63 return phys->cfg.speed == 0; 64 } 65 66 const char *physical_GetDevice(struct physical *phys) 67 { 68 return phys->name.full; 69 } 70 71 void 72 physical_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 86 int 87 physical_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 96 void 97 physical_SetSync(struct physical *phys) { 98 phys->cfg.speed = 0; 99 } 100 101 102 int 103 physical_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. */ 110 ssize_t 111 physical_Read(struct physical *phys, void *buf, size_t nbytes) { 112 return read(phys->fd, buf, nbytes); 113 } 114 115 ssize_t 116 physical_Write(struct physical *phys, const void *buf, size_t nbytes) { 117 return write(phys->fd, buf, nbytes); 118 } 119 120 int 121 physical_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 151 int 152 physical_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 178 int 179 physical_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 185 void 186 physical_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 208 void 209 physical_Logout(struct physical *phys) 210 { 211 if (phys->Utmp) { 212 ID0logout(phys->name.base); 213 phys->Utmp = 0; 214 } 215 } 216 217 int 218 physical_SetMode(struct physical *p, int mode) 219 { 220 if ((p->type & (PHYS_DIRECT|PHYS_DEDICATED) || 221 mode & (PHYS_DIRECT|PHYS_DEDICATED)) && 222 (!(p->type & PHYS_DIRECT) || !(mode & PHYS_BACKGROUND))) { 223 log_Printf(LogWARN, "%s: Cannot change mode %s to %s\n", p->link.name, 224 mode2Nam(p->type), mode2Nam(mode)); 225 return 0; 226 } 227 p->type = mode; 228 return 1; 229 } 230 231 void 232 physical_DeleteQueue(struct physical *p) 233 { 234 if (p->out) { 235 mbuf_Free(p->out); 236 p->out = NULL; 237 } 238 link_DeleteQueue(&p->link); 239 } 240