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