Subversion Repositories Code-Repo

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
141 Kevin 1
/*
2
 * esh-utils.c
3
 * A set of utility routines to manage esh objects.
4
 *
5
 * Developed by Godmar Back for CS 3214 Fall 2009
6
 * Virginia Tech.
7
 */
8
#include <stdio.h>
9
#include <sys/types.h>
10
#include <dirent.h>
11
#include <dlfcn.h>
12
#include <limits.h>
13
 
14
#include "esh.h"
15
 
16
static const char rcsid [] = "$Id: esh-utils.c,v 1.5 2011/03/29 15:46:28 cs3214 Exp $";
17
 
18
/* List of loaded plugins */
19
struct list esh_plugin_list;
20
 
21
/* Create new command structure and initialize first command word,
22
 * and/or input or output redirect file. */
23
struct esh_command * 
24
esh_command_create(char ** argv, 
25
                   char *iored_input, 
26
                   char *iored_output, 
27
                   bool append_to_output)
28
{
29
    struct esh_command *cmd = malloc(sizeof *cmd);
30
 
31
    cmd->iored_input = iored_input;
32
    cmd->iored_output = iored_output;
33
    cmd->argv = argv;
34
    cmd->append_to_output = append_to_output;
35
 
36
    return cmd;
37
}
38
 
39
/* Create a new pipeline containing only one command */
40
struct esh_pipeline *
41
esh_pipeline_create(struct esh_command *cmd)
42
{
43
    struct esh_pipeline *pipe = malloc(sizeof *pipe);
44
 
45
    pipe->bg_job = false;
46
    cmd->pipeline = pipe;
47
    list_init(&pipe->commands);
48
    list_push_back(&pipe->commands, &cmd->elem);
49
    return pipe;
50
}
51
 
52
/* Complete a pipe's setup by copying I/O redirection information */
53
void
54
esh_pipeline_finish(struct esh_pipeline *pipe)
55
{
56
    if (list_size(&pipe->commands) == 0)
57
        return;
58
 
59
    struct esh_command *first;
60
    first = list_entry(list_front(&pipe->commands), struct esh_command, elem);
61
    pipe->iored_input = first->iored_input;
62
 
63
    struct esh_command *last;
64
    last = list_entry(list_back(&pipe->commands), struct esh_command, elem);
65
    pipe->iored_output = last->iored_output;
66
    pipe->append_to_output = last->append_to_output;
67
}
68
 
69
/* Create an empty command line */
70
struct esh_command_line *
71
esh_command_line_create_empty(void)
72
{
73
    struct esh_command_line *cmdline = malloc(sizeof *cmdline);
74
 
75
    list_init(&cmdline->pipes);
76
    return cmdline;
77
}
78
 
79
/* Create a command line with a single pipeline */
80
struct esh_command_line *
81
esh_command_line_create(struct esh_pipeline *pipe)
82
{
83
    struct esh_command_line *cmdline = esh_command_line_create_empty();
84
 
85
    list_push_back(&cmdline->pipes, &pipe->elem);
86
    return cmdline;
87
}
88
 
89
/* Print esh_command structure to stdout */
90
void
91
esh_command_print(struct esh_command *cmd)
92
{
93
    char **p = cmd->argv;
94
 
95
    printf("  Command:");
96
    while (*p)
97
        printf(" %s", *p++);
98
 
99
    printf("\n");
100
 
101
    if (cmd->iored_output)
102
        printf("  stdout %ss to %s\n", 
103
                cmd->append_to_output ? "append" : "write",
104
                cmd->iored_output);
105
 
106
    if (cmd->iored_input)
107
        printf("  stdin reads from %s\n", cmd->iored_input);
108
}
109
 
110
/* Print esh_pipeline structure to stdout */
111
void
112
esh_pipeline_print(struct esh_pipeline *pipe)
113
{
114
    int i = 1;
115
    struct list_elem * e = list_begin (&pipe->commands); 
116
 
117
    printf(" Pipeline\n");
118
    for (; e != list_end (&pipe->commands); e = list_next (e)) {
119
        struct esh_command *cmd = list_entry(e, struct esh_command, elem);
120
 
121
        printf(" %d. ", i++);
122
        esh_command_print(cmd);
123
    }
124
 
125
    if (pipe->bg_job)
126
        printf("  - is a background job\n");
127
}
128
 
129
/* Print esh_command_line structure to stdout */
130
void 
131
esh_command_line_print(struct esh_command_line *cmdline)
132
{
133
    struct list_elem * e = list_begin (&cmdline->pipes); 
134
 
135
    printf("Command line\n");
136
    for (; e != list_end (&cmdline->pipes); e = list_next (e)) {
137
        struct esh_pipeline *pipe = list_entry(e, struct esh_pipeline, elem);
138
 
139
        printf(" ------------- \n");
140
        esh_pipeline_print(pipe);
141
    }
142
    printf("==========================================\n");
143
}
144
 
145
/* Deallocation functions. */
146
void 
147
esh_command_line_free(struct esh_command_line *cmdline)
148
{
149
    struct list_elem * e = list_begin (&cmdline->pipes); 
150
 
151
    for (; e != list_end (&cmdline->pipes); ) {
152
        struct esh_pipeline *pipe = list_entry(e, struct esh_pipeline, elem);
153
        e = list_remove(e);
154
        esh_pipeline_free(pipe);
155
    }
156
    free(cmdline);
157
}
158
 
159
void 
160
esh_pipeline_free(struct esh_pipeline *pipe)
161
{
162
    struct list_elem * e = list_begin (&pipe->commands); 
163
 
164
    for (; e != list_end (&pipe->commands); ) {
165
        struct esh_command *cmd = list_entry(e, struct esh_command, elem);
166
        e = list_remove(e);
167
        esh_command_free(cmd);
168
    }
169
    free(pipe);
170
}
171
 
172
void 
173
esh_command_free(struct esh_command * cmd)
174
{
175
    char ** p = cmd->argv;
176
    while (*p) {
177
        free(*p++);
178
    }
179
    if (cmd->iored_input)
180
        free(cmd->iored_input);
181
    if (cmd->iored_output)
182
        free(cmd->iored_output);
183
    free(cmd->argv);
184
    free(cmd);
185
}
186
 
187
#define PSH_MODULE_NAME "esh_module"
188
 
189
/* Load a plugin referred to by modname */
190
static struct esh_plugin *
191
load_plugin(char *modname)
192
{
193
    printf("Loading %s ...", modname);
194
    fflush(stdout);
195
 
196
    void *handle = dlopen(modname, RTLD_LAZY);
197
    if (handle == NULL) {
198
        fprintf(stderr, "Could not open %s: %s\n", modname, dlerror());
199
        return NULL;
200
    }
201
 
202
    struct esh_plugin * p = dlsym(handle, PSH_MODULE_NAME);
203
    if (p == NULL) {
204
        fprintf(stderr, "%s does not define %s\n", modname, PSH_MODULE_NAME);
205
        dlclose(handle);
206
        return NULL;
207
    }
208
 
209
    printf("done.\n");
210
    return p;
211
}
212
 
213
static bool sort_by_rank (const struct list_elem *a,
214
                          const struct list_elem *b,
215
                          void *aux __attribute__((unused)))
216
{
217
    struct esh_plugin * pa =  list_entry(a, struct esh_plugin, elem);
218
    struct esh_plugin * pb =  list_entry(b, struct esh_plugin, elem);
219
    return pa->rank < pb->rank;
220
}
221
 
222
/* Load plugins from directory dirname */
223
void 
224
esh_plugin_load_from_directory(char *dirname)
225
{
226
    DIR * dir = opendir(dirname);
227
    if (dir == NULL) {
228
        perror("opendir");
229
        return;
230
    }
231
 
232
    struct dirent * dentry;
233
    while ((dentry = readdir(dir)) != NULL) {
234
        if (!strstr(dentry->d_name, ".so"))
235
            continue;
236
 
237
        char modname[PATH_MAX + 1];
238
        snprintf(modname, sizeof modname, "%s/%s", dirname, dentry->d_name);
239
 
240
        struct esh_plugin * plugin = load_plugin(modname);
241
        if (plugin)
242
            list_push_back(&esh_plugin_list, &plugin->elem);
243
    }
244
    closedir(dir);
245
}
246
 
247
/* Initialize loaded plugins */
248
void 
249
esh_plugin_initialize(struct esh_shell *shell)
250
{
251
    /* Sort plugins and call init() method. */
252
    list_sort(&esh_plugin_list, sort_by_rank, NULL);
253
 
254
    struct list_elem * e = list_begin(&esh_plugin_list);
255
    for (; e != list_end(&esh_plugin_list); e = list_next(e)) {
256
        struct esh_plugin *plugin = list_entry(e, struct esh_plugin, elem);
257
        if (plugin->init)
258
            plugin->init(shell);
259
    }
260
}
261
 
262
/* TBD: implement unloading. */