C-Menu 0.2.9
A User Interface Toolkit
Loading...
Searching...
No Matches
Form Engine

Parses Form Descriptions, Handles User Input, and Integrates with External Commands for Calculations and Data Processing. More...

Functions

unsigned int display_form (Init *init)
 Display the form on the screen, including text elements and fields, and set up the form window based on the form configuration.
int field_navigator (Form *form)
 Handle user input for field entry, allowing navigation between fields and looping until an exit action is selected.
int form_desc_error (Form *form, int in_line_num, char *in_buf, char *em)
 Handle errors encountered while parsing the form description file, providing detailed error messages that include the file name, line number, and the specific error encountered.
void form_display_fields (Form *form)
 Display form fields on the screen, populating field values and formatting them according to the form configuration.
int form_engine (Init *init)
 Form main processing loop.
int form_exec_cmd (Form *form)
 Execute a command specified in the form description file, passing form field values as arguments, and optionally redirecting output to a file.
int form_exec_receiver (Init *init)
 Execute a command specified by the -R option on the form command line.
int form_parse_desc (Form *form)
 Parse the form description file to populate the Form data structure with field definitions, text elements, and other configuration specified in the description file.
int form_post (Init *init)
 Handle post-processing after field entry, allowing user to edit data, execute a provider command, or write data to an output file.
int form_process (Init *init)
 Handle integration with a getter program which will provide field data.
int form_read_data (Form *form)
 Read initial data for form fields from a specified input source, such as a file or standard input, and populate the form fields with the data.
int form_write (Form *form)
 Write form field values to a specified output destination, such as a file or standard output, based on the form configuration and user input.
int init_form (Init *init, int argc, char **argv, uint begy, uint begx)
 Initialize form data structure and parse description file.

Detailed Description

Parses Form Descriptions, Handles User Input, and Integrates with External Commands for Calculations and Data Processing.

Function Documentation

◆ display_form()

unsigned int display_form ( Init * init)

Display the form on the screen, including text elements and fields, and set up the form window based on the form configuration.

Parameters
initA pointer to the Init structure containing form data and state.
Returns
0 on success, or a non-zero value if an error occurs while creating the form window or rendering the form elements.

Definition at line 527 of file form_engine.c.

527 {
528 uint n, flin, fcol;
529 char tmp_str[MAXLEN];
530
531 Form *form = init->form;
532 form->lines = 0;
533 for (n = 0; n < form->dcnt; n++)
534 if (form->text[n]->line > form->lines)
535 form->lines = form->text[n]->line;
536 for (n = 0; n < form->fcnt; n++)
537 if (form->field[n]->line > form->lines)
538 form->lines = form->field[n]->line;
539 form->lines += 3;
540 if (form->lines > (LINES - form->begy))
541 form->lines = LINES - form->begy;
542 for (n = 0; n < form->fcnt; n++) {
543 if (form->field[n]->line >= (form->lines - 2))
544 form->fcnt = n;
545 }
546 form->cols += 2;
547 if (form->cols > (COLS - form->begx - 3))
548 form->cols = COLS - form->begx - 3;
549 if (ui_tracked_sfc_box(form->lines, form->cols, form->begy, form->begx, form->title)) {
550 strnz__cpy(tmp_str, _("ui_tracked_sfc_box failed: "), MAXLEN - 1);
551 strnz__cat(tmp_str, form->title, MAXLEN - 1);
552 ui_perror(tmp_str);
553 return (1);
554 }
556#ifdef DEBUG_IMMEDOK
557 ui_immedok(sfc, WIN, true);
558 ui_immedok(sfc, BOX, true);
559#endif
560 for (form->fidx = 0; form->fidx < form->fcnt; form->fidx++) {
561 if (form->brackets[0] != '\0' && form->brackets[1] != '\0') {
562 flin = form->field[form->fidx]->line + 1;
563 fcol = form->field[form->fidx]->col;
564 ui_mvwadd_wch(sfc, BOX, flin, fcol, &cell_brktl);
565 fcol += form->field[form->fidx]->len + 1;
566 ui_mvwadd_wch(sfc, BOX, flin, fcol, &cell_brktr);
567 }
568 }
569 for (n = 0; n < form->dcnt; n++) {
570 strnz(form->text[n]->str, form->cols - 3);
571 ui_mvwaddstr(sfc, WIN, form->text[n]->line, form->text[n]->col,
572 form->text[n]->str);
573 }
574 ui_render();
576 return 0;
577}
void ui_render()
Render the UI by updating panels and refreshing the display.
Definition ui_ncurses.c:884
uint COLS
Definition ui_backend.h:426
uint LINES
int sfc_ptr
Definition ui_ncurses.c:42
UiCell cell_brktl
Definition ui_common.c:104
int ui_tracked_sfc_box(uint wlines, uint wcols, uint wbegy, uint wbegx, const char *wtitle)
Create a new surface with a box window.
Definition ui_common.c:387
UiCell cell_brktr
Definition ui_common.c:105
UiSurface * ui_surface[UI_SFC_MAX]
Definition ui_ncurses.c:40
int ui_mvwaddstr(UiSurface *s, ss_t w, uint y, uint x, const char *text)
Draw a text string at a specific position in a surface window.
int ui_mvwadd_wch(UiSurface *s, ss_t w, uint y, uint x, const UiCell *cell)
Draw a complex character at a specific position in a surface window.
Form * form
Definition mem.c:37
#define MAXLEN
Definition curskeys.c:15
#define _(String)
Definition amort.c:23
void form_display_fields(Form *)
Display form fields on the screen, populating field values and formatting them according to the form ...
size_t strnz__cpy(char *, const char *, size_t)
safer alternative to strncpy
Definition whence.c:291
size_t strnz(char *, size_t)
terminates string at New Line, Carriage Return, or max_len
Definition futil.c:599
size_t strnz__cat(char *, const char *, size_t)
safer alternative to strncat
Definition whence.c:320
int ui_perror(char *emsg_str)
Display a simple error message window or print to stderr.
Definition ui_common.c:1257
Form * form
Definition common.h:189
Definition form.h:146

References Form::begx, Form::begy, Form::brackets, cell_brktl, cell_brktr, Field::col, Text::col, Form::cols, Form::dcnt, Form::fcnt, Form::fidx, Form::field, Init::form, form_display_fields(), Field::len, Field::line, Text::line, Form::lines, sfc_ptr, Text::str, strnz(), strnz__cat(), strnz__cpy(), Form::text, Form::title, ui_mvwadd_wch(), ui_mvwaddstr(), ui_perror(), ui_render(), ui_surface, and ui_tracked_sfc_box().

Referenced by form_engine().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ field_navigator()

int field_navigator ( Form * form)

Handle user input for field entry, allowing navigation between fields and looping until an exit action is selected.

Parameters
formA pointer to the Form structure containing form data and state.
Returns
An integer status code indicating the next action for the form processing loop (e.g., FA_ACCEPT, FA_HELP, FA_CALC, FA_CANCEL).

This function manages user input for field entry, including navigation between fields and handling of special keys for accepting, canceling, requesting help, or performing calculations. The function loops until the user selects an exit action (e.g., accept or cancel).

Definition at line 466 of file form_engine.c.

