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
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.
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]
23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
26 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
27 /* All Rights Reserved */
30 #pragma ident "%Z%%M% %I% %E% SMI"
35 #include <sys/types.h>
45 extern char *strsave();
46 extern void set_softcar();
49 static int get_flags();
50 static int get_ttyflags();
51 static int same_entry();
52 static int check_pmtab();
53 static void insert_pmtab();
54 static void free_pmtab();
55 static char *expand();
63 * - read and parse pmtab
64 * - store table in linked list pointed by global variable "PMtab"
65 * - exit if file does not exist or error detected.
70 register struct pmtab
*gptr
;
71 register char *ptr
, *wptr
;
73 int input
, state
, size
, rawc
, field
, linenum
;
77 static char *states
[] = {
78 "","tag","flags","identity","reserved1","reserved2","reserved3",
79 "device","ttyflags","count","service", "timeout","ttylabel",
80 "modules","prompt","disable msg","terminal type","soft-carrier"
84 debug("in read_pmtab");
87 if ((fp
= fopen(PMTABFILE
,"r")) == NULL
) {
88 fatal("open pmtab (%s) failed", PMTABFILE
);
92 if (check_version(PMTAB_VERS
, PMTABFILE
) != 0)
93 fatal("check pmtab version failed");
95 for (gptr
= PMtab
; gptr
; gptr
= gptr
->p_next
) {
96 if ((gptr
->p_status
== SESSION
) ||
97 (gptr
->p_status
== LOCKED
) ||
98 (gptr
->p_status
== UNACCESS
)) {
100 (void)close(gptr
->p_fd
);
103 gptr
->p_inservice
= gptr
->p_status
;
105 gptr
->p_status
= NOTVALID
;
114 for (ptr
= line
,oldc
= '\0'; ptr
< &line
[sizeof(line
)-1] &&
115 (rawc
=getc(fp
))!= '\n' && rawc
!= EOF
; ptr
++,oldc
=(char)rawc
){
116 if ((rawc
== '#') && (oldc
!= '\\'))
122 /* skip rest of the line */
123 if (rawc
!= EOF
&& rawc
!= '\n') {
125 log("Entry too long.\n");
126 while ((rawc
= getc(fp
)) != EOF
&& rawc
!= '\n')
131 if (ptr
== line
) break;
132 else input
= FINISHED
;
135 /* if empty line, skip */
136 for (ptr
=line
; *ptr
!= '\0' && isspace(*ptr
); ptr
++)
138 if (*ptr
== '\0') continue;
141 debug("**** Next Entry ****\n%s", line
);
143 log("Processing pmtab line #%d", linenum
);
145 /* Now we have the complete line */
147 if ((gptr
= ALLOC_PMTAB
) == PNULL
)
148 fatal("memory allocation failed");
150 /* set hangup flag, this is the default */
151 gptr
->p_ttyflags
|= H_FLAG
;
154 * For compatibility reasons, we cannot rely on these
155 * having values assigned from pmtab.
157 gptr
->p_termtype
= "";
158 gptr
->p_softcar
= "";
160 for (state
=P_TAG
,ptr
=line
;state
!=FAILURE
&& state
!=SUCCESS
;) {
163 gptr
->p_tag
= strsave(getword(ptr
,&size
,0));
166 (void)strcpy(wptr
, getword(ptr
,&size
,0));
167 if ((get_flags(wptr
, &gptr
->p_flags
)) != 0) {
173 gptr
->p_identity
=strsave(getword(ptr
,&size
,0));
176 gptr
->p_res1
=strsave(getword(ptr
,&size
,0));
179 gptr
->p_res2
=strsave(getword(ptr
,&size
,0));
182 gptr
->p_res3
=strsave(getword(ptr
,&size
,0));
185 gptr
->p_device
= strsave(getword(ptr
,&size
,0));
188 (void)strcpy(wptr
, getword(ptr
,&size
,0));
189 if ((get_ttyflags(wptr
,&gptr
->p_ttyflags
))!=0) {
195 (void)strcpy(wptr
, getword(ptr
,&size
,0));
196 if (strcheck(wptr
, NUM
) != 0) {
197 log("wait_read count must be a positive number");
202 gptr
->p_count
= atoi(wptr
);
206 strsave(expand(getword(ptr
,&size
,1),
210 (void)strcpy(wptr
, getword(ptr
,&size
,0));
211 if (strcheck(wptr
, NUM
) != 0) {
212 log("timeout value must be a positive number");
217 gptr
->p_timeout
= atoi(wptr
);
220 gptr
->p_ttylabel
=strsave(getword(ptr
,&size
,0));
223 gptr
->p_modules
= strsave(getword(ptr
,&size
,0));
224 if (vml(gptr
->p_modules
) != 0) {
230 gptr
->p_prompt
= strsave(getword(ptr
,&size
,TRUE
));
233 gptr
->p_dmsg
= strsave(getword(ptr
,&size
,TRUE
));
237 gptr
->p_termtype
= strsave(getword(ptr
,&size
,TRUE
));
241 gptr
->p_softcar
= strsave(getword(ptr
,&size
,TRUE
));
246 if (state
== FAILURE
)
249 ptr
++; /* Skip the ':' */
251 } else if (*ptr
!= '\0') {
257 * Maintain compatibility with older ttymon
258 * pmtab files. If Sun-added fields are
259 * missing, this should not be an error.
261 if (state
> P_DMSG
) {
270 if (state
== SUCCESS
) {
271 if (check_pmtab(gptr
) == 0) {
272 if (Nentries
< Maxfds
)
275 log("can't add more entries to "
276 "pmtab, Maxfds = %d", Maxfds
);
283 log("Parsing failure for entry: \n%s", line
);
284 log("-------------------------------------------");
289 log("Parsing failure in the \"%s\" field,\n%s"
290 "<--error detected here", states
[field
], line
);
291 log("-------------------------------------------");
294 } while (input
== ACTIVE
);
301 * get_flags - scan flags field to set U_FLAG and X_FLAG
304 get_flags(wptr
, flags
)
305 char *wptr
; /* pointer to the input string */
306 long *flags
; /* pointer to the flag to set */
309 for (p
= wptr
; *p
; p
++) {
318 log("Invalid flag -- %c", *p
);
326 * get_ttyflags - scan ttyflags field to set corresponding flags
329 get_ttyflags(wptr
, ttyflags
)
330 char *wptr
; /* pointer to the input string */
331 long *ttyflags
; /* pointer to the flag to be set*/
334 for (p
= wptr
; *p
; p
++) {
339 case 'h': /* h means don't hangup */
340 *ttyflags
&= ~H_FLAG
;
352 log("Invalid ttyflag -- %c", *p
);
361 * pflags - put service flags into intelligible form for output
366 long flags
; /* binary representation of the flags */
368 register int i
; /* scratch counter */
369 static char buf
[BUFSIZ
]; /* formatted flags */
374 if (flags
& U_FLAG
) {
378 if (flags
& X_FLAG
) {
383 log("Internal error in pflags");
389 * pttyflags - put ttyflags into intelligible form for output
394 long flags
; /* binary representation of ttyflags */
396 register int i
; /* scratch counter */
397 static char buf
[BUFSIZ
]; /* formatted flags */
402 if (flags
& C_FLAG
) {
410 if (flags
& B_FLAG
) {
414 if (flags
& R_FLAG
) {
418 if (flags
& I_FLAG
) {
423 log("Internal error in p_ttyflags");
433 debug("in dump_pmtab");
434 log("********** dumping pmtab **********");
436 for (gptr
=PMtab
; gptr
; gptr
= gptr
->p_next
) {
437 log("-------------------------------------------");
438 log("tag:\t\t%s", gptr
->p_tag
);
439 log("flags:\t\t%s",pflags(gptr
->p_flags
));
440 log("identity:\t%s", gptr
->p_identity
);
441 log("reserved1:\t%s", gptr
->p_res1
);
442 log("reserved2:\t%s", gptr
->p_res2
);
443 log("reserved3:\t%s", gptr
->p_res3
);
444 log("device:\t%s", gptr
->p_device
);
445 log("ttyflags:\t%s",pttyflags(gptr
->p_ttyflags
));
446 log("count:\t\t%d", gptr
->p_count
);
447 log("server:\t%s", gptr
->p_server
);
448 log("timeout:\t%d", gptr
->p_timeout
);
449 log("ttylabel:\t%s", gptr
->p_ttylabel
);
450 log("modules:\t%s", gptr
->p_modules
);
451 log("prompt:\t%s", gptr
->p_prompt
);
452 log("disable msg:\t%s", gptr
->p_dmsg
);
453 log("terminal type:\t%s", gptr
->p_termtype
);
454 log("soft-carrier:\t%s", gptr
->p_softcar
);
455 log("status:\t\t%d", gptr
->p_status
);
456 log("inservice:\t%d", gptr
->p_inservice
);
457 log("fd:\t\t%d", gptr
->p_fd
);
458 log("pid:\t\t%ld", gptr
->p_pid
);
459 log("uid:\t\t%ld", gptr
->p_uid
);
460 log("gid:\t\t%ld", gptr
->p_gid
);
461 log("dir:\t%s", gptr
->p_dir
);
464 log("********** end dumping pmtab **********");
469 * same_entry(e1,e2) - compare 2 entries of pmtab
470 * if the fields are different, copy e2 to e1
471 * return 1 if same, return 0 if different
475 struct pmtab
*e1
,*e2
;
478 if (strcmp(e1
->p_identity
, e2
->p_identity
) != 0)
480 if (strcmp(e1
->p_res1
, e2
->p_res1
) != 0)
482 if (strcmp(e1
->p_res2
, e2
->p_res2
) != 0)
484 if (strcmp(e1
->p_res3
, e2
->p_res3
) != 0)
486 if (strcmp(e1
->p_device
, e2
->p_device
) != 0)
488 if (strcmp(e1
->p_server
, e2
->p_server
) != 0)
490 if (strcmp(e1
->p_ttylabel
, e2
->p_ttylabel
) != 0)
492 if (strcmp(e1
->p_modules
, e2
->p_modules
) != 0)
494 if (strcmp(e1
->p_prompt
, e2
->p_prompt
) != 0)
496 if (strcmp(e1
->p_dmsg
, e2
->p_dmsg
) != 0)
498 if (strcmp(e1
->p_termtype
, e2
->p_termtype
) != 0)
500 if (strcmp(e1
->p_softcar
, e2
->p_softcar
) != 0)
502 if (e1
->p_flags
!= e2
->p_flags
)
505 * compare lowest 4 bits only,
506 * because A_FLAG is not part of original ttyflags
508 if ((e1
->p_ttyflags
& ~A_FLAG
) != (e2
->p_ttyflags
& ~A_FLAG
))
510 if (e1
->p_count
!= e2
->p_count
)
512 if (e1
->p_timeout
!= e2
->p_timeout
)
514 if (e1
->p_uid
!= e2
->p_uid
)
516 if (e1
->p_gid
!= e2
->p_gid
)
518 if (strcmp(e1
->p_dir
, e2
->p_dir
) != 0)
525 * insert_pmtab - insert a pmtab entry into the linked list
530 register struct pmtab
*sp
; /* ptr to entry to be inserted */
532 register struct pmtab
*tsp
, *savtsp
; /* scratch pointers */
533 int ret
; /* strcmp return value */
536 debug("in insert_pmtab");
538 savtsp
= tsp
= PMtab
;
541 * find the correct place to insert this element
545 ret
= strcmp(sp
->p_tag
, tsp
->p_tag
);
547 /* keep on looking */
554 /* this is a duplicate entry, ignore it */
555 log("Ignoring duplicate entry for <%s>",
559 if (same_entry(tsp
,sp
)) { /* same entry */
560 tsp
->p_status
= VALID
;
562 else { /* entry changed */
563 if ((sp
->p_flags
& X_FLAG
) &&
564 ((sp
->p_dmsg
== NULL
) ||
565 (*(sp
->p_dmsg
) == '\0'))) {
567 tsp
->p_status
= NOTVALID
;
571 debug("replacing <%s>", sp
->p_tag
);
573 /* replace old entry */
574 sp
->p_next
= tsp
->p_next
;
581 sp
->p_status
= CHANGED
;
582 sp
->p_fd
= tsp
->p_fd
;
583 sp
->p_pid
= tsp
->p_pid
;
595 if ((sp
->p_flags
& X_FLAG
) &&
596 ((sp
->p_dmsg
== NULL
) ||
597 (*(sp
->p_dmsg
) == '\0'))) { /* disabled entry */
602 * Set the state of soft-carrier.
603 * Since this is a one-time only operation,
604 * we do it when this service is added to
607 if (*sp
->p_softcar
!= '\0')
616 sp
->p_next
= savtsp
->p_next
;
620 debug("adding <%s>", sp
->p_tag
);
623 /* this entry is "current" */
624 sp
->p_status
= VALID
;
630 * either an empty list or should put element at end of list
633 if ((sp
->p_flags
& X_FLAG
) &&
634 ((sp
->p_dmsg
== NULL
) ||
635 (*(sp
->p_dmsg
) == '\0'))) { /* disabled entry */
636 free_pmtab(sp
); /* do not poll this entry */
640 * Set the state of soft-carrier.
641 * Since this is a one-time only operation,
642 * we do it when this service is added to
645 if (*sp
->p_softcar
!= '\0')
653 debug("adding <%s>", sp
->p_tag
);
656 /* this entry is "current" */
657 sp
->p_status
= VALID
;
662 * purge - purge linked list of "old" entries
669 register struct pmtab
*sp
; /* working pointer */
670 register struct pmtab
*savesp
, *tsp
; /* scratch pointers */
679 debug("p_status not 0");
691 savesp
->p_next
= sp
->p_next
;
693 debug("purging <%s>", sp
->p_tag
);
702 * free_pmtab - free one pmtab entry
709 debug("in free_pmtab");
730 * check_pmtab - check the fields to make sure things are correct
731 * - return 0 if everything is ok
732 * - return -1 if something is wrong
740 log("pmtab ptr is NULL");
744 /* check service tag */
745 if ((p
->p_tag
== NULL
) || (*(p
->p_tag
) == '\0')) {
746 log("port/service tag is missing");
749 if (strlen(p
->p_tag
) > (size_t)(MAXID
- 1)) {
750 log("port/service tag <%s> is longer than %d", p
->p_tag
,
754 if (strcheck(p
->p_tag
, ALNUM
) != 0) {
755 log("port/service tag <%s> is not alphanumeric", p
->p_tag
);
758 if (check_identity(p
) != 0) {
762 if (check_device(p
->p_device
) != 0)
765 if (check_cmd(p
->p_server
) != 0)
770 extern struct passwd
*getpwnam();
771 extern void endpwent();
772 extern struct group
*getgrgid();
773 extern void endgrent();
776 * check_identity - check to see if the identity is a valid user
777 * - log name in the passwd file,
778 * - and if its group id is a valid one
779 * - return 0 if everything is ok. Otherwise, return -1
786 register struct passwd
*pwdp
;
788 if ((p
->p_identity
== NULL
) || (*(p
->p_identity
) == '\0')) {
789 log("identity field is missing");
792 if ((pwdp
= getpwnam(p
->p_identity
)) == NULL
) {
793 log("missing or bad passwd entry for <%s>", p
->p_identity
);
797 if (getgrgid(pwdp
->pw_gid
) == NULL
) {
798 log("no group entry for %ld", pwdp
->pw_gid
);
803 p
->p_uid
= pwdp
->pw_uid
;
804 p
->p_gid
= pwdp
->pw_gid
;
805 p
->p_dir
= strsave(pwdp
->pw_dir
);
812 * expand(cmdp, devp) - expand %d to device name and %% to %,
813 * - any other characters are untouched.
814 * - return the expanded string
818 char *cmdp
; /* ptr to cmd string */
819 char *devp
; /* ptr to device name */
821 register char *cp
, *dp
, *np
;
822 static char buf
[BUFSIZ
];