1 #include <nm_core.h>
2 #include <nm_form.h>
3 #include <nm_utils.h>
4 #include <nm_string.h>
5 #include <nm_window.h>
6 #include <nm_menu.h>
7 #include <nm_database.h>
8 #include <nm_cfg_file.h>
9 #include <nm_vm_control.h>
10 #include <nm_9p_share.h>
11 
12 typedef struct {
13     nm_str_t mode;
14     nm_str_t path;
15     nm_str_t name;
16 } nm_9p_data_t;
17 
18 #define NM_INIT_9P_DATA (nm_9p_data_t) { NM_INIT_STR, NM_INIT_STR, NM_INIT_STR }
19 
20 static const char NM_9P_SET_MODE_SQL[] =
21     "UPDATE vms SET fs9p_enable='%s' WHERE name='%s'";
22 static const char NM_9P_SET_PATH_SQL[] =
23     "UPDATE vms SET fs9p_path='%s' WHERE name='%s'";
24 static const char NM_9P_SET_NAME_SQL[] =
25     "UPDATE vms SET fs9p_name='%s' WHERE name='%s'";
26 
27 static const char NM_LC_9P_FORM_MODE[] = "Enable sharing";
28 static const char NM_LC_9P_FORM_PATH[] = "Path to directory";
29 static const char NM_LC_9P_FORM_NAME[] = "Name of the share";
30 
31 static void nm_9p_init_windows(nm_form_t *form);
32 static void nm_9p_fields_setup(const nm_vmctl_data_t *cur);
33 static size_t nm_9p_labels_setup();
34 static int nm_9p_get_data(nm_9p_data_t *data, const nm_vmctl_data_t *cur);
35 static void nm_9p_update_db(const nm_str_t *name, const nm_9p_data_t *data);
36 
37 enum {
38     NM_LBL_9PMODE = 0, NM_FLD_9PMODE,
39     NM_LBL_9PPATH, NM_FLD_9PPATH,
40     NM_LBL_9PNAME, NM_FLD_9PNAME,
41     NM_FLD_COUNT
42 };
43 
44 static nm_field_t *fields[NM_FLD_COUNT + 1];
45 
nm_9p_init_windows(nm_form_t * form)46 static void nm_9p_init_windows(nm_form_t *form)
47 {
48     if (form) {
49         nm_form_window_init();
50         nm_form_data_t *form_data = (nm_form_data_t *)form_userptr(form);
51         if (form_data)
52             form_data->parent_window = action_window;
53     } else {
54         werase(action_window);
55         werase(help_window);
56     }
57 
58     nm_init_side();
59     nm_init_action(_(NM_MSG_9P_SHARE));
60     nm_init_help_edit();
61 
62     nm_print_vm_menu(NULL);
63 }
64 
nm_9p_share(const nm_str_t * name)65 void nm_9p_share(const nm_str_t *name)
66 {
67     nm_form_data_t *form_data = NULL;
68     nm_form_t *form = NULL;
69     nm_vmctl_data_t vm = NM_VMCTL_INIT_DATA;
70     nm_9p_data_t data = NM_INIT_9P_DATA;
71     size_t msg_len;
72 
73     nm_9p_init_windows(NULL);
74 
75     nm_vmctl_get_data(name, &vm);
76 
77     msg_len = nm_9p_labels_setup();
78 
79     form_data = nm_form_data_new(
80         action_window, nm_9p_init_windows, msg_len, NM_FLD_COUNT / 2, NM_TRUE);
81 
82     if (nm_form_data_update(form_data, 0, 0) != NM_OK)
83         goto out;
84 
85     for (size_t n = 0; n < NM_FLD_COUNT; n++) {
86         switch (n) {
87             case NM_FLD_9PMODE:
88                 fields[n] = nm_field_enum_new(
89                     n / 2, form_data, nm_form_yes_no, false, false);
90                 break;
91             case NM_FLD_9PPATH:
92                 fields[n] = nm_field_regexp_new(n / 2, form_data, "^/.*");
93                 break;
94             case NM_FLD_9PNAME:
95                 fields[n] = nm_field_regexp_new(n / 2, form_data, ".*");
96                 break;
97             default:
98                 fields[n] = nm_field_label_new(n / 2, form_data);
99                 break;
100         }
101     }
102     fields[NM_FLD_COUNT] = NULL;
103 
104     nm_9p_labels_setup();
105     nm_9p_fields_setup(&vm);
106     nm_fields_unset_status(fields);
107 
108     form = nm_form_new(form_data, fields);
109     nm_form_post(form);
110 
111     if (nm_form_draw(&form) != NM_OK)
112         goto out;
113 
114     if (nm_9p_get_data(&data, &vm) != NM_OK)
115         goto out;
116 
117     nm_9p_update_db(name, &data);
118 
119 out:
120     NM_FORM_EXIT();
121     nm_str_free(&data.mode);
122     nm_str_free(&data.name);
123     nm_str_free(&data.path);
124     nm_form_free(form);
125     nm_form_data_free(form_data);
126     nm_fields_free(fields);
127     nm_vmctl_free_data(&vm);
128 }
129 
nm_9p_fields_setup(const nm_vmctl_data_t * cur)130 static void nm_9p_fields_setup(const nm_vmctl_data_t *cur)
131 {
132     field_opts_off(fields[NM_FLD_9PPATH], O_STATIC);
133     field_opts_off(fields[NM_FLD_9PNAME], O_STATIC);
134 
135     set_field_buffer(fields[NM_FLD_9PMODE], 0,
136         (nm_str_cmp_st(nm_vect_str(&cur->main, NM_SQL_9FLG),
137             NM_ENABLE) == NM_OK) ? "yes" : "no");
138     set_field_buffer(fields[NM_FLD_9PPATH], 0, nm_vect_str_ctx(&cur->main, NM_SQL_9PTH));
139     set_field_buffer(fields[NM_FLD_9PNAME], 0, nm_vect_str_ctx(&cur->main, NM_SQL_9ID));
140 }
141 
nm_9p_labels_setup()142 static size_t nm_9p_labels_setup()
143 {
144     nm_str_t buf = NM_INIT_STR;
145     size_t max_label_len = 0;
146     size_t msg_len = 0;
147 
148     for (size_t n = 0; n < NM_FLD_COUNT; n++) {
149         switch (n) {
150         case NM_LBL_9PMODE:
151             nm_str_format(&buf, "%s", _(NM_LC_9P_FORM_MODE));
152             break;
153         case NM_LBL_9PPATH:
154             nm_str_format(&buf, "%s", _(NM_LC_9P_FORM_PATH));
155             break;
156         case NM_LBL_9PNAME:
157             nm_str_format(&buf, "%s", _(NM_LC_9P_FORM_NAME));
158             break;
159         default:
160             continue;
161         }
162 
163         msg_len = mbstowcs(NULL, buf.data, buf.len);
164         if (msg_len > max_label_len)
165             max_label_len = msg_len;
166 
167         if (fields[n])
168             set_field_buffer(fields[n], 0, buf.data);
169     }
170 
171     nm_str_free(&buf);
172     return max_label_len;
173 }
174 
nm_9p_get_data(nm_9p_data_t * data,const nm_vmctl_data_t * cur)175 static int nm_9p_get_data(nm_9p_data_t *data, const nm_vmctl_data_t *cur)
176 {
177     int rc = NM_OK;
178     nm_vect_t err = NM_INIT_VECT;
179 
180     nm_get_field_buf(fields[NM_FLD_9PMODE], &data->mode);
181     nm_get_field_buf(fields[NM_FLD_9PPATH], &data->path);
182     nm_get_field_buf(fields[NM_FLD_9PNAME], &data->name);
183 
184     if (field_status(fields[NM_FLD_9PMODE])) {
185         if (nm_str_cmp_st(&data->mode, "no") == NM_OK)
186             goto out;
187     }
188     else if (nm_str_cmp_st(nm_vect_str(&cur->main, NM_SQL_9FLG), NM_ENABLE) != NM_OK)
189             goto out;
190 
191     nm_form_check_data(_(NM_LC_9P_FORM_PATH), data->path, err);
192     nm_form_check_data(_(NM_LC_9P_FORM_NAME), data->name, err);
193 
194     if ((rc = nm_print_empty_fields(&err)) == NM_ERR)
195         nm_vect_free(&err, NULL);
196 
197 out:
198     return rc;
199 }
200 
nm_9p_update_db(const nm_str_t * name,const nm_9p_data_t * data)201 static void nm_9p_update_db(const nm_str_t *name, const nm_9p_data_t *data)
202 {
203     nm_str_t query = NM_INIT_STR;
204     nm_str_free(&query);
205 
206     if (field_status(fields[NM_FLD_9PMODE])) {
207         nm_str_format(&query, NM_9P_SET_MODE_SQL,
208             (nm_str_cmp_st(&data->mode, "yes") == NM_OK) ? "1" : "0", name->data);
209         nm_db_edit(query.data);
210         nm_str_trunc(&query, 0);
211     }
212 
213     if (field_status(fields[NM_FLD_9PPATH])) {
214         nm_str_format(&query, NM_9P_SET_PATH_SQL, data->path.data, name->data);
215         nm_db_edit(query.data);
216         nm_str_trunc(&query, 0);
217     }
218 
219     if (field_status(fields[NM_FLD_9PNAME])) {
220         nm_str_format(&query, NM_9P_SET_NAME_SQL, data->name.data, name->data);
221         nm_db_edit(query.data);
222     }
223 
224     nm_str_free(&query);
225 }
226 
227 /* vim:set ts=4 sw=4: */
228