/* $NetBSD: scanform.c,v 1.43 2005/01/12 17:38:40 peter Exp $ */ /* * Copyright (c) 2000 The NetBSD Foundation, Inc. * All rights reserved. * * Copyright (c) 2000 Tim Rightnour * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the NetBSD * Foundation, Inc. and its contributors. * 4. Neither the name of The NetBSD Foundation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "sushi.h" #include "functions.h" #include "scanform.h" #include "formtree.h" #include "handlers.h" #include "run.h" #include "blabel.h" extern func_record func_map[]; extern CDKSCREEN *cdkscreen; extern struct winsize ws; extern nl_catd catalog; extern char *lang_id; extern char *keylabel[10]; extern chtype keybinding[10]; static void scan_formindex(struct cqForm *, char *); static void form_status(FORM *form) { char buf[20]; wstandout(stdscr); mvwaddstr(stdscr, ws.ws_row - 3, 0, catgets(catalog, 4, 9, "PGUP/PGDN to change page, UP/DOWN switch field, ENTER submit.")); wstandend(stdscr); snprintf(buf, sizeof(buf), "%s (%d/%d)", catgets(catalog, 4, 8, "Form Page:"), form_page(form) + 1, form->max_page); /* XXX */ mvwaddstr(stdscr, ws.ws_row - 3, 62, buf); wrefresh(stdscr); } static int scan_form(struct cqForm *cqf, char *path) { FILE *filep; int lcnt; char *p, *t; size_t len; if ((filep = fopen(path, "r")) != NULL) { for (lcnt = 1; (p = fgetln(filep, &len)) != NULL; ++lcnt) { if (len == 1) /* Skip empty lines. */ continue; if (p[len - 1] == '#') /* Skip remarked lines. */ continue; if (p[len - 1] != '\n') {/* Skip corrupted lines. */ warnx("%s: line %d corrupted", path, lcnt); continue; } p[len - 1] = '\0'; /* Terminate the line. */ /* Skip leading spaces. */ for (; *p != '\0' && isspace((unsigned char)*p); ++p) continue; /* Skip empty/comment lines. */ if (*p == '\0' || *p == '#') continue; /* Find first token. */ for (t = p; *t && !isspace((unsigned char)*t); ++t) continue; if (*t == '\0') /* Need more than one token.*/ continue; *t = '\0'; scan_formindex(cqf, p); } fclose(filep); } else return (1); return (0); } static void form_appenditem(struct cqForm *cqf, char *desc, int type, char *data, int req) { FTREE_ENTRY *fte; if ((fte = malloc(sizeof(FTREE_ENTRY))) == NULL || ((fte->desc = strdup(desc)) == NULL) || ((fte->type = type) == 0) || ((fte->data = strdup(data)) == NULL)) bailout("malloc: %s", strerror(errno)); fte->required = req; fte->elen = 0; fte->origdata = fte->data; fte->list = NULL; CIRCLEQ_INIT(&fte->cqSubFormHead); CIRCLEQ_INSERT_TAIL(cqf, fte, cqFormEntries); } static void scan_formindex(struct cqForm *cqf, char *row) { char *t = row; char *x; char desc[80]; int type; int req = 0; while (*++t && !isspace((unsigned char)*t)) continue; x = (char *)strsep(&row, ":"); if (strcmp(x, "entry") == 0) { type = DATAT_ENTRY; } else if (strcmp(x, "req-entry") == 0) { type = DATAT_ENTRY; req = 1; } else if (strcmp(x, "escript") == 0) { type = DATAT_ESCRIPT; } else if (strcmp(x, "req-escript") == 0) { type = DATAT_ESCRIPT; req = 1; } else if (strcmp(x, "nescript") == 0) { type = DATAT_NESCRIPT; } else if (strcmp(x, "list") == 0) { type = DATAT_LIST; } else if (strcmp(x, "multilist") == 0) { type = DATAT_MLIST; } else if (strcmp(x, "req-list") == 0) { type = DATAT_LIST; req = 1; } else if (strcmp(x, "blank") == 0) { type = DATAT_BLANK; } else if (strcmp(x, "func") == 0) { type = DATAT_FUNC; } else if (strcmp(x, "multifunc") == 0) { type = DATAT_MFUNC; } else if (strcmp(x, "req-func") == 0) { type = DATAT_FUNC; req = 1; } else if (strcmp(x, "script") == 0) { type = DATAT_SCRIPT; } else if (strcmp(x, "multiscript") == 0) { type = DATAT_MSCRIPT; } else if (strcmp(x, "req-script") == 0) { type = DATAT_SCRIPT; req = 1; } else if (strcmp(x, "noedit") == 0) { type = DATAT_NOEDIT; } else if (strcmp(x, "invis") == 0) { type = DATAT_INVIS; } else if (strcmp(x, "integer") == 0) { type = DATAT_INTEGER; } else if (strcmp(x, "req-integer") == 0) { type = DATAT_INTEGER; req = 1; } else if (strcmp(x, "iscript") == 0) { type = DATAT_ISCRIPT; } else if (strcmp(x, "req-iscript") == 0) { type = DATAT_ISCRIPT; req = 1; } else if (strcmp(x, "ipv4") == 0) { type = DATAT_V4; } else if (strcmp(x, "req-ipv4") == 0) { type = DATAT_V4; req = 1; } else if (strcmp(x, "ipv4script") == 0) { type = DATAT_V4SCRIPT; } else if (strcmp(x, "req-ipv4script") == 0) { type = DATAT_V4SCRIPT; req = 1; } else if (strcmp(x, "ipv6") == 0) { type = DATAT_V6; } else if (strcmp(x, "req-ipv6") == 0) { type = DATAT_V6; req = 1; } else if (strcmp(x, "ipv6script") == 0) { type = DATAT_V6SCRIPT; } else if (strcmp(x, "req-ipv6script") == 0) { type = DATAT_V6SCRIPT; req = 1; } else { bailout("%s: %s", catgets(catalog, 1, 11, "invalid data type"), x); } while (*++t && isspace((unsigned char)*t)) continue; if (strlen(t) > 50) bailout("'%s': %s", t, catgets(catalog, 1, 12, "description too long")); snprintf(desc, sizeof(desc), "%s", t); if (strcmp(desc, "BLANK") == 0) snprintf(desc, sizeof(desc), " "); form_appenditem(cqf, desc, type, row, req); } int form_entries(struct cqForm *cqf) { FTREE_ENTRY *fte; int entries = 0; for (fte = CIRCLEQ_FIRST(cqf); fte != (void *)cqf; fte = CIRCLEQ_NEXT(fte, cqFormEntries)) ++entries; return (entries); } FTREE_ENTRY * form_getentry(struct cqForm *cqf, int entry) { FTREE_ENTRY *fte; int entries = 0; for (fte = CIRCLEQ_FIRST(cqf); (fte != (void *)cqf); fte = CIRCLEQ_NEXT(fte, cqFormEntries)) { if (entry == entries) return (fte); ++entries; } return (NULL); } void form_printtree(struct cqForm *cqf) { FTREE_ENTRY *ftp; for (ftp = CIRCLEQ_FIRST(cqf); ftp != (void *)cqf; ftp = CIRCLEQ_NEXT(ftp, cqFormEntries)) printf("%s\t- %d:%s\n", ftp->desc, ftp->type, ftp->data); } /* This is the keymap for the forms */ static int get_request(WINDOW *w) /* virtual key mapping */ { static int mode = REQ_INS_MODE; int i, c = wgetch(w); /* read a character */ /* printf("GOT A THINGIE: 0x%x %d\n", c, c); */ /* convert to an FKEY for case */ if (c != 0) for (i = 0; i < 10; i++) if (c == keybinding[i]) c = KEY_F(i+1); switch (c) { case KEY_F(1): return (SHOWHELP); case KEY_F(2): return (REFRESH); case KEY_F(3): return (BAIL); case KEY_F(4): return (GENLIST); case KEY_F(5): return (RESET); case KEY_F(6): return (COMMAND); case KEY_F(7): return (EDIT); case KEY_F(8): return (DUMPSCREEN); case KEY_F(9): return (SHELL); case KEY_F(10): return (FASTBAIL); case 0x1b: /* ESC */ return (BAIL); case 0x0d: return (QUIT); case KEY_ENTER: return (QUIT); case 0xa: /* LF */ return (QUIT); case KEY_NPAGE: /* ^F */ return (REQ_NEXT_PAGE); case KEY_PPAGE: /* ^B */ return (REQ_PREV_PAGE); case KEY_DOWN: return (REQ_NEXT_FIELD); case KEY_UP: return (REQ_PREV_FIELD); case 0x06: /* ^F */ return (REQ_NEXT_PAGE); case 0x02: /* ^B */ return (REQ_PREV_PAGE); case 0x0e: /* ^N */ return (REQ_NEXT_FIELD); case 0x10: /* ^P */ return (REQ_PREV_FIELD); case KEY_HOME: return (REQ_FIRST_FIELD); case KEY_LL: return (REQ_LAST_FIELD); case 0x0c: /* ^L */ return (REQ_LEFT_FIELD); case 0x12: /* ^R */ return (REQ_RIGHT_FIELD); case 0x15: /* ^U */ return (REQ_UP_FIELD); case 0x04: /* ^D */ return (REQ_DOWN_FIELD); case 0x17: /* ^W */ return (REQ_NEXT_WORD); case 0x14: /* ^T */ return (REQ_PREV_WORD); case 0x01: /* ^A */ return (REQ_BEG_FIELD); case 0x05: /* ^E */ return (REQ_END_FIELD); case KEY_LEFT: return (REQ_PREV_CHAR); case KEY_RIGHT: return (REQ_NEXT_CHAR); case 0x0f: /* ^O */ return (REQ_INS_LINE); case KEY_DC: case 0x16: /* ^V */ return (REQ_DEL_CHAR); case KEY_BACKSPACE: case 0x08: /* ^H */ return (REQ_DEL_PREV); case 0x19: /* ^Y */ return (REQ_DEL_LINE); case 0x07: /* ^G */ return (REQ_DEL_WORD); case 0x03: /* ^C */ return (REQ_CLR_EOL); case 0x0b: /* ^K */ return (REQ_CLR_EOF); case 0x18: /* ^X */ return (REQ_CLR_FIELD); case 0x9: /* tab*/ return (REQ_NEXT_CHOICE); case 0x1a: /* ^Z 0x1a*/ return (REQ_PREV_CHOICE); case KEY_IC: /* INS */ if (mode == REQ_INS_MODE) return (mode = REQ_OVL_MODE); else return (mode = REQ_INS_MODE); } return (c); } static int my_driver(FORM * form, int c, char *path) { CDKSCROLL *plist; CDKSELECTION *slist; CDKENTRY *entry; FIELD *curfield; char **list; int i, j, y, n, dcols, drows, dmax; char *tmp, *otmp, *p; char *choices[] = {" ", "+"}; char buf[1024]; switch (c) { case EDIT: curfield = current_field(form); if (field_opts(curfield) & O_STATIC) { field_info(curfield, &drows, &dcols, &j, &j, &j, &j); dmax = 0; } else dynamic_field_info(curfield, &drows, &dcols, &dmax); if (dmax == 0) dmax = dcols; entry = newCDKEntry(cdkscreen, BOTTOM, CENTER, catgets(catalog, 4, 6, "Enter the field data " "below, and hit enter to return to the form."), catgets(catalog, 4, 7, "Data Entry: "), A_REVERSE, field_pad(curfield), vMIXED, ws.ws_col - 20, 0, dmax, TRUE, FALSE); if (field_buffer(curfield, 0) == NULL) setCDKEntry(entry, "", 0, dmax, TRUE); else setCDKEntry(entry, field_buffer(curfield, 0), 0, dmax, TRUE); injectCDKEntry(entry, CDK_BEGOFLINE); tmp = activateCDKEntry(entry, NULL); if (entry->exitType == vESCAPE_HIT) { destroyCDKEntry(entry); return (FALSE); } set_field_buffer(curfield, 0, tmp); destroyCDKEntry(entry); touchwin(stdscr); wrefresh(stdscr); return (FALSE); /* NOTREACHED */ break; case COMMAND: /* for now, ignore this.. it's messy */ return (FALSE); /* NOTREACHED */ break; case RESET: return (2); /* hrmmm... */ /* NOTREACHED */ break; case REFRESH: touchwin(stdscr); wrefresh(stdscr); return (FALSE); /* NOTREACHED */ break; case SHELL: endwin(); system("/bin/sh"); wrefresh(stdscr); return (FALSE); /* NOTREACHED */ break; case DUMPSCREEN: do_scrdump(0, NULL, NULL, 0); return (FALSE); /* NOTREACHED */ break; case SHOWHELP: curs_set(0); if (simple_lang_handler(path, HELPFILE, handle_help) == -2) nohelp(); touchwin(stdscr); wrefresh(stdscr); curs_set(1); return (FALSE); /* NOTREACHED */ break; case GENLIST: /* pull the grand popup list */ curfield = current_field(form); list = (char **)field_userptr(curfield); if (list == NULL) break; for (i = 0, y = 0; list[i] != NULL; i++) if ((strlen(list[i]) + 1) > y) y = strlen(list[i]) + 1; if (field_buffer(curfield, 1) == NULL || field_buffer(curfield, 0) == NULL) return (FALSE); curs_set(0); otmp = tmp = strdup(field_buffer(curfield, 1)); stripWhiteSpace(vBOTH, tmp); if (*tmp == 'm') { slist = newCDKSelection(cdkscreen, RIGHT, CENTER, RIGHT, 10, y + 2, catgets(catalog, 4, 1, "Select choices"), list, i, choices, 2, A_REVERSE ,TRUE, FALSE); free(otmp); otmp = tmp = strdup(field_buffer(curfield, 0)); stripWhiteSpace(vBOTH, tmp); if (*tmp != '\0') for (p = tmp; p != NULL; p = strsep(&tmp, ",")) for (y = 0; y < i; y++) if (strcmp(p, list[y]) == 0) slist->selections[y] = 1; activateCDKSelection(slist, NULL); for (y = 0; y < i; y++) if (slist->selections[y] == 1) { memset(&buf, '\0', sizeof(buf)); break; } for (y = 0, n = 0; y < i; y++) if (slist->selections[y] == 1) { if (++n != 1) snprintf(buf, sizeof(buf), "%s,", buf); snprintf(buf, sizeof(buf), "%s%s", buf, list[y]); } free(otmp); tmp = buf; if (n) set_field_buffer(curfield, 0, tmp); destroyCDKSelection(slist); } else if (*tmp == 's') { plist = newCDKScroll(cdkscreen, RIGHT, CENTER, RIGHT, 10, y + 2, catgets(catalog, 4, 1, "Select choice"), list, i, FALSE, A_REVERSE ,TRUE, FALSE); i = activateCDKScroll(plist, NULL); if (i != -1) set_field_buffer(curfield, 0, list[i]); destroyCDKScroll(plist); free(otmp); } touchwin(stdscr); wrefresh(stdscr); curs_set(1); return (FALSE); /* NOTREACHED */ break; case QUIT: /* do something useful */ if (form_driver(form, REQ_VALIDATION) == E_OK) { if ((i = process_form(form, path)) == 0) return (TRUE); else if (i == -1) return (FALSE); else return (2); /* special meaning */ } /* NOTREACHED */ break; case BAIL: return (3); /* TRUE, so handle_preform can free F */ /* NOTREACHED */ break; case FASTBAIL: endwin(); exit(EXIT_SUCCESS); break; } beep(); return (FALSE); } static FIELD * LABEL(FIELD_RECORD *x) { char *tmp; FIELD *f = new_field(1, (int)(strlen(x->v)+2), x->frow, x->fcol, 0, 0); size_t l; if (f != NULL) { tmp = realloc(x->v, sizeof(char *) * (strlen(x->v) + 3)); if (tmp == NULL) bailout("realloc: %s", strerror(errno)); x->v = tmp; l = strlen(x->v); tmp = malloc(sizeof(char *) * l); if (tmp == NULL) bailout("malloc: %s", strerror(errno)); if (x->required == 1) (void)strncpy(tmp, "* ", l); else (void)strncpy(tmp, " ", l); (void)strncat(tmp, x->v, l); (void)strlcpy(x->v, tmp, l + 3); set_field_buffer(f, 0, x->v); free(tmp); field_opts_off(f, O_ACTIVE); if (x->newpage == 1) set_new_page(f, TRUE); } return (f); } static FIELD * STRING(FIELD_RECORD *x) { /* create a STRING field */ FIELD *f = new_field(x->rows, x->cols, x->frow, x->fcol, 0, 0); if (f != NULL) { set_field_back(f, A_UNDERLINE); if (x->newpage == 1) set_new_page(f, TRUE); if (x->required == 1) field_opts_off(f, O_NULLOK); if (x->bigfield) { field_opts_off(f, O_STATIC); set_max_field(f, x->rcols); } set_field_buffer(f, 0, x->v); } return (f); } static FIELD * IPV4(FIELD_RECORD *x) { /* create an IPV4 field */ FIELD *f = new_field(x->rows, x->cols, x->frow, x->fcol, 0, 0); if (f != NULL) { set_field_type(f, TYPE_IPV4); set_field_back(f, A_UNDERLINE); if (x->newpage == 1) set_new_page(f, TRUE); if (x->required == 1) field_opts_off(f, O_NULLOK); if (x->bigfield) { field_opts_off(f, O_STATIC); set_max_field(f, x->rcols); } set_field_buffer(f, 0, x->v); } return (f); } static FIELD * IPV6(FIELD_RECORD *x) { /* create an IPV6 field */ FIELD *f = new_field(x->rows, x->cols, x->frow, x->fcol, 0, 0); if (f != NULL) { set_field_type(f, TYPE_IPV6); set_field_back(f, A_UNDERLINE); if (x->newpage == 1) set_new_page(f, TRUE); if (x->required == 1) field_opts_off(f, O_NULLOK); if (x->bigfield) { field_opts_off(f, O_STATIC); set_max_field(f, x->rcols); } set_field_buffer(f, 0, x->v); } return (f); } static FIELD * MULTI(FIELD_RECORD *x) { /* create a MULTI field */ FIELD *f = new_field(x->rows, x->cols, x->frow, x->fcol, 0, 1); if (f != NULL) { set_field_back(f, A_REVERSE); if (x->newpage == 1) set_new_page(f, TRUE); field_opts_off(f, O_STATIC); field_opts_off(f, O_EDIT); set_field_userptr(f, x->list); set_field_buffer(f, 1, "multi"); } return (f); } static FIELD * INTEGER(FIELD_RECORD *x) { /* create an INTEGER field */ FIELD *f = new_field(x->rows, x->cols, x->frow, x->fcol, 0, 0); int pre, min, max; char *p, *q, *n; p = x->v; q = strsep(&p, ","); pre = atoi(q); q = strsep(&p, ","); min = atoi(q); n = strdup(p); q = strsep(&p, ","); if (p == NULL) max = atoi(n); else max = atoi(q); if (f != NULL) { set_field_back(f, A_UNDERLINE); set_field_type(f, TYPE_INTEGER, pre, min, max); if (x->newpage == 1) set_new_page(f, TRUE); if (x->required == 1) field_opts_off(f, O_NULLOK); if (x->bigfield) field_opts_off(f, O_STATIC); if (p != NULL) set_field_buffer(f, 0, p); } return (f); } static FIELD * INVIS(FIELD_RECORD *x) { /* create an INVIS field */ FIELD *f = new_field(x->rows, x->cols, x->frow, x->fcol, 0, 0); if (f != NULL) { set_field_opts(f, field_opts(f) & ~(O_ACTIVE|O_VISIBLE)); if (x->bigfield) { field_opts_off(f, O_STATIC); set_max_field(f, x->rcols); } if (x->newpage == 1) set_new_page(f, TRUE); set_field_buffer(f, 0, x->v); } return (f); } static FIELD * NOEDIT(FIELD_RECORD *x) { /* create a NOEDIT field */ FIELD *f = new_field(x->rows, x->cols, x->frow, x->fcol, 0, 0); if (f != NULL) { set_field_opts(f, field_opts(f) & ~(O_EDIT|O_ACTIVE)); if (x->newpage == 1) set_new_page(f, TRUE); if (x->bigfield) { field_opts_off(f, O_STATIC); set_max_field(f, x->rcols); } set_field_buffer(f, 0, x->v); } return (f); } static FIELD * ENUM(FIELD_RECORD *x) { /* create a ENUM field */ FIELD *f = new_field(x->rows, x->cols, x->frow, x->fcol, 0, 1); if (f != NULL) { set_field_back(f, A_REVERSE); set_field_type(f, TYPE_ENUM, x->list, FALSE, TRUE); set_field_userptr(f, x->list); if (x->newpage == 1) set_new_page(f, TRUE); if (x->required == 1) field_opts_off(f, O_NULLOK); field_opts_off(f, O_EDIT); set_field_buffer(f, 1, "single"); if (x->bigfield) field_opts_off(f, O_STATIC); set_field_buffer(f, 0, x->list[0]); } return (f); } static FIELD_RECORD *F; static int process_preform(FORM *form, char *path) { char file[PATH_MAX]; struct stat sb; char *p; int fc, lcnt, i, j; FIELD **f; char **args, **nargs; if (lang_id == NULL) { snprintf(file, sizeof(file), "%s/%s", path, FORMFILE); } else { snprintf(file, sizeof(file), "%s/%s.%s", path, FORMFILE, lang_id); if (stat(file, &sb) != 0) snprintf(file, sizeof(file), "%s/%s", path, FORMFILE); } args = malloc(sizeof(char *) * 2); if (args == NULL) bailout("malloc: %s", strerror(errno)); fc = lcnt = field_count(form); nargs = realloc(args, sizeof(char *) * (lcnt + 1)); if (nargs == NULL) bailout("realloc: %s", strerror(errno)); args = nargs; f = form_fields(form); for (lcnt = 0, i = 0; lcnt < fc; lcnt++) { if (F[lcnt].type != (PF_field)LABEL) { if (field_buffer(f[lcnt], 0) == NULL) args[i] = ""; else args[i] = strdup(field_buffer(f[lcnt], 0)); if (args[i] != NULL) { p = &args[i][strlen(args[i]) - 1]; while (isspace((unsigned char)*p)) *p-- = '\0'; } i++; } } args[i] = NULL; for (i = 0; F[i].type != NULL; i++) { free(F[i].v); if (F[i].list != NULL) { for (j = 0; F[i].list[j] != NULL; j++) free(F[i].list[j]); free(F[i].list); } } free(F); i = handle_form(path, file, args); for (j = 0; args[j] != NULL; j++) free(args[j]); free(args); return (i); } int process_form(FORM *form, char *path) { FILE *fp; char file[PATH_MAX], file2[PATH_MAX]; struct stat sb; char *exec, *t, *p; size_t len; int fc, lcnt, i, j; FIELD **f; char **args, **nargs; CDKLABEL *label; char *msg[1]; int key; /* handle the preform somewhere else */ if (strcmp("pre", form_userptr(form)) == 0) return (process_preform(form, path)); curs_set(0); *msg = catgets(catalog, 3, 17, "Are you sure? (Y/n)"); label = newCDKLabel(cdkscreen, CENTER, CENTER, msg, 1, TRUE, FALSE); activateCDKLabel(label, NULL); key = waitCDKLabel(label, 0); destroyCDKLabel(label); touchwin(stdscr); wrefresh(stdscr); curs_set(1); if (key != 13 && key != 10 && key != 121 && key != 89) /* enter y Y */ return (-1); if (lang_id == NULL) { snprintf(file, sizeof(file), "%s/%s", path, EXECFILE); snprintf(file2, sizeof(file2), "%s/%s", path, SCRIPTFILE); } else { snprintf(file, sizeof(file), "%s/%s.%s", path, EXECFILE, lang_id); snprintf(file2, sizeof(file2), "%s/%s.%s", path, SCRIPTFILE, lang_id); if (stat(file, &sb) != 0) snprintf(file, sizeof(file), "%s/%s", path, EXECFILE); if (stat(file2, &sb) != 0) snprintf(file2, sizeof(file2), "%s/%s", path, SCRIPTFILE); } args = malloc(sizeof(char *) * 2); if (args == NULL) bailout("malloc: %s", strerror(errno)); if ((fp = fopen(file, "r")) != NULL) { for (lcnt = 1; (exec = fgetln(fp, &len)) != NULL; ++lcnt) { if (len == 1) /* skip blank */ continue; if (exec[len - 1] == '#') /* Skip comments */ continue; if (exec[len - 1] != '\n') { /* corrupted? */ warnx("%s: line %d corrupted", path, lcnt); continue; } exec[len - 1] = '\0'; /* NUL terminate */ while (*exec != '\0' && isspace((unsigned char)*exec)) ++exec; if (*exec == '\0' || *exec == '#') continue; p = strsep(&exec, " "); for (i = 0; p != NULL; p = strsep(&exec, " "), i++) { nargs = realloc(args, sizeof(char *) * (i + 2)); if (nargs == NULL) bailout("realloc: %s", strerror(errno)); args = nargs; args[i] = strdup(p); } t = NULL; } fclose(fp); } else if (stat(file2, &sb) == 0) { t = strdup(file2); i = 1; } else bailout(catgets(catalog, 1, 13, "no files")); fc = lcnt = field_count(form); nargs = realloc(args, sizeof(char *) * (lcnt + 1 + i)); if (nargs == NULL) bailout("realloc: %s", strerror(errno)); args = nargs; f = form_fields(form); for (lcnt = 0; lcnt < fc; lcnt++) { if (F[lcnt].type != (PF_field)LABEL) { if (field_buffer(f[lcnt], 0) == NULL) args[i] = ""; else args[i] = strdup(field_buffer(f[lcnt], 0)); if (args[i] != NULL) { p = &args[i][strlen(args[i]) - 1]; while (isspace((unsigned char)*p)) *p-- = '\0'; } i++; } } if (t != NULL) args[0] = t; args[i] = NULL; i = run_prog(1, args); for (j = 0; args[j] != NULL; j++) free(args[j]); free(args); return (i); } static FIELD ** make_fields(void) { /* create the fields */ FIELD **f, **fields; int i; f = malloc(sizeof(FIELD *) * (MAX_FIELD + 1)); if (f == NULL) bailout("malloc: %s", strerror(errno)); fields = f; for (i = 0; i < MAX_FIELD && F[i].type; ++i, ++f) *f = (F[i].type)(&F[i]); *f = (FIELD *)0; return (fields); } struct cqForm cqFormHead, *cqFormHeadp; static int tstring(int max, char *string) { char hold[10]; int cur; if (max == 0) return (0); for (cur = 0; cur <= max; cur++) { snprintf(hold, sizeof(hold), "@@@%d@@@", cur); if (strcmp(hold, string) == 0) return (cur); } return (0); } static int strlen_data(FTREE_ENTRY *ftp) { int i, j; char *p, *q, *o; i = 0; switch (ftp->type) { case DATAT_BLANK: return (1); /* NOTREACHED */ break; case DATAT_ENTRY: case DATAT_ESCRIPT: case DATAT_NESCRIPT: case DATAT_V4: case DATAT_V4SCRIPT: case DATAT_V6: case DATAT_V6SCRIPT: case DATAT_INVIS: case DATAT_NOEDIT: return (ftp->elen); /* NOTREACHED */ break; case DATAT_LIST: case DATAT_FUNC: case DATAT_SCRIPT: case DATAT_MLIST: case DATAT_MFUNC: case DATAT_MSCRIPT: if (ftp->list == NULL) return (0); for (i = 0, j = 0; ftp->list[i] != NULL; i++) { size_t k; if ((k = strlen(ftp->list[i])) > j) j = k; } return (j); /* NOTREACHED */ break; case DATAT_INTEGER: case DATAT_ISCRIPT: o = p = strdup(ftp->data); q = strsep(&p, ","); i = atoi(q); free(o); return (i); /* NOTREACHED */ break; default: bailout(catgets(catalog, 1, 14, "invalid field type")); break; } return (1); /* eep! */ } static void gen_list(FTREE_ENTRY *ftp, int max, char **args) { int i = 0; int lmax = 10; int cur; char *p, *q; char **nlist; ftp->list = malloc(sizeof(char *) * lmax); if (ftp->list == NULL) bailout("malloc: %s", strerror(errno)); for (p = ftp->data; p != NULL;) { q = (char *)strsep(&p, ","); if (q != NULL) { cur = tstring(max, q); if (cur) ftp->list[i++] = strdup(args[cur-1]); else ftp->list[i++] = strdup(q); } if (i == lmax - 2) { nlist = realloc(ftp->list, sizeof(char*) * (lmax + 10)); if (nlist == NULL) bailout("realloc: %s", strerror(errno)); ftp->list = nlist; lmax += 10; } } ftp->list[i] = NULL; } static void gen_func(FTREE_ENTRY *ftp, int max, char **args) { int i, cur; char *p, *q; p = strsep(&ftp->data, ","); q = strsep(&ftp->data, ","); for (i = 0; func_map[i].funcname != NULL; i++) if (strcmp(func_map[i].funcname, p) == 0) break; if (func_map[i].function == NULL) bailout("%s: %s", catgets(catalog, 1, 5, "function not found"), p); cur = tstring(max, q); if (cur) ftp->list = func_map[i].function(args[cur-1]); else ftp->list = func_map[i].function(q); } static void gen_script(FTREE_ENTRY *ftp, char *dir, int max, char **args) { char *p, *q, *qo, *po, *comm, *test, *n; FILE *file; char buf[PATH_MAX+30]; #if 0 struct stat sb; #endif size_t len; int i, cur; int lmax = 10; size_t l; char **nlist; qo = q = strdup(ftp->data); l = strlen(q) + 2; comm = malloc(sizeof(char) * l); if (comm == NULL) bailout("malloc: %s", strerror(errno)); p = strsep(&q, ","); (void)strlcpy(comm, p, l); po = NULL; if (q != NULL) { for (po = p = strdup(q); p != NULL; p = strsep(&q, ",")) { (void)strlcat(comm, " ", l); for (test = p; *test != '\0'; test++) if (*test == ',') { *test = '\0'; test++; q = test; break; } cur = tstring(max, p); if (cur) { l = strlen(comm) + strlen(args[cur-1]) + 2; n = realloc(comm, sizeof(char) * l); if (n == NULL) bailout("realloc: %s", strerror(errno)); comm = n; (void)strlcat(comm, args[cur-1], l); } else { l = strlen(comm) + strlen(p) + 2; n = realloc(comm, sizeof(char) * l); if (n == NULL) bailout("realloc: %s", strerror(errno)); comm = n; (void)strlcat(comm, p, l); } } } free(qo); if (po != NULL) free(po); snprintf(buf, sizeof(buf), "%s/%s", dir, comm); #if 0 if (stat(buf, &sb) != 0) bailout("%s: %s", buf, strerror(errno)); #endif file = popen(buf, "r"); if (file == NULL) bailout("popen: %s", strerror(errno)); ftp->list = malloc(sizeof(char *) * lmax); if (ftp->list == NULL) bailout("malloc: %s", strerror(errno)); for (i = 0; (p = fgetln(file, &len)) != NULL;) { if (len <= 1) continue; ftp->list[i] = malloc(len); if (ftp->list[i] == NULL) bailout("malloc: %s", strerror(errno)); memcpy(ftp->list[i], p, len); ftp->list[i][len - 1] = '\0'; if (++i == lmax - 2) { nlist = realloc(ftp->list, sizeof(char *) * (lmax + 10)); if (nlist == NULL) bailout("realloc: %s", strerror(errno)); ftp->list = nlist; lmax += 10; } } pclose(file); if (i == 0) { ftp->list[0] = ""; ftp->list[1] = NULL; } else { ftp->list[i] = NULL; } free(comm); } static char * gen_escript(FTREE_ENTRY *ftp, char *dir, int max, char **args) { char *p, *q, *qo, *po, *test, *comm, *n; FILE *file; char buf[PATH_MAX+30]; size_t len; int cur; /* struct stat sb; */ size_t l; if (ftp->data == NULL) bailout(catgets(catalog, 1, 22, "Null filename in escript argument")); else qo = q = strdup(ftp->data); l = strlen(q) + 2; comm = malloc(sizeof(char) * l); if (comm == NULL) bailout("malloc: %s", strerror(errno)); p = strsep(&q, ","); (void)strlcpy(comm, p, l); po = NULL; if (q != NULL) { for (po = p = strdup(q); p != NULL; p = strsep(&q, ",")) { (void)strlcat(comm, " ", l); for (test = p; *test != '\0'; test++) if (*test == ',') { *test = '\0'; test++; q = test; break; } cur = tstring(max, p); if (cur) { l = strlen(comm) + strlen(args[cur-1]) + 2; n = realloc(comm, sizeof(char) * l); if (n == NULL) bailout("realloc: %s", strerror(errno)); comm = n; (void)strlcat(comm, args[cur-1], l); } else { l = strlen(comm) + strlen(p) + 2; n = realloc(comm, sizeof(char) * l); if (n == NULL) bailout("realloc: %s", strerror(errno)); comm = n; (void)strlcat(comm, p, l); } } } free(qo); if (po != NULL) free(po); snprintf(buf, sizeof(buf), "%s/%s", dir, comm); #if 0 if (stat(buf, &sb) != 0) bailout("%s: %s", buf, strerror(errno)); #endif file = popen(buf, "r"); if (file == NULL) bailout("popen: %s", strerror(errno)); p = fgetln(file, &len); if (p != NULL) { p[len - 1] = '\0'; /* strip newline & NUL terminate */ q = strdup(p); } else bailout("fgetln: on command '%s' gave error %s", buf, strerror(errno)); pclose(file); free(comm); return (q); } static char * gen_integer(FTREE_ENTRY *ftp, int max, char **args) { char *q, *qo, *tmp; char buf[PATH_MAX+30]; int pre, min, maxi, cur; qo = q = strdup(ftp->data); tmp = strsep(&q, ","); cur = tstring(max, tmp); if (cur) pre = atoi(args[cur-1]); else pre = atoi(tmp); tmp = strsep(&q, ","); cur = tstring(max, tmp); if (cur) min = atoi(args[cur-1]); else min = atoi(tmp); tmp = strsep(&q, ","); cur = tstring(max, tmp); if (cur) maxi = atoi(args[cur-1]); else maxi = atoi(tmp); if (q == NULL) snprintf(buf, sizeof(buf), "%d,%d,%d", pre, min, maxi); else snprintf(buf, sizeof(buf), "%d,%d,%d,%s", pre, min, maxi, q); q = strdup(buf); free(qo); return (q); } static char * gen_iscript(FTREE_ENTRY *ftp, char *dir, int max, char **args) { char *p, *q, *qo, *po, *test, *comm, *tmp, *n; FILE *file; char buf[PATH_MAX+30]; /* struct stat sb; */ size_t len; int cur, min, maxi, pre; size_t l; qo = q = strdup(ftp->data); tmp = strsep(&q, ","); pre = atoi(tmp); tmp = strsep(&q, ","); min = atoi(tmp); tmp = strsep(&q, ","); maxi = atoi(tmp); l = strlen(q) + 2; comm = malloc(sizeof(char) * l); if (comm == NULL) bailout("malloc: %s", strerror(errno)); tmp = strsep(&q, ","); (void)strlcpy(comm, tmp, l); po = NULL; if (q != NULL) { for (po = p = strdup(q); p != NULL; p = strsep(&q, ",")) { (void)strlcat(comm, " ", l); for (test = p; *test != '\0'; test++) if (*test == ',') { *test = '\0'; test++; q = test; break; } cur = tstring(max, p); if (cur) { l = strlen(comm) + strlen(args[cur-1]) + 2; n = realloc(comm, sizeof(char) * l); if (n == NULL) bailout("realloc: %s", strerror(errno)); comm = n; (void)strlcat(comm, args[cur-1], l); } else { l = strlen(comm) + strlen(p) + 2; n = realloc(comm, sizeof(char) * l); if (n == NULL) bailout("realloc: %s", strerror(errno)); comm = n; (void)strlcat(comm, p, l); } } } free(qo); if (po != NULL) free(po); snprintf(buf, sizeof(buf), "%s/%s", dir, comm); #if 0 if (stat(buf, &sb) != 0) bailout("%s: %s", buf, strerror(errno)); #endif file = popen(buf, "r"); if (file == NULL) bailout("popen: %s", strerror(errno)); p = fgetln(file, &len); if (p != NULL) { p[len - 1] = '\0'; /* strip newline & NUL terminate */ q = strdup(p); } else bailout("fgetln: on command '%s' gave error %s", buf, strerror(errno)); pclose(file); snprintf(buf, sizeof(buf), "%d,%d,%d,%s", pre, min, maxi, q); free(q); q = strdup(buf); free(comm); return (q); } static void form_generate(struct cqForm *cqf, char *basedir, char **args) { int i = 0; int lrow = 0; int max, cur; char *p; FTREE_ENTRY *ftp; for (max = 0, cur = 0; args[max] != NULL; max++) continue; for (ftp = CIRCLEQ_FIRST(cqf); ftp != (void *)cqf; ftp = CIRCLEQ_NEXT(ftp, cqFormEntries)) { F[i].type = LABEL; F[i].rows = 0; F[i].cols = 0; if (lrow >= ws.ws_row-6) { F[i].newpage = 1; lrow = 0; } else F[i].newpage = 0; F[i].frow = lrow; F[i].fcol = 0; F[i].v = strdup(ftp->desc); F[i].required = ftp->required; F[i].list = (char **)NULL; i++; if (ftp->type != DATAT_BLANK) { F[i].required = ftp->required; F[i].list = (char **)NULL; switch (ftp->type) { case DATAT_ENTRY: F[i].type = STRING; p = strsep(&ftp->data, ","); if (ftp->data == NULL) ftp->data = strdup(""); ftp->elen = atoi(p); cur = tstring(max, ftp->data); if (cur) F[i].v = strdup(args[cur-1]); else F[i].v = strdup(ftp->data); break; case DATAT_LIST: F[i].type = ENUM; F[i].v = strdup(ftp->data); gen_list(ftp, max, args); F[i].list = ftp->list; break; case DATAT_FUNC: F[i].type = ENUM; F[i].v = strdup(ftp->data); gen_func(ftp, max, args); F[i].list = ftp->list; break; case DATAT_SCRIPT: F[i].type = ENUM; F[i].v = strdup(ftp->data); gen_script(ftp, basedir, max, args); F[i].list = ftp->list; break; case DATAT_MLIST: F[i].type = MULTI; F[i].v = strdup(ftp->data); gen_list(ftp, max, args); F[i].list = ftp->list; break; case DATAT_MFUNC: F[i].type = MULTI; F[i].v = strdup(ftp->data); gen_func(ftp, max, args); F[i].list = ftp->list; break; case DATAT_MSCRIPT: F[i].type = MULTI; F[i].v = strdup(ftp->data); gen_script(ftp, basedir, max, args); F[i].list = ftp->list; break; case DATAT_NOEDIT: F[i].type = NOEDIT; cur = tstring(max, ftp->data); if (cur) F[i].v = strdup(args[cur-1]); else F[i].v = strdup(ftp->data); ftp->elen = strlen(F[i].v); break; case DATAT_INVIS: F[i].type = INVIS; cur = tstring(max, ftp->data); if (cur) F[i].v = strdup(args[cur-1]); else F[i].v = strdup(ftp->data); ftp->elen = strlen(F[i].v); break; case DATAT_INTEGER: F[i].type = INTEGER; F[i].v = gen_integer(ftp, max, args); break; case DATAT_ISCRIPT: F[i].type = INTEGER; F[i].v = gen_iscript(ftp, basedir, max, args); break; case DATAT_ESCRIPT: F[i].type = STRING; p = strsep(&ftp->data, ","); ftp->elen = atoi(p); F[i].v = gen_escript(ftp, basedir, max, args); if (strlen(F[i].v) > ftp->elen) ftp->elen = strlen(F[i].v); break; case DATAT_NESCRIPT: F[i].type = NOEDIT; F[i].v = gen_escript(ftp, basedir, max, args); ftp->elen = strlen(F[i].v); break; case DATAT_V4SCRIPT: F[i].type = IPV4; F[i].v = gen_escript(ftp, basedir, max, args); ftp->elen = 18; break; case DATAT_V4: F[i].type = IPV4; cur = tstring(max, ftp->data); if (cur) F[i].v = strdup(args[cur-1]); else { if (ftp->data == NULL) ftp->data = strdup(""); F[i].v = strdup(ftp->data); } ftp->elen = 18; break; case DATAT_V6SCRIPT: F[i].type = IPV6; F[i].v = gen_escript(ftp, basedir, max, args); ftp->elen = 48; break; case DATAT_V6: F[i].type = IPV6; cur = tstring(max, ftp->data); if (cur) F[i].v = strdup(args[cur-1]); else { if (ftp->data == NULL) ftp->data = strdup(""); F[i].v = strdup(ftp->data); } ftp->elen = 48; break; } F[i].rows = 1; F[i].rcols = F[i].cols = strlen_data(ftp); if (F[i].cols > 19) { F[i].bigfield = 1; F[i].cols = 19; } else F[i].bigfield = 0; F[i].newpage = 0; F[i].fcol = 55; F[i].frow = lrow; i++; } lrow++; } /* generate the final entry */ F[i].type = (PF_field)NULL; F[i].rows = 0; F[i].cols = 0; F[i].frow = 0; F[i].fcol = 0; F[i].v = (char *)NULL; F[i].list = (char **)NULL; F[i].newpage = 0; } static void tab_help(FORM *form) { CDKLABEL *label; char *msg[4]; char *buffer; FIELD *curfield; int lines; curfield = current_field(form); buffer = field_buffer(curfield, 1); if (buffer == NULL) return; if (*buffer == 's') { msg[0] = catgets(catalog, 3, 10, "The current field is a list " "field, and selections can only be made from"); msg[1] = catgets(catalog, 3, 11, "the pre-defined list. " "Please use TAB or the List(F4) command to edit."); msg[2] = catgets(catalog, 3, 12, "Press the ENTER key to " "return from the list popup."); lines = 3; } else if (*buffer == 'm') { msg[0] = catgets(catalog, 3, 13, "The current field is a " "multiple-selection list field. The field can only"); msg[1] = catgets(catalog, 3, 14, "be edited by issueing " "the List(F4) command, and toggling desired options"); msg[2] = catgets(catalog, 3, 15, "with the spacebar. " "Press the ENTER key to return from the list popup."); lines = 3; } else return; curs_set(0); label = newCDKLabel(cdkscreen, CENTER, CENTER, msg, lines, TRUE, FALSE); activateCDKLabel(label, NULL); waitCDKLabel(label, 0); destroyCDKLabel(label); touchwin(stdscr); wrefresh(stdscr); curs_set(1); } static void invalid_field_help(void) { CDKLABEL *label; char *msg[2]; msg[0] = catgets(catalog, 3, 18, "The data entered in this field is " "invalid."); msg[1] = catgets(catalog, 3, 19, "Please enter the correct " "information before continuing."); curs_set(0); label = newCDKLabel(cdkscreen, CENTER, CENTER, msg, 2, TRUE, FALSE); activateCDKLabel(label, NULL); waitCDKLabel(label, 0); destroyCDKLabel(label); touchwin(stdscr); wrefresh(stdscr); curs_set(1); } int handle_form(char *basedir, char *path, char **args) { WINDOW *formwin, *boxwin; CDKLABEL *label; char *msg[1]; FORM *menuform; FIELD **f; int done = FALSE; int c, i, j, fc; FTREE_ENTRY *ftp; CIRCLEQ_INIT(&cqFormHead); cqFormHeadp = &cqFormHead; if (scan_form(cqFormHeadp, path)) return (1); F = calloc(sizeof(FIELD_RECORD), form_entries(&cqFormHead) * 2 + 1); if (F == NULL) bailout("calloc: %s", strerror(errno)); fflush(NULL); curs_set(0); /* generate a label to let the user know we are thinking */ msg[0] = catgets(catalog, 4, 2, "Generating form data, please wait"); label = newCDKLabel(cdkscreen, CENTER, CENTER, msg, 1, TRUE, FALSE); activateCDKLabel(label, NULL); if (args == NULL) form_generate(&cqFormHead, basedir, (char **)NULL); else form_generate(&cqFormHead, basedir, args); if ((menuform = new_form(make_fields())) == NULL) bailout(catgets(catalog, 1, 15, "error return from new_form")); set_form_userptr(menuform, "post"); destroyCDKLabel(label); wclear(stdscr); formwin = subwin(stdscr, ws.ws_row-5, ws.ws_col-2, 1, 1); boxwin = subwin(stdscr, ws.ws_row-3, ws.ws_col, 0, 0); bottom_help(2); box(boxwin, 0, 0); keypad(formwin, TRUE); set_form_sub(menuform, formwin); post_form(menuform); wrefresh(stdscr); wrefresh(boxwin); form_status(menuform); curs_set(1); while (!done) { pos_form_cursor(menuform); wrefresh(formwin); switch (form_driver(menuform, c = get_request(formwin))) { case E_OK: if (c == REQ_NEXT_PAGE || c == REQ_PREV_PAGE || c == REQ_FIRST_PAGE || c == REQ_LAST_PAGE || c == REQ_NEXT_FIELD || c == REQ_PREV_FIELD) form_status(menuform); break; case E_UNKNOWN_COMMAND: done = my_driver(menuform, c, basedir); break; case E_REQUEST_DENIED: tab_help(menuform); break; case E_INVALID_FIELD: invalid_field_help(); break; } } curs_set(0); fc = field_count(menuform); f = form_fields(menuform); unpost_form(menuform); for (; fc > 0; fc--) free_field(*f++); free_form(menuform); for (i = 0; F[i].type != NULL; i++) { free(F[i].v); if (F[i].list != NULL) { for (j = 0; F[i].list[j] != NULL; j++) free(F[i].list[j]); free(F[i].list); } } free(F); ftp = CIRCLEQ_FIRST(&cqFormHead); for (; !CIRCLEQ_EMPTY(&cqFormHead); ftp = CIRCLEQ_FIRST(&cqFormHead)) { CIRCLEQ_REMOVE(&cqFormHead, ftp, cqFormEntries); free(ftp->desc); free(ftp->origdata); free(ftp); } delwin(formwin); delwin(boxwin); wclear(stdscr); wrefresh(stdscr); if (done == 2) return (1); return (0); } int handle_preform(char *basedir, char *path) { WINDOW *formwin, *boxwin; CDKLABEL *label; char *msg[1]; FORM *menuform; FIELD **f; int done = FALSE; int c, i, j, fc; char *args[2]; FTREE_ENTRY *ftp; CIRCLEQ_INIT(&cqFormHead); cqFormHeadp = &cqFormHead; if (scan_form(cqFormHeadp, path)) return (1); F = calloc(sizeof(FIELD_RECORD), form_entries(&cqFormHead) * 2 + 1); if (F == NULL) bailout("calloc: %s", strerror(errno)); fflush(NULL); curs_set(0); /* generate a label to let the user know we are thinking */ msg[0] = catgets(catalog, 4, 2, "Generating form data, please wait"); label = newCDKLabel(cdkscreen, CENTER, CENTER, msg, 1, TRUE, FALSE); activateCDKLabel(label, NULL); args[0] = NULL; form_generate(&cqFormHead, basedir, args); if ((menuform = new_form(make_fields())) == NULL) bailout(catgets(catalog, 1, 15, "error return from new_form")); set_form_userptr(menuform, "pre"); destroyCDKLabel(label); wclear(stdscr); formwin = subwin(stdscr, ws.ws_row-5, ws.ws_col-2, 1, 1); boxwin = subwin(stdscr, ws.ws_row-3, ws.ws_col, 0, 0); bottom_help(2); box(boxwin, 0, 0); keypad(formwin, TRUE); set_form_sub(menuform, formwin); post_form(menuform); wrefresh(stdscr); form_status(menuform); curs_set(1); while (!done) { pos_form_cursor(menuform); wrefresh(formwin); switch (form_driver(menuform, c = get_request(formwin))) { case E_OK: if (c == REQ_NEXT_PAGE || c == REQ_PREV_PAGE || c == REQ_FIRST_PAGE || c == REQ_LAST_PAGE || c == REQ_NEXT_FIELD || c == REQ_PREV_FIELD) form_status(menuform); break; case E_UNKNOWN_COMMAND: done = my_driver(menuform, c, basedir); break; case E_REQUEST_DENIED: tab_help(menuform); break; case E_INVALID_FIELD: invalid_field_help(); break; } } curs_set(0); fc = field_count(menuform); f = form_fields(menuform); unpost_form(menuform); for (; fc > 0; fc--) free_field(*f++); free_form(menuform); if (done == 3) { for (i = 0; F[i].type != NULL; i++) { free(F[i].v); if (F[i].list != NULL) { for (j = 0; F[i].list[j] != NULL; j++) free(F[i].list[j]); free(F[i].list); } } free(F); } ftp = CIRCLEQ_FIRST(&cqFormHead); for (; !CIRCLEQ_EMPTY(&cqFormHead); ftp = CIRCLEQ_FIRST(&cqFormHead)) { CIRCLEQ_REMOVE(&cqFormHead, ftp, cqFormEntries); free(ftp->desc); free(ftp->origdata); free(ftp); } delwin(formwin); delwin(boxwin); wclear(stdscr); wrefresh(stdscr); if (done == 2) return (1); return (0); }