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