xref: /titanic_50/usr/src/cmd/ssh/libssh/common/tildexpand.c (revision fa9e4066f08beec538e775443c5be79dd423fcab)
1 /*
2  * Author: Tatu Ylonen <ylo@cs.hut.fi>
3  * Copyright (c) 1995 Tatu Ylonen <ylo@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