1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate * CDDL HEADER START
3*0Sstevel@tonic-gate *
4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance
7*0Sstevel@tonic-gate * with the License.
8*0Sstevel@tonic-gate *
9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate * and limitations under the License.
13*0Sstevel@tonic-gate *
14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate *
20*0Sstevel@tonic-gate * CDDL HEADER END
21*0Sstevel@tonic-gate */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
24*0Sstevel@tonic-gate * Use is subject to license terms.
25*0Sstevel@tonic-gate */
26*0Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
27*0Sstevel@tonic-gate /* All Rights Reserved */
28*0Sstevel@tonic-gate
29*0Sstevel@tonic-gate
30*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
31*0Sstevel@tonic-gate
32*0Sstevel@tonic-gate
33*0Sstevel@tonic-gate #include <unistd.h>
34*0Sstevel@tonic-gate #include <stdlib.h>
35*0Sstevel@tonic-gate #include <sys/types.h>
36*0Sstevel@tonic-gate #include <ctype.h>
37*0Sstevel@tonic-gate #include <string.h>
38*0Sstevel@tonic-gate #include <pwd.h>
39*0Sstevel@tonic-gate #include <grp.h>
40*0Sstevel@tonic-gate #include <signal.h>
41*0Sstevel@tonic-gate #include "ttymon.h"
42*0Sstevel@tonic-gate #include "tmstruct.h"
43*0Sstevel@tonic-gate #include "tmextern.h"
44*0Sstevel@tonic-gate
45*0Sstevel@tonic-gate extern char *strsave();
46*0Sstevel@tonic-gate extern void set_softcar();
47*0Sstevel@tonic-gate extern int vml();
48*0Sstevel@tonic-gate void purge();
49*0Sstevel@tonic-gate static int get_flags();
50*0Sstevel@tonic-gate static int get_ttyflags();
51*0Sstevel@tonic-gate static int same_entry();
52*0Sstevel@tonic-gate static int check_pmtab();
53*0Sstevel@tonic-gate static void insert_pmtab();
54*0Sstevel@tonic-gate static void free_pmtab();
55*0Sstevel@tonic-gate static char *expand();
56*0Sstevel@tonic-gate
57*0Sstevel@tonic-gate int check_identity();
58*0Sstevel@tonic-gate
59*0Sstevel@tonic-gate int strcheck();
60*0Sstevel@tonic-gate
61*0Sstevel@tonic-gate /*
62*0Sstevel@tonic-gate * read_pmtab()
63*0Sstevel@tonic-gate * - read and parse pmtab
64*0Sstevel@tonic-gate * - store table in linked list pointed by global variable "PMtab"
65*0Sstevel@tonic-gate * - exit if file does not exist or error detected.
66*0Sstevel@tonic-gate */
67*0Sstevel@tonic-gate void
read_pmtab()68*0Sstevel@tonic-gate read_pmtab()
69*0Sstevel@tonic-gate {
70*0Sstevel@tonic-gate register struct pmtab *gptr;
71*0Sstevel@tonic-gate register char *ptr, *wptr;
72*0Sstevel@tonic-gate FILE *fp;
73*0Sstevel@tonic-gate int input, state, size, rawc, field, linenum;
74*0Sstevel@tonic-gate char oldc;
75*0Sstevel@tonic-gate char line[BUFSIZ];
76*0Sstevel@tonic-gate char wbuf[BUFSIZ];
77*0Sstevel@tonic-gate static char *states[] = {
78*0Sstevel@tonic-gate "","tag","flags","identity","reserved1","reserved2","reserved3",
79*0Sstevel@tonic-gate "device","ttyflags","count","service", "timeout","ttylabel",
80*0Sstevel@tonic-gate "modules","prompt","disable msg","terminal type","soft-carrier"
81*0Sstevel@tonic-gate };
82*0Sstevel@tonic-gate
83*0Sstevel@tonic-gate # ifdef DEBUG
84*0Sstevel@tonic-gate debug("in read_pmtab");
85*0Sstevel@tonic-gate # endif
86*0Sstevel@tonic-gate
87*0Sstevel@tonic-gate if ((fp = fopen(PMTABFILE,"r")) == NULL) {
88*0Sstevel@tonic-gate fatal("open pmtab (%s) failed", PMTABFILE);
89*0Sstevel@tonic-gate }
90*0Sstevel@tonic-gate
91*0Sstevel@tonic-gate Nentries = 0;
92*0Sstevel@tonic-gate if (check_version(PMTAB_VERS, PMTABFILE) != 0)
93*0Sstevel@tonic-gate fatal("check pmtab version failed");
94*0Sstevel@tonic-gate
95*0Sstevel@tonic-gate for (gptr = PMtab; gptr; gptr = gptr->p_next) {
96*0Sstevel@tonic-gate if ((gptr->p_status == SESSION) ||
97*0Sstevel@tonic-gate (gptr->p_status == LOCKED) ||
98*0Sstevel@tonic-gate (gptr->p_status == UNACCESS)) {
99*0Sstevel@tonic-gate if (gptr->p_fd > 0) {
100*0Sstevel@tonic-gate (void)close(gptr->p_fd);
101*0Sstevel@tonic-gate gptr->p_fd = 0;
102*0Sstevel@tonic-gate }
103*0Sstevel@tonic-gate gptr->p_inservice = gptr->p_status;
104*0Sstevel@tonic-gate }
105*0Sstevel@tonic-gate gptr->p_status = NOTVALID;
106*0Sstevel@tonic-gate }
107*0Sstevel@tonic-gate
108*0Sstevel@tonic-gate wptr = wbuf;
109*0Sstevel@tonic-gate input = ACTIVE;
110*0Sstevel@tonic-gate linenum = 0;
111*0Sstevel@tonic-gate do {
112*0Sstevel@tonic-gate linenum++;
113*0Sstevel@tonic-gate line[0] = '\0';
114*0Sstevel@tonic-gate for (ptr= line,oldc = '\0'; ptr < &line[sizeof(line)-1] &&
115*0Sstevel@tonic-gate (rawc=getc(fp))!= '\n' && rawc != EOF; ptr++,oldc=(char)rawc){
116*0Sstevel@tonic-gate if ((rawc == '#') && (oldc != '\\'))
117*0Sstevel@tonic-gate break;
118*0Sstevel@tonic-gate *ptr = (char)rawc;
119*0Sstevel@tonic-gate }
120*0Sstevel@tonic-gate *ptr = '\0';
121*0Sstevel@tonic-gate
122*0Sstevel@tonic-gate /* skip rest of the line */
123*0Sstevel@tonic-gate if (rawc != EOF && rawc != '\n') {
124*0Sstevel@tonic-gate if (rawc != '#')
125*0Sstevel@tonic-gate log("Entry too long.\n");
126*0Sstevel@tonic-gate while ((rawc = getc(fp)) != EOF && rawc != '\n')
127*0Sstevel@tonic-gate ;
128*0Sstevel@tonic-gate }
129*0Sstevel@tonic-gate
130*0Sstevel@tonic-gate if (rawc == EOF) {
131*0Sstevel@tonic-gate if (ptr == line) break;
132*0Sstevel@tonic-gate else input = FINISHED;
133*0Sstevel@tonic-gate }
134*0Sstevel@tonic-gate
135*0Sstevel@tonic-gate /* if empty line, skip */
136*0Sstevel@tonic-gate for (ptr=line; *ptr != '\0' && isspace(*ptr); ptr++)
137*0Sstevel@tonic-gate ;
138*0Sstevel@tonic-gate if (*ptr == '\0') continue;
139*0Sstevel@tonic-gate
140*0Sstevel@tonic-gate #ifdef DEBUG
141*0Sstevel@tonic-gate debug("**** Next Entry ****\n%s", line);
142*0Sstevel@tonic-gate #endif
143*0Sstevel@tonic-gate log("Processing pmtab line #%d", linenum);
144*0Sstevel@tonic-gate
145*0Sstevel@tonic-gate /* Now we have the complete line */
146*0Sstevel@tonic-gate
147*0Sstevel@tonic-gate if ((gptr = ALLOC_PMTAB) == PNULL)
148*0Sstevel@tonic-gate fatal("memory allocation failed");
149*0Sstevel@tonic-gate
150*0Sstevel@tonic-gate /* set hangup flag, this is the default */
151*0Sstevel@tonic-gate gptr->p_ttyflags |= H_FLAG;
152*0Sstevel@tonic-gate
153*0Sstevel@tonic-gate /*
154*0Sstevel@tonic-gate * For compatibility reasons, we cannot rely on these
155*0Sstevel@tonic-gate * having values assigned from pmtab.
156*0Sstevel@tonic-gate */
157*0Sstevel@tonic-gate gptr->p_termtype = "";
158*0Sstevel@tonic-gate gptr->p_softcar = "";
159*0Sstevel@tonic-gate
160*0Sstevel@tonic-gate for (state=P_TAG,ptr=line;state !=FAILURE && state !=SUCCESS;) {
161*0Sstevel@tonic-gate switch(state) {
162*0Sstevel@tonic-gate case P_TAG:
163*0Sstevel@tonic-gate gptr->p_tag = strsave(getword(ptr,&size,0));
164*0Sstevel@tonic-gate break;
165*0Sstevel@tonic-gate case P_FLAGS:
166*0Sstevel@tonic-gate (void)strcpy(wptr, getword(ptr,&size,0));
167*0Sstevel@tonic-gate if ((get_flags(wptr, &gptr->p_flags)) != 0) {
168*0Sstevel@tonic-gate field = state;
169*0Sstevel@tonic-gate state = FAILURE;
170*0Sstevel@tonic-gate }
171*0Sstevel@tonic-gate break;
172*0Sstevel@tonic-gate case P_IDENTITY:
173*0Sstevel@tonic-gate gptr->p_identity=strsave(getword(ptr,&size,0));
174*0Sstevel@tonic-gate break;
175*0Sstevel@tonic-gate case P_RES1:
176*0Sstevel@tonic-gate gptr->p_res1=strsave(getword(ptr,&size,0));
177*0Sstevel@tonic-gate break;
178*0Sstevel@tonic-gate case P_RES2:
179*0Sstevel@tonic-gate gptr->p_res2=strsave(getword(ptr,&size,0));
180*0Sstevel@tonic-gate break;
181*0Sstevel@tonic-gate case P_RES3:
182*0Sstevel@tonic-gate gptr->p_res3=strsave(getword(ptr,&size,0));
183*0Sstevel@tonic-gate break;
184*0Sstevel@tonic-gate case P_DEVICE:
185*0Sstevel@tonic-gate gptr->p_device = strsave(getword(ptr,&size,0));
186*0Sstevel@tonic-gate break;
187*0Sstevel@tonic-gate case P_TTYFLAGS:
188*0Sstevel@tonic-gate (void)strcpy(wptr, getword(ptr,&size,0));
189*0Sstevel@tonic-gate if ((get_ttyflags(wptr,&gptr->p_ttyflags))!=0) {
190*0Sstevel@tonic-gate field = state;
191*0Sstevel@tonic-gate state = FAILURE;
192*0Sstevel@tonic-gate }
193*0Sstevel@tonic-gate break;
194*0Sstevel@tonic-gate case P_COUNT:
195*0Sstevel@tonic-gate (void)strcpy(wptr, getword(ptr,&size,0));
196*0Sstevel@tonic-gate if (strcheck(wptr, NUM) != 0) {
197*0Sstevel@tonic-gate log("wait_read count must be a positive number");
198*0Sstevel@tonic-gate field = state;
199*0Sstevel@tonic-gate state = FAILURE;
200*0Sstevel@tonic-gate }
201*0Sstevel@tonic-gate else
202*0Sstevel@tonic-gate gptr->p_count = atoi(wptr);
203*0Sstevel@tonic-gate break;
204*0Sstevel@tonic-gate case P_SERVER:
205*0Sstevel@tonic-gate gptr->p_server =
206*0Sstevel@tonic-gate strsave(expand(getword(ptr,&size,1),
207*0Sstevel@tonic-gate gptr->p_device));
208*0Sstevel@tonic-gate break;
209*0Sstevel@tonic-gate case P_TIMEOUT:
210*0Sstevel@tonic-gate (void)strcpy(wptr, getword(ptr,&size,0));
211*0Sstevel@tonic-gate if (strcheck(wptr, NUM) != 0) {
212*0Sstevel@tonic-gate log("timeout value must be a positive number");
213*0Sstevel@tonic-gate field = state;
214*0Sstevel@tonic-gate state = FAILURE;
215*0Sstevel@tonic-gate }
216*0Sstevel@tonic-gate else
217*0Sstevel@tonic-gate gptr->p_timeout = atoi(wptr);
218*0Sstevel@tonic-gate break;
219*0Sstevel@tonic-gate case P_TTYLABEL:
220*0Sstevel@tonic-gate gptr->p_ttylabel=strsave(getword(ptr,&size,0));
221*0Sstevel@tonic-gate break;
222*0Sstevel@tonic-gate case P_MODULES:
223*0Sstevel@tonic-gate gptr->p_modules = strsave(getword(ptr,&size,0));
224*0Sstevel@tonic-gate if (vml(gptr->p_modules) != 0) {
225*0Sstevel@tonic-gate field = state;
226*0Sstevel@tonic-gate state = FAILURE;
227*0Sstevel@tonic-gate }
228*0Sstevel@tonic-gate break;
229*0Sstevel@tonic-gate case P_PROMPT:
230*0Sstevel@tonic-gate gptr->p_prompt = strsave(getword(ptr,&size,TRUE));
231*0Sstevel@tonic-gate break;
232*0Sstevel@tonic-gate case P_DMSG:
233*0Sstevel@tonic-gate gptr->p_dmsg = strsave(getword(ptr,&size,TRUE));
234*0Sstevel@tonic-gate break;
235*0Sstevel@tonic-gate
236*0Sstevel@tonic-gate case P_TERMTYPE:
237*0Sstevel@tonic-gate gptr->p_termtype = strsave(getword(ptr,&size,TRUE));
238*0Sstevel@tonic-gate break;
239*0Sstevel@tonic-gate
240*0Sstevel@tonic-gate case P_SOFTCAR:
241*0Sstevel@tonic-gate gptr->p_softcar = strsave(getword(ptr,&size,TRUE));
242*0Sstevel@tonic-gate break;
243*0Sstevel@tonic-gate
244*0Sstevel@tonic-gate } /* end switch */
245*0Sstevel@tonic-gate ptr += size;
246*0Sstevel@tonic-gate if (state == FAILURE)
247*0Sstevel@tonic-gate break;
248*0Sstevel@tonic-gate if (*ptr == ':') {
249*0Sstevel@tonic-gate ptr++; /* Skip the ':' */
250*0Sstevel@tonic-gate state++ ;
251*0Sstevel@tonic-gate } else if (*ptr != '\0') {
252*0Sstevel@tonic-gate field = state;
253*0Sstevel@tonic-gate state = FAILURE;
254*0Sstevel@tonic-gate }
255*0Sstevel@tonic-gate if (*ptr == '\0') {
256*0Sstevel@tonic-gate /*
257*0Sstevel@tonic-gate * Maintain compatibility with older ttymon
258*0Sstevel@tonic-gate * pmtab files. If Sun-added fields are
259*0Sstevel@tonic-gate * missing, this should not be an error.
260*0Sstevel@tonic-gate */
261*0Sstevel@tonic-gate if (state > P_DMSG) {
262*0Sstevel@tonic-gate state = SUCCESS;
263*0Sstevel@tonic-gate } else {
264*0Sstevel@tonic-gate field = state;
265*0Sstevel@tonic-gate state = FAILURE;
266*0Sstevel@tonic-gate }
267*0Sstevel@tonic-gate }
268*0Sstevel@tonic-gate } /* end for loop */
269*0Sstevel@tonic-gate
270*0Sstevel@tonic-gate if (state == SUCCESS) {
271*0Sstevel@tonic-gate if (check_pmtab(gptr) == 0) {
272*0Sstevel@tonic-gate if (Nentries < Maxfds)
273*0Sstevel@tonic-gate insert_pmtab(gptr);
274*0Sstevel@tonic-gate else {
275*0Sstevel@tonic-gate log("can't add more entries to "
276*0Sstevel@tonic-gate "pmtab, Maxfds = %d", Maxfds);
277*0Sstevel@tonic-gate free_pmtab(gptr);
278*0Sstevel@tonic-gate (void)fclose(fp);
279*0Sstevel@tonic-gate return;
280*0Sstevel@tonic-gate }
281*0Sstevel@tonic-gate }
282*0Sstevel@tonic-gate else {
283*0Sstevel@tonic-gate log("Parsing failure for entry: \n%s", line);
284*0Sstevel@tonic-gate log("-------------------------------------------");
285*0Sstevel@tonic-gate free_pmtab(gptr);
286*0Sstevel@tonic-gate }
287*0Sstevel@tonic-gate } else {
288*0Sstevel@tonic-gate *++ptr = '\0';
289*0Sstevel@tonic-gate log("Parsing failure in the \"%s\" field,\n%s"
290*0Sstevel@tonic-gate "<--error detected here", states[field], line);
291*0Sstevel@tonic-gate log("-------------------------------------------");
292*0Sstevel@tonic-gate free_pmtab(gptr);
293*0Sstevel@tonic-gate }
294*0Sstevel@tonic-gate } while (input == ACTIVE);
295*0Sstevel@tonic-gate
296*0Sstevel@tonic-gate (void)fclose(fp);
297*0Sstevel@tonic-gate return;
298*0Sstevel@tonic-gate }
299*0Sstevel@tonic-gate
300*0Sstevel@tonic-gate /*
301*0Sstevel@tonic-gate * get_flags - scan flags field to set U_FLAG and X_FLAG
302*0Sstevel@tonic-gate */
303*0Sstevel@tonic-gate static int
get_flags(wptr,flags)304*0Sstevel@tonic-gate get_flags(wptr, flags)
305*0Sstevel@tonic-gate char *wptr; /* pointer to the input string */
306*0Sstevel@tonic-gate long *flags; /* pointer to the flag to set */
307*0Sstevel@tonic-gate {
308*0Sstevel@tonic-gate register char *p;
309*0Sstevel@tonic-gate for (p = wptr; *p; p++) {
310*0Sstevel@tonic-gate switch (*p) {
311*0Sstevel@tonic-gate case 'x':
312*0Sstevel@tonic-gate *flags |= X_FLAG;
313*0Sstevel@tonic-gate break;
314*0Sstevel@tonic-gate case 'u':
315*0Sstevel@tonic-gate *flags |= U_FLAG;
316*0Sstevel@tonic-gate break;
317*0Sstevel@tonic-gate default:
318*0Sstevel@tonic-gate log("Invalid flag -- %c", *p);
319*0Sstevel@tonic-gate return(-1);
320*0Sstevel@tonic-gate }
321*0Sstevel@tonic-gate }
322*0Sstevel@tonic-gate return(0);
323*0Sstevel@tonic-gate }
324*0Sstevel@tonic-gate
325*0Sstevel@tonic-gate /*
326*0Sstevel@tonic-gate * get_ttyflags - scan ttyflags field to set corresponding flags
327*0Sstevel@tonic-gate */
328*0Sstevel@tonic-gate static int
get_ttyflags(wptr,ttyflags)329*0Sstevel@tonic-gate get_ttyflags(wptr, ttyflags)
330*0Sstevel@tonic-gate char *wptr; /* pointer to the input string */
331*0Sstevel@tonic-gate long *ttyflags; /* pointer to the flag to be set*/
332*0Sstevel@tonic-gate {
333*0Sstevel@tonic-gate register char *p;
334*0Sstevel@tonic-gate for (p = wptr; *p; p++) {
335*0Sstevel@tonic-gate switch (*p) {
336*0Sstevel@tonic-gate case 'c':
337*0Sstevel@tonic-gate *ttyflags |= C_FLAG;
338*0Sstevel@tonic-gate break;
339*0Sstevel@tonic-gate case 'h': /* h means don't hangup */
340*0Sstevel@tonic-gate *ttyflags &= ~H_FLAG;
341*0Sstevel@tonic-gate break;
342*0Sstevel@tonic-gate case 'b':
343*0Sstevel@tonic-gate *ttyflags |= B_FLAG;
344*0Sstevel@tonic-gate break;
345*0Sstevel@tonic-gate case 'r':
346*0Sstevel@tonic-gate *ttyflags |= R_FLAG;
347*0Sstevel@tonic-gate break;
348*0Sstevel@tonic-gate case 'I':
349*0Sstevel@tonic-gate *ttyflags |= I_FLAG;
350*0Sstevel@tonic-gate break;
351*0Sstevel@tonic-gate default:
352*0Sstevel@tonic-gate log("Invalid ttyflag -- %c", *p);
353*0Sstevel@tonic-gate return(-1);
354*0Sstevel@tonic-gate }
355*0Sstevel@tonic-gate }
356*0Sstevel@tonic-gate return(0);
357*0Sstevel@tonic-gate }
358*0Sstevel@tonic-gate
359*0Sstevel@tonic-gate # ifdef DEBUG
360*0Sstevel@tonic-gate /*
361*0Sstevel@tonic-gate * pflags - put service flags into intelligible form for output
362*0Sstevel@tonic-gate */
363*0Sstevel@tonic-gate
364*0Sstevel@tonic-gate char *
pflags(flags)365*0Sstevel@tonic-gate pflags(flags)
366*0Sstevel@tonic-gate long flags; /* binary representation of the flags */
367*0Sstevel@tonic-gate {
368*0Sstevel@tonic-gate register int i; /* scratch counter */
369*0Sstevel@tonic-gate static char buf[BUFSIZ]; /* formatted flags */
370*0Sstevel@tonic-gate
371*0Sstevel@tonic-gate if (flags == 0)
372*0Sstevel@tonic-gate return("-");
373*0Sstevel@tonic-gate i = 0;
374*0Sstevel@tonic-gate if (flags & U_FLAG) {
375*0Sstevel@tonic-gate buf[i++] = 'u';
376*0Sstevel@tonic-gate flags &= ~U_FLAG;
377*0Sstevel@tonic-gate }
378*0Sstevel@tonic-gate if (flags & X_FLAG) {
379*0Sstevel@tonic-gate buf[i++] = 'x';
380*0Sstevel@tonic-gate flags &= ~X_FLAG;
381*0Sstevel@tonic-gate }
382*0Sstevel@tonic-gate if (flags)
383*0Sstevel@tonic-gate log("Internal error in pflags");
384*0Sstevel@tonic-gate buf[i] = '\0';
385*0Sstevel@tonic-gate return(buf);
386*0Sstevel@tonic-gate }
387*0Sstevel@tonic-gate
388*0Sstevel@tonic-gate /*
389*0Sstevel@tonic-gate * pttyflags - put ttyflags into intelligible form for output
390*0Sstevel@tonic-gate */
391*0Sstevel@tonic-gate
392*0Sstevel@tonic-gate char *
pttyflags(flags)393*0Sstevel@tonic-gate pttyflags(flags)
394*0Sstevel@tonic-gate long flags; /* binary representation of ttyflags */
395*0Sstevel@tonic-gate {
396*0Sstevel@tonic-gate register int i; /* scratch counter */
397*0Sstevel@tonic-gate static char buf[BUFSIZ]; /* formatted flags */
398*0Sstevel@tonic-gate
399*0Sstevel@tonic-gate if (flags == 0)
400*0Sstevel@tonic-gate return("h");
401*0Sstevel@tonic-gate i = 0;
402*0Sstevel@tonic-gate if (flags & C_FLAG) {
403*0Sstevel@tonic-gate buf[i++] = 'c';
404*0Sstevel@tonic-gate flags &= ~C_FLAG;
405*0Sstevel@tonic-gate }
406*0Sstevel@tonic-gate if (flags & H_FLAG)
407*0Sstevel@tonic-gate flags &= ~H_FLAG;
408*0Sstevel@tonic-gate else
409*0Sstevel@tonic-gate buf[i++] = 'h';
410*0Sstevel@tonic-gate if (flags & B_FLAG) {
411*0Sstevel@tonic-gate buf[i++] = 'b';
412*0Sstevel@tonic-gate flags &= ~B_FLAG;
413*0Sstevel@tonic-gate }
414*0Sstevel@tonic-gate if (flags & R_FLAG) {
415*0Sstevel@tonic-gate buf[i++] = 'r';
416*0Sstevel@tonic-gate flags &= ~B_FLAG;
417*0Sstevel@tonic-gate }
418*0Sstevel@tonic-gate if (flags & I_FLAG) {
419*0Sstevel@tonic-gate buf[i++] = 'I';
420*0Sstevel@tonic-gate flags &= ~I_FLAG;
421*0Sstevel@tonic-gate }
422*0Sstevel@tonic-gate if (flags)
423*0Sstevel@tonic-gate log("Internal error in p_ttyflags");
424*0Sstevel@tonic-gate buf[i] = '\0';
425*0Sstevel@tonic-gate return(buf);
426*0Sstevel@tonic-gate }
427*0Sstevel@tonic-gate
428*0Sstevel@tonic-gate void
dump_pmtab()429*0Sstevel@tonic-gate dump_pmtab()
430*0Sstevel@tonic-gate {
431*0Sstevel@tonic-gate struct pmtab *gptr;
432*0Sstevel@tonic-gate
433*0Sstevel@tonic-gate debug("in dump_pmtab");
434*0Sstevel@tonic-gate log("********** dumping pmtab **********");
435*0Sstevel@tonic-gate log(" ");
436*0Sstevel@tonic-gate for (gptr=PMtab; gptr; gptr = gptr->p_next) {
437*0Sstevel@tonic-gate log("-------------------------------------------");
438*0Sstevel@tonic-gate log("tag:\t\t%s", gptr->p_tag);
439*0Sstevel@tonic-gate log("flags:\t\t%s",pflags(gptr->p_flags));
440*0Sstevel@tonic-gate log("identity:\t%s", gptr->p_identity);
441*0Sstevel@tonic-gate log("reserved1:\t%s", gptr->p_res1);
442*0Sstevel@tonic-gate log("reserved2:\t%s", gptr->p_res2);
443*0Sstevel@tonic-gate log("reserved3:\t%s", gptr->p_res3);
444*0Sstevel@tonic-gate log("device:\t%s", gptr->p_device);
445*0Sstevel@tonic-gate log("ttyflags:\t%s",pttyflags(gptr->p_ttyflags));
446*0Sstevel@tonic-gate log("count:\t\t%d", gptr->p_count);
447*0Sstevel@tonic-gate log("server:\t%s", gptr->p_server);
448*0Sstevel@tonic-gate log("timeout:\t%d", gptr->p_timeout);
449*0Sstevel@tonic-gate log("ttylabel:\t%s", gptr->p_ttylabel);
450*0Sstevel@tonic-gate log("modules:\t%s", gptr->p_modules);
451*0Sstevel@tonic-gate log("prompt:\t%s", gptr->p_prompt);
452*0Sstevel@tonic-gate log("disable msg:\t%s", gptr->p_dmsg);
453*0Sstevel@tonic-gate log("terminal type:\t%s", gptr->p_termtype);
454*0Sstevel@tonic-gate log("soft-carrier:\t%s", gptr->p_softcar);
455*0Sstevel@tonic-gate log("status:\t\t%d", gptr->p_status);
456*0Sstevel@tonic-gate log("inservice:\t%d", gptr->p_inservice);
457*0Sstevel@tonic-gate log("fd:\t\t%d", gptr->p_fd);
458*0Sstevel@tonic-gate log("pid:\t\t%ld", gptr->p_pid);
459*0Sstevel@tonic-gate log("uid:\t\t%ld", gptr->p_uid);
460*0Sstevel@tonic-gate log("gid:\t\t%ld", gptr->p_gid);
461*0Sstevel@tonic-gate log("dir:\t%s", gptr->p_dir);
462*0Sstevel@tonic-gate log(" ");
463*0Sstevel@tonic-gate }
464*0Sstevel@tonic-gate log("********** end dumping pmtab **********");
465*0Sstevel@tonic-gate }
466*0Sstevel@tonic-gate # endif
467*0Sstevel@tonic-gate
468*0Sstevel@tonic-gate /*
469*0Sstevel@tonic-gate * same_entry(e1,e2) - compare 2 entries of pmtab
470*0Sstevel@tonic-gate * if the fields are different, copy e2 to e1
471*0Sstevel@tonic-gate * return 1 if same, return 0 if different
472*0Sstevel@tonic-gate */
473*0Sstevel@tonic-gate static int
same_entry(e1,e2)474*0Sstevel@tonic-gate same_entry(e1,e2)
475*0Sstevel@tonic-gate struct pmtab *e1,*e2;
476*0Sstevel@tonic-gate {
477*0Sstevel@tonic-gate
478*0Sstevel@tonic-gate if (strcmp(e1->p_identity, e2->p_identity) != 0)
479*0Sstevel@tonic-gate return(0);
480*0Sstevel@tonic-gate if (strcmp(e1->p_res1, e2->p_res1) != 0)
481*0Sstevel@tonic-gate return(0);
482*0Sstevel@tonic-gate if (strcmp(e1->p_res2, e2->p_res2) != 0)
483*0Sstevel@tonic-gate return(0);
484*0Sstevel@tonic-gate if (strcmp(e1->p_res3, e2->p_res3) != 0)
485*0Sstevel@tonic-gate return(0);
486*0Sstevel@tonic-gate if (strcmp(e1->p_device, e2->p_device) != 0)
487*0Sstevel@tonic-gate return(0);
488*0Sstevel@tonic-gate if (strcmp(e1->p_server, e2->p_server) != 0)
489*0Sstevel@tonic-gate return(0);
490*0Sstevel@tonic-gate if (strcmp(e1->p_ttylabel, e2->p_ttylabel) != 0)
491*0Sstevel@tonic-gate return(0);
492*0Sstevel@tonic-gate if (strcmp(e1->p_modules, e2->p_modules) != 0)
493*0Sstevel@tonic-gate return(0);
494*0Sstevel@tonic-gate if (strcmp(e1->p_prompt, e2->p_prompt) != 0)
495*0Sstevel@tonic-gate return(0);
496*0Sstevel@tonic-gate if (strcmp(e1->p_dmsg, e2->p_dmsg) != 0)
497*0Sstevel@tonic-gate return(0);
498*0Sstevel@tonic-gate if (strcmp(e1->p_termtype, e2->p_termtype) != 0)
499*0Sstevel@tonic-gate return(0);
500*0Sstevel@tonic-gate if (strcmp(e1->p_softcar, e2->p_softcar) != 0)
501*0Sstevel@tonic-gate return(0);
502*0Sstevel@tonic-gate if (e1->p_flags != e2->p_flags)
503*0Sstevel@tonic-gate return(0);
504*0Sstevel@tonic-gate /*
505*0Sstevel@tonic-gate * compare lowest 4 bits only,
506*0Sstevel@tonic-gate * because A_FLAG is not part of original ttyflags
507*0Sstevel@tonic-gate */
508*0Sstevel@tonic-gate if ((e1->p_ttyflags & ~A_FLAG) != (e2->p_ttyflags & ~A_FLAG))
509*0Sstevel@tonic-gate return(0);
510*0Sstevel@tonic-gate if (e1->p_count != e2->p_count)
511*0Sstevel@tonic-gate return(0);
512*0Sstevel@tonic-gate if (e1->p_timeout != e2->p_timeout)
513*0Sstevel@tonic-gate return(0);
514*0Sstevel@tonic-gate if (e1->p_uid != e2->p_uid)
515*0Sstevel@tonic-gate return(0);
516*0Sstevel@tonic-gate if (e1->p_gid != e2->p_gid)
517*0Sstevel@tonic-gate return(0);
518*0Sstevel@tonic-gate if (strcmp(e1->p_dir, e2->p_dir) != 0)
519*0Sstevel@tonic-gate return(0);
520*0Sstevel@tonic-gate return(1);
521*0Sstevel@tonic-gate }
522*0Sstevel@tonic-gate
523*0Sstevel@tonic-gate
524*0Sstevel@tonic-gate /*
525*0Sstevel@tonic-gate * insert_pmtab - insert a pmtab entry into the linked list
526*0Sstevel@tonic-gate */
527*0Sstevel@tonic-gate
528*0Sstevel@tonic-gate static void
insert_pmtab(sp)529*0Sstevel@tonic-gate insert_pmtab(sp)
530*0Sstevel@tonic-gate register struct pmtab *sp; /* ptr to entry to be inserted */
531*0Sstevel@tonic-gate {
532*0Sstevel@tonic-gate register struct pmtab *tsp, *savtsp; /* scratch pointers */
533*0Sstevel@tonic-gate int ret; /* strcmp return value */
534*0Sstevel@tonic-gate
535*0Sstevel@tonic-gate # ifdef DEBUG
536*0Sstevel@tonic-gate debug("in insert_pmtab");
537*0Sstevel@tonic-gate # endif
538*0Sstevel@tonic-gate savtsp = tsp = PMtab;
539*0Sstevel@tonic-gate
540*0Sstevel@tonic-gate /*
541*0Sstevel@tonic-gate * find the correct place to insert this element
542*0Sstevel@tonic-gate */
543*0Sstevel@tonic-gate
544*0Sstevel@tonic-gate while (tsp) {
545*0Sstevel@tonic-gate ret = strcmp(sp->p_tag, tsp->p_tag);
546*0Sstevel@tonic-gate if (ret > 0) {
547*0Sstevel@tonic-gate /* keep on looking */
548*0Sstevel@tonic-gate savtsp = tsp;
549*0Sstevel@tonic-gate tsp = tsp->p_next;
550*0Sstevel@tonic-gate continue;
551*0Sstevel@tonic-gate }
552*0Sstevel@tonic-gate else if (ret == 0) {
553*0Sstevel@tonic-gate if (tsp->p_status) {
554*0Sstevel@tonic-gate /* this is a duplicate entry, ignore it */
555*0Sstevel@tonic-gate log("Ignoring duplicate entry for <%s>",
556*0Sstevel@tonic-gate tsp->p_tag);
557*0Sstevel@tonic-gate }
558*0Sstevel@tonic-gate else {
559*0Sstevel@tonic-gate if (same_entry(tsp,sp)) { /* same entry */
560*0Sstevel@tonic-gate tsp->p_status = VALID;
561*0Sstevel@tonic-gate }
562*0Sstevel@tonic-gate else { /* entry changed */
563*0Sstevel@tonic-gate if ((sp->p_flags & X_FLAG) &&
564*0Sstevel@tonic-gate ((sp->p_dmsg == NULL) ||
565*0Sstevel@tonic-gate (*(sp->p_dmsg) == '\0'))) {
566*0Sstevel@tonic-gate /* disabled entry */
567*0Sstevel@tonic-gate tsp->p_status = NOTVALID;
568*0Sstevel@tonic-gate }
569*0Sstevel@tonic-gate else {
570*0Sstevel@tonic-gate # ifdef DEBUG
571*0Sstevel@tonic-gate debug("replacing <%s>", sp->p_tag);
572*0Sstevel@tonic-gate # endif
573*0Sstevel@tonic-gate /* replace old entry */
574*0Sstevel@tonic-gate sp->p_next = tsp->p_next;
575*0Sstevel@tonic-gate if (tsp == PMtab) {
576*0Sstevel@tonic-gate PMtab = sp;
577*0Sstevel@tonic-gate }
578*0Sstevel@tonic-gate else {
579*0Sstevel@tonic-gate savtsp->p_next = sp;
580*0Sstevel@tonic-gate }
581*0Sstevel@tonic-gate sp->p_status = CHANGED;
582*0Sstevel@tonic-gate sp->p_fd = tsp->p_fd;
583*0Sstevel@tonic-gate sp->p_pid = tsp->p_pid;
584*0Sstevel@tonic-gate sp->p_inservice =
585*0Sstevel@tonic-gate tsp->p_inservice;
586*0Sstevel@tonic-gate sp = tsp;
587*0Sstevel@tonic-gate }
588*0Sstevel@tonic-gate }
589*0Sstevel@tonic-gate Nentries++;
590*0Sstevel@tonic-gate }
591*0Sstevel@tonic-gate free_pmtab(sp);
592*0Sstevel@tonic-gate return;
593*0Sstevel@tonic-gate }
594*0Sstevel@tonic-gate else {
595*0Sstevel@tonic-gate if ((sp->p_flags & X_FLAG) &&
596*0Sstevel@tonic-gate ((sp->p_dmsg == NULL) ||
597*0Sstevel@tonic-gate (*(sp->p_dmsg) == '\0'))) { /* disabled entry */
598*0Sstevel@tonic-gate free_pmtab(sp);
599*0Sstevel@tonic-gate return;
600*0Sstevel@tonic-gate }
601*0Sstevel@tonic-gate /*
602*0Sstevel@tonic-gate * Set the state of soft-carrier.
603*0Sstevel@tonic-gate * Since this is a one-time only operation,
604*0Sstevel@tonic-gate * we do it when this service is added to
605*0Sstevel@tonic-gate * the enabled list.
606*0Sstevel@tonic-gate */
607*0Sstevel@tonic-gate if (*sp->p_softcar != '\0')
608*0Sstevel@tonic-gate set_softcar(sp);
609*0Sstevel@tonic-gate
610*0Sstevel@tonic-gate /* insert it here */
611*0Sstevel@tonic-gate if (tsp == PMtab) {
612*0Sstevel@tonic-gate sp->p_next = PMtab;
613*0Sstevel@tonic-gate PMtab = sp;
614*0Sstevel@tonic-gate }
615*0Sstevel@tonic-gate else {
616*0Sstevel@tonic-gate sp->p_next = savtsp->p_next;
617*0Sstevel@tonic-gate savtsp->p_next = sp;
618*0Sstevel@tonic-gate }
619*0Sstevel@tonic-gate # ifdef DEBUG
620*0Sstevel@tonic-gate debug("adding <%s>", sp->p_tag);
621*0Sstevel@tonic-gate # endif
622*0Sstevel@tonic-gate Nentries++;
623*0Sstevel@tonic-gate /* this entry is "current" */
624*0Sstevel@tonic-gate sp->p_status = VALID;
625*0Sstevel@tonic-gate return;
626*0Sstevel@tonic-gate }
627*0Sstevel@tonic-gate }
628*0Sstevel@tonic-gate
629*0Sstevel@tonic-gate /*
630*0Sstevel@tonic-gate * either an empty list or should put element at end of list
631*0Sstevel@tonic-gate */
632*0Sstevel@tonic-gate
633*0Sstevel@tonic-gate if ((sp->p_flags & X_FLAG) &&
634*0Sstevel@tonic-gate ((sp->p_dmsg == NULL) ||
635*0Sstevel@tonic-gate (*(sp->p_dmsg) == '\0'))) { /* disabled entry */
636*0Sstevel@tonic-gate free_pmtab(sp); /* do not poll this entry */
637*0Sstevel@tonic-gate return;
638*0Sstevel@tonic-gate }
639*0Sstevel@tonic-gate /*
640*0Sstevel@tonic-gate * Set the state of soft-carrier.
641*0Sstevel@tonic-gate * Since this is a one-time only operation,
642*0Sstevel@tonic-gate * we do it when this service is added to
643*0Sstevel@tonic-gate * the enabled list.
644*0Sstevel@tonic-gate */
645*0Sstevel@tonic-gate if (*sp->p_softcar != '\0')
646*0Sstevel@tonic-gate set_softcar(sp);
647*0Sstevel@tonic-gate sp->p_next = NULL;
648*0Sstevel@tonic-gate if (PMtab == NULL)
649*0Sstevel@tonic-gate PMtab = sp;
650*0Sstevel@tonic-gate else
651*0Sstevel@tonic-gate savtsp->p_next = sp;
652*0Sstevel@tonic-gate # ifdef DEBUG
653*0Sstevel@tonic-gate debug("adding <%s>", sp->p_tag);
654*0Sstevel@tonic-gate # endif
655*0Sstevel@tonic-gate ++Nentries;
656*0Sstevel@tonic-gate /* this entry is "current" */
657*0Sstevel@tonic-gate sp->p_status = VALID;
658*0Sstevel@tonic-gate }
659*0Sstevel@tonic-gate
660*0Sstevel@tonic-gate
661*0Sstevel@tonic-gate /*
662*0Sstevel@tonic-gate * purge - purge linked list of "old" entries
663*0Sstevel@tonic-gate */
664*0Sstevel@tonic-gate
665*0Sstevel@tonic-gate
666*0Sstevel@tonic-gate void
purge()667*0Sstevel@tonic-gate purge()
668*0Sstevel@tonic-gate {
669*0Sstevel@tonic-gate register struct pmtab *sp; /* working pointer */
670*0Sstevel@tonic-gate register struct pmtab *savesp, *tsp; /* scratch pointers */
671*0Sstevel@tonic-gate
672*0Sstevel@tonic-gate # ifdef DEBUG
673*0Sstevel@tonic-gate debug("in purge");
674*0Sstevel@tonic-gate # endif
675*0Sstevel@tonic-gate sp = savesp = PMtab;
676*0Sstevel@tonic-gate while (sp) {
677*0Sstevel@tonic-gate if (sp->p_status) {
678*0Sstevel@tonic-gate # ifdef DEBUG
679*0Sstevel@tonic-gate debug("p_status not 0");
680*0Sstevel@tonic-gate # endif
681*0Sstevel@tonic-gate savesp = sp;
682*0Sstevel@tonic-gate sp = sp->p_next;
683*0Sstevel@tonic-gate }
684*0Sstevel@tonic-gate else {
685*0Sstevel@tonic-gate tsp = sp;
686*0Sstevel@tonic-gate if (tsp == PMtab) {
687*0Sstevel@tonic-gate PMtab = sp->p_next;
688*0Sstevel@tonic-gate savesp = PMtab;
689*0Sstevel@tonic-gate }
690*0Sstevel@tonic-gate else
691*0Sstevel@tonic-gate savesp->p_next = sp->p_next;
692*0Sstevel@tonic-gate # ifdef DEBUG
693*0Sstevel@tonic-gate debug("purging <%s>", sp->p_tag);
694*0Sstevel@tonic-gate # endif
695*0Sstevel@tonic-gate sp = sp->p_next;
696*0Sstevel@tonic-gate free_pmtab(tsp);
697*0Sstevel@tonic-gate }
698*0Sstevel@tonic-gate }
699*0Sstevel@tonic-gate }
700*0Sstevel@tonic-gate
701*0Sstevel@tonic-gate /*
702*0Sstevel@tonic-gate * free_pmtab - free one pmtab entry
703*0Sstevel@tonic-gate */
704*0Sstevel@tonic-gate static void
free_pmtab(p)705*0Sstevel@tonic-gate free_pmtab(p)
706*0Sstevel@tonic-gate struct pmtab *p;
707*0Sstevel@tonic-gate {
708*0Sstevel@tonic-gate #ifdef DEBUG
709*0Sstevel@tonic-gate debug("in free_pmtab");
710*0Sstevel@tonic-gate #endif
711*0Sstevel@tonic-gate free(p->p_tag);
712*0Sstevel@tonic-gate free(p->p_identity);
713*0Sstevel@tonic-gate free(p->p_res1);
714*0Sstevel@tonic-gate free(p->p_res2);
715*0Sstevel@tonic-gate free(p->p_res3);
716*0Sstevel@tonic-gate free(p->p_device);
717*0Sstevel@tonic-gate free(p->p_server);
718*0Sstevel@tonic-gate free(p->p_ttylabel);
719*0Sstevel@tonic-gate free(p->p_modules);
720*0Sstevel@tonic-gate free(p->p_prompt);
721*0Sstevel@tonic-gate free(p->p_dmsg);
722*0Sstevel@tonic-gate free(p->p_termtype);
723*0Sstevel@tonic-gate free(p->p_softcar);
724*0Sstevel@tonic-gate if (p->p_dir)
725*0Sstevel@tonic-gate free(p->p_dir);
726*0Sstevel@tonic-gate free(p);
727*0Sstevel@tonic-gate }
728*0Sstevel@tonic-gate
729*0Sstevel@tonic-gate /*
730*0Sstevel@tonic-gate * check_pmtab - check the fields to make sure things are correct
731*0Sstevel@tonic-gate * - return 0 if everything is ok
732*0Sstevel@tonic-gate * - return -1 if something is wrong
733*0Sstevel@tonic-gate */
734*0Sstevel@tonic-gate
735*0Sstevel@tonic-gate static int
check_pmtab(p)736*0Sstevel@tonic-gate check_pmtab(p)
737*0Sstevel@tonic-gate struct pmtab *p;
738*0Sstevel@tonic-gate {
739*0Sstevel@tonic-gate if (p == NULL) {
740*0Sstevel@tonic-gate log("pmtab ptr is NULL");
741*0Sstevel@tonic-gate return(-1);
742*0Sstevel@tonic-gate }
743*0Sstevel@tonic-gate
744*0Sstevel@tonic-gate /* check service tag */
745*0Sstevel@tonic-gate if ((p->p_tag == NULL) || (*(p->p_tag) == '\0')) {
746*0Sstevel@tonic-gate log("port/service tag is missing");
747*0Sstevel@tonic-gate return(-1);
748*0Sstevel@tonic-gate }
749*0Sstevel@tonic-gate if (strlen(p->p_tag) > (size_t)(MAXID - 1)) {
750*0Sstevel@tonic-gate log("port/service tag <%s> is longer than %d", p->p_tag,
751*0Sstevel@tonic-gate MAXID-1);
752*0Sstevel@tonic-gate return(-1);
753*0Sstevel@tonic-gate }
754*0Sstevel@tonic-gate if (strcheck(p->p_tag, ALNUM) != 0) {
755*0Sstevel@tonic-gate log("port/service tag <%s> is not alphanumeric", p->p_tag);
756*0Sstevel@tonic-gate return(-1);
757*0Sstevel@tonic-gate }
758*0Sstevel@tonic-gate if (check_identity(p) != 0) {
759*0Sstevel@tonic-gate return(-1);
760*0Sstevel@tonic-gate }
761*0Sstevel@tonic-gate
762*0Sstevel@tonic-gate if (check_device(p->p_device) != 0)
763*0Sstevel@tonic-gate return(-1);
764*0Sstevel@tonic-gate
765*0Sstevel@tonic-gate if (check_cmd(p->p_server) != 0)
766*0Sstevel@tonic-gate return(-1);
767*0Sstevel@tonic-gate return(0);
768*0Sstevel@tonic-gate }
769*0Sstevel@tonic-gate
770*0Sstevel@tonic-gate extern struct passwd *getpwnam();
771*0Sstevel@tonic-gate extern void endpwent();
772*0Sstevel@tonic-gate extern struct group *getgrgid();
773*0Sstevel@tonic-gate extern void endgrent();
774*0Sstevel@tonic-gate
775*0Sstevel@tonic-gate /*
776*0Sstevel@tonic-gate * check_identity - check to see if the identity is a valid user
777*0Sstevel@tonic-gate * - log name in the passwd file,
778*0Sstevel@tonic-gate * - and if its group id is a valid one
779*0Sstevel@tonic-gate * - return 0 if everything is ok. Otherwise, return -1
780*0Sstevel@tonic-gate */
781*0Sstevel@tonic-gate
782*0Sstevel@tonic-gate int
check_identity(p)783*0Sstevel@tonic-gate check_identity(p)
784*0Sstevel@tonic-gate struct pmtab *p;
785*0Sstevel@tonic-gate {
786*0Sstevel@tonic-gate register struct passwd *pwdp;
787*0Sstevel@tonic-gate
788*0Sstevel@tonic-gate if ((p->p_identity == NULL) || (*(p->p_identity) == '\0')) {
789*0Sstevel@tonic-gate log("identity field is missing");
790*0Sstevel@tonic-gate return(-1);
791*0Sstevel@tonic-gate }
792*0Sstevel@tonic-gate if ((pwdp = getpwnam(p->p_identity)) == NULL) {
793*0Sstevel@tonic-gate log("missing or bad passwd entry for <%s>", p->p_identity);
794*0Sstevel@tonic-gate endpwent();
795*0Sstevel@tonic-gate return(-1);
796*0Sstevel@tonic-gate }
797*0Sstevel@tonic-gate if (getgrgid(pwdp->pw_gid) == NULL) {
798*0Sstevel@tonic-gate log("no group entry for %ld", pwdp->pw_gid);
799*0Sstevel@tonic-gate endgrent();
800*0Sstevel@tonic-gate endpwent();
801*0Sstevel@tonic-gate return(-1);
802*0Sstevel@tonic-gate }
803*0Sstevel@tonic-gate p->p_uid = pwdp->pw_uid;
804*0Sstevel@tonic-gate p->p_gid = pwdp->pw_gid;
805*0Sstevel@tonic-gate p->p_dir = strsave(pwdp->pw_dir);
806*0Sstevel@tonic-gate endgrent();
807*0Sstevel@tonic-gate endpwent();
808*0Sstevel@tonic-gate return(0);
809*0Sstevel@tonic-gate }
810*0Sstevel@tonic-gate
811*0Sstevel@tonic-gate /*
812*0Sstevel@tonic-gate * expand(cmdp, devp) - expand %d to device name and %% to %,
813*0Sstevel@tonic-gate * - any other characters are untouched.
814*0Sstevel@tonic-gate * - return the expanded string
815*0Sstevel@tonic-gate */
816*0Sstevel@tonic-gate static char *
expand(cmdp,devp)817*0Sstevel@tonic-gate expand(cmdp,devp)
818*0Sstevel@tonic-gate char *cmdp; /* ptr to cmd string */
819*0Sstevel@tonic-gate char *devp; /* ptr to device name */
820*0Sstevel@tonic-gate {
821*0Sstevel@tonic-gate register char *cp, *dp, *np;
822*0Sstevel@tonic-gate static char buf[BUFSIZ];
823*0Sstevel@tonic-gate cp = cmdp;
824*0Sstevel@tonic-gate np = buf;
825*0Sstevel@tonic-gate dp = devp;
826*0Sstevel@tonic-gate while (*cp) {
827*0Sstevel@tonic-gate if (*cp != '%') {
828*0Sstevel@tonic-gate *np++ = *cp++;
829*0Sstevel@tonic-gate continue;
830*0Sstevel@tonic-gate }
831*0Sstevel@tonic-gate switch (*++cp) {
832*0Sstevel@tonic-gate case 'd':
833*0Sstevel@tonic-gate while (*dp) {
834*0Sstevel@tonic-gate *np++ = *dp++;
835*0Sstevel@tonic-gate }
836*0Sstevel@tonic-gate cp++;
837*0Sstevel@tonic-gate break;
838*0Sstevel@tonic-gate case '%':
839*0Sstevel@tonic-gate *np++ = *cp++;
840*0Sstevel@tonic-gate break;
841*0Sstevel@tonic-gate default:
842*0Sstevel@tonic-gate *np++ = *cp++;
843*0Sstevel@tonic-gate break;
844*0Sstevel@tonic-gate }
845*0Sstevel@tonic-gate }
846*0Sstevel@tonic-gate *np = '\0';
847*0Sstevel@tonic-gate return(buf);
848*0Sstevel@tonic-gate }
849*0Sstevel@tonic-gate
850