1d5ac70f0Sopenharmony_ci/* 2d5ac70f0Sopenharmony_ci * Get full filename 3d5ac70f0Sopenharmony_ci * Copyright (c) 2003 by Jaroslav Kysela <perex@perex.cz> 4d5ac70f0Sopenharmony_ci * 5d5ac70f0Sopenharmony_ci * This library is free software; you can redistribute it and/or modify 6d5ac70f0Sopenharmony_ci * it under the terms of the GNU Lesser General Public License as 7d5ac70f0Sopenharmony_ci * published by the Free Software Foundation; either version 2.1 of 8d5ac70f0Sopenharmony_ci * the License, or (at your option) any later version. 9d5ac70f0Sopenharmony_ci * 10d5ac70f0Sopenharmony_ci * This program is distributed in the hope that it will be useful, 11d5ac70f0Sopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 12d5ac70f0Sopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13d5ac70f0Sopenharmony_ci * GNU Lesser General Public License for more details. 14d5ac70f0Sopenharmony_ci * 15d5ac70f0Sopenharmony_ci * You should have received a copy of the GNU Lesser General Public 16d5ac70f0Sopenharmony_ci * License along with this library; if not, write to the Free Software 17d5ac70f0Sopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18d5ac70f0Sopenharmony_ci * 19d5ac70f0Sopenharmony_ci */ 20d5ac70f0Sopenharmony_ci 21d5ac70f0Sopenharmony_ci#include "config.h" 22d5ac70f0Sopenharmony_ci#include <string.h> 23d5ac70f0Sopenharmony_ci#include <errno.h> 24d5ac70f0Sopenharmony_ci#include <assert.h> 25d5ac70f0Sopenharmony_ci 26d5ac70f0Sopenharmony_ci/** 27d5ac70f0Sopenharmony_ci * \brief Get the full file name 28d5ac70f0Sopenharmony_ci * \param file The file name string to parse 29d5ac70f0Sopenharmony_ci * \param result The pointer to store the resultant file name 30d5ac70f0Sopenharmony_ci * \return 0 if successful, or a negative error code 31d5ac70f0Sopenharmony_ci * 32d5ac70f0Sopenharmony_ci * Parses the given file name with POSIX-Shell-like expansion and 33d5ac70f0Sopenharmony_ci * stores the first matchine one. The returned string is strdup'ed. 34d5ac70f0Sopenharmony_ci */ 35d5ac70f0Sopenharmony_ci 36d5ac70f0Sopenharmony_ci#ifdef HAVE_WORDEXP 37d5ac70f0Sopenharmony_ci#include <wordexp.h> 38d5ac70f0Sopenharmony_ciint snd_user_file(const char *file, char **result) 39d5ac70f0Sopenharmony_ci{ 40d5ac70f0Sopenharmony_ci wordexp_t we; 41d5ac70f0Sopenharmony_ci int err; 42d5ac70f0Sopenharmony_ci 43d5ac70f0Sopenharmony_ci assert(file && result); 44d5ac70f0Sopenharmony_ci err = wordexp(file, &we, WRDE_NOCMD); 45d5ac70f0Sopenharmony_ci switch (err) { 46d5ac70f0Sopenharmony_ci case WRDE_NOSPACE: 47d5ac70f0Sopenharmony_ci wordfree(&we); 48d5ac70f0Sopenharmony_ci return -ENOMEM; 49d5ac70f0Sopenharmony_ci case 0: 50d5ac70f0Sopenharmony_ci if (we.we_wordc == 1) 51d5ac70f0Sopenharmony_ci break; 52d5ac70f0Sopenharmony_ci wordfree(&we); 53d5ac70f0Sopenharmony_ci /* fall thru */ 54d5ac70f0Sopenharmony_ci default: 55d5ac70f0Sopenharmony_ci return -EINVAL; 56d5ac70f0Sopenharmony_ci } 57d5ac70f0Sopenharmony_ci *result = strdup(we.we_wordv[0]); 58d5ac70f0Sopenharmony_ci wordfree(&we); 59d5ac70f0Sopenharmony_ci if (*result == NULL) 60d5ac70f0Sopenharmony_ci return -ENOMEM; 61d5ac70f0Sopenharmony_ci return 0; 62d5ac70f0Sopenharmony_ci} 63d5ac70f0Sopenharmony_ci 64d5ac70f0Sopenharmony_ci#else /* !HAVE_WORDEX */ 65d5ac70f0Sopenharmony_ci 66d5ac70f0Sopenharmony_ci#include <sys/types.h> 67d5ac70f0Sopenharmony_ci#include <unistd.h> 68d5ac70f0Sopenharmony_ci#include <pwd.h> 69d5ac70f0Sopenharmony_ci#include <stdio.h> 70d5ac70f0Sopenharmony_ci#include <stdlib.h> 71d5ac70f0Sopenharmony_ci 72d5ac70f0Sopenharmony_ciint snd_user_file(const char *file, char **result) 73d5ac70f0Sopenharmony_ci{ 74d5ac70f0Sopenharmony_ci int err; 75d5ac70f0Sopenharmony_ci size_t len; 76d5ac70f0Sopenharmony_ci char *buf = NULL; 77d5ac70f0Sopenharmony_ci 78d5ac70f0Sopenharmony_ci assert(file && result); 79d5ac70f0Sopenharmony_ci *result = NULL; 80d5ac70f0Sopenharmony_ci 81d5ac70f0Sopenharmony_ci /* expand ~/ if needed */ 82d5ac70f0Sopenharmony_ci if (file[0] == '~' && file[1] == '/') { 83d5ac70f0Sopenharmony_ci const char *home = getenv("HOME"); 84d5ac70f0Sopenharmony_ci if (home == NULL) { 85d5ac70f0Sopenharmony_ci struct passwd pwent, *p = NULL; 86d5ac70f0Sopenharmony_ci uid_t id = getuid(); 87d5ac70f0Sopenharmony_ci size_t bufsize = 1024; 88d5ac70f0Sopenharmony_ci 89d5ac70f0Sopenharmony_ci buf = malloc(bufsize); 90d5ac70f0Sopenharmony_ci if (buf == NULL) 91d5ac70f0Sopenharmony_ci goto out; 92d5ac70f0Sopenharmony_ci 93d5ac70f0Sopenharmony_ci while ((err = getpwuid_r(id, &pwent, buf, bufsize, &p)) == ERANGE) { 94d5ac70f0Sopenharmony_ci char *newbuf; 95d5ac70f0Sopenharmony_ci bufsize += 1024; 96d5ac70f0Sopenharmony_ci if (bufsize < 1024) 97d5ac70f0Sopenharmony_ci break; 98d5ac70f0Sopenharmony_ci newbuf = realloc(buf, bufsize); 99d5ac70f0Sopenharmony_ci if (newbuf == NULL) 100d5ac70f0Sopenharmony_ci goto out; 101d5ac70f0Sopenharmony_ci buf = newbuf; 102d5ac70f0Sopenharmony_ci } 103d5ac70f0Sopenharmony_ci home = err ? "" : pwent.pw_dir; 104d5ac70f0Sopenharmony_ci } 105d5ac70f0Sopenharmony_ci len = strlen(home) + strlen(&file[2]) + 2; 106d5ac70f0Sopenharmony_ci *result = malloc(len); 107d5ac70f0Sopenharmony_ci if (*result) 108d5ac70f0Sopenharmony_ci snprintf(*result, len, "%s/%s", home, &file[2]); 109d5ac70f0Sopenharmony_ci } else { 110d5ac70f0Sopenharmony_ci *result = strdup(file); 111d5ac70f0Sopenharmony_ci } 112d5ac70f0Sopenharmony_ci 113d5ac70f0Sopenharmony_ciout: 114d5ac70f0Sopenharmony_ci if (buf) 115d5ac70f0Sopenharmony_ci free(buf); 116d5ac70f0Sopenharmony_ci 117d5ac70f0Sopenharmony_ci if (*result == NULL) 118d5ac70f0Sopenharmony_ci return -ENOMEM; 119d5ac70f0Sopenharmony_ci return 0; 120d5ac70f0Sopenharmony_ci} 121d5ac70f0Sopenharmony_ci 122d5ac70f0Sopenharmony_ci#endif /* HAVE_WORDEXP */ 123