1 /*
2 * (c) Copyright 1990, Kim Fabricius Storm. All rights reserved.
3 * Copyright (c) 1996-2005 Michael T Pins. All rights reserved.
4 *
5 * Directory access.
6 * read file names in directory 'dir' starting with 'prefix'
7 */
8
9 #include <stdlib.h>
10 #include <string.h>
11 #include "config.h"
12 #include "global.h"
13 #include "articles.h"
14 #include "dir.h"
15 #include "nn_term.h"
16
17
18 /* dir.c */
19
20 static int sort_directory(register char **f1, register char **f2);
21
22
23 static char dir_path[FILENAME], *dir_tail;
24
25 #ifdef HAVE_DIRECTORY
26 static string_marker str_mark;
27 static char **completions = NULL;
28 static char **comp_iterator;
29 static char **comp_help;
30
31 /*
32 * list_directory scans the directory twice; first time to find out how
33 * many matches there are, and second time to save the names, after
34 * sufficient memory have been allocated to store it all.
35 */
36
37 static int
sort_directory(register char ** f1,register char ** f2)38 sort_directory(register char **f1, register char **f2)
39 { /* Used by qsort */
40 return strcmp(*f1, *f2);
41 }
42
43 int
list_directory(char * dir,char * prefix)44 list_directory(char *dir, char *prefix)
45 {
46 DIR *dirp;
47 register Direntry *dp;
48 register char *cp;
49 register char **comp = NULL;
50 int pflen = strlen(prefix);
51 unsigned count = 0, comp_length = 0;
52
53 if ((dirp = opendir(dir)) == NULL)
54 return 0; /* tough luck */
55
56 mark_str(&str_mark);
57
58 while ((dp = readdir(dirp)) != NULL) {
59 cp = dp->d_name;
60
61 #ifdef FAKED_DIRECTORY
62 if (dp->d_ino == 0)
63 continue;
64 cp[14] = NUL;
65 #endif
66
67 if (*cp == '.' && (cp[1] == '\0' || (cp[1] == '.' && cp[2] == '\0')))
68 continue;
69 if (pflen && strncmp(prefix, cp, pflen))
70 continue;
71 if (count == comp_length) {
72 comp_length += 100;
73 completions = resizeobj(completions, char *, comp_length + 1);
74 comp = completions + count;
75 }
76 strcpy(*comp++ = alloc_str(strlen(cp)), cp);
77 count++;
78 }
79 closedir(dirp);
80 if (count == 0) {
81 release_str(&str_mark);
82 return 0;
83 }
84 quicksort(completions, count, char *, sort_directory);
85 *comp = (char *) 0;
86 comp_iterator = completions;
87 comp_help = completions;
88
89 dir_tail = dir_path;
90 while ((*dir_tail++ = *dir++));
91 dir_tail[-1] = '/';
92
93 return 1;
94 }
95
96 int
next_directory(register char * buffer,int add_slash)97 next_directory(register char *buffer, int add_slash)
98 {
99 if (*comp_iterator != NULL) {
100 strcpy(buffer, *comp_iterator);
101
102 if (add_slash) {
103 strcpy(dir_tail, *comp_iterator);
104 if (file_exist(dir_path, "d"))
105 strcat(buffer, "/");
106 }
107 comp_iterator++;
108 return 1;
109 }
110 close_directory();
111 return 0;
112 }
113
114 int
compl_help_directory(void)115 compl_help_directory(void)
116 {
117 list_completion((char *) NULL);
118
119 if (*comp_help == NULL)
120 comp_help = completions;
121 while (*comp_help && list_completion(*comp_help))
122 comp_help++;
123
124 fl;
125 return 1;
126 }
127
128 void
close_directory(void)129 close_directory(void)
130 {
131 if (completions) {
132 release_str(&str_mark);
133 freeobj(completions);
134 completions = NULL;
135 }
136 }
137
138 #else
139
140 static FILE *dirf;
141 static int prefix_lgt;
142
143 int
list_directory(char * dir,char * prefix)144 list_directory(char *dir, char *prefix)
145 {
146 if (prefix[0])
147 sprintf(dir_path, "cd %s && echo %s* 2>/dev/null", dir, prefix);
148 else
149 sprintf(dir_path, "cd %s && ls 2>/dev/null", dir);
150 prefix_lgt = strlen(prefix);
151
152 if ((dirf = popen(dir_path, "r")) == NULL)
153 return 0;
154
155 dir_tail = dir_path;
156 while (*dir_tail++ = *dir++);
157 dir_tail[-1] = '/';
158
159 return 1;
160 }
161
next_directory(char * buffer,int add_slash)162 next_directory(char *buffer, int add_slash)
163 {
164 register char *cp;
165 register int c;
166
167 cp = buffer;
168 while ((c = getc(dirf)) != EOF && (c != SP) && (c != NL))
169 *cp++ = c;
170
171 if (cp != buffer) {
172 *cp = NUL;
173 if (strcmp(buffer + prefix_lgt, "*")) {
174
175 if (!add_slash)
176 return 1;
177
178 strcpy(dir_tail, buffer);
179 if (file_exist(dir_path, "d")) {
180 *cp++ = '/';
181 *cp = NUL;
182 }
183 return 1;
184 }
185 }
186 close_directory();
187 return 0;
188 }
189
190 int
compl_help_directory(void)191 compl_help_directory(void)
192 {
193 return 0;
194 }
195
196 void
close_directory(void)197 close_directory(void)
198 {
199 if (dirf) {
200 pclose(dirf);
201 dirf = NULL;
202 }
203 }
204
205 #endif /* HAVE_DIRECTORY */
206