mutt stable branch with some hacks
at master 198 lines 5.2 kB view raw
1/* 2 * Copyright (C) 1996-2000,2007 Michael R. Elkins <me@mutt.org> 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 */ 18 19#if HAVE_CONFIG_H 20# include "config.h" 21#endif 22 23#include "mutt.h" 24#ifdef USE_IMAP 25#include "mailbox.h" 26#include "imap.h" 27#endif 28 29#include <dirent.h> 30#include <string.h> 31#include <sys/types.h> 32#include <sys/stat.h> 33#include <errno.h> 34 35/* given a partial pathname, this routine fills in as much of the rest of the 36 * path as is unique. 37 * 38 * return 0 if ok, -1 if no matches 39 */ 40int mutt_complete (char *s, size_t slen) 41{ 42 char *p; 43 DIR *dirp = NULL; 44 struct dirent *de; 45 int i ,init=0; 46 size_t len; 47 char dirpart[_POSIX_PATH_MAX], exp_dirpart[_POSIX_PATH_MAX]; 48 char filepart[_POSIX_PATH_MAX]; 49#ifdef USE_IMAP 50 char imap_path[LONG_STRING]; 51 52 dprint (2, (debugfile, "mutt_complete: completing %s\n", s)); 53 54 /* we can use '/' as a delimiter, imap_complete rewrites it */ 55 if (*s == '=' || *s == '+' || *s == '!') 56 { 57 if (*s == '!') 58 p = NONULL (Spoolfile); 59 else 60 p = NONULL (Maildir); 61 62 mutt_concat_path (imap_path, p, s+1, sizeof (imap_path)); 63 } 64 else 65 strfcpy (imap_path, s, sizeof(imap_path)); 66 67 if (mx_is_imap (imap_path)) 68 return imap_complete (s, slen, imap_path); 69#endif 70 71 if (*s == '=' || *s == '+' || *s == '!') 72 { 73 dirpart[0] = *s; 74 dirpart[1] = 0; 75 if (*s == '!') 76 strfcpy (exp_dirpart, NONULL (Spoolfile), sizeof (exp_dirpart)); 77 else 78 strfcpy (exp_dirpart, NONULL (Maildir), sizeof (exp_dirpart)); 79 if ((p = strrchr (s, '/'))) 80 { 81 char buf[_POSIX_PATH_MAX]; 82 if (mutt_concatn_path (buf, sizeof(buf), exp_dirpart, strlen(exp_dirpart), s + 1, (size_t)(p - s - 1)) == NULL) { 83 return -1; 84 } 85 strfcpy (exp_dirpart, buf, sizeof (exp_dirpart)); 86 mutt_substrcpy(dirpart, s, p+1, sizeof(dirpart)); 87 strfcpy (filepart, p + 1, sizeof (filepart)); 88 } 89 else 90 strfcpy (filepart, s + 1, sizeof (filepart)); 91 dirp = opendir (exp_dirpart); 92 } 93 else 94 { 95 if ((p = strrchr (s, '/'))) 96 { 97 if (p == s) /* absolute path */ 98 { 99 p = s + 1; 100 strfcpy (dirpart, "/", sizeof (dirpart)); 101 exp_dirpart[0] = 0; 102 strfcpy (filepart, p, sizeof (filepart)); 103 dirp = opendir (dirpart); 104 } 105 else 106 { 107 mutt_substrcpy(dirpart, s, p, sizeof(dirpart)); 108 strfcpy (filepart, p + 1, sizeof (filepart)); 109 strfcpy (exp_dirpart, dirpart, sizeof (exp_dirpart)); 110 mutt_expand_path (exp_dirpart, sizeof (exp_dirpart)); 111 dirp = opendir (exp_dirpart); 112 } 113 } 114 else 115 { 116 /* no directory name, so assume current directory. */ 117 dirpart[0] = 0; 118 strfcpy (filepart, s, sizeof (filepart)); 119 dirp = opendir ("."); 120 } 121 } 122 123 if (dirp == NULL) 124 { 125 dprint (1, (debugfile, "mutt_complete(): %s: %s (errno %d).\n", exp_dirpart, strerror (errno), errno)); 126 return (-1); 127 } 128 129 /* 130 * special case to handle when there is no filepart yet. find the first 131 * file/directory which is not ``.'' or ``..'' 132 */ 133 if ((len = mutt_strlen (filepart)) == 0) 134 { 135 while ((de = readdir (dirp)) != NULL) 136 { 137 if (mutt_strcmp (".", de->d_name) != 0 && mutt_strcmp ("..", de->d_name) != 0) 138 { 139 strfcpy (filepart, de->d_name, sizeof (filepart)); 140 init++; 141 break; 142 } 143 } 144 } 145 146 while ((de = readdir (dirp)) != NULL) 147 { 148 if (mutt_strncmp (de->d_name, filepart, len) == 0) 149 { 150 if (init) 151 { 152 for (i=0; filepart[i] && de->d_name[i]; i++) 153 { 154 if (filepart[i] != de->d_name[i]) 155 { 156 filepart[i] = 0; 157 break; 158 } 159 } 160 filepart[i] = 0; 161 } 162 else 163 { 164 char buf[_POSIX_PATH_MAX]; 165 struct stat st; 166 167 strfcpy (filepart, de->d_name, sizeof(filepart)); 168 169 /* check to see if it is a directory */ 170 if (dirpart[0]) 171 { 172 strfcpy (buf, exp_dirpart, sizeof (buf)); 173 strfcpy (buf + strlen (buf), "/", sizeof (buf) - strlen (buf)); 174 } 175 else 176 buf[0] = 0; 177 strfcpy (buf + strlen (buf), filepart, sizeof (buf) - strlen (buf)); 178 if (stat (buf, &st) != -1 && (st.st_mode & S_IFDIR)) 179 strfcpy (filepart + strlen (filepart), "/", 180 sizeof (filepart) - strlen (filepart)); 181 init = 1; 182 } 183 } 184 } 185 closedir (dirp); 186 187 if (dirpart[0]) 188 { 189 strfcpy (s, dirpart, slen); 190 if (mutt_strcmp ("/", dirpart) != 0 && dirpart[0] != '=' && dirpart[0] != '+') 191 strfcpy (s + strlen (s), "/", slen - strlen (s)); 192 strfcpy (s + strlen (s), filepart, slen - strlen (s)); 193 } 194 else 195 strfcpy (s, filepart, slen); 196 197 return (init ? 0 : -1); 198}