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