Home | History | Annotate | Download | only in common
      1 /*
      2  * Author: Tatu Ylonen <ylo (at) cs.hut.fi>
      3  * Copyright (c) 1995 Tatu Ylonen <ylo (at) cs.hut.fi>, Espoo, Finland
      4  *                    All rights reserved
      5  *
      6  * As far as I am concerned, the code I have written for this software
      7  * can be used freely for any purpose.  Any derived versions of this
      8  * software must be clearly marked as such, and if the derived work is
      9  * incompatible with the protocol description in the RFC file, it must be
     10  * called by a name other than "ssh" or "Secure Shell".
     11  */
     12 
     13 #include "includes.h"
     14 RCSID("$OpenBSD: tildexpand.c,v 1.13 2002/06/23 03:25:50 deraadt Exp $");
     15 
     16 #pragma ident	"%Z%%M%	%I%	%E% SMI"
     17 
     18 #include "xmalloc.h"
     19 #include "log.h"
     20 #include "tildexpand.h"
     21 
     22 /*
     23  * Expands tildes in the file name.  Returns data allocated by xmalloc.
     24  * Warning: this calls getpw*.
     25  */
     26 char *
     27 tilde_expand_filename(const char *filename, uid_t my_uid)
     28 {
     29 	const char *cp;
     30 	u_int userlen;
     31 	char *expanded;
     32 	struct passwd *pw;
     33 	char user[100];
     34 	int len;
     35 
     36 	/* Return immediately if no tilde. */
     37 	if (filename[0] != '~')
     38 		return xstrdup(filename);
     39 
     40 	/* Skip the tilde. */
     41 	filename++;
     42 
     43 	/* Find where the username ends. */
     44 	cp = strchr(filename, '/');
     45 	if (cp)
     46 		userlen = cp - filename;	/* Something after username. */
     47 	else
     48 		userlen = strlen(filename);	/* Nothing after username. */
     49 	if (userlen == 0)
     50 		pw = getpwuid(my_uid);		/* Own home directory. */
     51 	else {
     52 		/* Tilde refers to someone elses home directory. */
     53 		if (userlen > sizeof(user) - 1)
     54 			fatal("User name after tilde too long.");
     55 		memcpy(user, filename, userlen);
     56 		user[userlen] = 0;
     57 		pw = getpwnam(user);
     58 	}
     59 	if (!pw)
     60 		fatal("Unknown user %100s.", user);
     61 
     62 	/* If referring to someones home directory, return it now. */
     63 	if (!cp) {
     64 		/* Only home directory specified */
     65 		return xstrdup(pw->pw_dir);
     66 	}
     67 	/* Build a path combining the specified directory and path. */
     68 	len = strlen(pw->pw_dir) + strlen(cp + 1) + 2;
     69 	if (len > MAXPATHLEN)
     70 		fatal("Home directory too long (%d > %d", len-1, MAXPATHLEN-1);
     71 	expanded = xmalloc(len);
     72 	snprintf(expanded, len, "%s%s%s", pw->pw_dir,
     73 	    strcmp(pw->pw_dir, "/") ? "/" : "", cp + 1);
     74 	return expanded;
     75 }
     76