466 {
467
468 if (form->fidx >= form->fcnt)
469 form->fidx = 0;
470 while (1) {
472 switch (cmd_key) {
473 case UIKEY_F01: // F1 Help
474 return (FA_HELP);
475 case UIKEY_F02: // F2 Process
476 case UIKEY_F03: // F3 Calculate
477 case UIKEY_F04: // F4 Query
478 if (form->f_process)
479 return (FA_CALC);
480 break;
481 case UIKEY_F09: // F9 Cancel
482 return (FA_CANCEL);
483 case UIKEY_F10: // F10 Accept
484 return (FA_ACCEPT);
485 case 'k':
486 case UIKEY_UP:
487 if (form->fidx != 0)
488 form->fidx--;
489 break;
490 case '\r':
491 case UIKEY_ENTER:
492 if (form->fidx < form->fcnt - 1)
493 form->fidx++;
494 else if (form->fidx == form->fcnt - 1)
495 return (FA_ACCEPT);
496 break;
497 case 'j':
498 case UIKEY_DOWN:
499 if (form->fidx < form->fcnt - 1)
500 form->fidx++;
501 else if (form->fidx == form->fcnt - 1)
502 return (FA_ACCEPT);
503 break;
504 case UIKEY_BUTTON1:
505 break;
506 default:
507 break;
508 }
509 }
510}
@ FA_ACCEPT
Definition form.h:29
@ FA_CALC
Definition form.h:37
@ FA_HELP
Definition form.h:31
@ FA_CANCEL
Definition form.h:33
#define UIKEY_F02
#define UIKEY_F03
#define UIKEY_F09
#define UIKEY_F01
#define UIKEY_BUTTON1
#define UIKEY_UP
#define UIKEY_F10
#define UIKEY_ENTER
#define UIKEY_DOWN
#define UIKEY_F04
unsigned int cmd_key
Definition ui_common.c:32
int field_editor(Form *)
Accept input for a field.
Definition fields.c:47

References Form::f_process, FA_ACCEPT, FA_CALC, FA_CANCEL, FA_HELP, Form::fcnt, Form::fidx, and field_editor().

Referenced by form_engine().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ form_desc_error()

int form_desc_error ( Form * form,
int in_line_num,
char * in_buf,
char * em )

Handle errors encountered while parsing the form description file, providing detailed error messages that include the file name, line number, and the specific error encountered.

Parameters
formA pointer to the Form structure containing form data and state.
in_line_numThe line number in the description file where the error occurred.
in_bufThe content of the line that caused the error, for context.
emA specific error message describing the nature of the error.
Returns
An integer status code indicating how the user responded to the error message (e.g., which key they pressed to acknowledge the error).

Definition at line 1150 of file form_engine.c.

1150 {
1151 int cmd_key;
1152 ssnprintf(em0, MAXLEN - 1, "%s: %s", __FILE__, em);
1153 ssnprintf(em1, MAXLEN - 1, _("Desc file: %s, line: %d"), form->mapp_spec,
1154 in_line_num);
1155 strnz__cpy(em2, in_buf, MAXLEN - 1);
1156 cmd_key = ui_display_error(em0, em1, em2, nullptr);
1157 return cmd_key;
1158}
char em1[MAXLEN]
Definition ui_common.c:47
char em2[MAXLEN]
Definition ui_common.c:48
char em0[MAXLEN]
Definition ui_common.c:46
size_t ssnprintf(char *, size_t, const char *,...)
ssnprintf was designed to be a safer alternative to snprintf.
Definition futil.c:390
int ui_display_error(char *msg0, char *msg1, char *msg2, char *msg3)
Display an error message window or print to stderr.
Definition ui_common.c:1200

References em0, em1, em2, Form::mapp_spec, ssnprintf(), strnz__cpy(), and ui_display_error().

Referenced by form_parse_desc().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ form_display_fields()

void form_display_fields ( Form * form)

Display form fields on the screen, populating field values and formatting them according to the form configuration.

Parameters
formA pointer to the Form structure containing form data and state.

This function iterates through the defined form fields, formats their display values based on the specified fill character and field length, and renders them on the form window. It also updates the chyron with available commands for user interaction.

Definition at line 587 of file form_engine.c.

587 {
588 uint y, x;
589 uint pos = 0;
590 for (form->fidx = 0; form->fidx < form->fcnt; form->fidx++) {
591 if (form->field[form->fidx]->col + form->field[form->fidx]->len + 2 >
592 form->cols)
593 form->field[form->fidx]->len =
594 form->cols - (form->field[form->fidx]->col + 2);
595 // Make filler_cc
596 size_t fl = form->field[form->fidx]->len;
597 char *d = form->field[form->fidx]->filler_s;
598 size_t char_bytes = strlen(form->fill_char);
599 for (size_t i = 0; i < fl; i++) {
600 memcpy(d, form->fill_char, char_bytes);
601 d += char_bytes;
602 }
603 d = nullptr;
604
605 if (form->field[form->fidx]->accept_s[0] != '\0') {
606 strnz(form->field[form->fidx]->accept_s, form->field[form->fidx]->len);
607 // d = form->field[form->fidx]->accept_s;
608 } else {
609 memset(form->field[form->fidx]->accept_s, 0, MAXLEN);
610 // d = form->field[form->fidx]->accept_s;
611 }
612 strnz(form->field[form->fidx]->display_s, form->field[form->fidx]->len);
613
614 y = form->field[form->fidx]->line;
615 x = form->field[form->fidx]->col;
616
618 pos = 0;
619 ui_mbstr_to_cellstr(sfc, WIN,
620 form->field[form->fidx]->filler_cc,
621 form->field[form->fidx]->filler_s,
623 &pos,
624 form->field[form->fidx]->len + 1);
625
626 ui_mvwadd_wchstr(sfc, WIN, y, x, form->field[form->fidx]->filler_cc);
627 ui_render();
628
629 pos = 0;
630 ui_mbstr_to_cellstr(sfc, WIN, form->field[form->fidx]->display_cc, form->field[form->fidx]->display_s, &cell_nt, &pos, form->field[form->fidx]->len + 1);
631
632 ui_mvwadd_wchnstr(sfc, WIN, y, x, form->field[form->fidx]->display_cc, form->field[form->fidx]->len);
633 ui_render();
634 }
635 return;
636}
UiCell cell_nt
Definition ui_common.c:106
UiCell cell_fill_char
Definition ui_common.c:103
uint ui_mbstr_to_cellstr(UiSurface *sfc, ss_t w, UiCell *cmplx_buf, const char *str, const UiCell *cell_base, uint *p, const uint atmost)
Convert multibyte string to complex character array (Notcurses version).
int ui_mvwadd_wchnstr(UiSurface *s, ss_t w, uint y, uint x, const UiCell *cmplx_buf, uint n)
Draw a complex character string at a specific position in a surface window, with a maximum length.
int ui_mvwadd_wchstr(UiSurface *s, ss_t w, uint y, uint x, const UiCell *cmplx_buf)
Draw a complex character string at a specific position in a surface window.

References Field::accept_s, cell_fill_char, cell_nt, Field::col, Form::cols, Field::display_cc, Field::display_s, Form::fcnt, Form::fidx, Form::field, Form::fill_char, Field::filler_cc, Field::filler_s, Field::len, Field::line, sfc_ptr, strnz(), ui_mvwadd_wchnstr(), ui_mvwadd_wchstr(), ui_render(), and ui_surface.

Referenced by display_form(), and form_process().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ form_engine()

int form_engine ( Init * init)

Form main processing loop.

Parameters
initA pointer to the Init structure containing form data and state.
Returns
0 on successful completion, or a non-zero value if the user cancels the form or if an error occurs during processing.
  1. Parse the form description file to populate the form data structure.
  2. Read any initial data for the form fields from a specified input source.
  3. Display the form on the screen with the initial field values.
  4. Enter a loop to handle user input for field entry, calculation, help, and cancellation: a. If the user selects the accept action, perform any necessary calculations or post-processing, and then either return to field entry or exit the loop if the form is accepted. b. If the user selects the help action, display the help screen and return to the form after the user exits the help screen. c. If the user selects the cancel action, exit the loop and return a cancel status.

Definition at line 118 of file form_engine.c.

