1 #include <stdlib.h>
2 #include <assert.h>
3 #include <unistd.h>
4 #include <fcntl.h>
5
6 #include "lub/string.h"
7 #include "private.h"
8
9 /*----------------------------------------------------------- */
clish_shell_push(clish_shell_t * this,FILE * file,const char * fname,bool_t stop_on_error)10 static int clish_shell_push(clish_shell_t * this, FILE * file,
11 const char *fname, bool_t stop_on_error)
12 {
13 /* Allocate a control node */
14 clish_shell_file_t *node = malloc(sizeof(clish_shell_file_t));
15
16 assert(this);
17 assert(node);
18
19 /* intialise the node */
20 node->file = file;
21 if (fname)
22 node->fname = lub_string_dup(fname);
23 else
24 node->fname = NULL;
25 node->line = 0;
26 node->stop_on_error = stop_on_error;
27 node->next = this->current_file;
28
29 /* put the node at the top of the file stack */
30 this->current_file = node;
31
32 /* now switch the terminal's input stream */
33 tinyrl__set_istream(this->tinyrl, file);
34
35 return 0;
36 }
37
38 /*----------------------------------------------------------- */
clish_shell_push_file(clish_shell_t * this,const char * fname,bool_t stop_on_error)39 int clish_shell_push_file(clish_shell_t * this, const char * fname,
40 bool_t stop_on_error)
41 {
42 FILE *file;
43 int res;
44
45 assert(this);
46 if (!fname)
47 return -1;
48 file = fopen(fname, "r");
49 if (!file)
50 return -1;
51 #ifdef FD_CLOEXEC
52 fcntl(fileno(file), F_SETFD, fcntl(fileno(file), F_GETFD) | FD_CLOEXEC);
53 #endif
54 res = clish_shell_push(this, file, fname, stop_on_error);
55 if (res)
56 fclose(file);
57
58 return res;
59 }
60
61 /*----------------------------------------------------------- */
clish_shell_push_fd(clish_shell_t * this,FILE * file,bool_t stop_on_error)62 int clish_shell_push_fd(clish_shell_t *this, FILE *file,
63 bool_t stop_on_error)
64 {
65 return clish_shell_push(this, file, NULL, stop_on_error);
66 }
67
68 /*----------------------------------------------------------- */
clish_shell_pop_file(clish_shell_t * this)69 int clish_shell_pop_file(clish_shell_t *this)
70 {
71 int result = -1;
72 clish_shell_file_t *node = this->current_file;
73
74 if (!node)
75 return -1;
76
77 /* remove the current file from the stack... */
78 this->current_file = node->next;
79 /* and close the current file... */
80 fclose(node->file);
81 if (node->next) {
82 /* now switch the terminal's input stream */
83 tinyrl__set_istream(this->tinyrl, node->next->file);
84 result = 0;
85 }
86 /* and free up the memory */
87 if (node->fname)
88 lub_string_free(node->fname);
89 free(node);
90
91 return result;
92 }
93
94 /*----------------------------------------------------------- */
95