2 * Copyright notice from original mutt:
3 * Copyright (C) 1996-2000 Michael R. Elkins <me@mutt.org>
5 * This file is part of mutt-ng, see http://www.muttng.org/.
6 * It's licensed under the GNU General Public License,
7 * please see the file GPL in the top level source directory.
23 #include <lib-lib/str.h>
24 #include <lib-lib/file.h>
25 #include "lib/debug.h"
29 #include <sys/types.h>
33 /* given a partial pathname, this routine fills in as much of the rest of the
36 * return 0 if ok, -1 if no matches
38 int mutt_complete (char *s, size_t slen)
45 char dirpart[_POSIX_PATH_MAX], exp_dirpart[_POSIX_PATH_MAX];
46 char filepart[_POSIX_PATH_MAX];
49 char imap_path[LONG_STRING];
52 debug_print (2, ("completing %s\n", s));
55 if (option (OPTNEWS)) {
56 LIST *l = CurrentNewsSrv->list;
58 m_strcpy(filepart, sizeof(filepart), s);
61 * special case to handle when there is no filepart yet.
62 * find the first subscribed newsgroup
64 if ((len = m_strlen(filepart)) == 0) {
65 for (; l; l = l->next) {
66 NNTP_DATA *data = (NNTP_DATA *) l->data;
68 if (data && data->subscribed) {
69 m_strcpy(filepart, sizeof(filepart), data->group);
77 for (; l; l = l->next) {
78 NNTP_DATA *data = (NNTP_DATA *) l->data;
80 if (data && data->subscribed &&
81 m_strncmp(data->group, filepart, len) == 0) {
83 for (i = 0; filepart[i] && data->group[i]; i++) {
84 if (filepart[i] != data->group[i]) {
92 m_strcpy(filepart, sizeof(filepart), data->group);
100 return (init ? 0 : -1);
105 /* we can use '/' as a delimiter, imap_complete rewrites it */
106 if (*s == '=' || *s == '+' || *s == '!') {
107 const char *q = NONULL(*s == '!' ? Spoolfile : Maildir);
108 mutt_concat_path(imap_path, sizeof(imap_path), q, s + 1);
111 m_strcpy(imap_path, sizeof(imap_path), s);
113 if (mx_get_magic (imap_path) == M_IMAP)
114 return imap_complete (s, slen, imap_path);
117 if (*s == '=' || *s == '+' || *s == '!') {
121 m_strcpy(exp_dirpart, sizeof(exp_dirpart), NONULL(Spoolfile));
123 m_strcpy(exp_dirpart, sizeof(exp_dirpart), NONULL(Maildir));
124 if ((p = strrchr (s, '/'))) {
125 char buf[_POSIX_PATH_MAX];
128 mutt_concat_path(buf, sizeof(buf), exp_dirpart, s + 1);
129 m_strcpy(exp_dirpart, sizeof(exp_dirpart), buf);
130 snprintf (buf, sizeof (buf), "%s%s/", dirpart, s + 1);
131 m_strcpy(dirpart, sizeof(dirpart), buf);
132 m_strcpy(filepart, sizeof(filepart), p);
135 m_strcpy(filepart, sizeof(filepart), s + 1);
136 dirp = opendir (exp_dirpart);
139 if ((p = strrchr (s, '/'))) {
140 if (p == s) { /* absolute path */
142 m_strcpy(dirpart, sizeof(dirpart), "/");
144 m_strcpy(filepart, sizeof(filepart), p);
145 dirp = opendir (dirpart);
149 len = (size_t) (p - s);
150 memcpy(dirpart, s, len);
153 m_strcpy(filepart, sizeof(filepart), p);
154 m_strcpy(exp_dirpart, sizeof(exp_dirpart), dirpart);
155 mutt_expand_path (exp_dirpart, sizeof (exp_dirpart));
156 dirp = opendir (exp_dirpart);
160 /* no directory name, so assume current directory. */
162 m_strcpy(filepart, sizeof(filepart), s);
163 dirp = opendir (".");
168 debug_print (1, ("%s: %s (errno %d).\n", exp_dirpart, strerror (errno), errno));
173 * special case to handle when there is no filepart yet. find the first
174 * file/directory which is not ``.'' or ``..''
176 if ((len = m_strlen(filepart)) == 0) {
177 while ((de = readdir (dirp)) != NULL) {
178 if (m_strcmp(".", de->d_name) != 0
179 && m_strcmp("..", de->d_name) != 0) {
180 m_strcpy(filepart, sizeof(filepart), de->d_name);
187 while ((de = readdir (dirp)) != NULL) {
188 if (m_strncmp(de->d_name, filepart, len) == 0) {
190 for (i = 0; filepart[i] && de->d_name[i]; i++) {
191 if (filepart[i] != de->d_name[i]) {
199 char buf[_POSIX_PATH_MAX];
202 m_strcpy(filepart, sizeof(filepart), de->d_name);
204 /* check to see if it is a directory */
206 m_strcpy(buf, sizeof(buf), exp_dirpart);
207 m_strcpy(buf + m_strlen(buf), sizeof(buf) - m_strlen(buf), "/");
211 m_strcpy(buf + m_strlen(buf), sizeof(buf) - m_strlen(buf), filepart);
212 if (stat (buf, &st) != -1 && (st.st_mode & S_IFDIR))
213 m_strcpy(filepart + m_strlen(filepart),
214 sizeof(filepart) - m_strlen(filepart), "/");
222 m_strcpy(s, slen, dirpart);
223 if (m_strcmp("/", dirpart) != 0 && dirpart[0] != '='
224 && dirpart[0] != '+')
225 m_strcpy(s + m_strlen(s), slen - m_strlen(s), "/");
226 m_strcpy(s + m_strlen(s), slen - m_strlen(s), filepart);
229 m_strcpy(s, slen, filepart);
231 return (init ? 0 : -1);