1/* tport.c 2 Find a port in the Taylor UUCP 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_tport_rcsid[] = "$Id: tport.c,v 1.12 2002/03/05 19:10:43 ian Rel $"; 29#endif 30 31#include <errno.h> 32 33static int ipport P((pointer pglobal, int argc, char **argv, pointer pvar, 34 pointer pinfo)); 35static int ipunknown P((pointer pglobal, int argc, char **argv, 36 pointer pvar, pointer pinfo)); 37 38/* Find a port in the Taylor UUCP configuration files by name, baud 39 rate, and special purpose function. */ 40 41int 42uuconf_taylor_find_port (pglobal, zname, ibaud, ihighbaud, pifn, pinfo, 43 qport) 44 pointer pglobal; 45 const char *zname; 46 long ibaud; 47 long ihighbaud; 48 int (*pifn) P((struct uuconf_port *, pointer)); 49 pointer pinfo; 50 struct uuconf_port *qport; 51{ 52 struct sglobal *qglobal = (struct sglobal *) pglobal; 53 FILE *e; 54 pointer pblock; 55 char *zfree; 56 int iret; 57 char **pz; 58 59 if (ihighbaud == 0L) 60 ihighbaud = ibaud; 61 62 e = NULL; 63 pblock = NULL; 64 zfree = NULL; 65 iret = UUCONF_NOT_FOUND; 66 67 for (pz = qglobal->qprocess->pzportfiles; *pz != NULL; pz++) 68 { 69 struct uuconf_cmdtab as[2]; 70 char *zport; 71 struct uuconf_port sdefault; 72 int ilineno; 73 74 e = fopen (*pz, "r"); 75 if (e == NULL) 76 { 77 if (FNO_SUCH_FILE ()) 78 continue; 79 qglobal->ierrno = errno; 80 iret = UUCONF_FOPEN_FAILED | UUCONF_ERROR_ERRNO; 81 break; 82 } 83 84 qglobal->ilineno = 0; 85 86 /* Gather the default information from the top of the file. We 87 do this by handling the "port" command ourselves and passing 88 every other command to _uuconf_iport_cmd via ipunknown. The 89 value of zport will be an malloc block. */ 90 as[0].uuconf_zcmd = "port"; 91 as[0].uuconf_itype = UUCONF_CMDTABTYPE_FN | 2; 92 as[0].uuconf_pvar = (pointer) &zport; 93 as[0].uuconf_pifn = ipport; 94 95 as[1].uuconf_zcmd = NULL; 96 97 pblock = uuconf_malloc_block (); 98 if (pblock == NULL) 99 { 100 qglobal->ierrno = errno; 101 iret = UUCONF_MALLOC_FAILED | UUCONF_ERROR_ERRNO; 102 break; 103 } 104 105 _uuconf_uclear_port (&sdefault); 106 sdefault.uuconf_palloc = pblock; 107 zport = NULL; 108 iret = uuconf_cmd_file (pglobal, e, as, (pointer) &sdefault, 109 ipunknown, UUCONF_CMDTABFLAG_BACKSLASH, 110 pblock); 111 if (iret != UUCONF_SUCCESS) 112 { 113 zfree = zport; 114 break; 115 } 116 117 /* Now skip until we find a port with a matching name. If the 118 zname argument is NULL, we will have to read every port. */ 119 iret = UUCONF_NOT_FOUND; 120 while (zport != NULL) 121 { 122 uuconf_cmdtabfn piunknown; 123 boolean fmatch; 124 125 if (zname == NULL || strcmp (zname, zport) == 0) 126 { 127 piunknown = ipunknown; 128 *qport = sdefault; 129 qport->uuconf_zname = zport; 130 zfree = zport; 131 fmatch = TRUE; 132 } 133 else 134 { 135 piunknown = NULL; 136 free ((pointer) zport); 137 fmatch = FALSE; 138 } 139 140 zport = NULL; 141 ilineno = qglobal->ilineno; 142 iret = uuconf_cmd_file (pglobal, e, as, (pointer) qport, 143 piunknown, UUCONF_CMDTABFLAG_BACKSLASH, 144 pblock); 145 qglobal->ilineno += ilineno; 146 if (iret != UUCONF_SUCCESS) 147 break; 148 iret = UUCONF_NOT_FOUND; 149 150 /* We may have just gathered information about a port. See 151 if it matches the name, the baud rate and the special 152 function. */ 153 if (fmatch) 154 { 155 if (ibaud != 0) 156 { 157 if (qport->uuconf_ttype == UUCONF_PORTTYPE_MODEM) 158 { 159 long imbaud, imhigh, imlow; 160 161 imbaud = qport->uuconf_u.uuconf_smodem.uuconf_ibaud; 162 imhigh = qport->uuconf_u.uuconf_smodem.uuconf_ihighbaud; 163 imlow = qport->uuconf_u.uuconf_smodem.uuconf_ilowbaud; 164 165 if (imbaud == 0 && imlow == 0) 166 ; 167 else if (ibaud <= imbaud && imbaud <= ihighbaud) 168 ; 169 else if (imlow != 0 170 && imlow <= ihighbaud 171 && imhigh >= ibaud) 172 ; 173 else 174 fmatch = FALSE; 175 } 176 else if (qport->uuconf_ttype == UUCONF_PORTTYPE_DIRECT) 177 { 178 long idbaud; 179 180 idbaud = qport->uuconf_u.uuconf_sdirect.uuconf_ibaud; 181 if (idbaud != 0 && idbaud != ibaud) 182 fmatch = FALSE; 183 } 184 } 185 } 186 187 if (fmatch) 188 { 189 if (pifn != NULL) 190 { 191 iret = (*pifn) (qport, pinfo); 192 if (iret == UUCONF_NOT_FOUND) 193 fmatch = FALSE; 194 else if (iret != UUCONF_SUCCESS) 195 break; 196 } 197 } 198 199 if (fmatch) 200 { 201 if (uuconf_add_block (pblock, zfree) == 0) 202 { 203 zfree = NULL; 204 iret = UUCONF_SUCCESS; 205 } 206 else 207 { 208 qglobal->ierrno = errno; 209 iret = UUCONF_MALLOC_FAILED | UUCONF_ERROR_ERRNO; 210 } 211 break; 212 } 213 214 if (zfree != NULL) 215 { 216 free ((pointer) zfree); 217 zfree = NULL; 218 } 219 } 220 221 (void) fclose (e); 222 e = NULL; 223 224 if (iret != UUCONF_NOT_FOUND) 225 break; 226 227 uuconf_free_block (pblock); 228 pblock = NULL; 229 } 230 231 if (e != NULL) 232 (void) fclose (e); 233 if (zfree != NULL) 234 free ((pointer) zfree); 235 if (iret != UUCONF_SUCCESS && pblock != NULL) 236 uuconf_free_block (pblock); 237 238 if (iret != UUCONF_SUCCESS && iret != UUCONF_NOT_FOUND) 239 { 240 qglobal->zfilename = *pz; 241 iret |= UUCONF_ERROR_FILENAME; 242 } 243 244 return iret; 245} 246 247/* Handle a "port" command. This copies the string onto the heap and 248 returns the pointer in *pvar. It returns UUCONF_CMDTABRET_EXIT to 249 force uuconf_cmd_file to stop reading and return to the code above, 250 which will then check the port just read to see if it matches. */ 251 252/*ARGSUSED*/ 253static int 254ipport (pglobal, argc, argv, pvar, pinfo) 255 pointer pglobal; 256 int argc ATTRIBUTE_UNUSED; 257 char **argv; 258 pointer pvar; 259 pointer pinfo ATTRIBUTE_UNUSED; 260{ 261 struct sglobal *qglobal = (struct sglobal *) pglobal; 262 char **pz = (char **) pvar; 263 size_t csize; 264 265 csize = strlen (argv[1]) + 1; 266 *pz = malloc (csize); 267 if (*pz == NULL) 268 { 269 qglobal->ierrno = errno; 270 return (UUCONF_MALLOC_FAILED 271 | UUCONF_ERROR_ERRNO 272 | UUCONF_CMDTABRET_EXIT); 273 } 274 memcpy ((pointer) *pz, (pointer) argv[1], csize); 275 return UUCONF_CMDTABRET_EXIT; 276} 277 278/* Handle an unknown command by passing it on to _uuconf_iport_cmd, 279 which will parse it into the port structure. */ 280 281/*ARGSUSED*/ 282static int 283ipunknown (pglobal, argc, argv, pvar, pinfo) 284 pointer pglobal; 285 int argc; 286 char **argv; 287 pointer pvar ATTRIBUTE_UNUSED; 288 pointer pinfo; 289{ 290 struct sglobal *qglobal = (struct sglobal *) pglobal; 291 struct uuconf_port *qport = (struct uuconf_port *) pinfo; 292 int iret; 293 294 iret = _uuconf_iport_cmd (qglobal, argc, argv, qport); 295 if (UUCONF_ERROR_VALUE (iret) != UUCONF_SUCCESS) 296 iret |= UUCONF_CMDTABRET_EXIT; 297 return iret; 298} 299