118 {
119 char tmp_str[MAXLEN];
120 int form_action;
121 char *eargv[MAXARGS];
122 int eargc;
123
124 Form *form = init->form;
125 if (form == nullptr) {
126 ui_perror(_("FORM: form data structure is nullptr"));
127 }
128 if (form_parse_desc(form)) {
129 return 0;
130 }
132 display_form(init);
133 form->chyron = ui_new_chyron(ui_surface[sfc_ptr], WIN);
134 ui_set_chyron_key(form->chyron, 1, _("F1 Help"), UIKEY_F01);
135 ui_set_chyron_key_cb(form->chyron, 2, _("F2 Process"), UIKEY_F02, cell_nt_hl_rev);
136 ui_set_chyron_key_cb(form->chyron, 3, _("F3 Calculate"), UIKEY_F03, cell_nt_hl_rev);
137 ui_set_chyron_key_cb(form->chyron, 4, _("F4 Query"), UIKEY_F04, cell_nt_hl_rev);
138 ui_set_chyron_key_cb(form->chyron, 5, _("F5 Edit"), UIKEY_F05, cell_nt_hl_rev);
139 ui_set_chyron_key(form->chyron, 9, _("F9 Cancel"), UIKEY_F09);
140 ui_set_chyron_key(form->chyron, 10, _("F10 Accept"), UIKEY_F10);
141 ui_set_chyron_key(form->chyron, 18, "INS", UIKEY_IC);
142 form->chyron->key[2]->active = false; // F2 Process
143 form->chyron->key[3]->active = false; // F3 Calculate
144 form->chyron->key[4]->active = false; // F4 Query
145 form->chyron->key[5]->active = false; // F5 Edit
146 form->chyron->key[18]->active = false; // Insert
147 ui_compile_chyron(form->chyron);
149 ui_display_chyron(sfc, 1, form->chyron, form->lines - 1, form->chyron->l);
150 // 1 F1 Help
151 // 2 F2 Process
152 // 3 F3 Calculate
153 // 4 F4 Query
154 // 5 F5 Edit
155 // 9 F9 Cancel
156 // 10 F10 Accept
157 form->fidx = 0;
158 form_action = 0;
159 while (1) {
160 if (form_action == 0 || form_action == FA_CONTINUE)
161 form_action = field_navigator(form);
162 form->chyron->key[18]->active = false; // Insert
163 switch (form_action) {
164 case FA_ACCEPT:
165 if (form->f_process || form->f_calculate || form->f_query)
166 form_action = form_process(init);
167 else
168 form_action = form_post(init);
169 if (form_action == FA_HELP || form_action == FA_CANCEL ||
170 form_action == FA_CONTINUE || form_action == FA_END)
171 continue;
172 if (form_action == FA_ACCEPT) {
173 form_action = FA_END;
174 continue;
175 }
176 break;
177 case FA_END:
178 if (form->f_out_spec || form->out_spec[0] != '\0')
180 if (form->f_receiver_cmd || form->receiver_cmd[0] != '\0')
181 form_exec_receiver(init);
182 break;
183 case FA_HELP:
184 if (form->f_help_spec && form->help_spec[0] != '\0')
185 strnz__cpy(tmp_str, form->help_spec, MAXLEN - 1);
186 else {
187 strnz__cpy(tmp_str, init->mapp_help, MAXLEN - 1);
188 strnz__cat(tmp_str, "/", MAXLEN - 1);
189 strnz__cat(tmp_str, FORM_HELP_FILE, MAXLEN - 1);
190 }
191 eargc = 0;
192 eargv[eargc++] = strdup("view");
193 eargv[eargc++] = strdup("-Nf");
194 eargv[eargc++] = strdup(tmp_str);
195 eargv[eargc] = nullptr;
196 init->lines = 30;
197 init->cols = 66;
198 init->begy = form->begy + 1;
199 init->begx = form->begx + 1;
200 strnz__cpy(init->title, _("Form Help"), MAXLEN - 1);
201 popup_view(init, eargc, eargv, init->lines, init->cols, init->begy,
202 init->begx);
204 form_action = FA_CONTINUE;
205 break;
206 case FA_CANCEL:
207 return FA_CANCEL;
208 default:
209 form_action = FA_CONTINUE;
210 break;
211 }
212 if (form_action == FA_END)
213 break;
214 }
215 return 0;
216}
@ FA_END
Definition form.h:42
@ FA_CONTINUE
Definition form.h:27
#define FORM_HELP_FILE
Definition common.h:36
int popup_view(Init *, int, char **, uint, uint, uint, uint)
instantiate a view popup window
Definition popups.c:145
#define MAXARGS
Definition cm.h:64
UiCell cell_nt_hl_rev
Definition ui_common.c:109
#define UIKEY_IC
#define UIKEY_F05
void ui_set_chyron_key(UiChyron *chyron, uint k, char *s, uint kc)
Set chyron key with default color pair (cp_nt_rev).
Definition ui_common.c:717
UiChyron * ui_new_chyron(UiSurface *sfc, ss_t w)
Create new chyron structure.
Definition ui_common.c:601
void ui_display_chyron(UiSurface *sfc, ss_t w, UiChyron *chyron, uint line, uint col)
Display chyron on the specified line and column of the surface.
Definition ui_common.c:837
void ui_set_chyron_key_cb(UiChyron *chyron, uint k, char *s, uint kc, UiCell cell_base)
Set chyron key with color pair (cp).
Definition ui_common.c:693
void ui_compile_chyron(UiChyron *chyron)
construct the chyron string from the chyron structure
Definition ui_common.c:782
char * eargv[MAXARGS]
Definition futil.c:51
int eargc
Definition futil.c:50
int form_exec_receiver(Init *)
Execute a command specified by the -R option on the form command line.
int form_read_data(Form *)
Read initial data for form fields from a specified input source, such as a file or standard input,...
int form_parse_desc(Form *)
Parse the form description file to populate the Form data structure with field definitions,...
int form_write(Form *)
Write form field values to a specified output destination, such as a file or standard output,...
int form_process(Init *)
Handle integration with a getter program which will provide field data.
int form_post(Init *)
Handle post-processing after field entry, allowing user to edit data, execute a provider command,...
int field_navigator(Form *)
Handle user input for field entry, allowing navigation between fields and looping until an exit actio...
unsigned int display_form(Init *)
Display the form on the screen, including text elements and fields, and set up the form window based ...
int destroy_argv(uint argc, char **argv)
Deallocates memory allocated for argument strings in argv.
Definition futil.c:468
char title[MAXLEN]
Definition common.h:132
char mapp_help[MAXLEN]
Definition common.h:152
int begx
Definition common.h:121
int cols
Definition common.h:119
int begy
Definition common.h:120
int lines
Definition common.h:118

References Form::begx, Init::begx, Form::begy, Init::begy, cell_nt_hl_rev, Form::chyron, Init::cols, destroy_argv(), display_form(), Form::f_calculate, Form::f_help_spec, Form::f_out_spec, Form::f_process, Form::f_query, Form::f_receiver_cmd, FA_ACCEPT, FA_CANCEL, FA_CONTINUE, FA_END, FA_HELP, Form::fidx, field_navigator(), Init::form, form_exec_receiver(), form_parse_desc(), form_post(), form_process(), form_read_data(), form_write(), Form::help_spec, Form::lines, Init::lines, Init::mapp_help, Form::out_spec, popup_view(), Form::receiver_cmd, sfc_ptr, strnz__cat(), strnz__cpy(), Init::title, ui_compile_chyron(), ui_display_chyron(), ui_new_chyron(), ui_perror(), ui_set_chyron_key(), ui_set_chyron_key_cb(), and ui_surface.

Referenced by init_form().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ form_exec_cmd()

int form_exec_cmd ( Form * form)

Execute a command specified in the form description file, passing form field values as arguments, and optionally redirecting output to a file.

Parameters
formA pointer to the Form structure containing form data and state.
Returns
0 on success, or a non-zero value if an error occurs while constructing or executing the command.

