1 /* bnu.c
2 Read BNU configuration files.
3
4 Copyright (C) 1991, 1992 Ian Lance Taylor
5
6 This file is part of the Taylor UUCP package.
7
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License as
10 published by the Free Software Foundation; either version 2 of the
11 License, or (at your option) any later version.
12
13 This program 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 General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21
22 The author of the program may be contacted at ian@airs.com or
23 c/o AIRS, P.O. Box 520, Waltham, MA 02254.
24
25 $Log: bnu.c,v $
26 Revision 1.35 1992/04/06 19:49:49 ian
27 Erik Forsberg: support multiple character modem classes
28
29 Revision 1.34 1992/03/15 05:21:12 ian
30 Scott Ballantyne: accept "Any" as a device speed
31
32 Revision 1.33 1992/03/12 19:56:10 ian
33 Debugging based on types rather than number
34
35 Revision 1.32 1992/03/11 22:06:37 ian
36 Marty Shannon: added max-uuxqts command
37
38 Revision 1.31 1992/03/10 21:47:39 ian
39 Added protocol command for ports
40
41 Revision 1.30 1992/02/24 20:36:27 ian
42 Roberto Biancardi: skip spaces after strtok (NULL, "")
43
44 Revision 1.29 1992/02/24 04:58:47 ian
45 Only permit files to be received into directories that are world-writeable
46
47 Revision 1.28 1992/02/24 04:02:45 ian
48 Doug Evans: WRITE only applies to remote requests
49
50 Revision 1.27 1992/02/23 19:50:50 ian
51 Handle READ and WRITE in Permissions correctly
52
53 Revision 1.26 1992/02/14 16:45:09 ian
54 This time for sure
55
56 Revision 1.25 1992/02/14 16:43:07 ian
57 Make the last patch better
58
59 Revision 1.24 1992/02/14 16:39:31 ian
60 T. William Wells: must xstrdup before calling uadd_validate
61
62 Revision 1.23 1992/02/08 03:54:18 ian
63 Include <string.h> only in <uucp.h>, added 1992 copyright
64
65 Revision 1.22 1992/01/30 23:18:59 ian
66 Michael Nolan: stupid error in ubadd_perm
67
68 Revision 1.21 1992/01/15 07:06:29 ian
69 Set configuration directory in Makefile rather than sysdep.h
70
71 Revision 1.20 1991/12/28 03:49:23 ian
72 Added HAVE_MEMFNS and HAVE_BFNS; changed uses of memset to bzero
73
74 Revision 1.19 1991/12/17 23:14:08 ian
75 T. William Wells: allow dialer complete and abort to be chat scripts
76
77 Revision 1.18 1991/12/16 16:25:57 ian
78 Mike Bernson: ignore lines beginning with whitespace
79
80 Revision 1.17 1991/12/15 03:42:33 ian
81 Added tprocess_chat_cmd for all chat commands, and added CMDTABTYPE_PREFIX
82
83 Revision 1.16 1991/12/09 19:20:51 ian
84 Arne Ludwig: devices entry can be followed by list of protocols
85
86 Revision 1.15 1991/12/03 03:43:36 ian
87 Dave Buck: time strings with grades were not parsed correctly
88
89 Revision 1.14 1991/12/01 19:35:38 ian
90 David Nugent: read V2 and BNU files by default even with TAYLOR_CONFIG
91
92 Revision 1.13 1991/12/01 03:10:36 ian
93 Niels Baggesen: accept dialers with no substitutions
94
95 Revision 1.12 1991/12/01 03:04:20 ian
96 Niels Baggesen: don't free up zline in ubadd_perm; don't even pass it in
97
98 Revision 1.11 1991/12/01 02:44:12 ian
99 Niels Baggesen: didn't handle combinations of multiple MACHINE/LOGNAME
100
101 Revision 1.10 1991/12/01 02:31:36 ian
102 Made zread and zwrite fields of sperm structure const char *
103
104 Revision 1.9 1991/11/30 23:39:37 ian
105 Marty Shannon: allow comments in Sysfiles
106
107 Revision 1.8 1991/11/30 22:39:39 ian
108 Marty Shannon: don't initialize an auto array
109
110 Revision 1.7 1991/11/26 01:04:04 ian
111 Marty Shannon: initialize ireliable for BNU and V2 configuration files
112
113 Revision 1.6 1991/11/13 20:38:00 ian
114 Added TCP port type for connections over TCP
115
116 Revision 1.5 1991/11/11 23:47:24 ian
117 Added chat-program to run a program to do a chat script
118
119 Revision 1.4 1991/11/11 16:59:05 ian
120 Eliminate fread_port_info, allow NULL pflock arg to ffind_port
121
122 Revision 1.3 1991/11/07 18:26:13 ian
123 Chip Salzenberg: can't portably take address of casted value, obviously
124
125 Revision 1.2 1991/09/19 02:22:44 ian
126 Chip Salzenberg's patch to allow ";retrytime" at the end of a time string
127
128 Revision 1.1 1991/09/10 19:37:52 ian
129 Initial revision
130
131 */
132
133 #include "uucp.h"
134
135 #if HAVE_BNU_CONFIG
136
137 #if USE_RCS_ID
138 char bnu_rcsid[] = "$Id: bnu.c,v 1.35 1992/04/06 19:49:49 ian Rel $";
139 #endif
140
141 #include <ctype.h>
142
143 #include "port.h"
144 #include "sysdep.h"
145
146 /* Whether to use BNU configuration files. */
147 boolean fBnu = TRUE;
148
149 /* A list of space separated file names to interpret as Systems. */
150 char *zBnu_systems;
151
152 /* A list of space separated file names to interpret as Dialers. */
153 char *zBnu_dialers;
154
155 /* A list of space separated file names to interpret as Devices. */
156 char *zBnu_devices;
157
158 /* Local functions. */
159
160 static void ubadd_perm P((int csystems, struct ssysteminfo *passystems,
161 boolean **paffound));
162 static void ubadd_perm_alternate P((struct ssysteminfo *q,
163 boolean fmachine,
164 boolean flogname));
165
166 /* Read Sysfiles to get the file names to use. */
167
168 void
ubnu_read_sysfiles()169 ubnu_read_sysfiles ()
170 {
171 char ab[sizeof OLDCONFIGLIB + sizeof BNU_SYSFILES - 1];
172 FILE *e;
173 char *zline;
174
175 zBnu_systems = NULL;
176 zBnu_dialers = NULL;
177 zBnu_devices = NULL;
178
179 sprintf (ab, "%s%s", OLDCONFIGLIB, BNU_SYSFILES);
180 e = fopen (ab, "r");
181 if (e != NULL)
182 {
183 while ((zline = zfgets (e, TRUE)) != NULL)
184 {
185 int inl;
186 char *ztok;
187
188 inl = strlen (zline) - 1;
189 if (zline[inl] == '\n')
190 zline[inl] = '\0';
191 if (isspace (BUCHAR (zline[0])) || zline[0] == '#')
192 {
193 xfree ((pointer) zline);
194 continue;
195 }
196
197 ztok = strtok (zline, " \t");
198 if (ztok == NULL)
199 {
200 xfree ((pointer) zline);
201 continue;
202 }
203 if (strncmp (ztok, "service=", sizeof "service=" - 1) != 0)
204 {
205 ulog (LOG_ERROR, "Unrecognized Sysfiles line: %s", ztok);
206 xfree ((pointer) zline);
207 continue;
208 }
209
210 do
211 {
212 int c;
213
214 c = strcspn (ztok, ":");
215 if (c == sizeof "uucico" - 1
216 && strncmp (ztok, "uucico", sizeof "uucico" - 1) == 0)
217 break;
218 ztok += c;
219 if (*ztok == ':')
220 ++ztok;
221 }
222 while (*ztok != '\0');
223
224 if (*ztok == '\0')
225 {
226 xfree ((pointer) zline);
227 continue;
228 }
229
230 while ((ztok = strtok ((char *) NULL, " \t")) != NULL)
231 {
232 char **pz;
233 char *z;
234 boolean fend;
235
236 if (strncmp (ztok, "systems=", sizeof "systems=" - 1) == 0)
237 {
238 pz = &zBnu_systems;
239 ztok += sizeof "systems=" - 1;
240 }
241 else if (strncmp (ztok, "dialers=", sizeof "dialers=" - 1) == 0)
242 {
243 pz = &zBnu_dialers;
244 ztok += sizeof "dialers=" - 1;
245 }
246 else if (strncmp (ztok, "devices=", sizeof "devices=" - 1) == 0)
247 {
248 pz = &zBnu_devices;
249 ztok += sizeof "devices=" - 1;
250 }
251 else
252 {
253 ulog (LOG_ERROR, "Unrecognized Sysfiles command: %s", ztok);
254 continue;
255 }
256
257 /* Stick the configuration file directory in front of each
258 file. */
259 z = ztok;
260 do
261 {
262 int c;
263
264 c = strcspn (z, ":");
265 fend = z[c] == '\0';
266 z[c] = '\0';
267
268 /* Looking for a leading '/' is Unix dependent, and
269 should be changed. */
270 if (*z == '/')
271 uadd_string (pz, z, ' ');
272 else
273 {
274 char *zdir;
275
276 zdir = (char *) xmalloc (sizeof OLDCONFIGLIB
277 + strlen (z));
278 sprintf (zdir, "%s%s", OLDCONFIGLIB, z);
279 uadd_string (pz, zdir, ' ');
280 xfree ((pointer) zdir);
281 }
282
283 z += c + 1;
284 }
285 while (! fend);
286 }
287
288 xfree ((pointer) zline);
289 }
290
291 (void) fclose (e);
292 }
293
294 if (zBnu_systems == NULL)
295 {
296 zBnu_systems = (char *) xmalloc (sizeof OLDCONFIGLIB
297 + sizeof BNU_SYSTEMS - 1);
298 sprintf (zBnu_systems, "%s%s", OLDCONFIGLIB, BNU_SYSTEMS);
299 }
300 if (zBnu_dialers == NULL)
301 {
302 zBnu_dialers = (char *) xmalloc (sizeof OLDCONFIGLIB
303 + sizeof BNU_DIALERS - 1);
304 sprintf (zBnu_dialers, "%s%s", OLDCONFIGLIB, BNU_DIALERS);
305 }
306 if (zBnu_devices == NULL)
307 {
308 zBnu_devices = (char *) xmalloc (sizeof OLDCONFIGLIB
309 + sizeof BNU_DEVICES - 1);
310 sprintf (zBnu_devices, "%s%s", OLDCONFIGLIB, BNU_DEVICES);
311 }
312
313 #if ! HAVE_TAYLOR_CONFIG
314 /* If we are NOT reading the new configuration files, then look for
315 Maxuuxqts. It would be more efficient to only read the file in
316 uuxqt.c. Too bad. */
317 {
318 char *zmax;
319
320 zmax = (char *) alloca (sizeof OLDCONFIGLIB +
321 sizeof BNU_MAXUUXQTS - 1);
322 sprintf (zmax, "%s%s", OLDCONFIGLIB, BNU_MAXUUXQTS);
323 e = fopen (zmax, "r");
324 if (e != NULL)
325 {
326 zline = zfgets (e, FALSE);
327 if (zline != NULL)
328 {
329 cMaxuuxqts = atoi (zline);
330 if (cMaxuuxqts < 0)
331 cMaxuuxqts = 0;
332 xfree ((pointer) zline);
333 }
334 (void) fclose (e);
335 }
336 }
337 #endif /* ! HAVE_TAYLOR_CONFIG */
338 }
339
340 /* A little routine to add a grade and a time string to a system. */
341
342 static void ubadd_time P((struct ssysteminfo *q, int bgrade,
343 const char *ztime, int cretry));
344
345 static void
ubadd_time(q,bgrade,ztime,cretry)346 ubadd_time (q, bgrade, ztime, cretry)
347 struct ssysteminfo *q;
348 int bgrade;
349 const char *ztime;
350 int cretry;
351 {
352 char *zset;
353
354 zset = (char *) alloca (strlen (ztime) + 20);
355 if (cretry == 0)
356 sprintf (zset, "%c%s", bgrade, ztime);
357 else
358 sprintf (zset, "%c%s;%d", bgrade, ztime, cretry);
359 uadd_string (&q->ztime, zset, ' ');
360 }
361
362 /* These structures are used to read the Permissions file. */
363
364 static struct sperm
365 {
366 char *zlogname;
367 char *zmachine;
368 boolean frequest;
369 enum { SENDFILES_YES, SENDFILES_CALL, SENDFILES_NO } tsendfiles;
370 const char *zread;
371 const char *zwrite;
372 char *znoread;
373 char *znowrite;
374 boolean fcallback;
375 const char *zcommands;
376 char *zvalidate;
377 char *zmyname;
378 char *zpubdir;
379 } sBperm;
380
381 static enum tcmdtabret tbsendfiles P((int argc, char **argv,
382 pointer pvar, const char *zerr));
383
384 static struct scmdtab asBperm_cmds[] =
385 {
386 { "LOGNAME", CMDTABTYPE_STRING, (pointer) &sBperm.zlogname, NULL },
387 { "MACHINE", CMDTABTYPE_STRING, (pointer) &sBperm.zmachine, NULL },
388 { "REQUEST", CMDTABTYPE_BOOLEAN, (pointer) &sBperm.frequest, NULL },
389 { "SENDFILES", CMDTABTYPE_FN | 2, NULL, tbsendfiles },
390 { "READ", CMDTABTYPE_STRING, (pointer) &sBperm.zread, NULL },
391 { "WRITE", CMDTABTYPE_STRING, (pointer) &sBperm.zwrite, NULL },
392 { "NOREAD", CMDTABTYPE_STRING, (pointer) &sBperm.znoread, NULL },
393 { "NOWRITE", CMDTABTYPE_STRING, (pointer) &sBperm.znowrite, NULL },
394 { "CALLBACK", CMDTABTYPE_BOOLEAN, (pointer) &sBperm.fcallback, NULL },
395 { "COMMANDS", CMDTABTYPE_STRING, (pointer) &sBperm.zcommands, NULL },
396 { "VALIDATE", CMDTABTYPE_STRING, (pointer) &sBperm.zvalidate, NULL },
397 { "MYNAME", CMDTABTYPE_STRING, (pointer) &sBperm.zmyname, NULL },
398 { "PUBDIR", CMDTABTYPE_STRING, (pointer) &sBperm.zpubdir, NULL },
399 { NULL, 0, NULL, NULL }
400 };
401
402 static struct spermlist
403 {
404 struct spermlist *qnext;
405 struct sperm sperm;
406 } *qBothers;
407
408 /* Read BNU system information. This means reading the Systems file
409 and the Permissions file. */
410
411 void
ubnu_read_systems(pc,ppas)412 ubnu_read_systems (pc, ppas)
413 int *pc;
414 struct ssysteminfo **ppas;
415 {
416 int calc;
417 struct smulti_file *qmulti;
418 char *zline;
419
420 *pc = 0;
421 *ppas = NULL;
422 calc = 0;
423
424 /* Read the Systems file(s) first. */
425 qmulti = qmulti_open (zBnu_systems);
426 if (qmulti == NULL)
427 return;
428
429 while ((zline = zmulti_gets (qmulti, (boolean *) NULL,
430 (const char **) NULL, TRUE)) != NULL)
431 {
432 int inl;
433 char *ztok;
434 int i, cretry;
435 struct ssysteminfo *qset;
436 char *zsemi, *zslash;
437
438 inl = strlen (zline) - 1;
439 if (zline[inl] == '\n')
440 zline[inl] = '\0';
441 if (isspace (BUCHAR (zline[0])) || zline[0] == '#')
442 {
443 xfree ((pointer) zline);
444 continue;
445 }
446
447 ztok = strtok (zline, " \t");
448 if (ztok == NULL)
449 {
450 xfree ((pointer) zline);
451 continue;
452 }
453
454 DEBUG_MESSAGE1 (DEBUG_CONFIG,
455 "ubnu_read_systems: Reading system %s", ztok);
456
457 /* See if we already have information for this system. */
458 for (i = 0; i < *pc; i++)
459 if (strcmp ((*ppas)[i].zname, ztok) == 0)
460 break;
461 if (i >= *pc)
462 {
463 if (*pc >= calc)
464 {
465 calc += 10;
466 *ppas = ((struct ssysteminfo *)
467 xrealloc ((pointer) *ppas,
468 calc * sizeof (struct ssysteminfo)));
469 }
470 qset = &(*ppas)[*pc];
471 (*pc)++;
472 }
473 else
474 {
475 struct ssysteminfo **pq;
476
477 for (pq = &(*ppas)[i].qalternate;
478 *pq != NULL;
479 pq = &(*pq)->qalternate)
480 ;
481 *pq = (struct ssysteminfo *) xmalloc (sizeof (struct ssysteminfo));
482 qset = *pq;
483 }
484
485 uset_system_defaults (qset);
486 qset->zname = ztok;
487
488 /* Under BNU, a local request is permitted to write into any
489 directory that is world writeable. */
490 qset->zlocal_receive = "/";
491
492 /* Get the time string. */
493 ztok = strtok ((char *) NULL, " \t");
494 if (ztok == NULL)
495 continue;
496
497 /* The time string is "time/grade,time/grade;retry". A missing
498 grade is taken as 'z'. */
499
500 cretry = 0;
501 zsemi = strchr (ztok, ';');
502 if (zsemi != NULL)
503 {
504 *zsemi = '\0';
505 cretry = atoi (zsemi + 1);
506 }
507
508 qset->ztime = NULL;
509 while (TRUE)
510 {
511 char *zcomma;
512
513 zcomma = strchr (ztok, ',');
514 if (zcomma != NULL)
515 *zcomma = '\0';
516
517 zslash = strchr (ztok, '/');
518 if (zslash == NULL || zslash[1] == '\0')
519 ubadd_time (qset, BGRADE_LOW, ztok, cretry);
520 else
521 {
522 *zslash = '\0';
523 ubadd_time (qset, zslash[1], ztok, cretry);
524 }
525
526 if (zcomma == NULL)
527 break;
528
529 ztok = zcomma + 1;
530 }
531
532 /* Get the devices entry. */
533 qset->zport = strtok ((char *) NULL, " \t");
534
535 /* Get the speed entry. If it starts with a nondigit, it's a
536 modem class. We append it to the device name, and do the
537 same thing when reading the Devices file, since we don't need
538 to preserve the ``ACU''. I've heard that the modem class is
539 permitted at either end, but this code doesn't support that.
540 A range of speeds is also permitted. */
541 if (qset->zport != NULL)
542 {
543
544 /* According to Arne Ludwig, the devices entry can be
545 followed by a comma and a list of protocols. */
546 ztok = strrchr (qset->zport, ',');
547 if (ztok != NULL && ztok[1] != '\0')
548 {
549 qset->zprotocols = ztok + 1;
550 *ztok = '\0';
551 }
552
553 ztok = strtok ((char *) NULL, " \t");
554 if (ztok != NULL)
555 {
556 boolean fany;
557
558 fany = (strcmp (ztok, "Any") == 0
559 || strcmp (ztok, "-") == 0);
560
561 if (! isdigit (*ztok) && ! fany)
562 {
563 int clen;
564 char *zport, *zset;
565
566 clen = strlen (qset->zport);
567 zport = (char *) xmalloc (clen + strlen (ztok) + 1);
568 strcpy (zport, qset->zport);
569 zset = zport + clen;
570 while (*ztok != '\0' && ! isdigit (*ztok))
571 *zset++ = *ztok++;
572 *zset = '\0';
573 qset->zport = zport;
574 }
575
576 if (fany)
577 qset->ibaud = 0;
578 else
579 {
580 qset->ibaud = strtol (ztok, &ztok, 10);
581 if (*ztok == '-')
582 qset->ihighbaud = atol (ztok + 1);
583 }
584
585 /* Get the phone number. */
586 qset->zphone = strtok ((char *) NULL, " \t");
587
588 /* The rest of the line is the login script. */
589 if (qset->zphone != NULL)
590 {
591 qset->schat.zchat = strtok ((char *) NULL, "");
592 qset->schat.zchat += strspn (qset->schat.zchat, " \t");
593 }
594 }
595 }
596 }
597
598 (void) fmulti_close (qmulti);
599
600 /* Now we have to read the Permissions file. */
601
602 {
603 char abperm[sizeof OLDCONFIGLIB + sizeof BNU_PERMISSIONS - 1];
604 const char * const zpubdir = PUBDIR;
605 FILE *e;
606 boolean *affound;
607
608 sprintf (abperm, "%s%s", OLDCONFIGLIB, BNU_PERMISSIONS);
609 e = fopen (abperm, "r");
610 if (e == NULL)
611 return;
612
613 affound = (boolean *) alloca (*pc * sizeof (boolean));
614 bzero (affound, *pc * sizeof (boolean));
615
616 while ((zline = zfgets (e, TRUE)) != NULL)
617 {
618 int inl;
619 char *ztok;
620 boolean fany;
621
622 inl = strlen (zline) - 1;
623 if (zline[inl] == '\n')
624 zline[inl] = '\0';
625 if (isspace (BUCHAR (zline[0])) || zline[0] == '#')
626 {
627 xfree ((pointer) zline);
628 continue;
629 }
630
631 sBperm.zlogname = NULL;
632 sBperm.zmachine = NULL;
633 sBperm.frequest = FALSE;
634 sBperm.tsendfiles = SENDFILES_CALL;
635 sBperm.zread = zpubdir;
636 sBperm.zwrite = zpubdir;
637 sBperm.znoread = NULL;
638 sBperm.znowrite = NULL;
639 sBperm.fcallback = FALSE;
640 sBperm.zcommands = "rnews rmail";
641 sBperm.zvalidate = NULL;
642 sBperm.zmyname = NULL;
643 sBperm.zpubdir = NULL;
644
645 fany = FALSE;
646
647 for (ztok = strtok (zline, " \t");
648 ztok != NULL;
649 ztok = strtok ((char *) NULL, " \t"))
650 {
651 char *zeq;
652 char *azargs[2];
653
654 fany = TRUE;
655
656 zeq = strchr (ztok, '=');
657 if (zeq == NULL)
658 {
659 ulog (LOG_ERROR, "Bad %s entry: %s", BNU_PERMISSIONS,
660 ztok);
661 continue;
662 }
663 *zeq = '\0';
664
665 azargs[0] = ztok;
666 azargs[1] = zeq + 1;
667 (void) tprocess_one_cmd (2, azargs, asBperm_cmds,
668 BNU_PERMISSIONS, CMDFLAG_WARNUNRECOG);
669 }
670
671 if (! fany)
672 continue;
673
674 if (sBperm.zlogname != NULL)
675 {
676 char *zstart;
677 boolean fend;
678
679 /* Process each LOGNAME separately. */
680 zstart = sBperm.zlogname;
681 do
682 {
683 int c;
684
685 c = strcspn (zstart, ":");
686 fend = zstart[c] == '\0';
687 zstart[c] = '\0';
688
689 sBperm.zlogname = zstart;
690 ubadd_perm (*pc, *ppas, &affound);
691
692 zstart += c + 1;
693 }
694 while (! fend);
695 }
696 else if (sBperm.zmachine != NULL)
697 ubadd_perm (*pc, *ppas, &affound);
698 else
699 {
700 ulog (LOG_ERROR,
701 "%s: No MACHINE or LOGNAME entry: \"%s\"",
702 BNU_PERMISSIONS, zline);
703 xfree ((pointer) zline);
704 }
705 }
706
707 (void) fclose (e);
708
709 /* If there were any MACHINE=OTHER entry, add the permissions for
710 each machine that was not specified by name. */
711
712 while (qBothers != NULL)
713 {
714 int i;
715 struct spermlist *qnext;
716
717 sBperm = qBothers->sperm;
718 for (i = 0; i < *pc; i++)
719 {
720 if (! affound[i])
721 {
722 sBperm.zmachine = xstrdup ((*ppas)[i].zname);
723 ubadd_perm (*pc, *ppas, &affound);
724 xfree ((pointer) sBperm.zmachine);
725 }
726 }
727
728 qnext = qBothers->qnext;
729 xfree ((pointer) qBothers);
730 qBothers = qnext;
731 }
732 }
733 }
734
735 /* Look up a machine and attach permissions to it. */
736
737 static void
ubadd_perm(csystems,passystems,paffound)738 ubadd_perm (csystems, passystems, paffound)
739 int csystems;
740 struct ssysteminfo *passystems;
741 boolean **paffound;
742 {
743 if (sBperm.zmachine != NULL)
744 {
745 char *zcopy;
746 char *ztok;
747
748 if (strcmp (sBperm.zmachine, "OTHER") == 0)
749 {
750 struct spermlist *qnew;
751
752 qnew = (struct spermlist *) xmalloc (sizeof (struct spermlist));
753 qnew->qnext = qBothers;
754 qnew->sperm = sBperm;
755 qBothers = qnew;
756 return;
757 }
758
759 zcopy = (char *) alloca (strlen (sBperm.zmachine) + 1);
760 strcpy (zcopy, sBperm.zmachine);
761
762 for (ztok = strtok (zcopy, ":");
763 ztok != NULL;
764 ztok = strtok ((char *) NULL, ":"))
765 {
766 int i;
767 struct ssysteminfo *q;
768
769 for (i = 0; i < csystems; i++)
770 if (strcmp (passystems[i].zname, ztok) == 0)
771 break;
772 if (i >= csystems)
773 {
774 /* We just ignore Permissions entries for unknown
775 systems. */
776 continue;
777 }
778
779 if ((*paffound)[i])
780 {
781 struct ssysteminfo **pq;
782
783 /* We have already handled this machine. Make a copy of
784 the first alternate and set the login name to
785 whatever this entry wants. Then put the new entry at
786 the end of list of alternates. This will make
787 whatever we saw first the default. */
788 q = ((struct ssysteminfo *)
789 xmalloc (sizeof (struct ssysteminfo)));
790 *q = passystems[i];
791 q->qalternate = NULL;
792 for (pq = &passystems[i].qalternate;
793 *pq != NULL;
794 pq = &(*pq)->qalternate)
795 ;
796 *pq = q;
797 q->zcalled_login = "ANY";
798 ubadd_perm_alternate (q, TRUE, sBperm.zlogname != NULL);
799 }
800 else
801 {
802 (*paffound)[i] = TRUE;
803 for (q = &passystems[i]; q != NULL; q = q->qalternate)
804 ubadd_perm_alternate (q, TRUE,
805 sBperm.zlogname != NULL);
806 }
807 }
808 }
809 else
810 {
811 int i;
812
813 #if DEBUG > 0
814 if (sBperm.zlogname == NULL)
815 ulog (LOG_FATAL, "bnu.c: ubadd_perm: Can't happen");
816 #endif
817
818 /* There was a LOGNAME= but no MACHINE=. We must add an
819 alternate specifying this LOGNAME to all machines. */
820
821 for (i = 0; i < csystems; i++)
822 {
823 struct ssysteminfo *q;
824
825 if (passystems[i].zcalled_login == NULL)
826 passystems[i].zcalled_login = "ANY";
827
828 q = (struct ssysteminfo *) xmalloc (sizeof (struct ssysteminfo));
829 *q = passystems[i];
830 q->qalternate = passystems[i].qalternate;
831 passystems[i].qalternate = q;
832
833 ubadd_perm_alternate (q, FALSE, TRUE);
834 }
835 }
836 }
837
838 /* Attach permissions to a specific alternate of a machine. */
839
840 static void
ubadd_perm_alternate(q,fmachine,flogname)841 ubadd_perm_alternate (q, fmachine, flogname)
842 struct ssysteminfo *q;
843 boolean fmachine;
844 boolean flogname;
845 {
846 char *z, *zset;
847
848 if (flogname)
849 {
850 if (q->zcalled_login != NULL
851 && strcmp (q->zcalled_login, "ANY") != 0)
852 ulog (LOG_ERROR, "%s: Can't handle two login names for one machine",
853 q->zname);
854 else
855 q->zcalled_login = sBperm.zlogname;
856 }
857 if (fmachine)
858 q->fcall_request = sBperm.frequest;
859 if (flogname)
860 q->fcalled_request = sBperm.frequest;
861 if (flogname)
862 {
863 q->fcall_transfer = (sBperm.tsendfiles == SENDFILES_CALL
864 || (sBperm.tsendfiles == SENDFILES_YES));
865 q->fcalled_transfer = sBperm.tsendfiles == SENDFILES_YES;
866 }
867
868 zset = xstrdup (sBperm.zread);
869 while ((z = strchr (zset, ':')) != NULL)
870 *z = ' ';
871 if (sBperm.znoread != NULL)
872 {
873 char *zstart;
874 boolean fend;
875
876 zstart = xstrdup (sBperm.znoread);
877 do
878 {
879 char *zalloc;
880 int c;
881
882 c = strcspn (zstart, ":");
883 fend = zstart[c] == '\0';
884 zstart[c] = '\0';
885
886 zalloc = (char *) xmalloc (c + 2);
887 sprintf (zalloc, "!%s", zstart);
888 uadd_string (&zset, zalloc, ' ');
889 xfree ((pointer) zalloc);
890
891 zstart += c + 1;
892 }
893 while (! fend);
894 }
895 if (fmachine)
896 q->zremote_send = zset;
897 if (flogname)
898 {
899 if (fmachine)
900 q->zcalled_remote_send = NULL;
901 else
902 q->zcalled_remote_send = zset;
903 }
904
905 zset = xstrdup (sBperm.zwrite);
906 while ((z = strchr (zset, ':')) != NULL)
907 *z = ' ';
908 if (sBperm.znowrite != NULL)
909 {
910 char *zstart;
911 boolean fend;
912
913 zstart = xstrdup (sBperm.znowrite);
914 do
915 {
916 char *zalloc;
917 int c;
918
919 c = strcspn (zstart, ":");
920 fend = zstart[c] == '\0';
921 zstart[c] = '\0';
922
923 zalloc = (char *) xmalloc (c + 2);
924 sprintf (zalloc, "!%s", zstart);
925 uadd_string (&zset, zalloc, ' ');
926 xfree ((pointer) zalloc);
927
928 zstart += c + 1;
929 }
930 while (! fend);
931 }
932 if (fmachine)
933 q->zremote_receive = zset;
934 if (flogname)
935 {
936 if (fmachine)
937 q->zcalled_remote_receive = NULL;
938 else
939 q->zcalled_remote_receive = zset;
940 }
941
942 if (flogname)
943 q->fcallback = sBperm.fcallback;
944
945 if (fmachine && sBperm.zcommands != NULL)
946 {
947 q->zcmds = sBperm.zcommands;
948 while ((z = strchr (q->zcmds, ':')) != NULL)
949 *z = ' ';
950 }
951
952 if (flogname && sBperm.zvalidate != NULL)
953 {
954 char *zcopy;
955 boolean fend;
956
957 zcopy = xstrdup (sBperm.zvalidate);
958
959 do
960 {
961 int c;
962
963 c = strcspn (zcopy, ":");
964 fend = zcopy[c] == '\0';
965 zcopy[c] = '\0';
966
967 uadd_validate (sBperm.zlogname, 1, (const char **) &zcopy);
968
969 zcopy += c + 1;
970 }
971 while (! fend);
972 }
973
974 if (fmachine)
975 q->zlocalname = sBperm.zmyname;
976
977 /* This isn't quite right, since the BNU Permissions file can
978 specify a different public directory based on whether we are
979 calling out or are being called. */
980 if (sBperm.zpubdir != NULL)
981 q->zpubdir = sBperm.zpubdir;
982 }
983
984 /* Handle SENDFILES=string, where string can be YES, NO or CALL. We
985 actually only switch off on the first letter. */
986
987 /*ARGSUSED*/
988 static enum tcmdtabret
tbsendfiles(argc,argv,pvar,zerr)989 tbsendfiles (argc, argv, pvar, zerr)
990 int argc;
991 char **argv;
992 pointer pvar;
993 const char *zerr;
994 {
995 switch (argv[1][0])
996 {
997 case 'C':
998 case 'c':
999 sBperm.tsendfiles = SENDFILES_CALL;
1000 break;
1001 case 'N':
1002 case 'n':
1003 sBperm.tsendfiles = SENDFILES_NO;
1004 break;
1005 case 'Y':
1006 case 'y':
1007 sBperm.tsendfiles = SENDFILES_YES;
1008 break;
1009 default:
1010 ulog (LOG_ERROR, "%s: Unrecognized SENDFILES=%s", zerr, argv[1]);
1011 break;
1012 }
1013
1014 return CMDTABRET_FREE;
1015 }
1016
1017 /* Find a port with a given name and baud rate in the Devices file,
1018 and lock it. If found and locked, fill in the structure pointed at
1019 by qport. Set *pffound to TRUE if a port was found but could not
1020 be locked. */
1021
1022 boolean
fbnu_find_port(zname,ibaud,ihighbaud,qport,pflock,pffound)1023 fbnu_find_port (zname, ibaud, ihighbaud, qport, pflock, pffound)
1024 const char *zname;
1025 long ibaud;
1026 long ihighbaud;
1027 struct sport *qport;
1028 boolean (*pflock) P((struct sport *, boolean fin));
1029 boolean *pffound;
1030 {
1031 struct smulti_file *qmulti;
1032 char *zline;
1033
1034 qmulti = qmulti_open (zBnu_devices);
1035 if (qmulti == NULL)
1036 return FALSE;
1037
1038 while ((zline = zmulti_gets (qmulti, (boolean *) NULL,
1039 (const char **) NULL, TRUE)) != NULL)
1040 {
1041 int inl;
1042 char *ztok, *zportname, *zprotocols, *zdevice, *zdial_device;
1043 long ilow, ihigh;
1044
1045 inl = strlen (zline) - 1;
1046 if (zline[inl] == '\n')
1047 zline[inl] = '\0';
1048 if (isspace (BUCHAR (zline[0])) || zline[0] == '#')
1049 {
1050 xfree ((pointer) zline);
1051 continue;
1052 }
1053
1054 /* An entry in Devices is type device dial-device baud
1055 dialer-token pairs. */
1056
1057 /* Get the port type. */
1058 zportname = strtok (zline, " \t");
1059 if (zportname == NULL)
1060 {
1061 xfree ((pointer) zline);
1062 continue;
1063 }
1064
1065 /* There may be a comma separated list of protocols following
1066 the port name. */
1067 zprotocols = strchr (zportname, ',');
1068 if (zprotocols != NULL)
1069 {
1070 *zprotocols = '\0';
1071 ++zprotocols;
1072 }
1073
1074 /* Get the device name. */
1075 zdevice = strtok ((char *) NULL, " \t");
1076 if (zdevice == NULL)
1077 {
1078 xfree ((pointer) zline);
1079 continue;
1080 }
1081
1082 /* Some systems seem to permit ,M at the end of the device name;
1083 this means to open the port with O_NDELAY and then allow
1084 delays later. We always do this anyhow, so I just ignore the
1085 ,M. There may be portability problems here. */
1086 zdevice[strcspn (zdevice, ",")] = '\0';
1087
1088 /* Get the dial-device. A value of ``-'' means none. */
1089 zdial_device = strtok ((char *) NULL, " \t");
1090 if (zdial_device == NULL)
1091 {
1092 xfree ((pointer) zline);
1093 continue;
1094 }
1095 if (strcmp (zdial_device, "-") == 0)
1096 zdial_device = NULL;
1097
1098 /* Get the speed. */
1099 ztok = strtok ((char *) NULL, " \t");
1100 if (ztok == NULL)
1101 {
1102 xfree ((pointer) zline);
1103 continue;
1104 }
1105
1106 /* See whether we match the port name we are looking for. If
1107 the speed starts with a non-digit, it is a modem class (but
1108 "-" or "Any" mean any speed). When reading the Systems file
1109 we appended the modem class to the device name, so we must
1110 match appropriately. */
1111 if (isdigit (*ztok)
1112 || strcmp (ztok, "-") == 0
1113 || strcmp (ztok, "Any") == 0)
1114 {
1115 if (zname != NULL && strcmp (zname, zportname) != 0)
1116 {
1117 xfree ((pointer) zline);
1118 continue;
1119 }
1120 }
1121 else
1122 {
1123 char *zclass, *zset;
1124
1125 zclass = (char *) alloca (strlen (ztok) + 1);
1126 zset = zclass;
1127 while (*ztok != '\0' && ! isdigit (*ztok))
1128 *zset++ = *ztok++;
1129 *zset = '\0';
1130
1131 if (zname != NULL)
1132 {
1133 int clen;
1134
1135 clen = strlen (zportname);
1136 if (strncmp (zname, zportname, clen) != 0
1137 || strlen (zname) <= clen
1138 || strcmp (zname + clen, zclass) != 0)
1139 {
1140 xfree ((pointer) zline);
1141 continue;
1142 }
1143 }
1144 }
1145
1146 ilow = strtol (ztok, &ztok, 10);
1147 if (ilow == 0)
1148 ihigh = 38400L;
1149 else
1150 {
1151 if (*ztok == '-')
1152 ihigh = atol (ztok + 1);
1153 else
1154 ihigh = ilow;
1155 }
1156
1157 /* Now we must match the range ibaud to ihighbaud against to
1158 range ilow to ihigh. */
1159 if (ibaud != 0
1160 && (ihighbaud < ilow || ibaud > ihigh))
1161 {
1162 xfree ((pointer) zline);
1163 continue;
1164 }
1165
1166 /* We have found a matching port. We now fill in the sport
1167 structure so that we can try to lock it. */
1168 if (zname != NULL)
1169 qport->zname = zname;
1170 else
1171 qport->zname = zportname;
1172 qport->zprotocols = zprotocols;
1173 qport->cproto_params = 0;
1174 qport->qproto_params = NULL;
1175 qport->ireliable = 0;
1176 qport->zlockname = NULL;
1177 if (strcmp (qport->zname, "Direct") == 0)
1178 {
1179 qport->ttype = PORTTYPE_DIRECT;
1180 qport->u.sdirect.zdevice = zdevice;
1181 qport->u.sdirect.ibaud = ilow;
1182 #ifdef SYSDEP_DIRECT_INIT
1183 SYSDEP_DIRECT_INIT (&qport->u.sdirect.s);
1184 #endif
1185 }
1186 #if HAVE_TCP
1187 else if (strcmp (qport->zname, "TCP") == 0)
1188 {
1189 qport->ttype = PORTTYPE_TCP;
1190 qport->ireliable = (RELIABLE_ENDTOEND
1191 | RELIABLE_RELIABLE
1192 | RELIABLE_EIGHT
1193 | RELIABLE_SPECIFIED);
1194 qport->u.stcp.o = -1;
1195 qport->u.stcp.zport = zdevice;
1196 }
1197 #endif /* HAVE_TCP */
1198 else
1199 {
1200 qport->ttype = PORTTYPE_MODEM;
1201 qport->u.smodem.zdevice = zdevice;
1202 qport->u.smodem.zdial_device = zdial_device;
1203 if (ilow != ihigh)
1204 qport->u.smodem.ibaud = 0;
1205 else
1206 qport->u.smodem.ibaud = ilow;
1207 qport->u.smodem.ilowbaud = ilow;
1208 qport->u.smodem.ihighbaud = ihigh;
1209 qport->u.smodem.fcarrier = TRUE;
1210 qport->u.smodem.zdialer = strtok ((char *) NULL, "");
1211 qport->u.smodem.zdialer += strspn (qport->u.smodem.zdialer,
1212 " \t");
1213 qport->u.smodem.qdialer = NULL;
1214 #ifdef SYSDEP_MODEM_INIT
1215 SYSDEP_MODEM_INIT (&qport->u.smodem.s);
1216 #endif
1217 }
1218
1219 if (pffound != NULL)
1220 *pffound = TRUE;
1221
1222 if (pflock != NULL
1223 && ! (*pflock) (qport, FALSE))
1224 {
1225 xfree ((pointer) zline);
1226 continue;
1227 }
1228
1229 (void) fmulti_close (qmulti);
1230
1231 return TRUE;
1232 }
1233
1234 (void) fmulti_close (qmulti);
1235
1236 return FALSE;
1237 }
1238
1239 /* Read dialer information from the Dialers file. */
1240
1241 boolean
fbnu_read_dialer_info(zdialer,qdialer)1242 fbnu_read_dialer_info (zdialer, qdialer)
1243 const char *zdialer;
1244 struct sdialer *qdialer;
1245 {
1246 struct smulti_file *qmulti;
1247 char *zline;
1248
1249 qmulti = qmulti_open (zBnu_dialers);
1250 if (qmulti == NULL)
1251 return FALSE;
1252
1253 while ((zline = zmulti_gets (qmulti, (boolean *) NULL,
1254 (const char **) NULL, TRUE)) != NULL)
1255 {
1256 int inl;
1257 char *zname, *zsubs;
1258
1259 inl = strlen (zline) - 1;
1260 if (zline[inl] == '\n')
1261 zline[inl] = '\0';
1262 if (isspace (BUCHAR (zline[0])) || zline[0] == '#')
1263 {
1264 xfree ((pointer) zline);
1265 continue;
1266 }
1267
1268 zname = strtok (zline, " \t");
1269 if (zname == NULL
1270 || strcmp (zname, zdialer) != 0)
1271 {
1272 xfree ((pointer) zline);
1273 continue;
1274 }
1275
1276 /* We found the dialer we want. Get information from it. */
1277
1278 qdialer->zname = zdialer;
1279 INIT_CHAT (&qdialer->schat);
1280 qdialer->zdialtone = ",";
1281 qdialer->zpause = ",";
1282 qdialer->fcarrier = TRUE;
1283 qdialer->ccarrier_wait = 60;
1284 qdialer->fdtr_toggle = FALSE;
1285 qdialer->fdtr_toggle_wait = FALSE;
1286 INIT_CHAT (&qdialer->scomplete);
1287 INIT_CHAT (&qdialer->sabort);
1288 qdialer->cproto_params = 0;
1289 qdialer->qproto_params = NULL;
1290 qdialer->ireliable = 0;
1291
1292 zsubs = strtok ((char *) NULL, " \t");
1293
1294 if (zsubs != NULL && strcmp (zsubs, "\"\"") != 0)
1295 {
1296 char bnext;
1297
1298 bnext = *zsubs;
1299 while (bnext != '\0')
1300 {
1301 if (zsubs[1] == '\0')
1302 break;
1303 if (bnext == '=')
1304 qdialer->zdialtone = zsubs + 1;
1305 else if (bnext == '-')
1306 qdialer->zpause = zsubs + 1;
1307 zsubs += 2;
1308 bnext = *zsubs;
1309 *zsubs = '\0';
1310 }
1311 }
1312
1313 if (zsubs == NULL)
1314 qdialer->schat.zchat = NULL;
1315 else
1316 {
1317 qdialer->schat.zchat = strtok ((char *) NULL, "");
1318 qdialer->schat.zchat += strspn (qdialer->schat.zchat, " \t");
1319 }
1320
1321 (void) fmulti_close (qmulti);
1322
1323 return TRUE;
1324 }
1325
1326 (void) fmulti_close (qmulti);
1327
1328 return FALSE;
1329 }
1330
1331 #endif /* HAVE_BNU_CONFIG */
1332