1/* vport.c 2 Find a port in the V2 configuration files. 3 4 Copyright (C) 1992, 1993, 2002 Ian Lance Taylor 5 6 This file is part of the Taylor UUCP uuconf library. 7 8 This library is free software; you can redistribute it and/or 9 modify it under the terms of the GNU Library General Public License 10 as published by the Free Software Foundation; either version 2 of 11 the License, or (at your option) any later version. 12 13 This library is distributed in the hope that it will be useful, but 14 WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 Library General Public License for more details. 17 18 You should have received a copy of the GNU Library General Public 19 License along with this library; if not, write to the Free Software 20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. 21 22 The author of the program may be contacted at ian@airs.com. 23 */ 24 25#include "uucnfi.h" 26 27#if USE_RCS_ID 28const char _uuconf_vport_rcsid[] = "$Id: vport.c,v 1.12 2002/03/05 19:10:43 ian Rel $"; 29#endif 30 31#include <errno.h> 32#include <ctype.h> 33 34/* Find a port in the V2 configuration files by name, baud rate, and 35 special purpose function. */ 36 37int 38uuconf_v2_find_port (pglobal, zname, ibaud, ihighbaud, pifn, pinfo, qport) 39 pointer pglobal; 40 const char *zname; 41 long ibaud; 42 long ihighbaud ATTRIBUTE_UNUSED; 43 int (*pifn) P((struct uuconf_port *, pointer)); 44 pointer pinfo; 45 struct uuconf_port *qport; 46{ 47 struct sglobal *qglobal = (struct sglobal *) pglobal; 48 FILE *e; 49 char *zline; 50 size_t cline; 51 char **pzsplit; 52 size_t csplit; 53 int iret; 54 int cchars; 55 56 e = fopen (qglobal->qprocess->zv2devices, "r"); 57 if (e == NULL) 58 { 59 if (FNO_SUCH_FILE ()) 60 return UUCONF_NOT_FOUND; 61 qglobal->ierrno = errno; 62 qglobal->zfilename = qglobal->qprocess->zv2devices; 63 return (UUCONF_FOPEN_FAILED 64 | UUCONF_ERROR_ERRNO 65 | UUCONF_ERROR_FILENAME); 66 } 67 68 zline = NULL; 69 cline = 0; 70 pzsplit = NULL; 71 csplit = 0; 72 73 iret = UUCONF_NOT_FOUND; 74 75 qglobal->ilineno = 0; 76 77 while ((cchars = getline (&zline, &cline, e)) > 0) 78 { 79 int ctoks; 80 char *zend; 81 long ilow, ihigh; 82 pointer pblock; 83 84 ++qglobal->ilineno; 85 86 iret = UUCONF_NOT_FOUND; 87 88 --cchars; 89 if (zline[cchars] == '\n') 90 zline[cchars] = '\0'; 91 zline[strcspn (zline, "#")] = '\0'; 92 93 ctoks = _uuconf_istrsplit (zline, '\0', &pzsplit, &csplit); 94 if (ctoks < 0) 95 { 96 qglobal->ierrno = errno; 97 iret = UUCONF_MALLOC_FAILED | UUCONF_ERROR_ERRNO; 98 break; 99 } 100 101 /* An entry in L-devices is 102 103 type device dial-device baud dialer 104 105 The type (normally "ACU") is treated as the name. */ 106 107 /* If there aren't enough entries, ignore the line; this 108 should probably do something more useful. */ 109 if (ctoks < 4) 110 continue; 111 112 /* Make sure the name matches any argument. */ 113 if (zname != NULL 114 && strcmp (pzsplit[0], zname) != 0) 115 continue; 116 117 /* Get the baud rate. */ 118 ilow = strtol (pzsplit[3], &zend, 10); 119 if (*zend == '-') 120 ihigh = strtol (zend + 1, (char **) NULL, 10); 121 else 122 ihigh = ilow; 123 124 /* Make sure the baud rate matches any argument. */ 125 if (ibaud != 0 126 && ilow != 0 127 && (ilow > ibaud || ihigh < ibaud)) 128 continue; 129 130 /* Now we must construct the port information, so that we can 131 pass it to pifn. The port type is determined by it's name, 132 unfortunately. The name "DIR" is used for a direct port, and 133 anything else for a modem port. */ 134 pblock = NULL; 135 _uuconf_uclear_port (qport); 136 qport->uuconf_zname = pzsplit[0]; 137 if (strcmp (pzsplit[0], "DIR") == 0) 138 { 139 qport->uuconf_ttype = UUCONF_PORTTYPE_DIRECT; 140 qport->uuconf_u.uuconf_sdirect.uuconf_zdevice = pzsplit[1]; 141 qport->uuconf_u.uuconf_sdirect.uuconf_ibaud = ilow; 142 qport->uuconf_u.uuconf_sdirect.uuconf_fcarrier = FALSE; 143 qport->uuconf_u.uuconf_sdirect.uuconf_fhardflow = TRUE; 144 } 145 else 146 { 147 qport->uuconf_ttype = UUCONF_PORTTYPE_MODEM; 148 qport->uuconf_u.uuconf_smodem.uuconf_zdevice = pzsplit[1]; 149 if (strcmp (pzsplit[2], "-") != 0) 150 qport->uuconf_u.uuconf_smodem.uuconf_zdial_device = pzsplit[2]; 151 else 152 qport->uuconf_u.uuconf_smodem.uuconf_zdial_device = NULL; 153 if (ilow == ihigh) 154 { 155 qport->uuconf_u.uuconf_smodem.uuconf_ibaud = ilow; 156 qport->uuconf_u.uuconf_smodem.uuconf_ilowbaud = 0L; 157 qport->uuconf_u.uuconf_smodem.uuconf_ihighbaud = 0L; 158 } 159 else 160 { 161 qport->uuconf_u.uuconf_smodem.uuconf_ibaud = 0L; 162 qport->uuconf_u.uuconf_smodem.uuconf_ilowbaud = ilow; 163 qport->uuconf_u.uuconf_smodem.uuconf_ihighbaud = ihigh; 164 } 165 qport->uuconf_u.uuconf_smodem.uuconf_fcarrier = TRUE; 166 qport->uuconf_u.uuconf_smodem.uuconf_fhardflow = TRUE; 167 if (ctoks < 5) 168 qport->uuconf_u.uuconf_smodem.uuconf_pzdialer = NULL; 169 else 170 { 171 size_t c; 172 char **pzd; 173 174 /* We support dialer/token pairs, although normal V2 175 doesn't. */ 176 pblock = uuconf_malloc_block (); 177 if (pblock == NULL) 178 { 179 qglobal->ierrno = errno; 180 iret = UUCONF_MALLOC_FAILED | UUCONF_ERROR_ERRNO; 181 break; 182 } 183 c = (ctoks - 4) * sizeof (char *); 184 pzd = (char **) uuconf_malloc (pblock, c + sizeof (char *)); 185 if (pzd == NULL) 186 { 187 qglobal->ierrno = errno; 188 uuconf_free_block (pblock); 189 iret = UUCONF_MALLOC_FAILED | UUCONF_ERROR_ERRNO; 190 break; 191 } 192 memcpy ((pointer) pzd, (pointer) (pzsplit + 4), c); 193 pzd[ctoks - 4] = NULL; 194 195 qport->uuconf_u.uuconf_smodem.uuconf_pzdialer = pzd; 196 } 197 qport->uuconf_u.uuconf_smodem.uuconf_qdialer = NULL; 198 } 199 200 if (pifn != NULL) 201 { 202 iret = (*pifn) (qport, pinfo); 203 if (iret != UUCONF_SUCCESS) 204 { 205 if (pblock != NULL) 206 uuconf_free_block (pblock); 207 if (iret != UUCONF_NOT_FOUND) 208 break; 209 continue; 210 } 211 } 212 213 /* This is the port we want. */ 214 if (pblock == NULL) 215 { 216 pblock = uuconf_malloc_block (); 217 if (pblock == NULL) 218 { 219 qglobal->ierrno = errno; 220 iret = UUCONF_MALLOC_FAILED | UUCONF_ERROR_ERRNO; 221 break; 222 } 223 } 224 225 if (uuconf_add_block (pblock, zline) != 0) 226 { 227 qglobal->ierrno = errno; 228 uuconf_free_block (pblock); 229 iret = UUCONF_MALLOC_FAILED | UUCONF_ERROR_ERRNO; 230 break; 231 } 232 zline = NULL; 233 234 qport->uuconf_palloc = pblock; 235 236 break; 237 } 238 239 (void) fclose (e); 240 241 if (zline != NULL) 242 free ((pointer) zline); 243 if (pzsplit != NULL) 244 free ((pointer) pzsplit); 245 246 if (iret != UUCONF_SUCCESS && iret != UUCONF_NOT_FOUND) 247 { 248 qglobal->zfilename = qglobal->qprocess->zv2devices; 249 iret |= UUCONF_ERROR_FILENAME | UUCONF_ERROR_LINENO; 250 } 251 252 return iret; 253} 254