Definition at line 909 of file form_engine.c.

909 {
910 char earg_str[MAXLEN + 1];
911 uint i;
912 strnz__cpy(earg_str, form->receiver_cmd, MAXLEN - 1);
913 for (i = 0; i < form->fcnt; i++) {
914 strnz__cat(earg_str, " ", MAXLEN - 1);
915 strnz__cat(earg_str, form->field[i]->accept_s, MAXLEN - 1);
916 }
917 if (form->f_out_spec && form->f_process) {
918 strnz__cat(earg_str, " >", MAXLEN - 1);
919 strnz__cat(earg_str, form->out_spec, MAXLEN - 1);
920 }
922 return 0;
923}
char earg_str[MAXLEN]
Definition futil.c:49
int shell(char *)
Execute a shell command.
Definition exec.c:74

References Field::accept_s, Form::f_out_spec, Form::f_process, Form::fcnt, Form::field, Form::out_spec, Form::receiver_cmd, shell(), strnz__cat(), and strnz__cpy().

Here is the call graph for this function:

◆ form_exec_receiver()

int form_exec_receiver ( Init * init)

Execute a command specified by the -R option on the form command line.

Parameters
initA pointer to the Init structure
Returns
0 on success, or a non-zero value if an error occurs while constructing or executing the command.

This function constructs a command by taking the receiver_cmd appending field values as arguments, and handling special cases such as multiple command arguments or placeholder substitution. It then executes the command, either displaying the output in a popup view if the command is "view", or executing it directly in a child process for other commands. The function also handles error cases and ensures that resources are properly freed.

This is the line that gets the selected objects

initialize popup_view arguments and execute popup_view to display command output within form interface

fork failed, free eargv and return error

Prevent child process from writing to terminal

Child process to execute command

If execvp returns, it means execution failed, so free eargv and print error message before exiting

Definition at line 936 of file form_engine.c.

