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