7600 zfs rollback should pass target snapshot to kernel
[unleashed.git] / usr / src / cmd / bnu / sysfiles.c
blobdb147774d0add137daccab8f4bc7a0143be2586a
1 /*
2 * CDDL HEADER START
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]
19 * CDDL HEADER END
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 */
29 #include "uucp.h"
31 #include <unistd.h>
32 #include "sysfiles.h"
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.
42 * TODO:
43 * call bsfix()?
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 */
67 /*to be popped */
68 static int npushes; /* index into list of STREAMS modules */
69 /*to be pushed */
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 */
82 #define NTOKENS 16
83 static char *tokens[NTOKENS], **tokptr;
85 /* export these */
86 EXTERN void sysreset(), devreset(), dialreset(), setdevcfg(), setservice();
87 EXTERN char *strsave();
89 /* import these */
90 extern char *strcpy(), *strtok(), *strchr(), *strsave();
91 EXTERN int eaccess();
94 * setservice init's Systems, Devices, Dialers lists from Sysfiles
96 GLOBAL void
97 setservice(service)
98 char *service;
100 char *prev = _uu_setlocale(LC_ALL, "C");
102 setconfig();
103 scansys(service);
104 (void) _uu_resetlocale(LC_ALL, prev);
105 return;
109 * setdevcfg init's Pops, Pushes lists from Devconfig
112 GLOBAL void
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);
120 return;
123 /* administrative files access */
124 GLOBAL int
125 sysaccess(type)
126 int type;
128 switch (type) {
130 case ACCESS_SYSTEMS:
131 return(access(Systems[nsystems], R_OK));
132 case ACCESS_DEVICES:
133 return(access(Devices[ndevices], R_OK));
134 case ACCESS_DIALERS:
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));
142 default:
143 (void)sprintf(errformat, "bad access type %d", type);
144 logent(errformat, "sysaccess");
145 return(FAIL);
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.
155 static void
156 scansys(service)
157 char *service;
158 { FILE *f;
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)) {
168 tokenize();
169 nameparse();
172 (void) fclose(f);
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);
179 Systems[1] = NULL;
181 if (Devices[0] == NULL) {
182 Devices[0] = strsave(DEVICES);
183 ASSERT(Devices[0] != NULL, Ct_ALLOCATE, "scansys: Devices", 0);
184 Devices[1] = NULL;
186 if (Dialers[0] == NULL) {
187 Dialers[0] = strsave(DIALERS);
188 ASSERT(Dialers[0] != NULL, Ct_ALLOCATE, "scansys: Dialers", 0);
189 Dialers[1] = NULL;
191 return;
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.
199 static void
200 scancfg(service, device)
201 char *service, *device;
202 { FILE *f;
203 char *tok, buf[BUFSIZ];
205 /* (re)initialize device-specific information */
207 npops = npushes = 0;
208 Pops[0] = Pushes[0] = NULL;
209 connecttime = CONNECTTIME;
210 expecttime = EXPECTTIME;
211 msgtime = MSGTIME;
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)) {
221 tokenize();
222 nameparse();
226 (void) fclose(f);
229 return;
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!
239 static int
240 getaline(f, line)
241 FILE *f;
242 char *line;
243 { char *lptr, *lend;
245 lptr = line;
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! */
250 break;
251 *--lend = '\0'; /* lop off ending '\n' */
252 if ( lend == line ) /* empty line - ignore */
253 continue;
254 lptr = lend;
255 if (lend[-1] != '\\')
256 break;
257 /* continuation */
258 lend[-1] = ' ';
260 return(lptr - line);
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;
267 * else return false
269 static int
270 namematch(label, line, name)
271 char *label, *line, *name;
272 { char *lend;
274 if (strncmp(label, line, strlen(label)) != SAME) {
275 return(FALSE); /* probably a comment line */
277 line += strlen(label);
278 if (*line == '\0')
279 return(FALSE);
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) {
287 *lend = '\0';
288 if (strcmp(line, name) == SAME)
289 return(TRUE);
290 line = lend+1;
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.
300 static void
301 tokenize()
302 { char *tok;
304 tokptr = tokens;
305 while ((tok = strtok((char *) NULL, " \t")) != NULL) {
306 *tokptr++ = tok;
307 if (tokptr - tokens >= NTOKENS)
308 break;
310 *tokptr = NULL;
311 return;
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.
320 static void
321 nameparse()
322 { char **line, *equals;
323 int temp;
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, '=');
329 if (equals == NULL)
330 continue; /* may be meaningful someday? */
331 *equals = '\0';
332 /* ignore entry with empty rhs */
333 if (*++equals == '\0')
334 continue;
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);
351 else {
352 (void)sprintf(errformat,"unrecognized label %s",*line);
353 logent(errformat, "Sysfiles|Devconfig");
356 return;
360 * given the list for a particular type (systems, devices,...)
361 * and a line of colon-separated files, add 'em to list
364 static void
365 setfile(type, line)
366 char **type, *line;
367 { char **tptr, *tok;
368 char expandpath[BUFSIZ];
370 if (*line == 0)
371 return;
372 tptr = type;
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';
379 if ( *tok != '/' )
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 */
385 continue;
386 *tptr = strsave(expandpath);
387 ASSERT(*tptr != NULL, Ct_ALLOCATE, "setfile: tptr", 0);
388 tptr++;
390 return;
394 * given the list for a particular ioctl (push, pop)
395 * and a line of colon-separated modules, add 'em to list
398 static void
399 setioctl(type, line)
400 char **type, *line;
401 { char **tptr, *tok;
403 if (*line == 0)
404 return;
405 tptr = type;
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);
412 tptr++;
414 return;
418 * reset Systems files
420 GLOBAL void
421 sysreset()
423 if (fsystems)
424 fclose(fsystems);
425 fsystems = NULL;
426 nsystems = 0;
427 devreset();
428 return;
432 * reset Devices files
434 GLOBAL void
435 devreset()
437 if (fdevices)
438 fclose(fdevices);
439 fdevices = NULL;
440 ndevices = 0;
441 dialreset();
442 return;
446 * reset Dialers files
448 GLOBAL void
449 dialreset()
451 if (fdialers)
452 fclose(fdialers);
453 fdialers = NULL;
454 ndialers = 0;
455 return;
459 * get next line from Systems file
460 * return TRUE if successful, FALSE if not
462 GLOBAL int
463 getsysline(buf, len)
464 char *buf;
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 */
473 /* from systems */
474 devreset();
475 if (fsystems == NULL)
476 if (nextsystems() == FALSE) {
477 (void) _uu_resetlocale(LC_ALL, prev);
478 return(FALSE);
481 ASSERT(len >= BUFSIZ, "BUFFER TOO SMALL", "getsysline", 0);
482 for(;;) {
483 while (getaline(fsystems, buf) != NULL)
484 if ((*buf != '#') && (*buf != ' ') &&
485 (*buf != '\t') && (*buf != '\n')) {
486 (void) _uu_resetlocale(LC_ALL, prev);
487 return(TRUE);
489 if (nextsystems() == FALSE) {
490 (void) _uu_resetlocale(LC_ALL, prev);
491 return(FALSE);
497 * move to next systems file. return TRUE if successful, FALSE if not
499 static int
500 nextsystems()
502 devreset();
504 if (fsystems != NULL) {
505 (void) fclose(fsystems);
506 nsystems++;
507 } else {
508 nsystems = 0;
510 for ( ; Systems[nsystems] != NULL; nsystems++)
511 if ((fsystems = fopen(Systems[nsystems], "r")) != NULL)
512 return(TRUE);
513 return(FALSE);
517 * get next line from Devices file
518 * return TRUE if successful, FALSE if not
520 GLOBAL int
521 getdevline(buf, len)
522 char *buf;
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);
533 return(FALSE);
535 for(;;) {
536 if (fgets(buf, len, fdevices) != NULL) {
537 (void) _uu_resetlocale(LC_ALL, prev);
538 return(TRUE);
540 if (nextdevices() == FALSE) {
541 (void) _uu_resetlocale(LC_ALL, prev);
542 return(FALSE);
548 * move to next devices file. return TRUE if successful, FALSE if not
550 static int
551 nextdevices()
553 if (fdevices != NULL) {
554 (void) fclose(fdevices);
555 ndevices++;
556 } else {
557 ndevices = 0;
559 for ( ; Devices[ndevices] != NULL; ndevices++)
560 if ((fdevices = fopen(Devices[ndevices], "r")) != NULL)
561 return(TRUE);
562 return(FALSE);
567 * get next line from Dialers file
568 * return TRUE if successful, FALSE if not
571 GLOBAL int
572 getdialline(buf, len)
573 char *buf;
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);
584 return(FALSE);
586 for(;;) {
587 if (fgets(buf, len, fdialers) != NULL) {
588 (void) _uu_resetlocale(LC_ALL, prev);
589 return(TRUE);
591 if (nextdialers() == FALSE) {
592 (void) _uu_resetlocale(LC_ALL, prev);
593 return(FALSE);
599 * move to next dialers file. return TRUE if successful, FALSE if not
601 static int
602 nextdialers()
604 if (fdialers) {
605 (void) fclose(fdialers);
606 ndialers++;
607 } else {
608 ndialers = 0;
611 for ( ; Dialers[ndialers] != NULL; ndialers++)
612 if ((fdialers = fopen(Dialers[ndialers], "r")) != NULL)
613 return(TRUE);
614 return(FALSE);
618 * get next module to be popped
619 * return TRUE if successful, FALSE if not
621 static int
622 getpop(buf, len, optional)
623 char *buf;
624 int len, *optional;
626 int slen;
628 if ( Pops[0] == NULL || Pops[npops] == NULL )
629 return(FALSE);
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] == ')' ) {
635 *optional = 1;
636 len = ( slen < len ? slen : len );
637 strncpy(buf, &(Pops[npops++][1]), len);
638 } else {
639 *optional = 0;
640 strncpy(buf, Pops[npops++], len);
642 buf[len-1] = '\0';
643 return(TRUE);
647 * get next module to be pushed
648 * return TRUE if successful, FALSE if not
650 static int
651 getpush(buf, len)
652 char *buf;
653 int len;
655 if ( Pushes[0] == NULL || Pushes[npushes] == NULL )
656 return(FALSE);
657 strncpy(buf, Pushes[npushes++], len);
658 return(TRUE);
662 * pop/push requested modules
663 * return TRUE if successful, FALSE if not
665 GLOBAL int
666 pop_push(fd)
667 int fd;
669 char strmod[FMNAMESZ], onstream[FMNAMESZ];
670 int optional;
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);
681 return(FALSE);
683 if ( strcmp(strmod, onstream) != SAME ) {
684 if ( optional )
685 continue;
686 DEBUG(5, "pop_push: I_POP: %s not there\n", strmod);
687 (void) _uu_resetlocale(LC_ALL, prev);
688 return(FALSE);
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);
694 return(FALSE);
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);
705 return(FALSE);
708 (void) _uu_resetlocale(LC_ALL, prev);
709 return(TRUE);
713 * return name of currently open Systems file
715 GLOBAL char *
716 currsys()
718 return(Systems[nsystems]);
722 * return name of currently open Devices file
724 GLOBAL char *
725 currdev()
727 return(Devices[ndevices]);
731 * return name of currently open Dialers file
733 GLOBAL char *
734 currdial()
736 return(Dialers[ndialers]);
740 * set configuration parameters provided in Config file
742 static void
743 setconfig()
745 FILE *f;
746 char buf[BUFSIZ];
747 char *tok;
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 != '#') ) {
755 /* got a token */
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);
769 } else {
770 DEBUG(7, "Unknown configuration parameter %s\n", tok);