comparison usr/src/cmd/bnu/sysfiles.c @ 0:c9caec207d52 b86

Initial porting based on b86
author Koji Uno <koji.uno@sun.com>
date Tue, 02 Jun 2009 18:56:50 +0900
parents
children 1a15d5aaf794
comparison
equal deleted inserted replaced
-1:000000000000 0:c9caec207d52
1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22 /*
23 * Copyright 1998 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
29
30
31 #pragma ident "@(#)sysfiles.c 1.12 05/06/08 SMI"
32
33 #include "uucp.h"
34
35 #include <unistd.h>
36 #include "sysfiles.h"
37 #include <sys/stropts.h>
38
39 /*
40 * manage systems files (Systems, Devices, and Dialcodes families).
41 *
42 * also manage new file Devconfig, allows per-device setup.
43 * present use is to specify what streams modules to push/pop for
44 * AT&T TLI/streams network.
45 *
46 * TODO:
47 * call bsfix()?
48 * combine the 3 versions of everything (sys, dev, and dial) into one.
49 * allow arbitrary classes of service.
50 * need verifysys() for uucheck.
51 * nameserver interface?
52 * pass sysname (or 0) to getsysline(). (might want reg. exp. or NS processing
53 */
54
55 /* private variables */
56 static void tokenize(), nameparse(), setfile(), setioctl(),
57 scansys(), scancfg(), setconfig();
58 static int namematch(), nextdialers(), nextdevices(), nextsystems(), getline();
59
60 /* pointer arrays might be dynamically allocated */
61 static char *Systems[64] = {0}; /* list of Systems files */
62 static char *Devices[64] = {0}; /* list of Devices files */
63 static char *Dialers[64] = {0}; /* list of Dialers files */
64 static char *Pops[64] = {0}; /* list of STREAMS modules to be popped */
65 static char *Pushes[64] = {0}; /* list of STREAMS modules to be pushed */
66
67 static int nsystems; /* index into list of Systems files */
68 static int ndevices; /* index into list of Devices files */
69 static int ndialers; /* index into list of Dialers files */
70 static int npops; /* index into list of STREAMS modules */
71 /*to be popped */
72 static int npushes; /* index into list of STREAMS modules */
73 /*to be pushed */
74
75 GLOBAL unsigned connecttime = CONNECTTIME;
76 GLOBAL unsigned expecttime = EXPECTTIME;
77 GLOBAL unsigned msgtime = MSGTIME;
78
79 static FILE *fsystems;
80 static FILE *fdevices;
81 static FILE *fdialers;
82
83 static char errformat[BUFSIZ];
84
85 /* this might be dynamically allocated */
86 #define NTOKENS 16
87 static char *tokens[NTOKENS], **tokptr;
88
89 /* export these */
90 EXTERN void sysreset(), devreset(), dialreset(), setdevcfg(), setservice();
91 EXTERN char *strsave();
92
93 /* import these */
94 extern char *strcpy(), *strtok(), *strchr(), *strsave();
95 EXTERN int eaccess();
96
97 /*
98 * setservice init's Systems, Devices, Dialers lists from Sysfiles
99 */
100 GLOBAL void
101 setservice(service)
102 char *service;
103 {
104 char *prev = _uu_setlocale(LC_ALL, "C");
105
106 setconfig();
107 scansys(service);
108 (void) _uu_resetlocale(LC_ALL, prev);
109 return;
110 }
111
112 /*
113 * setdevcfg init's Pops, Pushes lists from Devconfig
114 */
115
116 GLOBAL void
117 setdevcfg(service, device)
118 char *service, *device;
119 {
120 char *prev = _uu_setlocale(LC_ALL, "C");
121
122 scancfg(service, device);
123 (void) _uu_resetlocale(LC_ALL, prev);
124 return;
125 }
126
127 /* administrative files access */
128 GLOBAL int
129 sysaccess(type)
130 int type;
131 {
132 switch (type) {
133
134 case ACCESS_SYSTEMS:
135 return(access(Systems[nsystems], R_OK));
136 case ACCESS_DEVICES:
137 return(access(Devices[ndevices], R_OK));
138 case ACCESS_DIALERS:
139 return(access(Dialers[ndialers], R_OK));
140 case EACCESS_SYSTEMS:
141 return(eaccess(Systems[nsystems], R_OK));
142 case EACCESS_DEVICES:
143 return(eaccess(Devices[ndevices], R_OK));
144 case EACCESS_DIALERS:
145 return(eaccess(Dialers[ndialers], R_OK));
146 default:
147 (void)sprintf(errformat, "bad access type %d", type);
148 logent(errformat, "sysaccess");
149 return(FAIL);
150 }
151 }
152
153
154 /*
155 * read Sysfiles, set up lists of Systems/Devices/Dialers file names.
156 * allow multiple entries for a given service, allow a service
157 * type to describe resources more than once, e.g., systems=foo:baz systems=bar.
158 */
159 static void
160 scansys(service)
161 char *service;
162 { FILE *f;
163 char *tok, buf[BUFSIZ];
164
165 Systems[0] = Devices[0] = Dialers[0] = NULL;
166 if ((f = fopen(SYSFILES, "r")) != 0) {
167 while (getline(f, buf) > 0) {
168 /* got a (logical) line from Sysfiles */
169 /* strtok's of this buf continue in tokenize() */
170 tok = strtok(buf, " \t");
171 if (namematch("service=", tok, service)) {
172 tokenize();
173 nameparse();
174 }
175 }
176 (void) fclose(f);
177 }
178
179 /* if didn't find entries in Sysfiles, use defaults */
180 if (Systems[0] == NULL) {
181 Systems[0] = strsave(SYSTEMS);
182 ASSERT(Systems[0] != NULL, Ct_ALLOCATE, "scansys: Systems", 0);
183 Systems[1] = NULL;
184 }
185 if (Devices[0] == NULL) {
186 Devices[0] = strsave(DEVICES);
187 ASSERT(Devices[0] != NULL, Ct_ALLOCATE, "scansys: Devices", 0);
188 Devices[1] = NULL;
189 }
190 if (Dialers[0] == NULL) {
191 Dialers[0] = strsave(DIALERS);
192 ASSERT(Dialers[0] != NULL, Ct_ALLOCATE, "scansys: Dialers", 0);
193 Dialers[1] = NULL;
194 }
195 return;
196 }
197
198
199 /*
200 * read Devconfig. allow multiple entries for a given service, allow a service
201 * type to describe resources more than once, e.g., push=foo:baz push=bar.
202 */
203 static void
204 scancfg(service, device)
205 char *service, *device;
206 { FILE *f;
207 char *tok, buf[BUFSIZ];
208
209 /* (re)initialize device-specific information */
210
211 npops = npushes = 0;
212 Pops[0] = Pushes[0] = NULL;
213 connecttime = CONNECTTIME;
214 expecttime = EXPECTTIME;
215 msgtime = MSGTIME;
216
217 if ((f = fopen(DEVCONFIG, "r")) != 0) {
218 while (getline(f, buf) > 0) {
219 /* got a (logical) line from Devconfig */
220 /* strtok's of this buf continue in tokenize() */
221 tok = strtok(buf, " \t");
222 if (namematch("service=", tok, service)) {
223 tok = strtok((char *)0, " \t");
224 if ( namematch("device=", tok, device)) {
225 tokenize();
226 nameparse();
227 }
228 }
229 }
230 (void) fclose(f);
231 }
232
233 return;
234
235 }
236
237 /*
238 * given a file pointer and buffer, construct logical line in buffer
239 * (i.e., concatenate lines ending in '\'). return length of line
240 * ASSUMES that buffer is BUFSIZ long!
241 */
242
243 static int
244 getline(f, line)
245 FILE *f;
246 char *line;
247 { char *lptr, *lend;
248
249 lptr = line;
250 while (fgets(lptr, (line + BUFSIZ) - lptr, f) != NULL) {
251 lend = lptr + strlen(lptr);
252 if (lend == lptr || lend[-1] != '\n')
253 /* empty buf or line too long! */
254 break;
255 *--lend = '\0'; /* lop off ending '\n' */
256 if ( lend == line ) /* empty line - ignore */
257 continue;
258 lptr = lend;
259 if (lend[-1] != '\\')
260 break;
261 /* continuation */
262 lend[-1] = ' ';
263 }
264 return(lptr - line);
265 }
266
267 /*
268 * given a label (e.g., "service=", "device="), a name ("cu", "uucico"),
269 * and a line: if line begins with the label and if the name appears
270 * in a colon-separated list of names following the label, return true;
271 * else return false
272 */
273 static int
274 namematch(label, line, name)
275 char *label, *line, *name;
276 { char *lend;
277
278 if (strncmp(label, line, strlen(label)) != SAME) {
279 return(FALSE); /* probably a comment line */
280 }
281 line += strlen(label);
282 if (*line == '\0')
283 return(FALSE);
284 /*
285 * can't use strtok() in the following because scansys(),
286 * scancfg() do an initializing call to strtok() before
287 * coming here and then CONTINUE calling strtok() in tokenize(),
288 * after returning from namematch().
289 */
290 while ((lend = strchr(line, ':')) != NULL) {
291 *lend = '\0';
292 if (strcmp(line, name) == SAME)
293 return(TRUE);
294 line = lend+1;
295 }
296 return(strcmp(line, name) == SAME);
297 }
298
299 /*
300 * tokenize() continues pulling tokens out of a buffer -- the
301 * initializing call to strtok must have been made before calling
302 * tokenize() -- and starts stuffing 'em into tokptr.
303 */
304 static void
305 tokenize()
306 { char *tok;
307
308 tokptr = tokens;
309 while ((tok = strtok((char *) NULL, " \t")) != NULL) {
310 *tokptr++ = tok;
311 if (tokptr - tokens >= NTOKENS)
312 break;
313 }
314 *tokptr = NULL;
315 return;
316 }
317
318 /*
319 * look at top token in array: should be line of the form
320 * name=item1:item2:item3...
321 * if name is one we recognize, then call set[file|ioctl] to set up
322 * corresponding list. otherwise, log bad name.
323 */
324 static void
325 nameparse()
326 { char **line, *equals;
327 int temp;
328
329 #define setuint(a,b,c) a = ( ((temp = atoi(b)) <= 0) ? (c) : temp )
330
331 for (line = tokens; (line - tokens) < NTOKENS && *line; line++) {
332 equals = strchr(*line, '=');
333 if (equals == NULL)
334 continue; /* may be meaningful someday? */
335 *equals = '\0';
336 /* ignore entry with empty rhs */
337 if (*++equals == '\0')
338 continue;
339 if (strcmp(*line, "systems") == SAME)
340 setfile(Systems, equals);
341 else if (strcmp(*line, "devices") == SAME)
342 setfile(Devices, equals);
343 else if (strcmp(*line, "dialers") == SAME)
344 setfile(Dialers, equals);
345 else if (strcmp(*line, "pop") == SAME)
346 setioctl(Pops, equals);
347 else if (strcmp(*line, "push") == SAME)
348 setioctl(Pushes, equals);
349 else if (strcmp(*line, "connecttime") == SAME)
350 setuint(connecttime, equals, CONNECTTIME);
351 else if (strcmp(*line, "expecttime") == SAME)
352 setuint(expecttime, equals, EXPECTTIME);
353 else if (strcmp(*line, "msgtime") == SAME)
354 setuint(msgtime, equals, MSGTIME);
355 else {
356 (void)sprintf(errformat,"unrecognized label %s",*line);
357 logent(errformat, "Sysfiles|Devconfig");
358 }
359 }
360 return;
361 }
362
363 /*
364 * given the list for a particular type (systems, devices,...)
365 * and a line of colon-separated files, add 'em to list
366 */
367
368 static void
369 setfile(type, line)
370 char **type, *line;
371 { char **tptr, *tok;
372 char expandpath[BUFSIZ];
373
374 if (*line == 0)
375 return;
376 tptr = type;
377 while (*tptr) /* skip over existing entries to*/
378 tptr++; /* concatenate multiple entries */
379
380 for (tok = strtok(line, ":"); tok != NULL;
381 tok = strtok((char *) NULL, ":")) {
382 expandpath[0] = '\0';
383 if ( *tok != '/' )
384 /* by default, file names are relative to SYSDIR */
385 sprintf(expandpath, "%s/", SYSDIR);
386 strcat(expandpath, tok);
387 if (eaccess(expandpath, R_OK) != 0)
388 /* if we can't read it, no point in adding to list */
389 continue;
390 *tptr = strsave(expandpath);
391 ASSERT(*tptr != NULL, Ct_ALLOCATE, "setfile: tptr", 0);
392 tptr++;
393 }
394 return;
395 }
396
397 /*
398 * given the list for a particular ioctl (push, pop)
399 * and a line of colon-separated modules, add 'em to list
400 */
401
402 static void
403 setioctl(type, line)
404 char **type, *line;
405 { char **tptr, *tok;
406
407 if (*line == 0)
408 return;
409 tptr = type;
410 while (*tptr) /* skip over existing entries to*/
411 tptr++; /* concatenate multiple entries */
412 for (tok = strtok(line, ":"); tok != NULL;
413 tok = strtok((char *) NULL, ":")) {
414 *tptr = strsave(tok);
415 ASSERT(*tptr != NULL, Ct_ALLOCATE, "setioctl: tptr", 0);
416 tptr++;
417 }
418 return;
419 }
420
421 /*
422 * reset Systems files
423 */
424 GLOBAL void
425 sysreset()
426 {
427 if (fsystems)
428 fclose(fsystems);
429 fsystems = NULL;
430 nsystems = 0;
431 devreset();
432 return;
433 }
434
435 /*
436 * reset Devices files
437 */
438 GLOBAL void
439 devreset()
440 {
441 if (fdevices)
442 fclose(fdevices);
443 fdevices = NULL;
444 ndevices = 0;
445 dialreset();
446 return;
447 }
448
449 /*
450 * reset Dialers files
451 */
452 GLOBAL void
453 dialreset()
454 {
455 if (fdialers)
456 fclose(fdialers);
457 fdialers = NULL;
458 ndialers = 0;
459 return;
460 }
461
462 /*
463 * get next line from Systems file
464 * return TRUE if successful, FALSE if not
465 */
466 GLOBAL int
467 getsysline(buf, len)
468 char *buf;
469 {
470 char *prev = _uu_setlocale(LC_ALL, "C");
471
472 if (Systems[0] == NULL)
473 /* not initialized via setservice() - use default */
474 setservice("uucico");
475
476 /* initialize devices and dialers whenever a new line is read */
477 /* from systems */
478 devreset();
479 if (fsystems == NULL)
480 if (nextsystems() == FALSE) {
481 (void) _uu_resetlocale(LC_ALL, prev);
482 return(FALSE);
483 }
484
485 ASSERT(len >= BUFSIZ, "BUFFER TOO SMALL", "getsysline", 0);
486 for(;;) {
487 while (getline(fsystems, buf) != NULL)
488 if ((*buf != '#') && (*buf != ' ') &&
489 (*buf != '\t') && (*buf != '\n')) {
490 (void) _uu_resetlocale(LC_ALL, prev);
491 return(TRUE);
492 }
493 if (nextsystems() == FALSE) {
494 (void) _uu_resetlocale(LC_ALL, prev);
495 return(FALSE);
496 }
497 }
498 }
499
500 /*
501 * move to next systems file. return TRUE if successful, FALSE if not
502 */
503 static int
504 nextsystems()
505 {
506 devreset();
507
508 if (fsystems != NULL) {
509 (void) fclose(fsystems);
510 nsystems++;
511 } else {
512 nsystems = 0;
513 }
514 for ( ; Systems[nsystems] != NULL; nsystems++)
515 if ((fsystems = fopen(Systems[nsystems], "r")) != NULL)
516 return(TRUE);
517 return(FALSE);
518 }
519
520 /*
521 * get next line from Devices file
522 * return TRUE if successful, FALSE if not
523 */
524 GLOBAL int
525 getdevline(buf, len)
526 char *buf;
527 {
528 char *prev = _uu_setlocale(LC_ALL, "C");
529
530 if (Devices[0] == NULL)
531 /* not initialized via setservice() - use default */
532 setservice("uucico");
533
534 if (fdevices == NULL)
535 if (nextdevices() == FALSE) {
536 (void) _uu_resetlocale(LC_ALL, prev);
537 return(FALSE);
538 }
539 for(;;) {
540 if (fgets(buf, len, fdevices) != NULL) {
541 (void) _uu_resetlocale(LC_ALL, prev);
542 return(TRUE);
543 }
544 if (nextdevices() == FALSE) {
545 (void) _uu_resetlocale(LC_ALL, prev);
546 return(FALSE);
547 }
548 }
549 }
550
551 /*
552 * move to next devices file. return TRUE if successful, FALSE if not
553 */
554 static int
555 nextdevices()
556 {
557 if (fdevices != NULL) {
558 (void) fclose(fdevices);
559 ndevices++;
560 } else {
561 ndevices = 0;
562 }
563 for ( ; Devices[ndevices] != NULL; ndevices++)
564 if ((fdevices = fopen(Devices[ndevices], "r")) != NULL)
565 return(TRUE);
566 return(FALSE);
567 }
568
569
570 /*
571 * get next line from Dialers file
572 * return TRUE if successful, FALSE if not
573 */
574
575 GLOBAL int
576 getdialline(buf, len)
577 char *buf;
578 {
579 char *prev = _uu_setlocale(LC_ALL, "C");
580
581 if (Dialers[0] == NULL)
582 /* not initialized via setservice() - use default */
583 setservice("uucico");
584
585 if (fdialers == NULL)
586 if (nextdialers() == FALSE) {
587 (void) _uu_resetlocale(LC_ALL, prev);
588 return(FALSE);
589 }
590 for(;;) {
591 if (fgets(buf, len, fdialers) != NULL) {
592 (void) _uu_resetlocale(LC_ALL, prev);
593 return(TRUE);
594 }
595 if (nextdialers() == FALSE) {
596 (void) _uu_resetlocale(LC_ALL, prev);
597 return(FALSE);
598 }
599 }
600 }
601
602 /*
603 * move to next dialers file. return TRUE if successful, FALSE if not
604 */
605 static int
606 nextdialers()
607 {
608 if (fdialers) {
609 (void) fclose(fdialers);
610 ndialers++;
611 } else {
612 ndialers = 0;
613 }
614
615 for ( ; Dialers[ndialers] != NULL; ndialers++)
616 if ((fdialers = fopen(Dialers[ndialers], "r")) != NULL)
617 return(TRUE);
618 return(FALSE);
619 }
620
621 /*
622 * get next module to be popped
623 * return TRUE if successful, FALSE if not
624 */
625 static int
626 getpop(buf, len, optional)
627 char *buf;
628 int len, *optional;
629 {
630 int slen;
631
632 if ( Pops[0] == NULL || Pops[npops] == NULL )
633 return(FALSE);
634
635 /* if the module name is enclosed in parentheses, */
636 /* is optional. set flag & strip parens */
637 slen = strlen(Pops[npops]) - 1;
638 if ( Pops[npops][0] == '(' && Pops[npops][slen] == ')' ) {
639 *optional = 1;
640 len = ( slen < len ? slen : len );
641 strncpy(buf, &(Pops[npops++][1]), len);
642 } else {
643 *optional = 0;
644 strncpy(buf, Pops[npops++], len);
645 }
646 buf[len-1] = '\0';
647 return(TRUE);
648 }
649
650 /*
651 * get next module to be pushed
652 * return TRUE if successful, FALSE if not
653 */
654 static int
655 getpush(buf, len)
656 char *buf;
657 int len;
658 {
659 if ( Pushes[0] == NULL || Pushes[npushes] == NULL )
660 return(FALSE);
661 strncpy(buf, Pushes[npushes++], len);
662 return(TRUE);
663 }
664
665 /*
666 * pop/push requested modules
667 * return TRUE if successful, FALSE if not
668 */
669 GLOBAL int
670 pop_push(fd)
671 int fd;
672 {
673 char strmod[FMNAMESZ], onstream[FMNAMESZ];
674 int optional;
675 char *prev = _uu_setlocale(LC_ALL, "C");
676
677 /* check for streams modules to pop */
678 while ( getpop(strmod, sizeof(strmod), &optional) ) {
679 DEBUG(5, (optional ? "pop_push: optionally POPing %s\n"
680 : "pop_push: POPing %s\n" ), strmod);
681 if ( ioctl(fd, I_LOOK, onstream) == -1 ) {
682 DEBUG(5, "pop_push: I_LOOK on fd %d failed ", fd);
683 DEBUG(5, "errno %d\n", errno);
684 (void) _uu_resetlocale(LC_ALL, prev);
685 return(FALSE);
686 }
687 if ( strcmp(strmod, onstream) != SAME ) {
688 if ( optional )
689 continue;
690 DEBUG(5, "pop_push: I_POP: %s not there\n", strmod);
691 (void) _uu_resetlocale(LC_ALL, prev);
692 return(FALSE);
693 }
694 if ( ioctl(fd, I_POP, 0) == -1 ) {
695 DEBUG(5, "pop_push: I_POP on fd %d failed ", fd);
696 DEBUG(5, "errno %d\n", errno);
697 (void) _uu_resetlocale(LC_ALL, prev);
698 return(FALSE);
699 }
700 }
701
702 /* check for streams modules to push */
703 while ( getpush(strmod, sizeof(strmod)) ) {
704 DEBUG(5, "pop_push: PUSHing %s\n", strmod);
705 if ( ioctl(fd, I_PUSH, strmod) == -1 ) {
706 DEBUG(5, "pop_push: I_PUSH on fd %d failed ", fd);
707 DEBUG(5, "errno %d\n", errno);
708 (void) _uu_resetlocale(LC_ALL, prev);
709 return(FALSE);
710 }
711 }
712 (void) _uu_resetlocale(LC_ALL, prev);
713 return(TRUE);
714 }
715
716 /*
717 * return name of currently open Systems file
718 */
719 GLOBAL char *
720 currsys()
721 {
722 return(Systems[nsystems]);
723 }
724
725 /*
726 * return name of currently open Devices file
727 */
728 GLOBAL char *
729 currdev()
730 {
731 return(Devices[ndevices]);
732 }
733
734 /*
735 * return name of currently open Dialers file
736 */
737 GLOBAL char *
738 currdial()
739 {
740 return(Dialers[ndialers]);
741 }
742
743 /*
744 * set configuration parameters provided in Config file
745 */
746 static void
747 setconfig()
748 {
749 FILE *f;
750 char buf[BUFSIZ];
751 char *tok;
752 extern char _ProtoCfg[];
753
754 if ((f = fopen(CONFIG, "r")) != 0) {
755 while (getline(f, buf) > 0) {
756 /* got a (logical) line from Config file */
757 tok = strtok(buf, " \t");
758 if ( (tok != NULL) && (*tok != '#') ) {
759 /* got a token */
760
761 /* this probably should be table driven when
762 * the list of configurable parameters grows.
763 */
764 if (strncmp("Protocol=", tok, strlen("Protocol=")) == SAME) {
765 tok += strlen("Protocol=");
766 if ( *tok != '\0' ) {
767 if ( _ProtoCfg[0] != '\0' ) {
768 DEBUG(7, "Protocol string %s ", tok);
769 DEBUG(7, "overrides %s\n", _ProtoCfg);
770 }
771 strcpy(_ProtoCfg, tok);
772 }
773 } else {
774 DEBUG(7, "Unknown configuration parameter %s\n", tok);
775 }
776 }
777 }
778 }
779 }