/* bnu.c Read BNU configuration files. Copyright (C) 1991, 1992 Ian Lance Taylor This file is part of the Taylor UUCP package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. The author of the program may be contacted at ian@airs.com or c/o AIRS, P.O. Box 520, Waltham, MA 02254. $Log: bnu.c,v $ Revision 1.1.1.1 1993/03/21 09:45:37 cgd initial import of 386bsd-0.1 sources Revision 1.35 1992/04/06 19:49:49 ian Erik Forsberg: support multiple character modem classes Revision 1.34 1992/03/15 05:21:12 ian Scott Ballantyne: accept "Any" as a device speed Revision 1.33 1992/03/12 19:56:10 ian Debugging based on types rather than number Revision 1.32 1992/03/11 22:06:37 ian Marty Shannon: added max-uuxqts command Revision 1.31 1992/03/10 21:47:39 ian Added protocol command for ports Revision 1.30 1992/02/24 20:36:27 ian Roberto Biancardi: skip spaces after strtok (NULL, "") Revision 1.29 1992/02/24 04:58:47 ian Only permit files to be received into directories that are world-writeable Revision 1.28 1992/02/24 04:02:45 ian Doug Evans: WRITE only applies to remote requests Revision 1.27 1992/02/23 19:50:50 ian Handle READ and WRITE in Permissions correctly Revision 1.26 1992/02/14 16:45:09 ian This time for sure Revision 1.25 1992/02/14 16:43:07 ian Make the last patch better Revision 1.24 1992/02/14 16:39:31 ian T. William Wells: must xstrdup before calling uadd_validate Revision 1.23 1992/02/08 03:54:18 ian Include only in , added 1992 copyright Revision 1.22 1992/01/30 23:18:59 ian Michael Nolan: stupid error in ubadd_perm Revision 1.21 1992/01/15 07:06:29 ian Set configuration directory in Makefile rather than sysdep.h Revision 1.20 1991/12/28 03:49:23 ian Added HAVE_MEMFNS and HAVE_BFNS; changed uses of memset to bzero Revision 1.19 1991/12/17 23:14:08 ian T. William Wells: allow dialer complete and abort to be chat scripts Revision 1.18 1991/12/16 16:25:57 ian Mike Bernson: ignore lines beginning with whitespace Revision 1.17 1991/12/15 03:42:33 ian Added tprocess_chat_cmd for all chat commands, and added CMDTABTYPE_PREFIX Revision 1.16 1991/12/09 19:20:51 ian Arne Ludwig: devices entry can be followed by list of protocols Revision 1.15 1991/12/03 03:43:36 ian Dave Buck: time strings with grades were not parsed correctly Revision 1.14 1991/12/01 19:35:38 ian David Nugent: read V2 and BNU files by default even with TAYLOR_CONFIG Revision 1.13 1991/12/01 03:10:36 ian Niels Baggesen: accept dialers with no substitutions Revision 1.12 1991/12/01 03:04:20 ian Niels Baggesen: don't free up zline in ubadd_perm; don't even pass it in Revision 1.11 1991/12/01 02:44:12 ian Niels Baggesen: didn't handle combinations of multiple MACHINE/LOGNAME Revision 1.10 1991/12/01 02:31:36 ian Made zread and zwrite fields of sperm structure const char * Revision 1.9 1991/11/30 23:39:37 ian Marty Shannon: allow comments in Sysfiles Revision 1.8 1991/11/30 22:39:39 ian Marty Shannon: don't initialize an auto array Revision 1.7 1991/11/26 01:04:04 ian Marty Shannon: initialize ireliable for BNU and V2 configuration files Revision 1.6 1991/11/13 20:38:00 ian Added TCP port type for connections over TCP Revision 1.5 1991/11/11 23:47:24 ian Added chat-program to run a program to do a chat script Revision 1.4 1991/11/11 16:59:05 ian Eliminate fread_port_info, allow NULL pflock arg to ffind_port Revision 1.3 1991/11/07 18:26:13 ian Chip Salzenberg: can't portably take address of casted value, obviously Revision 1.2 1991/09/19 02:22:44 ian Chip Salzenberg's patch to allow ";retrytime" at the end of a time string Revision 1.1 1991/09/10 19:37:52 ian Initial revision */ #include "uucp.h" #if HAVE_BNU_CONFIG #if USE_RCS_ID char bnu_rcsid[] = "$Id: bnu.c,v 1.1.1.1 1993/03/21 09:45:37 cgd Exp $"; #endif #include #include "port.h" #include "sysdep.h" /* Whether to use BNU configuration files. */ boolean fBnu = TRUE; /* A list of space separated file names to interpret as Systems. */ char *zBnu_systems; /* A list of space separated file names to interpret as Dialers. */ char *zBnu_dialers; /* A list of space separated file names to interpret as Devices. */ char *zBnu_devices; /* Local functions. */ static void ubadd_perm P((int csystems, struct ssysteminfo *passystems, boolean **paffound)); static void ubadd_perm_alternate P((struct ssysteminfo *q, boolean fmachine, boolean flogname)); /* Read Sysfiles to get the file names to use. */ void ubnu_read_sysfiles () { char ab[sizeof OLDCONFIGLIB + sizeof BNU_SYSFILES - 1]; FILE *e; char *zline; zBnu_systems = NULL; zBnu_dialers = NULL; zBnu_devices = NULL; sprintf (ab, "%s%s", OLDCONFIGLIB, BNU_SYSFILES); e = fopen (ab, "r"); if (e != NULL) { while ((zline = zfgets (e, TRUE)) != NULL) { int inl; char *ztok; inl = strlen (zline) - 1; if (zline[inl] == '\n') zline[inl] = '\0'; if (isspace (BUCHAR (zline[0])) || zline[0] == '#') { xfree ((pointer) zline); continue; } ztok = strtok (zline, " \t"); if (ztok == NULL) { xfree ((pointer) zline); continue; } if (strncmp (ztok, "service=", sizeof "service=" - 1) != 0) { ulog (LOG_ERROR, "Unrecognized Sysfiles line: %s", ztok); xfree ((pointer) zline); continue; } do { int c; c = strcspn (ztok, ":"); if (c == sizeof "uucico" - 1 && strncmp (ztok, "uucico", sizeof "uucico" - 1) == 0) break; ztok += c; if (*ztok == ':') ++ztok; } while (*ztok != '\0'); if (*ztok == '\0') { xfree ((pointer) zline); continue; } while ((ztok = strtok ((char *) NULL, " \t")) != NULL) { char **pz; char *z; boolean fend; if (strncmp (ztok, "systems=", sizeof "systems=" - 1) == 0) { pz = &zBnu_systems; ztok += sizeof "systems=" - 1; } else if (strncmp (ztok, "dialers=", sizeof "dialers=" - 1) == 0) { pz = &zBnu_dialers; ztok += sizeof "dialers=" - 1; } else if (strncmp (ztok, "devices=", sizeof "devices=" - 1) == 0) { pz = &zBnu_devices; ztok += sizeof "devices=" - 1; } else { ulog (LOG_ERROR, "Unrecognized Sysfiles command: %s", ztok); continue; } /* Stick the configuration file directory in front of each file. */ z = ztok; do { int c; c = strcspn (z, ":"); fend = z[c] == '\0'; z[c] = '\0'; /* Looking for a leading '/' is Unix dependent, and should be changed. */ if (*z == '/') uadd_string (pz, z, ' '); else { char *zdir; zdir = (char *) xmalloc (sizeof OLDCONFIGLIB + strlen (z)); sprintf (zdir, "%s%s", OLDCONFIGLIB, z); uadd_string (pz, zdir, ' '); xfree ((pointer) zdir); } z += c + 1; } while (! fend); } xfree ((pointer) zline); } (void) fclose (e); } if (zBnu_systems == NULL) { zBnu_systems = (char *) xmalloc (sizeof OLDCONFIGLIB + sizeof BNU_SYSTEMS - 1); sprintf (zBnu_systems, "%s%s", OLDCONFIGLIB, BNU_SYSTEMS); } if (zBnu_dialers == NULL) { zBnu_dialers = (char *) xmalloc (sizeof OLDCONFIGLIB + sizeof BNU_DIALERS - 1); sprintf (zBnu_dialers, "%s%s", OLDCONFIGLIB, BNU_DIALERS); } if (zBnu_devices == NULL) { zBnu_devices = (char *) xmalloc (sizeof OLDCONFIGLIB + sizeof BNU_DEVICES - 1); sprintf (zBnu_devices, "%s%s", OLDCONFIGLIB, BNU_DEVICES); } #if ! HAVE_TAYLOR_CONFIG /* If we are NOT reading the new configuration files, then look for Maxuuxqts. It would be more efficient to only read the file in uuxqt.c. Too bad. */ { char *zmax; zmax = (char *) alloca (sizeof OLDCONFIGLIB + sizeof BNU_MAXUUXQTS - 1); sprintf (zmax, "%s%s", OLDCONFIGLIB, BNU_MAXUUXQTS); e = fopen (zmax, "r"); if (e != NULL) { zline = zfgets (e, FALSE); if (zline != NULL) { cMaxuuxqts = atoi (zline); if (cMaxuuxqts < 0) cMaxuuxqts = 0; xfree ((pointer) zline); } (void) fclose (e); } } #endif /* ! HAVE_TAYLOR_CONFIG */ } /* A little routine to add a grade and a time string to a system. */ static void ubadd_time P((struct ssysteminfo *q, int bgrade, const char *ztime, int cretry)); static void ubadd_time (q, bgrade, ztime, cretry) struct ssysteminfo *q; int bgrade; const char *ztime; int cretry; { char *zset; zset = (char *) alloca (strlen (ztime) + 20); if (cretry == 0) sprintf (zset, "%c%s", bgrade, ztime); else sprintf (zset, "%c%s;%d", bgrade, ztime, cretry); uadd_string (&q->ztime, zset, ' '); } /* These structures are used to read the Permissions file. */ static struct sperm { char *zlogname; char *zmachine; boolean frequest; enum { SENDFILES_YES, SENDFILES_CALL, SENDFILES_NO } tsendfiles; const char *zread; const char *zwrite; char *znoread; char *znowrite; boolean fcallback; const char *zcommands; char *zvalidate; char *zmyname; char *zpubdir; } sBperm; static enum tcmdtabret tbsendfiles P((int argc, char **argv, pointer pvar, const char *zerr)); static struct scmdtab asBperm_cmds[] = { { "LOGNAME", CMDTABTYPE_STRING, (pointer) &sBperm.zlogname, NULL }, { "MACHINE", CMDTABTYPE_STRING, (pointer) &sBperm.zmachine, NULL }, { "REQUEST", CMDTABTYPE_BOOLEAN, (pointer) &sBperm.frequest, NULL }, { "SENDFILES", CMDTABTYPE_FN | 2, NULL, tbsendfiles }, { "READ", CMDTABTYPE_STRING, (pointer) &sBperm.zread, NULL }, { "WRITE", CMDTABTYPE_STRING, (pointer) &sBperm.zwrite, NULL }, { "NOREAD", CMDTABTYPE_STRING, (pointer) &sBperm.znoread, NULL }, { "NOWRITE", CMDTABTYPE_STRING, (pointer) &sBperm.znowrite, NULL }, { "CALLBACK", CMDTABTYPE_BOOLEAN, (pointer) &sBperm.fcallback, NULL }, { "COMMANDS", CMDTABTYPE_STRING, (pointer) &sBperm.zcommands, NULL }, { "VALIDATE", CMDTABTYPE_STRING, (pointer) &sBperm.zvalidate, NULL }, { "MYNAME", CMDTABTYPE_STRING, (pointer) &sBperm.zmyname, NULL }, { "PUBDIR", CMDTABTYPE_STRING, (pointer) &sBperm.zpubdir, NULL }, { NULL, 0, NULL, NULL } }; static struct spermlist { struct spermlist *qnext; struct sperm sperm; } *qBothers; /* Read BNU system information. This means reading the Systems file and the Permissions file. */ void ubnu_read_systems (pc, ppas) int *pc; struct ssysteminfo **ppas; { int calc; struct smulti_file *qmulti; char *zline; *pc = 0; *ppas = NULL; calc = 0; /* Read the Systems file(s) first. */ qmulti = qmulti_open (zBnu_systems); if (qmulti == NULL) return; while ((zline = zmulti_gets (qmulti, (boolean *) NULL, (const char **) NULL, TRUE)) != NULL) { int inl; char *ztok; int i, cretry; struct ssysteminfo *qset; char *zsemi, *zslash; inl = strlen (zline) - 1; if (zline[inl] == '\n') zline[inl] = '\0'; if (isspace (BUCHAR (zline[0])) || zline[0] == '#') { xfree ((pointer) zline); continue; } ztok = strtok (zline, " \t"); if (ztok == NULL) { xfree ((pointer) zline); continue; } DEBUG_MESSAGE1 (DEBUG_CONFIG, "ubnu_read_systems: Reading system %s", ztok); /* See if we already have information for this system. */ for (i = 0; i < *pc; i++) if (strcmp ((*ppas)[i].zname, ztok) == 0) break; if (i >= *pc) { if (*pc >= calc) { calc += 10; *ppas = ((struct ssysteminfo *) xrealloc ((pointer) *ppas, calc * sizeof (struct ssysteminfo))); } qset = &(*ppas)[*pc]; (*pc)++; } else { struct ssysteminfo **pq; for (pq = &(*ppas)[i].qalternate; *pq != NULL; pq = &(*pq)->qalternate) ; *pq = (struct ssysteminfo *) xmalloc (sizeof (struct ssysteminfo)); qset = *pq; } uset_system_defaults (qset); qset->zname = ztok; /* Under BNU, a local request is permitted to write into any directory that is world writeable. */ qset->zlocal_receive = "/"; /* Get the time string. */ ztok = strtok ((char *) NULL, " \t"); if (ztok == NULL) continue; /* The time string is "time/grade,time/grade;retry". A missing grade is taken as 'z'. */ cretry = 0; zsemi = strchr (ztok, ';'); if (zsemi != NULL) { *zsemi = '\0'; cretry = atoi (zsemi + 1); } qset->ztime = NULL; while (TRUE) { char *zcomma; zcomma = strchr (ztok, ','); if (zcomma != NULL) *zcomma = '\0'; zslash = strchr (ztok, '/'); if (zslash == NULL || zslash[1] == '\0') ubadd_time (qset, BGRADE_LOW, ztok, cretry); else { *zslash = '\0'; ubadd_time (qset, zslash[1], ztok, cretry); } if (zcomma == NULL) break; ztok = zcomma + 1; } /* Get the devices entry. */ qset->zport = strtok ((char *) NULL, " \t"); /* Get the speed entry. If it starts with a nondigit, it's a modem class. We append it to the device name, and do the same thing when reading the Devices file, since we don't need to preserve the ``ACU''. I've heard that the modem class is permitted at either end, but this code doesn't support that. A range of speeds is also permitted. */ if (qset->zport != NULL) { /* According to Arne Ludwig, the devices entry can be followed by a comma and a list of protocols. */ ztok = strrchr (qset->zport, ','); if (ztok != NULL && ztok[1] != '\0') { qset->zprotocols = ztok + 1; *ztok = '\0'; } ztok = strtok ((char *) NULL, " \t"); if (ztok != NULL) { boolean fany; fany = (strcmp (ztok, "Any") == 0 || strcmp (ztok, "-") == 0); if (! isdigit (*ztok) && ! fany) { int clen; char *zport, *zset; clen = strlen (qset->zport); zport = (char *) xmalloc (clen + strlen (ztok) + 1); strcpy (zport, qset->zport); zset = zport + clen; while (*ztok != '\0' && ! isdigit (*ztok)) *zset++ = *ztok++; *zset = '\0'; qset->zport = zport; } if (fany) qset->ibaud = 0; else { qset->ibaud = strtol (ztok, &ztok, 10); if (*ztok == '-') qset->ihighbaud = atol (ztok + 1); } /* Get the phone number. */ qset->zphone = strtok ((char *) NULL, " \t"); /* The rest of the line is the login script. */ if (qset->zphone != NULL) { qset->schat.zchat = strtok ((char *) NULL, ""); qset->schat.zchat += strspn (qset->schat.zchat, " \t"); } } } } (void) fmulti_close (qmulti); /* Now we have to read the Permissions file. */ { char abperm[sizeof OLDCONFIGLIB + sizeof BNU_PERMISSIONS - 1]; const char * const zpubdir = PUBDIR; FILE *e; boolean *affound; sprintf (abperm, "%s%s", OLDCONFIGLIB, BNU_PERMISSIONS); e = fopen (abperm, "r"); if (e == NULL) return; affound = (boolean *) alloca (*pc * sizeof (boolean)); bzero (affound, *pc * sizeof (boolean)); while ((zline = zfgets (e, TRUE)) != NULL) { int inl; char *ztok; boolean fany; inl = strlen (zline) - 1; if (zline[inl] == '\n') zline[inl] = '\0'; if (isspace (BUCHAR (zline[0])) || zline[0] == '#') { xfree ((pointer) zline); continue; } sBperm.zlogname = NULL; sBperm.zmachine = NULL; sBperm.frequest = FALSE; sBperm.tsendfiles = SENDFILES_CALL; sBperm.zread = zpubdir; sBperm.zwrite = zpubdir; sBperm.znoread = NULL; sBperm.znowrite = NULL; sBperm.fcallback = FALSE; sBperm.zcommands = "rnews rmail"; sBperm.zvalidate = NULL; sBperm.zmyname = NULL; sBperm.zpubdir = NULL; fany = FALSE; for (ztok = strtok (zline, " \t"); ztok != NULL; ztok = strtok ((char *) NULL, " \t")) { char *zeq; char *azargs[2]; fany = TRUE; zeq = strchr (ztok, '='); if (zeq == NULL) { ulog (LOG_ERROR, "Bad %s entry: %s", BNU_PERMISSIONS, ztok); continue; } *zeq = '\0'; azargs[0] = ztok; azargs[1] = zeq + 1; (void) tprocess_one_cmd (2, azargs, asBperm_cmds, BNU_PERMISSIONS, CMDFLAG_WARNUNRECOG); } if (! fany) continue; if (sBperm.zlogname != NULL) { char *zstart; boolean fend; /* Process each LOGNAME separately. */ zstart = sBperm.zlogname; do { int c; c = strcspn (zstart, ":"); fend = zstart[c] == '\0'; zstart[c] = '\0'; sBperm.zlogname = zstart; ubadd_perm (*pc, *ppas, &affound); zstart += c + 1; } while (! fend); } else if (sBperm.zmachine != NULL) ubadd_perm (*pc, *ppas, &affound); else { ulog (LOG_ERROR, "%s: No MACHINE or LOGNAME entry: \"%s\"", BNU_PERMISSIONS, zline); xfree ((pointer) zline); } } (void) fclose (e); /* If there were any MACHINE=OTHER entry, add the permissions for each machine that was not specified by name. */ while (qBothers != NULL) { int i; struct spermlist *qnext; sBperm = qBothers->sperm; for (i = 0; i < *pc; i++) { if (! affound[i]) { sBperm.zmachine = xstrdup ((*ppas)[i].zname); ubadd_perm (*pc, *ppas, &affound); xfree ((pointer) sBperm.zmachine); } } qnext = qBothers->qnext; xfree ((pointer) qBothers); qBothers = qnext; } } } /* Look up a machine and attach permissions to it. */ static void ubadd_perm (csystems, passystems, paffound) int csystems; struct ssysteminfo *passystems; boolean **paffound; { if (sBperm.zmachine != NULL) { char *zcopy; char *ztok; if (strcmp (sBperm.zmachine, "OTHER") == 0) { struct spermlist *qnew; qnew = (struct spermlist *) xmalloc (sizeof (struct spermlist)); qnew->qnext = qBothers; qnew->sperm = sBperm; qBothers = qnew; return; } zcopy = (char *) alloca (strlen (sBperm.zmachine) + 1); strcpy (zcopy, sBperm.zmachine); for (ztok = strtok (zcopy, ":"); ztok != NULL; ztok = strtok ((char *) NULL, ":")) { int i; struct ssysteminfo *q; for (i = 0; i < csystems; i++) if (strcmp (passystems[i].zname, ztok) == 0) break; if (i >= csystems) { /* We just ignore Permissions entries for unknown systems. */ continue; } if ((*paffound)[i]) { struct ssysteminfo **pq; /* We have already handled this machine. Make a copy of the first alternate and set the login name to whatever this entry wants. Then put the new entry at the end of list of alternates. This will make whatever we saw first the default. */ q = ((struct ssysteminfo *) xmalloc (sizeof (struct ssysteminfo))); *q = passystems[i]; q->qalternate = NULL; for (pq = &passystems[i].qalternate; *pq != NULL; pq = &(*pq)->qalternate) ; *pq = q; q->zcalled_login = "ANY"; ubadd_perm_alternate (q, TRUE, sBperm.zlogname != NULL); } else { (*paffound)[i] = TRUE; for (q = &passystems[i]; q != NULL; q = q->qalternate) ubadd_perm_alternate (q, TRUE, sBperm.zlogname != NULL); } } } else { int i; #if DEBUG > 0 if (sBperm.zlogname == NULL) ulog (LOG_FATAL, "bnu.c: ubadd_perm: Can't happen"); #endif /* There was a LOGNAME= but no MACHINE=. We must add an alternate specifying this LOGNAME to all machines. */ for (i = 0; i < csystems; i++) { struct ssysteminfo *q; if (passystems[i].zcalled_login == NULL) passystems[i].zcalled_login = "ANY"; q = (struct ssysteminfo *) xmalloc (sizeof (struct ssysteminfo)); *q = passystems[i]; q->qalternate = passystems[i].qalternate; passystems[i].qalternate = q; ubadd_perm_alternate (q, FALSE, TRUE); } } } /* Attach permissions to a specific alternate of a machine. */ static void ubadd_perm_alternate (q, fmachine, flogname) struct ssysteminfo *q; boolean fmachine; boolean flogname; { char *z, *zset; if (flogname) { if (q->zcalled_login != NULL && strcmp (q->zcalled_login, "ANY") != 0) ulog (LOG_ERROR, "%s: Can't handle two login names for one machine", q->zname); else q->zcalled_login = sBperm.zlogname; } if (fmachine) q->fcall_request = sBperm.frequest; if (flogname) q->fcalled_request = sBperm.frequest; if (flogname) { q->fcall_transfer = (sBperm.tsendfiles == SENDFILES_CALL || (sBperm.tsendfiles == SENDFILES_YES)); q->fcalled_transfer = sBperm.tsendfiles == SENDFILES_YES; } zset = xstrdup (sBperm.zread); while ((z = strchr (zset, ':')) != NULL) *z = ' '; if (sBperm.znoread != NULL) { char *zstart; boolean fend; zstart = xstrdup (sBperm.znoread); do { char *zalloc; int c; c = strcspn (zstart, ":"); fend = zstart[c] == '\0'; zstart[c] = '\0'; zalloc = (char *) xmalloc (c + 2); sprintf (zalloc, "!%s", zstart); uadd_string (&zset, zalloc, ' '); xfree ((pointer) zalloc); zstart += c + 1; } while (! fend); } if (fmachine) q->zremote_send = zset; if (flogname) { if (fmachine) q->zcalled_remote_send = NULL; else q->zcalled_remote_send = zset; } zset = xstrdup (sBperm.zwrite); while ((z = strchr (zset, ':')) != NULL) *z = ' '; if (sBperm.znowrite != NULL) { char *zstart; boolean fend; zstart = xstrdup (sBperm.znowrite); do { char *zalloc; int c; c = strcspn (zstart, ":"); fend = zstart[c] == '\0'; zstart[c] = '\0'; zalloc = (char *) xmalloc (c + 2); sprintf (zalloc, "!%s", zstart); uadd_string (&zset, zalloc, ' '); xfree ((pointer) zalloc); zstart += c + 1; } while (! fend); } if (fmachine) q->zremote_receive = zset; if (flogname) { if (fmachine) q->zcalled_remote_receive = NULL; else q->zcalled_remote_receive = zset; } if (flogname) q->fcallback = sBperm.fcallback; if (fmachine && sBperm.zcommands != NULL) { q->zcmds = sBperm.zcommands; while ((z = strchr (q->zcmds, ':')) != NULL) *z = ' '; } if (flogname && sBperm.zvalidate != NULL) { char *zcopy; boolean fend; zcopy = xstrdup (sBperm.zvalidate); do { int c; c = strcspn (zcopy, ":"); fend = zcopy[c] == '\0'; zcopy[c] = '\0'; uadd_validate (sBperm.zlogname, 1, (const char **) &zcopy); zcopy += c + 1; } while (! fend); } if (fmachine) q->zlocalname = sBperm.zmyname; /* This isn't quite right, since the BNU Permissions file can specify a different public directory based on whether we are calling out or are being called. */ if (sBperm.zpubdir != NULL) q->zpubdir = sBperm.zpubdir; } /* Handle SENDFILES=string, where string can be YES, NO or CALL. We actually only switch off on the first letter. */ /*ARGSUSED*/ static enum tcmdtabret tbsendfiles (argc, argv, pvar, zerr) int argc; char **argv; pointer pvar; const char *zerr; { switch (argv[1][0]) { case 'C': case 'c': sBperm.tsendfiles = SENDFILES_CALL; break; case 'N': case 'n': sBperm.tsendfiles = SENDFILES_NO; break; case 'Y': case 'y': sBperm.tsendfiles = SENDFILES_YES; break; default: ulog (LOG_ERROR, "%s: Unrecognized SENDFILES=%s", zerr, argv[1]); break; } return CMDTABRET_FREE; } /* Find a port with a given name and baud rate in the Devices file, and lock it. If found and locked, fill in the structure pointed at by qport. Set *pffound to TRUE if a port was found but could not be locked. */ boolean fbnu_find_port (zname, ibaud, ihighbaud, qport, pflock, pffound) const char *zname; long ibaud; long ihighbaud; struct sport *qport; boolean (*pflock) P((struct sport *, boolean fin)); boolean *pffound; { struct smulti_file *qmulti; char *zline; qmulti = qmulti_open (zBnu_devices); if (qmulti == NULL) return FALSE; while ((zline = zmulti_gets (qmulti, (boolean *) NULL, (const char **) NULL, TRUE)) != NULL) { int inl; char *ztok, *zportname, *zprotocols, *zdevice, *zdial_device; long ilow, ihigh; inl = strlen (zline) - 1; if (zline[inl] == '\n') zline[inl] = '\0'; if (isspace (BUCHAR (zline[0])) || zline[0] == '#') { xfree ((pointer) zline); continue; } /* An entry in Devices is type device dial-device baud dialer-token pairs. */ /* Get the port type. */ zportname = strtok (zline, " \t"); if (zportname == NULL) { xfree ((pointer) zline); continue; } /* There may be a comma separated list of protocols following the port name. */ zprotocols = strchr (zportname, ','); if (zprotocols != NULL) { *zprotocols = '\0'; ++zprotocols; } /* Get the device name. */ zdevice = strtok ((char *) NULL, " \t"); if (zdevice == NULL) { xfree ((pointer) zline); continue; } /* Some systems seem to permit ,M at the end of the device name; this means to open the port with O_NDELAY and then allow delays later. We always do this anyhow, so I just ignore the ,M. There may be portability problems here. */ zdevice[strcspn (zdevice, ",")] = '\0'; /* Get the dial-device. A value of ``-'' means none. */ zdial_device = strtok ((char *) NULL, " \t"); if (zdial_device == NULL) { xfree ((pointer) zline); continue; } if (strcmp (zdial_device, "-") == 0) zdial_device = NULL; /* Get the speed. */ ztok = strtok ((char *) NULL, " \t"); if (ztok == NULL) { xfree ((pointer) zline); continue; } /* See whether we match the port name we are looking for. If the speed starts with a non-digit, it is a modem class (but "-" or "Any" mean any speed). When reading the Systems file we appended the modem class to the device name, so we must match appropriately. */ if (isdigit (*ztok) || strcmp (ztok, "-") == 0 || strcmp (ztok, "Any") == 0) { if (zname != NULL && strcmp (zname, zportname) != 0) { xfree ((pointer) zline); continue; } } else { char *zclass, *zset; zclass = (char *) alloca (strlen (ztok) + 1); zset = zclass; while (*ztok != '\0' && ! isdigit (*ztok)) *zset++ = *ztok++; *zset = '\0'; if (zname != NULL) { int clen; clen = strlen (zportname); if (strncmp (zname, zportname, clen) != 0 || strlen (zname) <= clen || strcmp (zname + clen, zclass) != 0) { xfree ((pointer) zline); continue; } } } ilow = strtol (ztok, &ztok, 10); if (ilow == 0) ihigh = 38400L; else { if (*ztok == '-') ihigh = atol (ztok + 1); else ihigh = ilow; } /* Now we must match the range ibaud to ihighbaud against to range ilow to ihigh. */ if (ibaud != 0 && (ihighbaud < ilow || ibaud > ihigh)) { xfree ((pointer) zline); continue; } /* We have found a matching port. We now fill in the sport structure so that we can try to lock it. */ if (zname != NULL) qport->zname = zname; else qport->zname = zportname; qport->zprotocols = zprotocols; qport->cproto_params = 0; qport->qproto_params = NULL; qport->ireliable = 0; qport->zlockname = NULL; if (strcmp (qport->zname, "Direct") == 0) { qport->ttype = PORTTYPE_DIRECT; qport->u.sdirect.zdevice = zdevice; qport->u.sdirect.ibaud = ilow; #ifdef SYSDEP_DIRECT_INIT SYSDEP_DIRECT_INIT (&qport->u.sdirect.s); #endif } #if HAVE_TCP else if (strcmp (qport->zname, "TCP") == 0) { qport->ttype = PORTTYPE_TCP; qport->ireliable = (RELIABLE_ENDTOEND | RELIABLE_RELIABLE | RELIABLE_EIGHT | RELIABLE_SPECIFIED); qport->u.stcp.o = -1; qport->u.stcp.zport = zdevice; } #endif /* HAVE_TCP */ else { qport->ttype = PORTTYPE_MODEM; qport->u.smodem.zdevice = zdevice; qport->u.smodem.zdial_device = zdial_device; if (ilow != ihigh) qport->u.smodem.ibaud = 0; else qport->u.smodem.ibaud = ilow; qport->u.smodem.ilowbaud = ilow; qport->u.smodem.ihighbaud = ihigh; qport->u.smodem.fcarrier = TRUE; qport->u.smodem.zdialer = strtok ((char *) NULL, ""); qport->u.smodem.zdialer += strspn (qport->u.smodem.zdialer, " \t"); qport->u.smodem.qdialer = NULL; #ifdef SYSDEP_MODEM_INIT SYSDEP_MODEM_INIT (&qport->u.smodem.s); #endif } if (pffound != NULL) *pffound = TRUE; if (pflock != NULL && ! (*pflock) (qport, FALSE)) { xfree ((pointer) zline); continue; } (void) fmulti_close (qmulti); return TRUE; } (void) fmulti_close (qmulti); return FALSE; } /* Read dialer information from the Dialers file. */ boolean fbnu_read_dialer_info (zdialer, qdialer) const char *zdialer; struct sdialer *qdialer; { struct smulti_file *qmulti; char *zline; qmulti = qmulti_open (zBnu_dialers); if (qmulti == NULL) return FALSE; while ((zline = zmulti_gets (qmulti, (boolean *) NULL, (const char **) NULL, TRUE)) != NULL) { int inl; char *zname, *zsubs; inl = strlen (zline) - 1; if (zline[inl] == '\n') zline[inl] = '\0'; if (isspace (BUCHAR (zline[0])) || zline[0] == '#') { xfree ((pointer) zline); continue; } zname = strtok (zline, " \t"); if (zname == NULL || strcmp (zname, zdialer) != 0) { xfree ((pointer) zline); continue; } /* We found the dialer we want. Get information from it. */ qdialer->zname = zdialer; INIT_CHAT (&qdialer->schat); qdialer->zdialtone = ","; qdialer->zpause = ","; qdialer->fcarrier = TRUE; qdialer->ccarrier_wait = 60; qdialer->fdtr_toggle = FALSE; qdialer->fdtr_toggle_wait = FALSE; INIT_CHAT (&qdialer->scomplete); INIT_CHAT (&qdialer->sabort); qdialer->cproto_params = 0; qdialer->qproto_params = NULL; qdialer->ireliable = 0; zsubs = strtok ((char *) NULL, " \t"); if (zsubs != NULL && strcmp (zsubs, "\"\"") != 0) { char bnext; bnext = *zsubs; while (bnext != '\0') { if (zsubs[1] == '\0') break; if (bnext == '=') qdialer->zdialtone = zsubs + 1; else if (bnext == '-') qdialer->zpause = zsubs + 1; zsubs += 2; bnext = *zsubs; *zsubs = '\0'; } } if (zsubs == NULL) qdialer->schat.zchat = NULL; else { qdialer->schat.zchat = strtok ((char *) NULL, ""); qdialer->schat.zchat += strspn (qdialer->schat.zchat, " \t"); } (void) fmulti_close (qmulti); return TRUE; } (void) fmulti_close (qmulti); return FALSE; } #endif /* HAVE_BNU_CONFIG */