mutt stable branch with some hacks
at jcs 217 lines 5.6 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 BUFFER *dirpart = NULL; 48 BUFFER *exp_dirpart = NULL; 49 BUFFER *filepart = NULL; 50 BUFFER *buf = NULL; 51 52#ifdef USE_IMAP 53 BUFFER *imap_path = NULL; 54 int rc; 55 56 dprint (2, (debugfile, "mutt_complete: completing %s\n", s)); 57 58 imap_path = mutt_buffer_pool_get (); 59 /* we can use '/' as a delimiter, imap_complete rewrites it */ 60 if (*s == '=' || *s == '+' || *s == '!') 61 { 62 if (*s == '!') 63 p = NONULL (Spoolfile); 64 else 65 p = NONULL (Maildir); 66 67 mutt_buffer_concat_path (imap_path, p, s+1); 68 } 69 else 70 mutt_buffer_strcpy (imap_path, s); 71 72 if (mx_is_imap (mutt_b2s (imap_path))) 73 { 74 rc = imap_complete (s, slen, mutt_b2s (imap_path)); 75 mutt_buffer_pool_release (&imap_path); 76 return rc; 77 } 78 79 mutt_buffer_pool_release (&imap_path); 80#endif 81 82 dirpart = mutt_buffer_pool_get (); 83 exp_dirpart = mutt_buffer_pool_get (); 84 filepart = mutt_buffer_pool_get (); 85 buf = mutt_buffer_pool_get (); 86 87 if (*s == '=' || *s == '+' || *s == '!') 88 { 89 mutt_buffer_addch (dirpart, *s); 90 if (*s == '!') 91 mutt_buffer_strcpy (exp_dirpart, NONULL (Spoolfile)); 92 else 93 mutt_buffer_strcpy (exp_dirpart, NONULL (Maildir)); 94 if ((p = strrchr (s, '/'))) 95 { 96 mutt_buffer_concatn_path (buf, 97 mutt_b2s (exp_dirpart), mutt_buffer_len (exp_dirpart), 98 s + 1, (size_t)(p - s - 1)); 99 mutt_buffer_strcpy (exp_dirpart, mutt_b2s (buf)); 100 mutt_buffer_substrcpy (dirpart, s, p+1); 101 mutt_buffer_strcpy (filepart, p + 1); 102 } 103 else 104 mutt_buffer_strcpy (filepart, s + 1); 105 dirp = opendir (mutt_b2s (exp_dirpart)); 106 } 107 else 108 { 109 if ((p = strrchr (s, '/'))) 110 { 111 if (p == s) /* absolute path */ 112 { 113 p = s + 1; 114 mutt_buffer_strcpy (dirpart, "/"); 115 mutt_buffer_strcpy (filepart, p); 116 dirp = opendir (mutt_b2s (dirpart)); 117 } 118 else 119 { 120 mutt_buffer_substrcpy (dirpart, s, p); 121 mutt_buffer_strcpy (filepart, p + 1); 122 mutt_buffer_strcpy (exp_dirpart, mutt_b2s (dirpart)); 123 mutt_buffer_expand_path (exp_dirpart); 124 dirp = opendir (mutt_b2s (exp_dirpart)); 125 } 126 } 127 else 128 { 129 /* no directory name, so assume current directory. */ 130 mutt_buffer_strcpy (filepart, s); 131 dirp = opendir ("."); 132 } 133 } 134 135 if (dirp == NULL) 136 { 137 dprint (1, (debugfile, "mutt_complete(): %s: %s (errno %d).\n", 138 mutt_b2s (exp_dirpart), strerror (errno), errno)); 139 goto cleanup; 140 } 141 142 /* 143 * special case to handle when there is no filepart yet. find the first 144 * file/directory which is not ``.'' or ``..'' 145 */ 146 if ((len = mutt_buffer_len (filepart)) == 0) 147 { 148 while ((de = readdir (dirp)) != NULL) 149 { 150 if (mutt_strcmp (".", de->d_name) != 0 && mutt_strcmp ("..", de->d_name) != 0) 151 { 152 mutt_buffer_strcpy (filepart, de->d_name); 153 init++; 154 break; 155 } 156 } 157 } 158 159 while ((de = readdir (dirp)) != NULL) 160 { 161 if (mutt_strncmp (de->d_name, mutt_b2s (filepart), len) == 0) 162 { 163 if (init) 164 { 165 char *fpch; 166 167 for (i=0, fpch = filepart->data; *fpch && de->d_name[i]; i++, fpch++) 168 { 169 if (*fpch != de->d_name[i]) 170 break; 171 } 172 *fpch = 0; 173 mutt_buffer_fix_dptr (filepart); 174 } 175 else 176 { 177 struct stat st; 178 179 mutt_buffer_strcpy (filepart, de->d_name); 180 181 /* check to see if it is a directory */ 182 if (mutt_buffer_len (dirpart)) 183 { 184 mutt_buffer_strcpy (buf, mutt_b2s (exp_dirpart)); 185 mutt_buffer_addch (buf, '/'); 186 } 187 else 188 mutt_buffer_clear (buf); 189 mutt_buffer_addstr (buf, mutt_b2s (filepart)); 190 if (stat (mutt_b2s (buf), &st) != -1 && (st.st_mode & S_IFDIR)) 191 mutt_buffer_addch (filepart, '/'); 192 init = 1; 193 } 194 } 195 } 196 closedir (dirp); 197 198 if (mutt_buffer_len (dirpart)) 199 { 200 strfcpy (s, mutt_b2s (dirpart), slen); 201 if (mutt_strcmp ("/", mutt_b2s (dirpart)) != 0 && 202 mutt_b2s (dirpart)[0] != '=' && 203 mutt_b2s (dirpart)[0] != '+') 204 strfcpy (s + strlen (s), "/", slen - strlen (s)); 205 strfcpy (s + strlen (s), mutt_b2s (filepart), slen - strlen (s)); 206 } 207 else 208 strfcpy (s, mutt_b2s (filepart), slen); 209 210cleanup: 211 mutt_buffer_pool_release (&dirpart); 212 mutt_buffer_pool_release (&exp_dirpart); 213 mutt_buffer_pool_release (&filepart); 214 mutt_buffer_pool_release (&buf); 215 216 return (init ? 0 : -1); 217}