936 {
937 int rc = -1;
938 uint eargc;
939 char *eargv[MAXARGS];
940 char tmp_str[MAXLEN] = {'\0'};
941 char title[MAXLEN];
942 char sav_arg[MAXLEN];
943 char *out_s;
944 uint eargx = 0;
945 uint i = 0;
946 pid_t pid = 0;
947 bool f_append_values = false;
948
949 title[0] = '\0';
950 Form *form = init->form;
951 if (form->receiver_cmd[0] == '\0')
952 return -1;
953 // Eliminate leading and trailing quotes
954 if (form->receiver_cmd[0] == '\\' || form->receiver_cmd[0] == '\"') {
955 size_t len = strlen(form->receiver_cmd);
956 if (len > 1 && form->receiver_cmd[len - 1] == '\"') {
957 memmove(form->receiver_cmd, form->receiver_cmd + 1, len - 2);
958 form->receiver_cmd[len - 2] = '\0';
959 }
960 }
961 eargc = str_to_args(eargv, form->receiver_cmd, MAXARGS - 1);
962 tmp_str[0] = '\0';
963 if (form->f_multiple_cmd_args) {
964 // concatenate fields into a single argument
965 for (i = 0; i < form->fcnt; i++) {
966 if (form->field[i]->accept_s[0] && eargc < MAXARGS) {
967 if (tmp_str[0] != '\0')
968 strnz__cat(tmp_str, " ", MAXLEN - 1);
969 strnz__cat(tmp_str, form->field[i]->accept_s, MAXLEN - 1);
970 }
971 }
972 eargv[eargc++] = strdup(tmp_str);
973 } else {
974 f_append_values = false;
975 // find lines with "%%" to determine where to insert field values
976 i = 0;
977 while (i < eargc) {
979 if (strstr(eargv[i], "%%") != nullptr) {
980 tmp_str[0] = '\0';
981 f_append_values = true;
982 strnz__cpy(sav_arg, eargv[i], MAXLEN - 1);
983 eargx = i;
984 break;
985 }
986 i++;
987 }
988 for (i = 0; i < form->fcnt; i++) {
989 // concatenate field values onto tmp_str
990 if (form->field[i]->accept_s[0] && eargc < MAXARGS - 1) {
991 if (f_append_values == true) {
992 if (tmp_str[0] != '\0')
993 strnz__cat(tmp_str, " ", MAXLEN - 1);
994 strnz__cat(tmp_str, form->field[i]->accept_s, MAXLEN - 1);
995 continue;
996 }
997 eargv[eargc++] = strdup(form->field[i]->accept_s);
998 }
999 }
1000 // replace "%%" with concatenated field values
1001 if (f_append_values == true) {
1002 if (eargv[eargx] != nullptr) {
1003 free(eargv[eargx]);
1004 eargv[eargx] = nullptr;
1005 }
1006 out_s = rep_substring(sav_arg, "%%", tmp_str);
1007 if (out_s == nullptr || out_s[0] == '\0') {
1008 i = 0;
1009 while (i < eargc) {
1010 if (eargv[i] != nullptr)
1011 free(eargv[i]);
1012 i++;
1013 }
1014 ui_perror(_("rep_substring() failed in form_exec_objects"));
1015 return 1;
1016 }
1017 strnz__cpy(title, out_s, MAXLEN - 1);
1018 eargv[eargx] = strdup(out_s);
1019 if (out_s != nullptr) {
1020 free(out_s);
1021 out_s = nullptr;
1022 }
1023 }
1024 }
1025 if (eargc > 0)
1026 eargv[eargc] = nullptr;
1027 base_name(tmp_str, eargv[0]);
1028 if (tmp_str[0] != '\0' && (strcmp(tmp_str, "view") == 0)) {
1031 init->lines = 60;
1032 init->cols = 80;
1033 init->begy = form->begy + 1;
1034 init->begx = form->begx + 1;
1035 if (title[0] != '\0')
1036 strnz__cpy(init->title, title, MAXLEN - 1);
1037 else
1038 strnz__cpy(init->title, eargv[eargc], MAXLEN - 1);
1039 popup_view(init, eargc, eargv, init->lines, init->cols, init->begy,
1040 init->begx);
1041 i = 0;
1042 while (i < eargc) {
1043 if (eargv[i] != nullptr)
1044 free(eargv[i]);
1045 i++;
1046 }
1047 return 0;
1048 } else {
1049 ui_endwin();
1050 if ((pid = fork()) == -1) {
1052 i = 0;
1053 while (i < eargc) {
1054 if (eargv[i] != nullptr)
1055 free(eargv[i]);
1056 i++;
1057 }
1058 ui_perror(_("fork() failed in form_exec_objects"));
1059 return (1);
1060 }
1061 if (pid == 0) {
1063 int dev_null = open("/dev/null", O_WRONLY);
1064 if (dev_null == -1) {
1065 ui_perror(_("open(/dev/null) failed in init_form child process"));
1066 exit(EXIT_FAILURE);
1067 }
1068 dup2(dev_null, STDERR_FILENO);
1069 close(dev_null);
1071 execvp(eargv[0], eargv);
1074 strnz__cpy(tmp_str, _("Can't exec form cmd: "), MAXLEN - 1);
1075 strnz__cat(tmp_str, eargv[0], MAXLEN - 1);
1076 ui_perror(tmp_str);
1077 exit(EXIT_FAILURE);
1078 }
1079 }
1080 waitpid(pid, nullptr, 0);
1082 sig_prog_mode();
1084 return rc;
1085}
char * rep_substring(const char *, const char *, const char *) __attribute__((nonnull(1
Replace all occurrences of "tgt_s" in "org_s" with "rep_s".
Definition futil.c:1449
void ui_restore_wins()
Restore the state of all windows in the UI. This function refreshes the standard screen and all surfa...
void ui_endwin()
End the UI application, cleaning up resources and shutting down the UI runtime.
Definition ui_ncurses.c:412
int str_to_args(char **, char *, uint)
Converts a string into an array of argument strings.
Definition futil.c:412
bool base_name(char *, char *)
Returns the base name of a file specification.
Definition futil.c:1132
void sig_prog_mode()
Set up signal handlers for interrupt signals.
Definition sig.c:61

References Field::accept_s, base_name(), Form::begx, Init::begx, Form::begy, Init::begy, Init::cols, destroy_argv(), Form::f_multiple_cmd_args, Form::fcnt, Form::field, Init::form, Init::lines, popup_view(), Form::receiver_cmd, rep_substring(), sig_prog_mode(), str_to_args(), strnz__cat(), strnz__cpy(), Init::title, ui_endwin(), ui_perror(), and ui_restore_wins().

Referenced by form_engine().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ form_parse_desc()

int form_parse_desc ( Form * form)

Parse the form description file to populate the Form data structure with field definitions, text elements, and other configuration specified in the description file.

Parameters
formA pointer to the Form structure containing form data and state.
Returns
0 on success, or a non-zero value if an error occurs while parsing the description file (e.g., file not found, invalid format, missing directives).

Definition at line 646 of file form_engine.c.

646 {
647 FILE *form_desc_fp;
648 char *token;
649 char *s;
650 uint cols = 0;
651 uint i, l;
652 int in_line_num = 0;
653 char in_buf[BUFSIZ];
654 char tmp_buf[BUFSIZ];
655 char *tmp_buf_p;
656 char tmp_str[BUFSIZ];
657 char delim[5];
658 char directive;
659
660 form_desc_fp = fopen(form->mapp_spec, "r");
661 if (form_desc_fp == nullptr) {
662 ssnprintf(em0, MAXLEN - 1, "%s, line: %d", __FILE__, __LINE__ - 2);
663 strnz__cpy(em1, "fopen ", MAXLEN - 1);
664 strnz__cat(em1, form->mapp_spec, MAXLEN - 1);
665 strerror__r(errno, em2, MAXLEN);
666 ui_display_error(em0, em1, em2, nullptr);
667 return (1);
668 }
669 for (i = 0; i < FIELD_MAXCNT; i++) {
670 form->field[i] = calloc(1, sizeof(Field));
671 if (!form->field[i]) {
672 sprintf(tmp_str, _("FORM: calloc failed for fields"));
673 ui_abend(EXIT_FAILURE, tmp_str);
674 }
675 }
676 for (i = 0; i < FIELD_MAXCNT; i++) {
677 form->text[i] = calloc(1, sizeof(Text));
678 if (!form->text[i]) {
679 sprintf(tmp_str, _("FORM: calloc failed for text"));
680 ui_abend(EXIT_FAILURE, tmp_str);
681 }
682 }
683 form->didx = 0;
684 form->fidx = 0;
685 form->fcnt = 0;
686 form->cols = 34;
687 while ((fgets(in_buf, MAXLEN, form_desc_fp)) != nullptr) {
688 s = in_buf;
689 in_line_num++;
690 l = trim(in_buf);
691 if (l == 0)
692 continue;
693 if (*s == D_COMMENT)
694 continue;
695 delim[0] = '\n';
696 delim[1] = in_buf[1];
697 delim[2] = '\0';
698 strnz__cpy(tmp_buf, in_buf, MAXLEN - 1);
699 tmp_buf_p = tmp_buf;
700 if (!(token = strtok(tmp_buf_p, delim))) {
701 continue;
702 }
703 directive = *token;
704 switch ((int)directive) {
705 case D_COMMENT:
706 break;
707 case D_CALC:
708 form->f_calculate = true;
709 break;
710 case D_QUERY:
711 form->f_query = true;
712 break;
713 case D_GETTER:
714 form->f_process = true;
715 break;
716 case D_CMD:
717 if (!(token = strtok(nullptr, delim))) {
718 form_desc_error(form, in_line_num, in_buf,
719 _("FORM: receiver_cmd delimiter"));
720 continue;
721 }
722 strnz__cpy(form->receiver_cmd, token, MAXLEN - 1);
723 break;
724 case D_HELP:
725 if (!(token = strtok(nullptr, delim))) {
726 form_desc_error(form, in_line_num, in_buf,
727 _("FORM: help_spec delimiter"));
728 }
729 strnz__cpy(form->help_spec, token, MAXLEN - 1);
730 break;
731 case D_FIELD:
732 if (form->field[form->fidx] == nullptr) {
733 sprintf(tmp_str, _("FORM: calloc failed for fields"));
734 ui_abend(EXIT_FAILURE, tmp_str);
735 }
736 if (!(token = strtok(nullptr, delim))) {
737 form_desc_error(form, in_line_num, in_buf,
738 _("FORM: line number delimiter"));
739 return 1;
740 }
741 form->field[form->fidx]->line = atoi(token);
742 if (form->field[form->fidx]->line >= FIELD_MAXCNT) {
743 form_desc_error(form, in_line_num, in_buf,
744 _("FORM: invalid line number"));
745 return 1;
746 }
747 if (!(token = strtok(nullptr, delim))) {
748 form_desc_error(form, in_line_num, in_buf,
749 _("FORM: column number delimiter"));
750 return 1;
751 }
752 form->field[form->fidx]->col = atoi(token);
753 if (form->field[form->fidx]->col >= FIELD_MAXLEN) {
754 form_desc_error(form, in_line_num, in_buf,
755 _("FORM: invalid column number"));
756 break;
757 }
758 if (!(token = strtok(nullptr, delim))) {
759 strnz__cpy(tmp_str, in_buf, MAXLEN - 1);
760 form_desc_error(form, in_line_num, tmp_str, _("FORM: length delimiter"));
761 break;
762 }
763 form->field[form->fidx]->len = atoi(token);
764 if (form->field[form->fidx]->len > FIELD_MAXLEN) {
765 form_desc_error(form, in_line_num, in_buf, _("FORM: invalid length"));
766 break;
767 }
768 if (!(token = strtok(nullptr, delim))) {
769 form_desc_error(form, in_line_num, in_buf,
770 _("FORM: validation code delimiter"));
771 break;
772 }
773 form->field[form->fidx]->ff = 0;
774 for (i = 0; i < FF_INVALID; i++) {
775 str_to_lower(token);
777 if (!strcmp(token, ff_tbl[i])) {
778 form->field[form->fidx]->ff = i;
779 break;
780 }
781 }
782 if (form->field[form->fidx]->ff >= FF_INVALID) {
783 form_desc_error(form, in_line_num, in_buf,
784 _("FORM: invalid format code"));
785 break;
786 }
787 cols =
788 form->field[form->fidx]->col + form->field[form->fidx]->len + 1;
789 if (cols > form->cols)
790 form->cols = cols;
791 form->fidx++;
792 form->fcnt = form->fidx;
793 break;
794 case D_TEXT:
795 if (form->text[form->didx] == nullptr) {
796 sprintf(tmp_str, _("FORM: calloc failed for text"));
797 ui_abend(EXIT_FAILURE, tmp_str);
798 }
799 if (!(token = strtok(nullptr, delim))) {
800 form_desc_error(form, in_line_num, in_buf,
801 _("FORM: line number delimiter"));
802 break;
803 }
804 form->text[form->didx]->line = atoi(token);
805 if (form->text[form->didx]->line >= FIELD_MAXCNT) {
806 form_desc_error(form, in_line_num, in_buf,
807 _("FORM: invalid line number"));
808 break;
809 }
810 if (!(token = strtok(nullptr, delim))) {
811 form_desc_error(form, in_line_num, in_buf,
812 _("FORM: column number delimiter"));
813 break;
814 }
815 form->text[form->didx]->col = atoi(token);
816 if (form->text[form->didx]->col >= FIELD_MAXLEN) {
817 form_desc_error(form, in_line_num, in_buf,
818 _("FORM: invalid column number"));
819 break;
820 }
821 if (!(token = strtok(nullptr, delim))) {
822 form_desc_error(form, in_line_num, in_buf, _("FORM: text delimiter"));
823 break;
824 }
825 strnz__cpy(form->text[form->didx]->str, token, MAXLEN - 1);
826 form->text[form->didx]->len = strlen(form->text[form->didx]->str);
827 if (form->text[form->didx]->len > FIELD_MAXLEN) {
828 form_desc_error(form, in_line_num, in_buf, _("FORM: invalid length"));
829 break;
830 }
831 cols =
832 form->text[form->didx]->col + form->text[form->didx]->len + 1;
833 if (cols > form->cols)
834 form->cols = cols;
835 form->didx++;
836 form->dcnt = form->didx;
837 break;
838 case D_HEADER:
839 if ((token = strtok(nullptr, delim))) {
840 strnz__cpy(form->title, token, MAXLEN - 1);
841 }
842 break;
843 default:
844 form_desc_error(form, in_line_num, in_buf, _("invalid directive"));
845 break;
846 }
847 }
848 fclose(form_desc_fp);
849 if (form->didx < 1 && form->fidx < 1) {
850 ssnprintf(em0, MAXLEN - 1, _("%s, line: %d"), __FILE__, __LINE__);
851 ssnprintf(em1, MAXLEN - 1, "%s", _("Error in description file:"));
852 ssnprintf(em2, MAXLEN - 1, "%s", form->mapp_spec);
853 ui_display_error(em0, em1, em2, nullptr);
854 return (1);
855 }
856 return (0);
857}
#define FIELD_MAXLEN
Definition form.h:18
@ FF_INVALID
Definition form.h:68
#define FIELD_MAXCNT
Definition form.h:19
#define BUFSIZ
Definition view.h:38
void ui_abend(int ec, char *s)
Convert multibyte string to complex character array.
Definition ui_common.c:362
char ff_tbl[][26]
Definition fields.c:25
int form_desc_error(Form *form, int, char *, char *)
Handle errors encountered while parsing the form description file, providing detailed error messages ...
size_t trim(char *)
Trims leading and trailing spaces from string s in place.
Definition futil.c:361
bool str_to_lower(char *)
Converts a string to lowercase.
Definition futil.c:482
char * strerror__r(int errnum, char *buf, size_t buflen)
A thread-safe alternative to strerror() that writes the error message corresponding to errnum into th...
Definition futil.c:748
structure for form fields
Definition form.h:99
structure for form fields
Definition form.h:112

References Field::col, Text::col, Form::cols, Form::dcnt, Form::didx, em0, em1, em2, Form::f_calculate, Form::f_process, Form::f_query, Form::fcnt, Field::ff, FF_INVALID, ff_tbl, Form::fidx, Form::field, form_desc_error(), Form::help_spec, Field::len, Text::len, Field::line, Text::line, Form::mapp_spec, Form::receiver_cmd, ssnprintf(), Text::str, str_to_lower(), strerror__r(), strnz__cat(), strnz__cpy(), Form::text, Form::title, trim(), ui_abend(), and ui_display_error().

Referenced by form_engine().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ form_post()

int form_post ( Init * init)

Handle post-processing after field entry, allowing user to edit data, execute a provider command, or write data to an output file.

Parameters
initA pointer to the Init structure containing form data and state.
Returns
An integer status code indicating the next action for the form processing loop (e.g., FA_CONTINUE, FA_CANCEL, FA_ACCEPT, FA_HELP).

Definition at line 223 of file form_engine.c.

223 {
224 bool loop = true;
225 int c, rc;
226 click_y = click_x = -1;
227 Form *form = init->form;
229 UiEvent event;
230 uint maxy, maxx;
231 ui_cursor_move(sfc, WIN, form->lines - 1, 0);
232 ui_wclrtoeol(sfc, WIN);
233 // 1 F1 Help
234 // 2 F2 Process
235 // 3 F3 Calculate
236 // 4 F4 Query
237 // 5 F5 Edit
238 // 9 F9 Cancel
239 // 10 F10 Continue
240 // 11 F10 Commit
241 // 18 INS Insert
242 form->chyron->key[5]->active = true; // F5 Edit
243 form->chyron->key[10]->active = false; // F10 Continue
244 form->chyron->key[18]->active = false; // INS Insert
245 ui_compile_chyron(form->chyron);
246 rc = -1;
247 while (loop) {
248 if (rc == -1) {
249 ui_display_chyron(sfc, WIN, form->chyron, form->lines - 1, form->chyron->l);
250 c = ui_get_event(sfc, WIN, form->chyron, &event, -1);
251 ui_getmaxyx(sfc, WIN, &maxy, &maxx);
252 if (event.in_win == 1 && event.y == maxy - 1)
253 c = ui_get_chyron_key(form->chyron, event.x);
254 }
255 switch (c) {
256 case UIKEY_F01:
257 return FA_HELP;
258 case UIKEY_F05: // F5 Edit
259 if (ui_is_set_chyron_key(form->chyron, 5)) {
260 loop = false;
261 rc = FA_CONTINUE;
262 break;
263 }
264 continue;
265 case UIKEY_F09:
266 loop = false;
267 rc = FA_CANCEL;
268 break;
269 case UIKEY_F10:
270 loop = false;
271 rc = FA_ACCEPT;
272 break;
273 case UIKEY_BUTTON1:
274 continue;
275 default:
276 break;
277 }
278 }
279 form->chyron->key[5]->active = false; // F5 Edit
280 return rc;
281}
void ui_getmaxyx(UiSurface *s, ss_t w, uint *lines, uint *cols)
Get the maximum dimensions of a UiSurface.
Definition ui_ncurses.c:690
int ui_cursor_move(UiSurface *s, ss_t w, uint y, uint x)
Move the cursor to a specified position within a UiSurface.
Definition ui_ncurses.c:666
int click_x
Definition ui_common.c:30
int click_y
Definition ui_common.c:29
int ui_wclrtoeol(UiSurface *s, ss_t w)
Clear to the end of the line in a surface window.
int ui_get_event(UiSurface *s, ss_t w, UiChyron *chyron, UiEvent *ev, int timeout_ms)
Read input events.
bool ui_is_set_chyron_key(UiChyron *chyron, uint k)
Check if function key label is set.
Definition ui_common.c:677
int ui_get_chyron_key(UiChyron *chyron, uint x)
Get keycode from chyron.
Definition ui_common.c:861
ss_t in_win
Definition ui_backend.h:112

References Form::chyron, click_x, click_y, FA_ACCEPT, FA_CANCEL, FA_CONTINUE, FA_HELP, Init::form, UiEvent::in_win, Form::lines, sfc_ptr, ui_compile_chyron(), ui_cursor_move(), ui_display_chyron(), ui_get_chyron_key(), ui_get_event(), ui_getmaxyx(), ui_is_set_chyron_key(), ui_surface, ui_wclrtoeol(), UiEvent::x, and UiEvent::y.

Referenced by form_engine().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ form_process()

int form_process ( Init * init)

Handle integration with a getter program which will provide field data.

Parameters
initA pointer to the Init structure containing form data and state.
Returns
An integer status code indicating the next action for the form processing loop (e.g., FA_CONTINUE, FA_CANCEL, FA_ACCEPT, FA_HELP).

This function provides integration with getter programs. The requirements are:

  1. The form description file must have a line containing only 'C' (calculate), 'Q' (query), org 'G' (getter) to indicate that the form supports a getter.
  2. The form description file must specify the provider command using a line starting with '!' followed by the command and its arguments.
  3. The getter program must be able to accept field data from a file, from standard input, or as command line parameters.
  4. The getter program must output field values in a format that can be read by the form (e.g., one value per line), either to a file or to standard output.
     The sequence of operations is as follows:
    
     1. The 'C', 'Q', or 'G' option causes Form to pause and display an
    
    UIKEY_F05 Calculate, Query, or Getter. option on the chyron.
  1. The user can then cancel the operation by pressing UIKEY_F09 or activate the getter option by pressing UIKEY_F05.
  2. Form outputs its data to file, standard output, or as command line parameters.
  3. Form executes the getter program.
  4. The getter program processes the data and outputs the results.
  5. Form reads the results and populates the appropriate form fields.
  6. Form presents the user with an option to edit the data, and the sequence restarts at 1.

This function forks and executes the getter executable as a child process, creates a pipe to read the output from the provider command, reads the output, and updates the Form fields.

Prevent child process from writing to terminal

Definition at line 320 of file form_engine.c.

320 {
321 uint i, c;
322 int rc;
323 char earg_str[MAXLEN + 1];
324 char *eargv[MAXARGS];
325 int eargc;
326 char file_spec[MAXLEN];
327 bool loop = true;
328 pid_t pid;
329 int pipe_fd[2];
331 UiEvent event;
332 Form *form = init->form;
333 ui_cursor_move(sfc, WIN, form->lines - 1, 0);
334 uint maxy, maxx;
335 //
336 // 1 F1 Help
337 // 2 F2 Process
338 // 3 F3 Calculate
339 // 4 F4 Query
340 // 5 F5 Edit
341 // 9 F9 Cancel
342 // 10 F10 Continue
343 // 11 F10 Commit
344 form->chyron->key[2]->active = form->f_process > 0 ? true : false;
345 form->chyron->key[3]->active = form->f_calculate > 0 ? true : false;
346 form->chyron->key[4]->active = form->f_query > 0 ? true : false; // PgUp
347 form->chyron->key[10]->active = false; // F10 Continue
348 form->chyron->key[18]->active = false; // INS Insert
349
350 while (loop) {
351 ui_compile_chyron(form->chyron);
352 ui_display_chyron(sfc, 1, form->chyron, form->lines - 1, form->chyron->l);
353 click_y = click_x = -1;
354 c = ui_get_event(sfc, WIN, form->chyron, &event, -1);
355 ui_getmaxyx(sfc, WIN, &maxy, &maxx);
356 if (event.in_win == 1 && event.y == maxy - 1)
357 c = ui_get_chyron_key(form->chyron, event.x);
358
359 switch (c) {
360 case UIKEY_F01:
361 return FA_HELP;
362 case UIKEY_F02: // F2 Process
363 case UIKEY_F03: // F3 Calculate
364 case UIKEY_F04: // F4 Query
365 if (form->f_out_spec)
367 if (form->f_provider_cmd) {
368 strnz__cpy(earg_str, form->provider_cmd, MAXLEN - 1);
369 for (i = 0; i < form->fcnt; i++) {
370 strnz__cat(earg_str, " ", MAXLEN - 1);
371 strnz__cat(earg_str, form->field[i]->accept_s, MAXLEN - 1);
372 }
374 strnz__cpy(file_spec, eargv[0], MAXLEN - 1);
375 base_name(eargv[0], file_spec);
376 if (pipe(pipe_fd) == -1) {
378 ui_perror(_("pipe(pipe_fd) failed in init_form"));
379 return (1);
380 }
381 if ((pid = fork()) == -1) {
383 ui_perror(_("fork() failed in init_form"));
384 return (1);
385 }
386 if (pid == 0) { // Child
388 int dev_null = open("/dev/null", O_WRONLY);
389 if (dev_null == -1) {
390 ui_perror(_("open(/dev/null) failed in init_pick child process"));
391 exit(EXIT_FAILURE);
392 }
393 dup2(dev_null, STDERR_FILENO);
394 close(dev_null);
395 close(pipe_fd[P_READ]);
396 dup2(pipe_fd[P_WRITE], STDOUT_FILENO);
397 stdio_fdnames(stdio_names_str, "form_engine.c:367");
398 close(pipe_fd[P_WRITE]);
399 execvp(eargv[0], eargv);
400 ssnprintf(em0, MAXLEN, _("%s, line: %d"), __FILE__,
401 __LINE__ - 2);
402 strnz__cpy(em1, "execvp(", MAXLEN - 1);
403 strnz__cat(em1, eargv[0], MAXLEN - 1);
404 strnz__cat(em1, ", ", MAXLEN - 1);
406 strnz__cat(em1, ")", MAXLEN - 1);
407 strerror__r(errno, em2, MAXLEN);
408 ui_display_error(em0, em1, em2, nullptr);
409 exit(EXIT_FAILURE);
410 } // Back to parent
411 close(pipe_fd[P_WRITE]);
412 form->in_fp = fdopen(pipe_fd[P_READ], "rb");
413 form->f_in_pipe = true;
415 close(pipe_fd[P_READ]);
416 waitpid(pid, nullptr, 0);
417 stdio_fdnames(stdio_names_str, "form_engine.c:387");
420 form->chyron->key[2]->active = false; // F2 Process
421 form->chyron->key[3]->active = false; // F3 Calculate
422 form->chyron->key[4]->active = false; // F4 Query
423 form->chyron->key[5]->active = true; // F5 Edit
424 form->chyron->key[10]->active = true; // F10 Accept
425 ui_compile_chyron(form->chyron);
426 continue;
427 }
428 break;
429 case UIKEY_F05:
430 if (ui_is_set_chyron_key(form->chyron, 5)) {
431 loop = false;
432 rc = FA_CONTINUE;
433 break;
434 }
435 continue;
436 case UIKEY_F09:
437 loop = false;
438 rc = FA_CANCEL;
439 break;
440 case UIKEY_F10:
441 loop = false;
442 rc = FA_ACCEPT;
443 break;
444 case UIKEY_BUTTON1:
445 break;
446 default:
447 break;
448 }
449 }
450 form->chyron->key[2]->active = false; // F2 Process
451 form->chyron->key[3]->active = false; // F3 Calculate
452 form->chyron->key[4]->active = false; // F4 Query
453 form->chyron->key[5]->active = false; // F5 Edit
454 return rc;
455}
#define P_READ
Definition common.h:53
#define P_WRITE
Definition common.h:54
char stdio_names_str[4096]
Definition futil.c:122
char * stdio_fdnames(char *, char *)
Definition futil.c:1108
int pipe_fd[2]
Definition pick_engine.c:46

References Field::accept_s, base_name(), Form::chyron, click_x, click_y, destroy_argv(), em0, em1, em2, Form::f_calculate, Form::f_in_pipe, Form::f_out_spec, Form::f_process, Form::f_provider_cmd, Form::f_query, FA_ACCEPT, FA_CANCEL, FA_CONTINUE, FA_HELP, Form::fcnt, Form::field, Init::form, form_display_fields(), form_read_data(), form_write(), Form::in_fp, UiEvent::in_win, Form::lines, Form::provider_cmd, sfc_ptr, ssnprintf(), stdio_fdnames(), stdio_names_str, str_to_args(), strerror__r(), strnz__cat(), strnz__cpy(), ui_compile_chyron(), ui_cursor_move(), ui_display_chyron(), ui_display_error(), ui_get_chyron_key(), ui_get_event(), ui_getmaxyx(), ui_is_set_chyron_key(), ui_perror(), ui_surface, UiEvent::x, and UiEvent::y.

Referenced by form_engine().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ form_read_data()

int form_read_data ( Form * form)

Read initial data for form fields from a specified input source, such as a file or standard input, and populate the form fields with the data.

Parameters
formA pointer to the Form structure containing form data and state.
Returns
0 on success, or a non-zero value if an error occurs while reading the data or if the specified input source is invalid or empty.

Definition at line 866 of file form_engine.c.

866 {
867 struct stat sb;
868 char in_buf[MAXLEN];
869 char field[MAXLEN];
870 int cmd_key;
871
872 if (!form->f_in_pipe) {
873 if (form->f_in_spec && form->in_spec[0] != '\0') {
874 if ((lstat(form->in_spec, &sb) == -1) || (sb.st_size == 0) ||
875 ((form->in_fp = fopen(form->in_spec, "rb")) == nullptr)) {
876 strnz__cat(em0, form->in_spec, MAXLEN - 1);
877 if (sb.st_size == 0)
878 strnz__cpy(em1, _("File is empty"), MAXLEN - 1);
879 else
880 strnz__cpy(em1, _("File does not exist"), MAXLEN - 1);
881 strnz__cpy(em2, _("Fields will be blank or zero"), MAXLEN - 1);
882 cmd_key = ui_display_error(em0, em1, em2, nullptr);
883 if (cmd_key == UIKEY_F09)
884 return (1);
885 }
886 if (form->in_fp == nullptr)
887 return (1);
888 } else
889 return (0);
890 }
891 form->fidx = 0;
892 if (form->in_fp != nullptr) {
893 while ((fgets(in_buf, MAXLEN, form->in_fp)) != nullptr) {
894 if (form->fidx < FIELD_MAXCNT)
895 strnz__cpy(field, in_buf, MAXLEN - 1);
896 form_fmt_field(form, field);
897 form->fidx++;
898 }
899 fclose(form->in_fp);
900 }
901 return (0);
902}
int form_fmt_field(Form *form, char *s)
Format field according to its format type.
Definition fields.c:449

References em0, em1, em2, Form::f_in_pipe, Form::f_in_spec, Form::fidx, form_fmt_field(), Form::in_fp, Form::in_spec, strnz__cat(), strnz__cpy(), and ui_display_error().

Referenced by form_engine(), and form_process().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ form_write()

int form_write ( Form * form)

Write form field values to a specified output destination, such as a file or standard output, based on the form configuration and user input.

Parameters
formA pointer to the Form structure containing form data and state.
Returns
0 on success, or a non-zero value if an error occurs while writing the data or if the specified output destination is invalid.

Definition at line 1094 of file form_engine.c.

1094 {
1095 uint n;
1096 if (form->out_spec[0] == '\0' || strcmp(form->out_spec, "-") == 0 ||
1097 strcmp(form->out_spec, "/dev/stdout") == 0) {
1098 strnz__cpy(form->out_spec, "/dev/stdout", MAXLEN - 1);
1099 close(form->out_fd);
1100 // form->out_fd = open(form->out_spec, O_CREAT | O_RDWR | O_TRUNC,
1101 // 0644);
1102 form->out_fd = dup(STDOUT_FILENO);
1103 if (form->out_fd == -1) {
1104 ssnprintf(em0, MAXLEN - 1, _("%s, line: %d"), __FILE__, __LINE__ - 1);
1105 strnz__cpy(em1, "open ", MAXLEN - 1);
1106 strnz__cat(em1, form->out_spec, MAXLEN - 1);
1107 strerror__r(errno, em2, MAXLEN);
1108 ui_display_error(em0, em1, em2, nullptr);
1109 return (1);
1110 }
1111 // dup2(form->out_fd, STDOUT_FILENO);
1112 form->out_fp = fdopen(form->out_fd, "w");
1113 form->f_out_spec = true;
1114 form->f_out_pipe = true;
1115 } else {
1116 if ((form->out_fp = fopen(form->out_spec, "w")) == nullptr) {
1117 ssnprintf(em0, MAXLEN - 1, _("%s, line: %d"), __FILE__, __LINE__ - 1);
1118 strerror__r(errno, em2, MAXLEN);
1119 ui_display_error(em0, em1, em2, nullptr);
1120 return (1);
1121 }
1122 }
1123 if (form->out_fp == nullptr) {
1124 ssnprintf(em0, MAXLEN - 1, _("%s, line: %d"), __FILE__, __LINE__ - 1);
1125 strnz__cpy(em1, "fopen ", MAXLEN - 1);
1126 strnz__cat(em1, form->out_spec, MAXLEN - 1);
1127 strerror__r(errno, em2, MAXLEN);
1128 ui_display_error(em0, em1, em2, nullptr);
1129 return (1);
1130 }
1131 for (n = 0; n < form->fcnt; n++)
1132 fprintf(form->out_fp, "%s\n", form->field[n]->accept_s);
1133 if (form->out_fp != nullptr)
1134 fclose(form->out_fp);
1135 return (0);
1136}

References Field::accept_s, em0, em1, em2, Form::f_out_pipe, Form::f_out_spec, Form::fcnt, Form::field, Form::out_fd, Form::out_fp, Form::out_spec, ssnprintf(), strerror__r(), strnz__cat(), strnz__cpy(), and ui_display_error().

Referenced by form_engine(), and form_process().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ init_form()

int init_form ( Init * init,
int argc,
char ** argv,
uint begy,
uint begx )

Initialize form data structure and parse description file.

Parameters
initA pointer to the Init structure containing form data and state.
argcThe number of command line arguments passed to the form.
argvThe array of command line arguments passed to the form.
begyThe y-coordinate for the top-left corner of the form window.
begxThe x-coordinate for the top-left corner of the form window.
Returns
0 on success, or a non-zero value if an error occurs during

Definition at line 61 of file form_engine.c.

61 {
62 int rc;
63 char tmp_str[MAXLEN];
64 if (init->form != nullptr)
65 destroy_form(init);
66 init->form = new_form(init, argc, argv, begy, begx);
67 Form *form = init->form;
68 if (!form->f_mapp_spec) {
69 if (form->mapp_spec[0] == '\0') {
70 rc = ui_perror(_("Error: No form specification file given"));
71 } else {
72 strnz__cpy(tmp_str, "form->mapp_spec: ", MAXLEN - 1);
73 strnz__cat(tmp_str, form->mapp_spec, MAXLEN - 1);
74 strnz__cat(tmp_str, _(" not found"), MAXLEN - 1);
75 rc = ui_perror(tmp_str);
76 }
77 destroy_form(init);
78 return rc;
79 }
80 if (begy != 0)
81 form->begy = begy;
82 if (begx != 0)
83 form->begx = begx;
84 if ((form->f_in_spec && (form->in_spec[0] == '\0')) ||
85 (strcmp(form->in_spec, "-") == 0) ||
86 strcmp(form->in_spec, "/dev/stdin") == 0) {
87 strnz__cpy(form->in_spec, "/dev/stdin", MAXLEN - 1);
88 form->f_in_pipe = true;
89 }
90 if (form->title[0] == '\0')
91 strnz__cpy(form->title, form->in_spec, MAXLEN - 1);
92 rc = form_engine(init);
94 ui_destroy_chyron(form->chyron);
95 if (sfc)
97 destroy_form(init);
98 return rc;
99}
int ui_cm_surface_destroy(UiSurface *sfc)
Destroy the most recently created surface.
Definition ui_common.c:466
UiChyron * ui_destroy_chyron(UiChyron *chyron)
Destroy UiChyron structure.
Definition ui_common.c:656
int form_engine(Init *)
Form main processing loop.
Form * destroy_form(Init *init)
Destroy Form structure.
Definition mem.c:267
Form * new_form(Init *init, int argc, char **argv, uint begy, uint begx)
Create and initialize Form structure.
Definition mem.c:244

References Form::begx, Form::begy, Form::chyron, destroy_form(), Form::f_in_pipe, Form::f_in_spec, Form::f_mapp_spec, Init::form, form_engine(), Form::in_spec, Form::mapp_spec, new_form(), sfc_ptr, strnz__cat(), strnz__cpy(), Form::title, ui_cm_surface_destroy(), ui_destroy_chyron(), ui_perror(), and ui_surface.

Referenced by main(), and popup_form().

Here is the call graph for this function:
Here is the caller graph for this function: