1/* tsinfo.c 2 Get information about a system from the Taylor UUCP configuration files. 3 4 Copyright (C) 1992, 1993, 1995, 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_tsinfo_rcsid[] = "$Id: tsinfo.c,v 1.21 2002/03/05 19:10:43 ian Rel $"; 29#endif 30 31#include <errno.h> 32#include <ctype.h> 33 34#ifndef SEEK_SET 35#define SEEK_SET 0 36#endif 37 38static void uiset_call P((struct uuconf_system *qsys)); 39static int iisizecmp P((long i1, long i2)); 40 41/* Local functions needed to parse the system information file. */ 42 43#define CMDTABFN(z) \ 44 static int z P((pointer, int, char **, pointer, pointer)) 45 46CMDTABFN (iisystem); 47CMDTABFN (iialias); 48CMDTABFN (iialternate); 49CMDTABFN (iidefault_alternates); 50CMDTABFN (iitime); 51CMDTABFN (iitimegrade); 52CMDTABFN (iisize); 53CMDTABFN (iibaud_range); 54CMDTABFN (iiport); 55CMDTABFN (iichat); 56CMDTABFN (iidebug); 57CMDTABFN (iicalled_login); 58CMDTABFN (iiproto_param); 59CMDTABFN (iirequest); 60CMDTABFN (iitransfer); 61CMDTABFN (iiforward); 62CMDTABFN (iiunknown); 63 64#undef CMDTABFN 65 66/* We have to pass a fair amount of information in and out of the 67 various system commands. Using global variables would make the 68 code non-reentrant, so we instead pass a pointer to single 69 structure as the pinfo argument to the system commands. */ 70 71struct sinfo 72{ 73 /* The system information we're building up. */ 74 struct uuconf_system *qsys; 75 /* Whether any alternates have been used. */ 76 boolean falternates; 77 /* A list of the previous alternates. */ 78 struct uuconf_system salternate; 79 /* Whether to use extra alternates from the file wide defaults. */ 80 int fdefault_alternates; 81}; 82 83/* The command table for system commands. */ 84static const struct cmdtab_offset asIcmds[] = 85{ 86 { "system", UUCONF_CMDTABTYPE_FN | 2, (size_t) -1, iisystem }, 87 { "alias", UUCONF_CMDTABTYPE_FN | 2, (size_t) -1, iialias }, 88 { "alternate", UUCONF_CMDTABTYPE_FN | 0, (size_t) -1, iialternate }, 89 { "default-alternates", UUCONF_CMDTABTYPE_FN | 2, (size_t) -1, 90 iidefault_alternates }, 91 { "time", UUCONF_CMDTABTYPE_FN | 0, 92 offsetof (struct uuconf_system, uuconf_qtimegrade), iitime }, 93 { "timegrade", UUCONF_CMDTABTYPE_FN | 0, 94 offsetof (struct uuconf_system, uuconf_qtimegrade), iitimegrade }, 95 { "max-retries", UUCONF_CMDTABTYPE_INT, 96 offsetof (struct uuconf_system, uuconf_cmax_retries), NULL }, 97 { "success-wait", UUCONF_CMDTABTYPE_INT, 98 offsetof (struct uuconf_system, uuconf_csuccess_wait), NULL }, 99 { "call-timegrade", UUCONF_CMDTABTYPE_FN | 3, 100 offsetof (struct uuconf_system, uuconf_qcalltimegrade), iitimegrade }, 101 { "called-timegrade", UUCONF_CMDTABTYPE_FN | 3, 102 offsetof (struct uuconf_system, uuconf_qcalledtimegrade), iitimegrade }, 103 { "call-local-size", UUCONF_CMDTABTYPE_FN | 3, 104 offsetof (struct uuconf_system, uuconf_qcall_local_size), iisize }, 105 { "call-remote-size", UUCONF_CMDTABTYPE_FN | 3, 106 offsetof (struct uuconf_system, uuconf_qcall_remote_size), iisize }, 107 { "called-local-size", UUCONF_CMDTABTYPE_FN | 3, 108 offsetof (struct uuconf_system, uuconf_qcalled_local_size), iisize }, 109 { "called-remote-size", UUCONF_CMDTABTYPE_FN | 3, 110 offsetof (struct uuconf_system, uuconf_qcalled_remote_size), iisize }, 111 { "timetable", UUCONF_CMDTABTYPE_FN | 3, (size_t) -1, _uuconf_itimetable }, 112 { "baud", UUCONF_CMDTABTYPE_LONG, 113 offsetof (struct uuconf_system, uuconf_ibaud), NULL }, 114 { "speed", UUCONF_CMDTABTYPE_LONG, 115 offsetof (struct uuconf_system, uuconf_ibaud), NULL }, 116 { "baud-range", UUCONF_CMDTABTYPE_FN | 3, 0, iibaud_range }, 117 { "speed-range", UUCONF_CMDTABTYPE_FN | 3, 0, iibaud_range }, 118 { "port", UUCONF_CMDTABTYPE_FN | 0, (size_t) -1, iiport }, 119 { "phone", UUCONF_CMDTABTYPE_STRING, 120 offsetof (struct uuconf_system, uuconf_zphone), NULL }, 121 { "address", UUCONF_CMDTABTYPE_STRING, 122 offsetof (struct uuconf_system, uuconf_zphone), NULL }, 123 { "chat", UUCONF_CMDTABTYPE_PREFIX | 0, 124 offsetof (struct uuconf_system, uuconf_schat), iichat }, 125 { "call-login", UUCONF_CMDTABTYPE_STRING, 126 offsetof (struct uuconf_system, uuconf_zcall_login), NULL }, 127 { "call-password", UUCONF_CMDTABTYPE_STRING, 128 offsetof (struct uuconf_system, uuconf_zcall_password), NULL }, 129 { "called-login", UUCONF_CMDTABTYPE_FN | 0, 130 offsetof (struct uuconf_system, uuconf_zcalled_login), iicalled_login }, 131 { "callback", UUCONF_CMDTABTYPE_BOOLEAN, 132 offsetof (struct uuconf_system, uuconf_fcallback), NULL }, 133 { "sequence", UUCONF_CMDTABTYPE_BOOLEAN, 134 offsetof (struct uuconf_system, uuconf_fsequence), NULL }, 135 { "protocol", UUCONF_CMDTABTYPE_STRING, 136 offsetof (struct uuconf_system, uuconf_zprotocols), NULL }, 137 { "protocol-parameter", UUCONF_CMDTABTYPE_FN | 0, 138 offsetof (struct uuconf_system, uuconf_qproto_params), iiproto_param }, 139 { "called-chat", UUCONF_CMDTABTYPE_PREFIX | 0, 140 offsetof (struct uuconf_system, uuconf_scalled_chat), iichat }, 141 { "debug", UUCONF_CMDTABTYPE_FN | 0, 142 offsetof (struct uuconf_system, uuconf_zdebug), iidebug }, 143 { "max-remote-debug", UUCONF_CMDTABTYPE_STRING, 144 offsetof (struct uuconf_system, uuconf_zmax_remote_debug), NULL }, 145 { "send-request", UUCONF_CMDTABTYPE_BOOLEAN, 146 offsetof (struct uuconf_system, uuconf_fsend_request), NULL }, 147 { "receive-request", UUCONF_CMDTABTYPE_BOOLEAN, 148 offsetof (struct uuconf_system, uuconf_frec_request), NULL }, 149 { "request", UUCONF_CMDTABTYPE_FN | 2, (size_t) -1, iirequest }, 150 { "call-transfer", UUCONF_CMDTABTYPE_BOOLEAN, 151 offsetof (struct uuconf_system, uuconf_fcall_transfer), NULL }, 152 { "called-transfer", UUCONF_CMDTABTYPE_BOOLEAN, 153 offsetof (struct uuconf_system, uuconf_fcalled_transfer), NULL }, 154 { "transfer", UUCONF_CMDTABTYPE_FN | 2, (size_t) -1, iitransfer }, 155 { "local-send", UUCONF_CMDTABTYPE_FULLSTRING, 156 offsetof (struct uuconf_system, uuconf_pzlocal_send), NULL }, 157 { "remote-send", UUCONF_CMDTABTYPE_FULLSTRING, 158 offsetof (struct uuconf_system, uuconf_pzremote_send), NULL }, 159 { "local-receive", UUCONF_CMDTABTYPE_FULLSTRING, 160 offsetof (struct uuconf_system, uuconf_pzlocal_receive), NULL }, 161 { "remote-receive", UUCONF_CMDTABTYPE_FULLSTRING, 162 offsetof (struct uuconf_system, uuconf_pzremote_receive), NULL }, 163 { "command-path", UUCONF_CMDTABTYPE_FULLSTRING, 164 offsetof (struct uuconf_system, uuconf_pzpath), NULL }, 165 { "commands", UUCONF_CMDTABTYPE_FULLSTRING, 166 offsetof (struct uuconf_system, uuconf_pzcmds), NULL }, 167 { "free-space", UUCONF_CMDTABTYPE_LONG, 168 offsetof (struct uuconf_system, uuconf_cfree_space), NULL }, 169 { "forward-from", UUCONF_CMDTABTYPE_FULLSTRING, 170 offsetof (struct uuconf_system, uuconf_pzforward_from), NULL }, 171 { "forward-to", UUCONF_CMDTABTYPE_FULLSTRING, 172 offsetof (struct uuconf_system, uuconf_pzforward_to), NULL }, 173 { "forward", UUCONF_CMDTABTYPE_FN | 0, (size_t) -1, iiforward }, 174 { "pubdir", UUCONF_CMDTABTYPE_STRING, 175 offsetof (struct uuconf_system, uuconf_zpubdir), NULL }, 176 { "myname", UUCONF_CMDTABTYPE_STRING, 177 offsetof (struct uuconf_system, uuconf_zlocalname), NULL }, 178 { "max-file-time", UUCONF_CMDTABTYPE_LONG, 179 offsetof (struct uuconf_system, uuconf_cmax_file_time), NULL }, 180 { NULL, 0, 0, NULL } 181}; 182 183#define CSYSTEM_CMDS (sizeof asIcmds / sizeof asIcmds[0]) 184 185/* Get information about the system zsystem from the Taylor UUCP 186 configuration files. Sets *qsys. This does not ensure that all 187 default information is set. */ 188 189int 190_uuconf_itaylor_system_internal (qglobal, zsystem, qsys) 191 struct sglobal *qglobal; 192 const char *zsystem; 193 struct uuconf_system *qsys; 194{ 195 int iret; 196 struct stsysloc *qloc; 197 struct uuconf_cmdtab as[CSYSTEM_CMDS]; 198 struct sinfo si; 199 struct uuconf_system sdefaults; 200 201 if (! qglobal->qprocess->fread_syslocs) 202 { 203 iret = _uuconf_iread_locations (qglobal); 204 if (iret != UUCONF_SUCCESS) 205 return iret; 206 } 207 208 /* Find the system in the list of locations. */ 209 for (qloc = qglobal->qprocess->qsyslocs; qloc != NULL; qloc = qloc->qnext) 210 if (qloc->zname[0] == zsystem[0] 211 && strcmp (qloc->zname, zsystem) == 0) 212 break; 213 if (qloc == NULL) 214 return UUCONF_NOT_FOUND; 215 216 /* If this is an alias, then the real system is the next non-alias 217 in the list. */ 218 while (qloc->falias) 219 { 220 qloc = qloc->qnext; 221 if (qloc == NULL) 222 return UUCONF_NOT_FOUND; 223 } 224 225 _uuconf_ucmdtab_base (asIcmds, CSYSTEM_CMDS, (char *) qsys, as); 226 227 rewind (qloc->e); 228 229 /* Read the file wide defaults from the start of the file. */ 230 _uuconf_uclear_system (qsys); 231 232 si.qsys = qsys; 233 si.falternates = FALSE; 234 si.fdefault_alternates = TRUE; 235 qsys->uuconf_palloc = uuconf_malloc_block (); 236 if (qsys->uuconf_palloc == NULL) 237 { 238 qglobal->ierrno = errno; 239 return UUCONF_MALLOC_FAILED | UUCONF_ERROR_ERRNO; 240 } 241 242 iret = uuconf_cmd_file ((pointer) qglobal, qloc->e, as, (pointer) &si, 243 iiunknown, UUCONF_CMDTABFLAG_BACKSLASH, 244 qsys->uuconf_palloc); 245 if (iret != UUCONF_SUCCESS) 246 { 247 qglobal->zfilename = qloc->zfile; 248 return iret | UUCONF_ERROR_FILENAME; 249 } 250 251 if (! si.falternates) 252 uiset_call (qsys); 253 else 254 { 255 /* Attach the final alternate. */ 256 iret = iialternate ((pointer) qglobal, 0, (char **) NULL, 257 (pointer) NULL, (pointer) &si); 258 if (iret != UUCONF_SUCCESS) 259 return iret; 260 } 261 262 /* Save off the defaults. */ 263 sdefaults = *qsys; 264 265 /* Advance to the information for the system we want. */ 266 if (fseek (qloc->e, qloc->iloc, SEEK_SET) != 0) 267 { 268 qglobal->ierrno = errno; 269 qglobal->zfilename = qloc->zfile; 270 return (UUCONF_FSEEK_FAILED 271 | UUCONF_ERROR_ERRNO 272 | UUCONF_ERROR_FILENAME); 273 } 274 275 /* Read in the system we want. */ 276 _uuconf_uclear_system (qsys); 277 qsys->uuconf_zname = (char *) qloc->zname; 278 qsys->uuconf_palloc = sdefaults.uuconf_palloc; 279 280 si.falternates = FALSE; 281 282 iret = uuconf_cmd_file (qglobal, qloc->e, as, (pointer) &si, iiunknown, 283 UUCONF_CMDTABFLAG_BACKSLASH, qsys->uuconf_palloc); 284 qglobal->ilineno += qloc->ilineno; 285 286 if (iret == UUCONF_SUCCESS) 287 { 288 if (! si.falternates) 289 uiset_call (qsys); 290 else 291 iret = iialternate ((pointer) qglobal, 0, (char **) NULL, 292 (pointer) NULL, (pointer) &si); 293 } 294 295 /* Merge in the defaults. */ 296 if (iret == UUCONF_SUCCESS) 297 iret = _uuconf_isystem_default (qglobal, qsys, &sdefaults, 298 si.fdefault_alternates); 299 300 /* The first alternate is always available for calling in. It is 301 always available for calling out if it has some way to choose a 302 port (this would normally be set by uiset_call anyhow, but it 303 won't be if all the port information comes from the defaults). */ 304 if (iret == UUCONF_SUCCESS) 305 { 306 qsys->uuconf_fcalled = TRUE; 307 if (qsys->uuconf_zport != (char *) &_uuconf_unset 308 || qsys->uuconf_qport != (struct uuconf_port *) &_uuconf_unset 309 || qsys->uuconf_ibaud >= 0 310 || qsys->uuconf_zphone != (char *) &_uuconf_unset) 311 qsys->uuconf_fcall = TRUE; 312 } 313 314 if (iret != UUCONF_SUCCESS) 315 { 316 qglobal->zfilename = qloc->zfile; 317 iret |= UUCONF_ERROR_FILENAME; 318 } 319 320 return iret; 321} 322 323/* Set the fcall and fcalled field for the system. This marks a 324 particular alternate for use when calling out or calling in. This 325 is where we implement the semantics described in the documentation: 326 a change to a relevant field implies that the alternate is used. 327 If all the relevant fields are unchanged, the alternate is not 328 used. */ 329 330static void 331uiset_call (qsys) 332 struct uuconf_system *qsys; 333{ 334 qsys->uuconf_fcall = 335 (qsys->uuconf_qtimegrade != (struct uuconf_timespan *) &_uuconf_unset 336 || qsys->uuconf_zport != (char *) &_uuconf_unset 337 || qsys->uuconf_qport != (struct uuconf_port *) &_uuconf_unset 338 || qsys->uuconf_ibaud >= 0 339 || qsys->uuconf_zphone != (char *) &_uuconf_unset 340 || qsys->uuconf_schat.uuconf_pzchat != (char **) &_uuconf_unset 341 || qsys->uuconf_schat.uuconf_pzprogram != (char **) &_uuconf_unset); 342 343 qsys->uuconf_fcalled = 344 qsys->uuconf_zcalled_login != (char *) &_uuconf_unset; 345} 346 347/* Handle the "system" command. Because we skip directly to the 348 system we want to read, a "system" command means we've reached the 349 end of it. */ 350 351static int 352iisystem (pglobal, argc, argv, pvar, pinfo) 353 pointer pglobal ATTRIBUTE_UNUSED; 354 int argc ATTRIBUTE_UNUSED; 355 char **argv ATTRIBUTE_UNUSED; 356 pointer pvar ATTRIBUTE_UNUSED; 357 pointer pinfo ATTRIBUTE_UNUSED; 358{ 359 return UUCONF_CMDTABRET_EXIT; 360} 361 362/* Handle the "alias" command. */ 363 364/*ARGSUSED*/ 365static int 366iialias (pglobal, argc, argv, pvar, pinfo) 367 pointer pglobal; 368 int argc ATTRIBUTE_UNUSED; 369 char **argv; 370 pointer pvar ATTRIBUTE_UNUSED; 371 pointer pinfo; 372{ 373 struct sglobal *qglobal = (struct sglobal *) pglobal; 374 struct sinfo *qinfo = (struct sinfo *) pinfo; 375 int iret; 376 377 iret = _uuconf_iadd_string (qglobal, argv[1], TRUE, FALSE, 378 &qinfo->qsys->uuconf_pzalias, 379 qinfo->qsys->uuconf_palloc); 380 if (iret != UUCONF_SUCCESS) 381 iret |= UUCONF_CMDTABRET_EXIT; 382 return iret; 383} 384 385/* Handle the "alternate" command. The information just read is in 386 sIhold. If this is the first "alternate" command for this system, 387 we save off the current information in sIalternate. Otherwise we 388 default this information to sIalternate, and then add it to the end 389 of the list of alternates in sIalternate. */ 390 391static int 392iialternate (pglobal, argc, argv, pvar, pinfo) 393 pointer pglobal; 394 int argc; 395 char **argv; 396 pointer pvar ATTRIBUTE_UNUSED; 397 pointer pinfo; 398{ 399 struct sglobal *qglobal = (struct sglobal *) pglobal; 400 struct sinfo *qinfo = (struct sinfo *) pinfo; 401 402 uiset_call (qinfo->qsys); 403 404 if (! qinfo->falternates) 405 { 406 qinfo->salternate = *qinfo->qsys; 407 qinfo->falternates = TRUE; 408 } 409 else 410 { 411 int iret; 412 struct uuconf_system *qnew, **pq; 413 414 iret = _uuconf_isystem_default (qglobal, qinfo->qsys, 415 &qinfo->salternate, FALSE); 416 if (iret != UUCONF_SUCCESS) 417 return iret | UUCONF_CMDTABRET_EXIT; 418 qnew = ((struct uuconf_system *) 419 uuconf_malloc (qinfo->qsys->uuconf_palloc, 420 sizeof (struct uuconf_system))); 421 if (qnew == NULL) 422 { 423 qglobal->ierrno = errno;; 424 return (UUCONF_MALLOC_FAILED 425 | UUCONF_ERROR_ERRNO 426 | UUCONF_CMDTABRET_EXIT); 427 } 428 *qnew = *qinfo->qsys; 429 for (pq = &qinfo->salternate.uuconf_qalternate; 430 *pq != NULL; 431 pq = &(*pq)->uuconf_qalternate) 432 ; 433 *pq = qnew; 434 } 435 436 /* If this is the last alternate command, move the information back 437 to qinfo->qsys. */ 438 if (argc == 0) 439 *qinfo->qsys = qinfo->salternate; 440 else 441 { 442 _uuconf_uclear_system (qinfo->qsys); 443 qinfo->qsys->uuconf_zname = qinfo->salternate.uuconf_zname; 444 qinfo->qsys->uuconf_palloc = qinfo->salternate.uuconf_palloc; 445 if (argc > 1) 446 { 447 qinfo->qsys->uuconf_zalternate = argv[1]; 448 return UUCONF_CMDTABRET_KEEP; 449 } 450 } 451 452 return UUCONF_CMDTABRET_CONTINUE; 453} 454 455/* Handle the "default-alternates" command. This just takes a boolean 456 argument which is used to set the fdefault_alternates field of the 457 sinfo structure. */ 458 459/*ARGSUSED*/ 460static int 461iidefault_alternates (pglobal, argc, argv, pvar, pinfo) 462 pointer pglobal; 463 int argc ATTRIBUTE_UNUSED; 464 char **argv; 465 pointer pvar ATTRIBUTE_UNUSED; 466 pointer pinfo; 467{ 468 struct sglobal *qglobal = (struct sglobal *) pglobal; 469 struct sinfo *qinfo = (struct sinfo *) pinfo; 470 471 return _uuconf_iboolean (qglobal, argv[1], &qinfo->fdefault_alternates); 472} 473 474/* Handle the "time" command. We do this by turning it into a 475 "timegrade" command with a grade of BGRADE_LOW. The first argument 476 is a time string, and the optional second argument is the retry 477 time. */ 478 479/*ARGSUSED*/ 480static int 481iitime (pglobal, argc, argv, pvar, pinfo) 482 pointer pglobal; 483 int argc; 484 char **argv; 485 pointer pvar; 486 pointer pinfo; 487{ 488 char *aznew[4]; 489 char ab[2]; 490 491 if (argc != 2 && argc != 3) 492 return UUCONF_SYNTAX_ERROR | UUCONF_CMDTABRET_EXIT; 493 494 aznew[0] = argv[0]; 495 ab[0] = UUCONF_GRADE_LOW; 496 ab[1] = '\0'; 497 aznew[1] = ab; 498 aznew[2] = argv[1]; 499 if (argc > 2) 500 aznew[3] = argv[2]; 501 502 return iitimegrade (pglobal, argc + 1, aznew, pvar, pinfo); 503} 504 505/* Handle the "timegrade" command by calling _uuconf_itime_parse with 506 appropriate ival (the work grade) and cretry (the retry time) 507 arguments. */ 508 509static int 510iitimegrade (pglobal, argc, argv, pvar, pinfo) 511 pointer pglobal; 512 int argc; 513 char **argv; 514 pointer pvar; 515 pointer pinfo; 516{ 517 struct sglobal *qglobal = (struct sglobal *) pglobal; 518 struct uuconf_timespan **pqspan = (struct uuconf_timespan **) pvar; 519 struct sinfo *qinfo = (struct sinfo *) pinfo; 520 int cretry; 521 int iret; 522 523 if (argc < 3 || argc > 4) 524 return UUCONF_SYNTAX_ERROR | UUCONF_CMDTABRET_EXIT; 525 526 if (argv[1][1] != '\0' || ! UUCONF_GRADE_LEGAL (argv[1][0])) 527 return UUCONF_SYNTAX_ERROR | UUCONF_CMDTABRET_EXIT; 528 529 if (argc == 3) 530 cretry = 0; 531 else 532 { 533 iret = _uuconf_iint (qglobal, argv[3], (pointer) &cretry, TRUE); 534 if (iret != UUCONF_SUCCESS) 535 return iret; 536 } 537 538 iret = _uuconf_itime_parse (qglobal, argv[2], (long) argv[1][0], 539 cretry, _uuconf_itime_grade_cmp, pqspan, 540 qinfo->qsys->uuconf_palloc); 541 if (iret != UUCONF_SUCCESS) 542 iret |= UUCONF_CMDTABRET_EXIT; 543 return iret; 544} 545 546/* Handle the "baud-range" command, also known as "speed-range". */ 547 548static int 549iibaud_range (pglobal, argc, argv, pvar, pinfo) 550 pointer pglobal; 551 int argc ATTRIBUTE_UNUSED; 552 char **argv; 553 pointer pvar; 554 pointer pinfo ATTRIBUTE_UNUSED; 555{ 556 struct sglobal *qglobal = (struct sglobal *) pglobal; 557 struct uuconf_system *qsys = (struct uuconf_system *) pvar; 558 int iret; 559 560 iret = _uuconf_iint (qglobal, argv[1], (pointer) &qsys->uuconf_ibaud, 561 FALSE); 562 if (iret != UUCONF_SUCCESS) 563 return iret; 564 return _uuconf_iint (qglobal, argv[2], (pointer) &qsys->uuconf_ihighbaud, 565 FALSE); 566} 567 568/* Handle one of the size commands ("call-local-size", etc.). The 569 first argument is a number of bytes, and the second argument is a 570 time string. The pvar argument points to the string array to which 571 we add this new string. */ 572 573/*ARGSUSED*/ 574static int 575iisize (pglobal, argc, argv, pvar, pinfo) 576 pointer pglobal; 577 int argc ATTRIBUTE_UNUSED; 578 char **argv; 579 pointer pvar; 580 pointer pinfo; 581{ 582 struct sglobal *qglobal = (struct sglobal *) pglobal; 583 struct uuconf_timespan **pqspan = (struct uuconf_timespan **) pvar; 584 struct sinfo *qinfo = (struct sinfo *) pinfo; 585 long ival; 586 int iret; 587 588 iret = _uuconf_iint (qglobal, argv[1], (pointer) &ival, FALSE); 589 if (iret != UUCONF_SUCCESS) 590 return iret; 591 592 iret = _uuconf_itime_parse (qglobal, argv[2], ival, 0, iisizecmp, 593 pqspan, qinfo->qsys->uuconf_palloc); 594 if (iret != UUCONF_SUCCESS) 595 iret |= UUCONF_CMDTABRET_EXIT; 596 return iret; 597} 598 599/* A comparison function for sizes to pass to _uuconf_itime_parse. */ 600 601static int 602iisizecmp (i1, i2) 603 long i1; 604 long i2; 605{ 606 /* We can't just return i1 - i2 because that would be a long. */ 607 if (i1 < i2) 608 return -1; 609 else if (i1 == i2) 610 return 0; 611 else 612 return 1; 613} 614 615/* Handle the "port" command. If there is one argument, this names a 616 port. Otherwise, the remaining arguments form a command describing 617 the port. */ 618 619/*ARGSUSED*/ 620static int 621iiport (pglobal, argc, argv, pvar, pinfo) 622 pointer pglobal; 623 int argc; 624 char **argv; 625 pointer pvar ATTRIBUTE_UNUSED; 626 pointer pinfo; 627{ 628 struct sglobal *qglobal = (struct sglobal *) pglobal; 629 struct sinfo *qinfo = (struct sinfo *) pinfo; 630 631 if (argc < 2) 632 return UUCONF_SYNTAX_ERROR | UUCONF_CMDTABRET_EXIT; 633 else if (argc == 2) 634 { 635 qinfo->qsys->uuconf_zport = argv[1]; 636 return UUCONF_CMDTABRET_KEEP; 637 } 638 else 639 { 640 int iret; 641 642 if (qinfo->qsys->uuconf_qport 643 == (struct uuconf_port *) &_uuconf_unset) 644 { 645 struct uuconf_port *qnew; 646 647 qnew = ((struct uuconf_port *) 648 uuconf_malloc (qinfo->qsys->uuconf_palloc, 649 sizeof (struct uuconf_port))); 650 if (qnew == NULL) 651 { 652 qglobal->ierrno = errno; 653 return (UUCONF_MALLOC_FAILED 654 | UUCONF_ERROR_ERRNO 655 | UUCONF_CMDTABRET_EXIT); 656 } 657 658 _uuconf_uclear_port (qnew); 659 660 if (qinfo->qsys->uuconf_zname == NULL) 661 qnew->uuconf_zname = (char *) "default system file port"; 662 else 663 { 664 char *zname; 665 size_t clen; 666 667 clen = strlen (qinfo->qsys->uuconf_zname); 668 zname = (char *) uuconf_malloc (qinfo->qsys->uuconf_palloc, 669 clen + sizeof "system port"); 670 if (zname == NULL) 671 { 672 qglobal->ierrno = errno; 673 return (UUCONF_MALLOC_FAILED 674 | UUCONF_ERROR_ERRNO 675 | UUCONF_CMDTABRET_EXIT); 676 } 677 678 memcpy ((pointer) zname, (pointer) "system ", 679 sizeof "system " - 1); 680 memcpy ((pointer) (zname + sizeof "system " - 1), 681 (pointer) qinfo->qsys->uuconf_zname, 682 clen); 683 memcpy ((pointer) (zname + sizeof "system " - 1 + clen), 684 (pointer) " port", sizeof " port"); 685 686 qnew->uuconf_zname = zname; 687 } 688 689 qnew->uuconf_palloc = qinfo->qsys->uuconf_palloc; 690 691 qinfo->qsys->uuconf_qport = qnew; 692 } 693 694 iret = _uuconf_iport_cmd (qglobal, argc - 1, argv + 1, 695 qinfo->qsys->uuconf_qport); 696 if (UUCONF_ERROR_VALUE (iret) != UUCONF_SUCCESS) 697 iret |= UUCONF_CMDTABRET_EXIT; 698 return iret; 699 } 700} 701 702/* Handle the "chat" and "called-chat" set of commands. These just 703 hand off to the generic chat script function. */ 704 705static int 706iichat (pglobal, argc, argv, pvar, pinfo) 707 pointer pglobal; 708 int argc; 709 char **argv; 710 pointer pvar; 711 pointer pinfo; 712{ 713 struct sglobal *qglobal = (struct sglobal *) pglobal; 714 struct sinfo *qinfo = (struct sinfo *) pinfo; 715 struct uuconf_chat *qchat = (struct uuconf_chat *) pvar; 716 int iret; 717 718 iret = _uuconf_ichat_cmd (qglobal, argc, argv, qchat, 719 qinfo->qsys->uuconf_palloc); 720 if (UUCONF_ERROR_VALUE (iret) != UUCONF_SUCCESS) 721 iret |= UUCONF_CMDTABRET_EXIT; 722 return iret; 723} 724 725/* Local interface to the _uuconf_idebug_cmd function, which handles 726 the "debug" command. */ 727 728static int 729iidebug (pglobal, argc, argv, pvar, pinfo) 730 pointer pglobal; 731 int argc; 732 char **argv; 733 pointer pvar; 734 pointer pinfo; 735{ 736 struct sglobal *qglobal = (struct sglobal *) pglobal; 737 struct sinfo *qinfo = (struct sinfo *) pinfo; 738 char **pzdebug = (char **) pvar; 739 740 return _uuconf_idebug_cmd (qglobal, pzdebug, argc, argv, 741 qinfo->qsys->uuconf_palloc); 742} 743 744/* Handle the "called-login" command. This only needs to be in a 745 function because there can be additional arguments listing the 746 remote systems which are permitted to use this login name. The 747 additional arguments are not actually handled here; they are 748 handled by uuconf_taylor_system_names, which already has to go 749 through all the system files. */ 750 751/*ARGSUSED*/ 752static int 753iicalled_login (pglobal, argc, argv, pvar, pinfo) 754 pointer pglobal ATTRIBUTE_UNUSED; 755 int argc; 756 char **argv; 757 pointer pvar; 758 pointer pinfo ATTRIBUTE_UNUSED; 759{ 760 char **pz = (char **) pvar; 761 762 if (argc < 2) 763 return UUCONF_SYNTAX_ERROR | UUCONF_CMDTABRET_EXIT; 764 *pz = argv[1]; 765 return UUCONF_CMDTABRET_KEEP; 766} 767 768/* Handle the "protocol-parameter" command. This just hands off to 769 the generic protocol parameter handler. */ 770 771static int 772iiproto_param (pglobal, argc, argv, pvar, pinfo) 773 pointer pglobal; 774 int argc; 775 char **argv; 776 pointer pvar; 777 pointer pinfo; 778{ 779 struct sglobal *qglobal = (struct sglobal *) pglobal; 780 struct uuconf_proto_param **pqparam = (struct uuconf_proto_param **) pvar; 781 struct sinfo *qinfo = (struct sinfo *) pinfo; 782 783 if (*pqparam == (struct uuconf_proto_param *) &_uuconf_unset) 784 *pqparam = NULL; 785 return _uuconf_iadd_proto_param (qglobal, argc - 1, argv + 1, pqparam, 786 qinfo->qsys->uuconf_palloc); 787} 788 789/* Handle the "request" command. This is equivalent to specifying 790 both "call-request" and "called-request". */ 791 792/*ARGSUSED*/ 793static int 794iirequest (pglobal, argc, argv, pvar, pinfo) 795 pointer pglobal; 796 int argc ATTRIBUTE_UNUSED; 797 char **argv; 798 pointer pvar ATTRIBUTE_UNUSED; 799 pointer pinfo; 800{ 801 struct sglobal *qglobal = (struct sglobal *) pglobal; 802 struct sinfo *qinfo = (struct sinfo *) pinfo; 803 int iret; 804 805 iret = _uuconf_iboolean (qglobal, argv[1], 806 &qinfo->qsys->uuconf_fsend_request); 807 if (UUCONF_ERROR_VALUE (iret) == UUCONF_SUCCESS) 808 qinfo->qsys->uuconf_frec_request = qinfo->qsys->uuconf_fsend_request; 809 810 return iret; 811} 812 813/* Handle the "transfer" command. This is equivalent to specifying 814 both "call-transfer" and "called-transfer". */ 815 816/*ARGSUSED*/ 817static int 818iitransfer (pglobal, argc, argv, pvar, pinfo) 819 pointer pglobal; 820 int argc ATTRIBUTE_UNUSED; 821 char **argv; 822 pointer pvar ATTRIBUTE_UNUSED; 823 pointer pinfo; 824{ 825 struct sglobal *qglobal = (struct sglobal *) pglobal; 826 struct sinfo *qinfo = (struct sinfo *) pinfo; 827 int iret; 828 829 iret = _uuconf_iboolean (qglobal, argv[1], 830 &qinfo->qsys->uuconf_fcall_transfer); 831 if (UUCONF_ERROR_VALUE (iret) == UUCONF_SUCCESS) 832 qinfo->qsys->uuconf_fcalled_transfer = qinfo->qsys->uuconf_fcall_transfer; 833 834 return iret; 835} 836 837/* Handle the "forward" command. This is equivalent to specifying 838 both "forward-from" and "forward-to". */ 839 840/*ARGSUSED*/ 841static int 842iiforward (pglobal, argc, argv, pvar, pinfo) 843 pointer pglobal; 844 int argc; 845 char **argv; 846 pointer pvar ATTRIBUTE_UNUSED; 847 pointer pinfo; 848{ 849 struct sglobal *qglobal = (struct sglobal *) pglobal; 850 struct sinfo *qinfo = (struct sinfo *) pinfo; 851 struct uuconf_system *qsys; 852 int i; 853 int iret; 854 855 qsys = qinfo->qsys; 856 qsys->uuconf_pzforward_from = NULL; 857 qsys->uuconf_pzforward_to = NULL; 858 for (i = 1; i < argc; i++) 859 { 860 iret = _uuconf_iadd_string (qglobal, argv[i], FALSE, FALSE, 861 &qsys->uuconf_pzforward_to, 862 qsys->uuconf_palloc); 863 if (iret != UUCONF_SUCCESS) 864 return iret | UUCONF_CMDTABRET_KEEP | UUCONF_CMDTABRET_EXIT; 865 iret = _uuconf_iadd_string (qglobal, argv[i], FALSE, FALSE, 866 &qsys->uuconf_pzforward_from, 867 qsys->uuconf_palloc); 868 if (iret != UUCONF_SUCCESS) 869 return iret | UUCONF_CMDTABRET_KEEP | UUCONF_CMDTABRET_EXIT; 870 } 871 872 return UUCONF_CMDTABRET_KEEP; 873} 874 875/* Handle an unknown command. This should probably be done more 876 intelligently. */ 877 878/*ARGSUSED*/ 879static int 880iiunknown (pglobal, argc, argv, pvar, pinfo) 881 pointer pglobal ATTRIBUTE_UNUSED; 882 int argc ATTRIBUTE_UNUSED; 883 char **argv ATTRIBUTE_UNUSED; 884 pointer pvar ATTRIBUTE_UNUSED; 885 pointer pinfo ATTRIBUTE_UNUSED; 886{ 887 return UUCONF_SYNTAX_ERROR | UUCONF_CMDTABRET_EXIT; 888} 889 890/* Return information for an unknown system. It would be better to 891 put this in a different file, but it would require breaking several 892 functions out of this file. Perhaps I will do it sometime. */ 893 894int 895uuconf_taylor_system_unknown (pglobal, qsys) 896 pointer pglobal; 897 struct uuconf_system *qsys; 898{ 899 struct sglobal *qglobal = (struct sglobal *) pglobal; 900 struct uuconf_cmdtab as[CSYSTEM_CMDS]; 901 struct sinfo si; 902 struct sunknown *q; 903 int iret; 904 905 if (qglobal->qprocess->qunknown == NULL) 906 return UUCONF_NOT_FOUND; 907 908 _uuconf_ucmdtab_base (asIcmds, CSYSTEM_CMDS, (char *) qsys, as); 909 910 _uuconf_uclear_system (qsys); 911 912 si.qsys = qsys; 913 si.falternates = FALSE; 914 si.fdefault_alternates = TRUE; 915 qsys->uuconf_palloc = uuconf_malloc_block (); 916 if (qsys->uuconf_palloc == NULL) 917 { 918 qglobal->ierrno = errno; 919 return UUCONF_MALLOC_FAILED | UUCONF_ERROR_ERRNO; 920 } 921 922 for (q = qglobal->qprocess->qunknown; q != NULL; q = q->qnext) 923 { 924 iret = uuconf_cmd_args (pglobal, q->cargs, q->pzargs, as, 925 (pointer) &si, iiunknown, 926 UUCONF_CMDTABFLAG_BACKSLASH, 927 qsys->uuconf_palloc); 928 iret &=~ UUCONF_CMDTABRET_KEEP; 929 if (UUCONF_ERROR_VALUE (iret) != UUCONF_SUCCESS) 930 { 931 qglobal->zfilename = qglobal->qprocess->zconfigfile; 932 qglobal->ilineno = q->ilineno; 933 return ((iret &~ UUCONF_CMDTABRET_EXIT) 934 | UUCONF_ERROR_FILENAME 935 | UUCONF_ERROR_LINENO); 936 } 937 if ((iret & UUCONF_CMDTABRET_EXIT) != 0) 938 break; 939 } 940 941 if (! si.falternates) 942 uiset_call (qsys); 943 else 944 { 945 iret = iialternate (pglobal, 0, (char **) NULL, (pointer) NULL, 946 (pointer) &si); 947 if (iret != UUCONF_SUCCESS) 948 return iret; 949 } 950 951 /* The first alternate is always available for calling in. */ 952 qsys->uuconf_fcalled = TRUE; 953 954 return _uuconf_isystem_basic_default (qglobal, qsys); 955} 956