1*35200Smarc /*
2*35200Smarc 
3*35200Smarc  *      Copyright (c) 1984, 1985, 1986 AT&T
4*35200Smarc  *      All Rights Reserved
5*35200Smarc 
6*35200Smarc  *      THIS IS UNPUBLISHED PROPRIETARY SOURCE
7*35200Smarc  *      CODE OF AT&T.
8*35200Smarc  *      The copyright notice above does not
9*35200Smarc  *      evidence any actual or intended
10*35200Smarc  *      publication of such source code.
11*35200Smarc 
12*35200Smarc  */
13*35200Smarc /* @(#)tilde.c	1.1 */
14*35200Smarc 
15*35200Smarc /*
16*35200Smarc  *  logdir - get login directory given login name
17*35200Smarc  *
18*35200Smarc  *   David Korn
19*35200Smarc  *   AT&T Bell Laboratories
20*35200Smarc  *   Room 5D-112
21*35200Smarc  *   Murray Hill, N. J. 07974
22*35200Smarc  *   Tel. x7975
23*35200Smarc  *
24*35200Smarc  *   February, 1983
25*35200Smarc  */
26*35200Smarc 
27*35200Smarc 
28*35200Smarc #include	<stdio.h>
29*35200Smarc #ifdef KSHELL
30*35200Smarc #include	"flags.h"
31*35200Smarc #include	"name.h"
32*35200Smarc #include	"builtins.h"
33*35200Smarc extern struct Namnod *bltin_nodes;
34*35200Smarc #else
35*35200Smarc #define HOMENOD	"HOME"
36*35200Smarc #define valup(arg)	getenv(arg)
37*35200Smarc #endif	/* KSHELL */
38*35200Smarc 
39*35200Smarc #define UNAME	20
40*35200Smarc #define LOGDIR	64
41*35200Smarc static char u_name[UNAME];
42*35200Smarc static char u_logdir[LOGDIR];
43*35200Smarc 
44*35200Smarc #ifdef BSD
45*35200Smarc #define strrchr rindex
46*35200Smarc #endif	/* BSD */
47*35200Smarc extern char	*strrchr();
48*35200Smarc extern char	*strcpy();
49*35200Smarc extern char	*valup();
50*35200Smarc extern void	setbuf();
51*35200Smarc 
52*35200Smarc static char	*logdir();
53*35200Smarc static int	passwdent();
54*35200Smarc 
55*35200Smarc /*
56*35200Smarc  * This routine is used to resolve ~ filenames.
57*35200Smarc  * If string starts with ~ then ~name is replaced with login directory of name.
58*35200Smarc  * A ~ by itself is replaced with the users login directory.
59*35200Smarc  * A ~- is replaced by the last working directory in Shell.
60*35200Smarc  * If string doesn't start with ~ then NULL returned.
61*35200Smarc  * If not found then the NULL string is returned.
62*35200Smarc  */
63*35200Smarc 
tilde(string)64*35200Smarc char *tilde(string)
65*35200Smarc char *string;
66*35200Smarc {
67*35200Smarc 	register char *sp = string;
68*35200Smarc 	register char *cp;
69*35200Smarc 	register int c;
70*35200Smarc 	if(*sp++!='~')
71*35200Smarc 		return(NULL);
72*35200Smarc 	if((c = *sp)==0 || c=='/')
73*35200Smarc 	{
74*35200Smarc 		return(valup(HOME));
75*35200Smarc 	}
76*35200Smarc #ifdef KSHELL
77*35200Smarc 	if((c=='-' || c=='+') && ((c= *(sp+1))==0 || c=='/'))
78*35200Smarc 	{
79*35200Smarc 		char *oldpwd;
80*35200Smarc 		if(*sp=='+')
81*35200Smarc 			return(valup(PWDNOD));
82*35200Smarc 		else if(oldpwd=valup(OLDPWDNOD))
83*35200Smarc 			return(oldpwd);
84*35200Smarc 		else
85*35200Smarc 			return(valup(HOME));
86*35200Smarc 	}
87*35200Smarc #endif	/* KSHELL */
88*35200Smarc 	if((cp=strrchr(sp,'/')) != NULL)
89*35200Smarc 		*cp = 0;
90*35200Smarc 	sp = logdir(sp);
91*35200Smarc 	if(cp)
92*35200Smarc 		*cp = '/';
93*35200Smarc 	return(sp);
94*35200Smarc }
95*35200Smarc 
96*35200Smarc 
97*35200Smarc /*
98*35200Smarc  * This routine returns a pointer to a null-terminated string that
99*35200Smarc  * contains the login directory of the given <user>.
100*35200Smarc  * NULL is returned if there is no entry for the given user in the
101*35200Smarc  * /etc/passwd file or if no room for directory entry.
102*35200Smarc  * The most recent login directory is saved for future access
103*35200Smarc  */
104*35200Smarc 
logdir(user)105*35200Smarc static char *logdir(user)
106*35200Smarc char *user;
107*35200Smarc {
108*35200Smarc 	if(strcmp(user,u_name))
109*35200Smarc 	{
110*35200Smarc 		if(passwdent(user)<0)
111*35200Smarc 			return(NULL);
112*35200Smarc 	}
113*35200Smarc 	return(u_logdir);
114*35200Smarc }
115*35200Smarc 
116*35200Smarc 
117*35200Smarc /*
118*35200Smarc  * read the passwd entry for a given <user> and save the uid, gid and home
119*35200Smarc  */
120*35200Smarc 
passwdent(user)121*35200Smarc static int passwdent(user)
122*35200Smarc char *user;
123*35200Smarc {
124*35200Smarc 	register char *sp=user;
125*35200Smarc 	register int c;
126*35200Smarc 	register int field=0;
127*35200Smarc 	register FILE *fd;
128*35200Smarc 	int rval = -1;
129*35200Smarc 	int val = 0;
130*35200Smarc 	char buff[BUFSIZ];
131*35200Smarc 	if(strlen(sp)>=UNAME)
132*35200Smarc 		return(-1);
133*35200Smarc 	if((fd=fdopen(open("/etc/passwd",0),"r"))==NULL)
134*35200Smarc 		return(-1);
135*35200Smarc 	setbuf(fd,buff);
136*35200Smarc 	while((c=getc(fd)) !=EOF)
137*35200Smarc 	{
138*35200Smarc 		if(c == ':')
139*35200Smarc 		{
140*35200Smarc 			if(field==5)
141*35200Smarc 				goto good;
142*35200Smarc 			else if(field++ ==0)
143*35200Smarc 			{
144*35200Smarc 				if(*sp)
145*35200Smarc 					field = 10;
146*35200Smarc 				else
147*35200Smarc 					sp = u_logdir;
148*35200Smarc 			}
149*35200Smarc 		}
150*35200Smarc 		else if(c=='\n')
151*35200Smarc 		{
152*35200Smarc 			if(field==5)
153*35200Smarc 				goto good;
154*35200Smarc 			sp = user;
155*35200Smarc 			field = 0;
156*35200Smarc 		}
157*35200Smarc 		else
158*35200Smarc 		{
159*35200Smarc 			switch(field)
160*35200Smarc 			{
161*35200Smarc 				/* match name */
162*35200Smarc 				case 0:
163*35200Smarc 					if(c != *sp++)
164*35200Smarc 						field = 10;
165*35200Smarc 					break;
166*35200Smarc 
167*35200Smarc 				case 5:
168*35200Smarc 					*sp++ = c;
169*35200Smarc 					/* see if too big */
170*35200Smarc 					if(sp >= (u_logdir+LOGDIR))
171*35200Smarc 						goto leave;
172*35200Smarc 			}
173*35200Smarc 		}
174*35200Smarc 	}
175*35200Smarc 	while(c != EOF);
176*35200Smarc 	goto leave;
177*35200Smarc good:
178*35200Smarc 	rval = 0;
179*35200Smarc 	*sp = 0;
180*35200Smarc 	strcpy(u_name,user);
181*35200Smarc leave:
182*35200Smarc 	setbuf(fd,(char*)0);
183*35200Smarc 	fclose(fd);
184*35200Smarc 	return(rval);
185*35200Smarc }
186*35200Smarc 
187