Fix exec from setuid/setgid binaries
[dragonfly.git] / gnu / lib / libdialog / fselect.c
blob6669edc529b2ef4e707855036b8499288c334517
1 /*
2 * program: fselect.c
3 * author: Marc van Kempen (wmbfmk@urc.tue.nl)
4 * Desc: File selection routine
6 * Copyright (c) 1995, Marc van Kempen
8 * All rights reserved.
10 * This software may be used, modified, copied, distributed, and
11 * sold, in both source and binary form provided that the above
12 * copyright and these terms are retained, verbatim, as the first
13 * lines of this file. Under no circumstances is the author
14 * responsible for the proper functioning of this software, nor does
15 * the author assume any responsibility for damages incurred with
16 * its use.
20 #include <stdlib.h>
21 #include <unistd.h>
22 #include <sys/param.h>
23 #include <dialog.h>
24 #include "ui_objects.h"
25 #include "dir.h"
26 #include "dialog.priv.h"
29 * Local prototypes
32 char *dialog_dfselect(char *dir, char *fmask, int is_fselect);
35 * Functions
38 void
39 get_directories(DirList *d, int n, char ***names, int *nd)
41 * Desc: return the directorienames in <dir> as an array in
42 * <names>, the # of entries in <nd>, memory allocated
43 * to *names should be freed when done with it.
46 int i;
48 /* count the directories, which are in front */
49 *nd = 0;
50 while ((*nd < n) && (S_ISDIR(d[*nd].filestatus.st_mode))) (*nd)++;
51 *names = (char **) malloc( *nd * sizeof(char *) );
52 for (i=0; i<*nd; i++) {
53 (*names)[i] = (char *) malloc( strlen(d[i].filename) + 1);
54 strcpy((*names)[i], d[i].filename);
57 return;
58 } /* get_directories() */
60 void
61 get_filenames(DirList *d, int n, char ***names, int *nf)
63 * Desc: return the filenames in <dir> as an arry in
64 * <names>, the # of entries in <nf>, memory allocated
65 * to *names should be freed when done.
68 int nd, i;
70 /* the # of regular files is the total # of files - # of directories */
71 /* count the # of directories */
72 nd = 0;
73 while ((nd < n) && (S_ISDIR(d[nd].filestatus.st_mode))) nd++;
75 *names = (char **) malloc( (n-nd) * sizeof(char *) );
76 *nf = n - nd;
77 for (i=0; i<*nf; i++) {
78 (*names)[i] = (char *) malloc( strlen(d[i+nd].filename) + 1);
79 strcpy((*names)[i], d[i+nd].filename);
82 return;
83 } /* get_filenames() */
85 void
86 FreeNames(char **names, int n)
88 * Desc: free the space occupied by names
91 int i;
93 /* free the space occupied by names */
94 for (i=0; i<n; i++) {
95 free(names[i]);
97 free(names);
99 return;
100 } /* FreeNames() */
103 dialog_dselect_old(void)
105 * Desc: starting from the current directory,
106 * choose a new current directory
109 DirList *d = NULL;
110 char **names, old_dir[MAXPATHLEN];
111 WINDOW *ds_win;
112 ButtonObj *okbut, *cancelbut;
113 ListObj *dirs_obj;
114 StringObj *dir_obj;
115 char o_dir[MAXPATHLEN];
116 struct ComposeObj *obj = NULL;
117 int n, nd, okbutton, cancelbutton,
118 quit, cancel, ret;
120 ds_win = newwin(LINES-8, COLS-30, 4, 15);
121 if (ds_win == NULL) {
122 fprintf(stderr, "\nnewwin(%d,%d,%d,%d) failed, maybe wrong dims\n",
123 LINES-8, COLS-30, 4, 15);
124 exit(1);
126 draw_box(ds_win, 0, 0, LINES-8, COLS-30, dialog_attr, border_attr);
127 wattrset(ds_win, dialog_attr);
128 mvwaddstr(ds_win, 0, (COLS-30)/2 - 9, " Directory Select ");
129 draw_shadow(stdscr, 4, 15, LINES-8, COLS-30);
130 display_helpline(ds_win, LINES-9, COLS-30);
132 /* the Directory string input field */
133 getcwd(o_dir, MAXPATHLEN);
134 dir_obj = NewStringObj(ds_win, "Directory:", o_dir, 1, 2, COLS-34, MAXPATHLEN-1);
135 AddObj(&obj, STRINGOBJ, (void *) dir_obj);
137 /* the list of directories */
138 get_dir(".", "*", &d, &n);
139 get_directories(d, n, &names, &nd);
140 dirs_obj = NewListObj(ds_win, "Directories:", names, o_dir, 5, 2,
141 LINES-15, COLS-48, nd);
142 AddObj(&obj, LISTOBJ, (void *) dirs_obj);
144 /* the Ok-button */
145 okbutton = FALSE;
146 okbut = NewButtonObj(ds_win, "Continue", &okbutton, 7, COLS-45);
147 AddObj(&obj, BUTTONOBJ, (void *) okbut);
149 /* the Cancel-button */
150 cancelbutton = FALSE;
151 cancelbut = NewButtonObj(ds_win, "Return", &cancelbutton, 11, COLS-44);
152 AddObj(&obj, BUTTONOBJ, (void *) cancelbut);
154 quit = FALSE;
155 cancel = FALSE;
156 strcpy(old_dir, o_dir);
157 while (!quit) {
158 ret = PollObj(&obj);
159 switch(ret) {
160 case SEL_BUTTON:
161 if (okbutton) {
162 quit = TRUE;
164 if (cancelbutton) {
165 quit = TRUE;
166 cancel = TRUE;
168 break;
169 case SEL_CR:
170 if (strcmp(old_dir, o_dir)) {
171 /* the directory was changed, cd into it */
172 if (chdir(o_dir)) {
173 dialog_notify("Could not change into directory");
174 strcpy(o_dir, old_dir);
175 } else {
176 getcwd(o_dir, MAXPATHLEN);
177 strcpy(old_dir, o_dir);
179 RefreshStringObj(dir_obj);
181 get_dir(".", "*", &d, &n);
182 FreeNames(names, nd);
183 get_directories(d, n, &names, &nd);
184 UpdateListObj(dirs_obj, names, nd);
185 if (((obj->prev)->obj == (void *) dirs_obj)) {
186 obj=obj->prev;
188 break;
189 case SEL_ESC:
190 quit = TRUE;
191 cancel = TRUE;
192 break;
193 case KEY_F(1):
194 display_helpfile();
195 break;
199 FreeNames(names, nd);
200 DelObj(obj);
201 delwin(ds_win);
203 return(cancel);
205 } /* dialog_dselect() */
208 dialog_dselect(char *dir, char *fmask)
210 * Desc: Choose a directory
213 if (dialog_dfselect(dir, fmask, FALSE)) {
214 return(FALSE); /* esc or cancel was pressed */
215 } else {
216 return(TRUE); /* directory was selected */
218 } /* dialog_dselect() */
220 char *
221 dialog_fselect(char *dir, char *fmask)
223 * Desc: Choose a file from a directory
226 return(dialog_dfselect(dir, fmask, TRUE));
227 } /* dialog_fselect() */
229 char *
230 dialog_dfselect(char *dir, char *fmask, int is_fselect)
232 * Desc: choose a file from the directory <dir>, which
233 * initially display files with the mask <filemask>
234 * pre: <dir> is the initial directory
235 * only files corresponding to the mask <fmask> are displayed
236 * post: returns NULL if no file was selected
237 * else returns pointer to filename, space is allocated, should
238 * be freed after use.
241 DirList *d = NULL;
242 char msg[512];
243 char **fnames, **dnames, *ret_name;
244 WINDOW *fs_win;
245 int n, nd, nf, ret;
246 StringObj *fm_obj, *dir_obj, *sel_obj;
247 char o_fm[255], o_dir[MAXPATHLEN], o_sel[MAXPATHLEN];
248 char old_fmask[255], old_dir[MAXPATHLEN];
249 ListObj *dirs_obj, *files_obj;
250 struct ComposeObj *obj = NULL, *o;
251 int quit, cancel;
252 ButtonObj *okbut_obj, *canbut_obj;
253 int ok_button, cancel_button;
255 if (chdir(dir)) {
256 sprintf(msg, "Could not move into specified directory: %s", dir);
257 dialog_notify(msg);
258 return(NULL);
260 getcwd(o_dir, MAXPATHLEN);
262 /* setup the fileselect-window and initialize its components */
263 fs_win = newwin(LINES-2, COLS-20, 1, 10);
264 if (fs_win == NULL) {
265 endwin();
266 fprintf(stderr, "\nnewwin(%d,%d,%d,%d) failed, maybe wrong dims\n",
267 LINES-2, COLS-20, 2, 10);
268 exit(1);
270 draw_box(fs_win, 0, 0, LINES-2, COLS-20, dialog_attr, border_attr);
271 wattrset(fs_win, dialog_attr);
272 if (is_fselect) {
273 mvwaddstr(fs_win, 0, (COLS-20)/2 - 7, " File Select ");
274 } else {
275 mvwaddstr(fs_win, 0, (COLS-20)/2 - 9, " Directory Select ");
277 draw_shadow(stdscr, 1, 10, LINES-2, COLS-20);
278 display_helpline(fs_win, LINES-3, COLS-20);
280 /* Filemask entry */
281 strcpy(o_fm, fmask);
282 fm_obj = NewStringObj(fs_win, "Filemask:", o_fm, 1, 2, 19, 255);
283 AddObj(&obj, STRINGOBJ, (void *) fm_obj);
285 /* Directory entry */
286 dir_obj = NewStringObj(fs_win, "Directory:", o_dir, 1, 22, COLS-44, 255);
287 AddObj(&obj, STRINGOBJ, (void *) dir_obj);
289 /* Directory list */
290 get_dir(".", fmask, &d, &n); /* read the entire directory */
291 get_directories(d, n, &dnames, &nd); /* extract the dir-entries */
292 if (is_fselect) {
293 dirs_obj = NewListObj(fs_win, "Directories:", dnames, o_dir, 5, 2,
294 LINES-16, (COLS-20)/2-2, nd);
295 } else {
296 dirs_obj = NewListObj(fs_win, "Directories:", dnames, o_dir, 5, 2,
297 LINES-12, (COLS-20)/2-2, nd);
299 AddObj(&obj, LISTOBJ, (void *) dirs_obj);
301 /* Filenames list */
302 get_filenames(d, n, &fnames, &nf); /* extract the filenames */
303 if (is_fselect) {
304 files_obj = NewListObj(fs_win, "Files:", fnames, o_sel, 5, (COLS-20)/2+1,
305 LINES-16, (COLS-20)/2-3, nf);
306 } else {
307 files_obj = NewListObj(fs_win, "Files:", fnames, o_sel, 5, (COLS-20)/2+1,
308 LINES-12, (COLS-20)/2-3, nf);
310 AddObj(&obj, LISTOBJ, (void *) files_obj);
312 if (is_fselect) {
313 /* Selection entry */
314 o_sel[0] = '\0';
315 sel_obj = NewStringObj(fs_win, "Selection:", o_sel, LINES-10, 2, COLS-24, 255);
316 AddObj(&obj, STRINGOBJ, (void *) sel_obj);
319 /* Ok button */
320 ok_button = FALSE;
321 okbut_obj = NewButtonObj(fs_win, "Ok", &ok_button, LINES-6, 20);
322 AddObj(&obj, BUTTONOBJ, (void *) okbut_obj);
324 /* Cancel button */
325 cancel_button = FALSE;
326 canbut_obj = NewButtonObj(fs_win, "Cancel", &cancel_button, LINES-6, 30);
327 AddObj(&obj, BUTTONOBJ, (void *) canbut_obj);
329 /* Make sure all objects on the window are drawn */
330 wrefresh(fs_win);
331 keypad(fs_win, TRUE);
333 /* Start the reading */
334 o = obj;
335 strcpy(old_fmask, o_fm);
336 strcpy(old_dir, o_dir);
337 quit = FALSE;
338 cancel = FALSE;
339 while (!quit) {
340 ret = PollObj(&o);
341 switch(ret) {
342 case SEL_CR:
343 if (strcmp(old_fmask, o_fm) || strcmp(old_dir, o_dir)) {
344 /* reread directory and update the listobjects */
345 if (strcmp(old_dir, o_dir)) { /* dir entry was changed */
346 if (chdir(o_dir)) {
347 dialog_notify("Could not change into directory");
348 strcpy(o_dir, old_dir);
349 } else {
350 getcwd(o_dir, MAXPATHLEN);
351 strcpy(old_dir, o_dir);
353 RefreshStringObj(dir_obj);
354 } else { /* fmask entry was changed */
355 strcpy(old_fmask, o_fm);
357 get_dir(".", o_fm, &d, &n);
358 FreeNames(dnames, nd);
359 get_directories(d, n, &dnames, &nd);
360 UpdateListObj(dirs_obj, dnames, nd);
361 FreeNames(fnames, nf);
362 get_filenames(d, n, &fnames, &nf);
363 UpdateListObj(files_obj, fnames, nf);
364 if (((o->prev)->obj == (void *) dirs_obj)) {
365 o=o->prev;
368 break;
369 case SEL_BUTTON:
370 /* check which button was pressed */
371 if (ok_button) {
372 quit = TRUE;
374 if (cancel_button) {
375 quit = TRUE;
376 cancel = TRUE;
378 break;
379 case SEL_ESC:
380 quit = TRUE;
381 cancel = TRUE;
382 break;
383 case KEY_F(1):
384 case '?':
385 display_helpfile();
386 break;
389 DelObj(obj);
390 FreeNames(dnames, nd);
391 FreeNames(fnames, nf);
392 delwin(fs_win);
394 if (cancel || (strlen(o_sel) == 0)) {
395 return(NULL);
396 } else {
397 ret_name = (char *) malloc( strlen(o_sel) + 1 );
398 strcpy(ret_name, o_sel);
399 return(ret_name);
401 } /* dialog_fselect() */