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