4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved.
26 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
27 /* All Rights Reserved */
33 #include <sys/stropts.h>
36 * manage systems files (Systems, Devices, and Dialcodes families).
38 * also manage new file Devconfig, allows per-device setup.
39 * present use is to specify what streams modules to push/pop for
40 * AT&T TLI/streams network.
44 * combine the 3 versions of everything (sys, dev, and dial) into one.
45 * allow arbitrary classes of service.
46 * need verifysys() for uucheck.
47 * nameserver interface?
48 * pass sysname (or 0) to getsysline(). (might want reg. exp. or NS processing
51 /* private variables */
52 static void tokenize(), nameparse(), setfile(), setioctl(),
53 scansys(), scancfg(), setconfig();
54 static int namematch(), nextdialers(), nextdevices(), nextsystems(), getaline();
56 /* pointer arrays might be dynamically allocated */
57 static char *Systems
[64] = {0}; /* list of Systems files */
58 static char *Devices
[64] = {0}; /* list of Devices files */
59 static char *Dialers
[64] = {0}; /* list of Dialers files */
60 static char *Pops
[64] = {0}; /* list of STREAMS modules to be popped */
61 static char *Pushes
[64] = {0}; /* list of STREAMS modules to be pushed */
63 static int nsystems
; /* index into list of Systems files */
64 static int ndevices
; /* index into list of Devices files */
65 static int ndialers
; /* index into list of Dialers files */
66 static int npops
; /* index into list of STREAMS modules */
68 static int npushes
; /* index into list of STREAMS modules */
71 GLOBAL
unsigned connecttime
= CONNECTTIME
;
72 GLOBAL
unsigned expecttime
= EXPECTTIME
;
73 GLOBAL
unsigned msgtime
= MSGTIME
;
75 static FILE *fsystems
;
76 static FILE *fdevices
;
77 static FILE *fdialers
;
79 static char errformat
[BUFSIZ
];
81 /* this might be dynamically allocated */
83 static char *tokens
[NTOKENS
], **tokptr
;
86 EXTERN
void sysreset(), devreset(), dialreset(), setdevcfg(), setservice();
87 EXTERN
char *strsave();
90 extern char *strcpy(), *strtok(), *strchr(), *strsave();
94 * setservice init's Systems, Devices, Dialers lists from Sysfiles
100 char *prev
= _uu_setlocale(LC_ALL
, "C");
104 (void) _uu_resetlocale(LC_ALL
, prev
);
109 * setdevcfg init's Pops, Pushes lists from Devconfig
113 setdevcfg(service
, device
)
114 char *service
, *device
;
116 char *prev
= _uu_setlocale(LC_ALL
, "C");
118 scancfg(service
, device
);
119 (void) _uu_resetlocale(LC_ALL
, prev
);
123 /* administrative files access */
131 return(access(Systems
[nsystems
], R_OK
));
133 return(access(Devices
[ndevices
], R_OK
));
135 return(access(Dialers
[ndialers
], R_OK
));
136 case EACCESS_SYSTEMS
:
137 return(eaccess(Systems
[nsystems
], R_OK
));
138 case EACCESS_DEVICES
:
139 return(eaccess(Devices
[ndevices
], R_OK
));
140 case EACCESS_DIALERS
:
141 return(eaccess(Dialers
[ndialers
], R_OK
));
143 (void)sprintf(errformat
, "bad access type %d", type
);
144 logent(errformat
, "sysaccess");
151 * read Sysfiles, set up lists of Systems/Devices/Dialers file names.
152 * allow multiple entries for a given service, allow a service
153 * type to describe resources more than once, e.g., systems=foo:baz systems=bar.
159 char *tok
, buf
[BUFSIZ
];
161 Systems
[0] = Devices
[0] = Dialers
[0] = NULL
;
162 if ((f
= fopen(SYSFILES
, "r")) != 0) {
163 while (getaline(f
, buf
) > 0) {
164 /* got a (logical) line from Sysfiles */
165 /* strtok's of this buf continue in tokenize() */
166 tok
= strtok(buf
, " \t");
167 if (namematch("service=", tok
, service
)) {
175 /* if didn't find entries in Sysfiles, use defaults */
176 if (Systems
[0] == NULL
) {
177 Systems
[0] = strsave(SYSTEMS
);
178 ASSERT(Systems
[0] != NULL
, Ct_ALLOCATE
, "scansys: Systems", 0);
181 if (Devices
[0] == NULL
) {
182 Devices
[0] = strsave(DEVICES
);
183 ASSERT(Devices
[0] != NULL
, Ct_ALLOCATE
, "scansys: Devices", 0);
186 if (Dialers
[0] == NULL
) {
187 Dialers
[0] = strsave(DIALERS
);
188 ASSERT(Dialers
[0] != NULL
, Ct_ALLOCATE
, "scansys: Dialers", 0);
196 * read Devconfig. allow multiple entries for a given service, allow a service
197 * type to describe resources more than once, e.g., push=foo:baz push=bar.
200 scancfg(service
, device
)
201 char *service
, *device
;
203 char *tok
, buf
[BUFSIZ
];
205 /* (re)initialize device-specific information */
208 Pops
[0] = Pushes
[0] = NULL
;
209 connecttime
= CONNECTTIME
;
210 expecttime
= EXPECTTIME
;
213 if ((f
= fopen(DEVCONFIG
, "r")) != 0) {
214 while (getaline(f
, buf
) > 0) {
215 /* got a (logical) line from Devconfig */
216 /* strtok's of this buf continue in tokenize() */
217 tok
= strtok(buf
, " \t");
218 if (namematch("service=", tok
, service
)) {
219 tok
= strtok((char *)0, " \t");
220 if ( namematch("device=", tok
, device
)) {
234 * given a file pointer and buffer, construct logical line in buffer
235 * (i.e., concatenate lines ending in '\'). return length of line
236 * ASSUMES that buffer is BUFSIZ long!
246 while (fgets(lptr
, (line
+ BUFSIZ
) - lptr
, f
) != NULL
) {
247 lend
= lptr
+ strlen(lptr
);
248 if (lend
== lptr
|| lend
[-1] != '\n')
249 /* empty buf or line too long! */
251 *--lend
= '\0'; /* lop off ending '\n' */
252 if ( lend
== line
) /* empty line - ignore */
255 if (lend
[-1] != '\\')
264 * given a label (e.g., "service=", "device="), a name ("cu", "uucico"),
265 * and a line: if line begins with the label and if the name appears
266 * in a colon-separated list of names following the label, return true;
270 namematch(label
, line
, name
)
271 char *label
, *line
, *name
;
274 if (strncmp(label
, line
, strlen(label
)) != SAME
) {
275 return(FALSE
); /* probably a comment line */
277 line
+= strlen(label
);
281 * can't use strtok() in the following because scansys(),
282 * scancfg() do an initializing call to strtok() before
283 * coming here and then CONTINUE calling strtok() in tokenize(),
284 * after returning from namematch().
286 while ((lend
= strchr(line
, ':')) != NULL
) {
288 if (strcmp(line
, name
) == SAME
)
292 return(strcmp(line
, name
) == SAME
);
296 * tokenize() continues pulling tokens out of a buffer -- the
297 * initializing call to strtok must have been made before calling
298 * tokenize() -- and starts stuffing 'em into tokptr.
305 while ((tok
= strtok((char *) NULL
, " \t")) != NULL
) {
307 if (tokptr
- tokens
>= NTOKENS
)
315 * look at top token in array: should be line of the form
316 * name=item1:item2:item3...
317 * if name is one we recognize, then call set[file|ioctl] to set up
318 * corresponding list. otherwise, log bad name.
322 { char **line
, *equals
;
325 #define setuint(a,b,c) a = ( ((temp = atoi(b)) <= 0) ? (c) : temp )
327 for (line
= tokens
; (line
- tokens
) < NTOKENS
&& *line
; line
++) {
328 equals
= strchr(*line
, '=');
330 continue; /* may be meaningful someday? */
332 /* ignore entry with empty rhs */
333 if (*++equals
== '\0')
335 if (strcmp(*line
, "systems") == SAME
)
336 setfile(Systems
, equals
);
337 else if (strcmp(*line
, "devices") == SAME
)
338 setfile(Devices
, equals
);
339 else if (strcmp(*line
, "dialers") == SAME
)
340 setfile(Dialers
, equals
);
341 else if (strcmp(*line
, "pop") == SAME
)
342 setioctl(Pops
, equals
);
343 else if (strcmp(*line
, "push") == SAME
)
344 setioctl(Pushes
, equals
);
345 else if (strcmp(*line
, "connecttime") == SAME
)
346 setuint(connecttime
, equals
, CONNECTTIME
);
347 else if (strcmp(*line
, "expecttime") == SAME
)
348 setuint(expecttime
, equals
, EXPECTTIME
);
349 else if (strcmp(*line
, "msgtime") == SAME
)
350 setuint(msgtime
, equals
, MSGTIME
);
352 (void)sprintf(errformat
,"unrecognized label %s",*line
);
353 logent(errformat
, "Sysfiles|Devconfig");
360 * given the list for a particular type (systems, devices,...)
361 * and a line of colon-separated files, add 'em to list
368 char expandpath
[BUFSIZ
];
373 while (*tptr
) /* skip over existing entries to*/
374 tptr
++; /* concatenate multiple entries */
376 for (tok
= strtok(line
, ":"); tok
!= NULL
;
377 tok
= strtok((char *) NULL
, ":")) {
378 expandpath
[0] = '\0';
380 /* by default, file names are relative to SYSDIR */
381 sprintf(expandpath
, "%s/", SYSDIR
);
382 strcat(expandpath
, tok
);
383 if (eaccess(expandpath
, R_OK
) != 0)
384 /* if we can't read it, no point in adding to list */
386 *tptr
= strsave(expandpath
);
387 ASSERT(*tptr
!= NULL
, Ct_ALLOCATE
, "setfile: tptr", 0);
394 * given the list for a particular ioctl (push, pop)
395 * and a line of colon-separated modules, add 'em to list
406 while (*tptr
) /* skip over existing entries to*/
407 tptr
++; /* concatenate multiple entries */
408 for (tok
= strtok(line
, ":"); tok
!= NULL
;
409 tok
= strtok((char *) NULL
, ":")) {
410 *tptr
= strsave(tok
);
411 ASSERT(*tptr
!= NULL
, Ct_ALLOCATE
, "setioctl: tptr", 0);
418 * reset Systems files
432 * reset Devices files
446 * reset Dialers files
459 * get next line from Systems file
460 * return TRUE if successful, FALSE if not
466 char *prev
= _uu_setlocale(LC_ALL
, "C");
468 if (Systems
[0] == NULL
)
469 /* not initialized via setservice() - use default */
470 setservice("uucico");
472 /* initialize devices and dialers whenever a new line is read */
475 if (fsystems
== NULL
)
476 if (nextsystems() == FALSE
) {
477 (void) _uu_resetlocale(LC_ALL
, prev
);
481 ASSERT(len
>= BUFSIZ
, "BUFFER TOO SMALL", "getsysline", 0);
483 while (getaline(fsystems
, buf
) != NULL
)
484 if ((*buf
!= '#') && (*buf
!= ' ') &&
485 (*buf
!= '\t') && (*buf
!= '\n')) {
486 (void) _uu_resetlocale(LC_ALL
, prev
);
489 if (nextsystems() == FALSE
) {
490 (void) _uu_resetlocale(LC_ALL
, prev
);
497 * move to next systems file. return TRUE if successful, FALSE if not
504 if (fsystems
!= NULL
) {
505 (void) fclose(fsystems
);
510 for ( ; Systems
[nsystems
] != NULL
; nsystems
++)
511 if ((fsystems
= fopen(Systems
[nsystems
], "r")) != NULL
)
517 * get next line from Devices file
518 * return TRUE if successful, FALSE if not
524 char *prev
= _uu_setlocale(LC_ALL
, "C");
526 if (Devices
[0] == NULL
)
527 /* not initialized via setservice() - use default */
528 setservice("uucico");
530 if (fdevices
== NULL
)
531 if (nextdevices() == FALSE
) {
532 (void) _uu_resetlocale(LC_ALL
, prev
);
536 if (fgets(buf
, len
, fdevices
) != NULL
) {
537 (void) _uu_resetlocale(LC_ALL
, prev
);
540 if (nextdevices() == FALSE
) {
541 (void) _uu_resetlocale(LC_ALL
, prev
);
548 * move to next devices file. return TRUE if successful, FALSE if not
553 if (fdevices
!= NULL
) {
554 (void) fclose(fdevices
);
559 for ( ; Devices
[ndevices
] != NULL
; ndevices
++)
560 if ((fdevices
= fopen(Devices
[ndevices
], "r")) != NULL
)
567 * get next line from Dialers file
568 * return TRUE if successful, FALSE if not
572 getdialline(buf
, len
)
575 char *prev
= _uu_setlocale(LC_ALL
, "C");
577 if (Dialers
[0] == NULL
)
578 /* not initialized via setservice() - use default */
579 setservice("uucico");
581 if (fdialers
== NULL
)
582 if (nextdialers() == FALSE
) {
583 (void) _uu_resetlocale(LC_ALL
, prev
);
587 if (fgets(buf
, len
, fdialers
) != NULL
) {
588 (void) _uu_resetlocale(LC_ALL
, prev
);
591 if (nextdialers() == FALSE
) {
592 (void) _uu_resetlocale(LC_ALL
, prev
);
599 * move to next dialers file. return TRUE if successful, FALSE if not
605 (void) fclose(fdialers
);
611 for ( ; Dialers
[ndialers
] != NULL
; ndialers
++)
612 if ((fdialers
= fopen(Dialers
[ndialers
], "r")) != NULL
)
618 * get next module to be popped
619 * return TRUE if successful, FALSE if not
622 getpop(buf
, len
, optional
)
628 if ( Pops
[0] == NULL
|| Pops
[npops
] == NULL
)
631 /* if the module name is enclosed in parentheses, */
632 /* is optional. set flag & strip parens */
633 slen
= strlen(Pops
[npops
]) - 1;
634 if ( Pops
[npops
][0] == '(' && Pops
[npops
][slen
] == ')' ) {
636 len
= ( slen
< len
? slen
: len
);
637 strncpy(buf
, &(Pops
[npops
++][1]), len
);
640 strncpy(buf
, Pops
[npops
++], len
);
647 * get next module to be pushed
648 * return TRUE if successful, FALSE if not
655 if ( Pushes
[0] == NULL
|| Pushes
[npushes
] == NULL
)
657 strncpy(buf
, Pushes
[npushes
++], len
);
662 * pop/push requested modules
663 * return TRUE if successful, FALSE if not
669 char strmod
[FMNAMESZ
], onstream
[FMNAMESZ
];
671 char *prev
= _uu_setlocale(LC_ALL
, "C");
673 /* check for streams modules to pop */
674 while ( getpop(strmod
, sizeof(strmod
), &optional
) ) {
675 DEBUG(5, (optional
? "pop_push: optionally POPing %s\n"
676 : "pop_push: POPing %s\n" ), strmod
);
677 if ( ioctl(fd
, I_LOOK
, onstream
) == -1 ) {
678 DEBUG(5, "pop_push: I_LOOK on fd %d failed ", fd
);
679 DEBUG(5, "errno %d\n", errno
);
680 (void) _uu_resetlocale(LC_ALL
, prev
);
683 if ( strcmp(strmod
, onstream
) != SAME
) {
686 DEBUG(5, "pop_push: I_POP: %s not there\n", strmod
);
687 (void) _uu_resetlocale(LC_ALL
, prev
);
690 if ( ioctl(fd
, I_POP
, 0) == -1 ) {
691 DEBUG(5, "pop_push: I_POP on fd %d failed ", fd
);
692 DEBUG(5, "errno %d\n", errno
);
693 (void) _uu_resetlocale(LC_ALL
, prev
);
698 /* check for streams modules to push */
699 while ( getpush(strmod
, sizeof(strmod
)) ) {
700 DEBUG(5, "pop_push: PUSHing %s\n", strmod
);
701 if ( ioctl(fd
, I_PUSH
, strmod
) == -1 ) {
702 DEBUG(5, "pop_push: I_PUSH on fd %d failed ", fd
);
703 DEBUG(5, "errno %d\n", errno
);
704 (void) _uu_resetlocale(LC_ALL
, prev
);
708 (void) _uu_resetlocale(LC_ALL
, prev
);
713 * return name of currently open Systems file
718 return(Systems
[nsystems
]);
722 * return name of currently open Devices file
727 return(Devices
[ndevices
]);
731 * return name of currently open Dialers file
736 return(Dialers
[ndialers
]);
740 * set configuration parameters provided in Config file
748 extern char _ProtoCfg
[];
750 if ((f
= fopen(CONFIG
, "r")) != 0) {
751 while (getaline(f
, buf
) > 0) {
752 /* got a (logical) line from Config file */
753 tok
= strtok(buf
, " \t");
754 if ( (tok
!= NULL
) && (*tok
!= '#') ) {
757 /* this probably should be table driven when
758 * the list of configurable parameters grows.
760 if (strncmp("Protocol=", tok
, strlen("Protocol=")) == SAME
) {
761 tok
+= strlen("Protocol=");
762 if ( *tok
!= '\0' ) {
763 if ( _ProtoCfg
[0] != '\0' ) {
764 DEBUG(7, "Protocol string %s ", tok
);
765 DEBUG(7, "overrides %s\n", _ProtoCfg
);
767 strcpy(_ProtoCfg
, tok
);
770 DEBUG(7, "Unknown configuration parameter %s\n", tok
);