jcs
/subtext
/amendments
/100
session: Add session_menu, use it everywhere
Start on sysop board management
jcs made amendment 100 over 2 years ago
--- db.c Thu May 12 15:29:53 2022
+++ db.c Sun May 15 21:48:28 2022
@@ -48,13 +48,36 @@ struct struct_field config_fields[] = {
1, member_size(struct config, modem_init) },
{ "Max Idle Minutes", CONFIG_TYPE_SHORT,
offsetof(struct config, max_idle_minutes),
- 1, 65535 },
+ 1, USHRT_MAX },
};
size_t nconfig_fields = nitems(config_fields);
+struct struct_field board_fields[] = {
+ { "Board ID", CONFIG_TYPE_LONG,
+ offsetof(struct board, id),
+ 1, ULONG_MAX },
+ { "Name", CONFIG_TYPE_STRING,
+ offsetof(struct board, name),
+ 1, member_size(struct board, name) },
+ { "Description", CONFIG_TYPE_STRING,
+ offsetof(struct board, description),
+ 0, member_size(struct board, description) },
+ { "Restricted Posting", CONFIG_TYPE_BOOLEAN,
+ offsetof(struct board, restricted_posting),
+ 0, 0 },
+ { "Restricted Viewing", CONFIG_TYPE_BOOLEAN,
+ offsetof(struct board, restricted_viewing),
+ 0, 0 },
+ { "Days of Retention", CONFIG_TYPE_SHORT,
+ offsetof(struct board, retention_days),
+ 0, USHRT_MAX },
+};
+size_t nboard_fields = nitems(board_fields);
+
struct db * db_init(Str255 file, short vrefnum, struct bile *bile);
short db_migrate(struct db *tdb, short is_new);
void db_config_load(struct db *tdb);
+void db_boards_load(struct db *tdb);
struct db *
db_open(Str255 file, short vrefnum)
@@ -172,8 +195,10 @@ db_init(Str255 path, short vrefnum, struct bile *bile)
return NULL;
}
- if (!was_new)
+ if (!was_new) {
db_config_load(tdb);
+ db_boards_load(tdb);
+ }
PtoCstr(fullpath);
strlcat((char *)&fullpath, "-sessions", sizeof(fullpath));
@@ -279,4 +304,60 @@ db_config_load(struct db *tdb)
memcpy(&tdb->config, newconfig, sizeof(tdb->config));
free(newconfig);
+}
+
+void
+db_boards_load(struct db *tdb)
+{
+ size_t n;
+ struct bile_object *obj;
+
+ if (tdb->boards) {
+ free(tdb->boards);
+ tdb->boards = NULL;
+ }
+
+ tdb->nboards = bile_count_by_type(tdb->bile, DB_BOARD_RTYPE);
+ if (!tdb->nboards)
+ return;
+
+ tdb->boards = xmallocarray(tdb->nboards, sizeof(struct board));
+
+ for (n = 0; n < tdb->nboards; n++) {
+ obj = bile_get_nth_of_type(tdb->bile, n, DB_BOARD_RTYPE);
+ if (obj == NULL)
+ break;
+
+ bile_read(tdb->bile, DB_BOARD_RTYPE, obj->id,
+ (char *)(&tdb->boards[n]), obj->size);
+ }
+}
+
+void
+db_board_create(struct db *tdb, struct board *board)
+{
+ Str255 db_filename, board_filename;
+ struct bile *board_bile;
+
+ if (bile_write(tdb->bile, DB_BOARD_RTYPE, board->id,
+ board, sizeof(struct board)) != sizeof(struct board))
+ panic("save of new board failed: %d", bile_error(tdb->bile));
+
+ if (getpath(tdb->bile->vrefnum, tdb->bile->filename, &db_filename,
+ false) != 0)
+ panic("getpath failed on %s", PtoCstr(tdb->bile->filename));
+
+ PtoCstr(db_filename);
+
+ snprintf((char *)board_filename, sizeof(board_filename), "%s:%ld.brd",
+ db_filename, board->id);
+ CtoPstr(board_filename);
+
+ board_bile = bile_create(board_filename, tdb->bile->vrefnum,
+ SUBTEXT_CREATOR, DB_BOARD_RTYPE);
+ if (board_bile == NULL)
+ panic("failed creating new board bile at %s: %d",
+ PtoCstr(board_filename), bile_error(tdb->bile));
+
+ db_boards_load(tdb);
}
--- db.h Thu May 12 15:30:48 2022
+++ db.h Sun May 15 14:54:06 2022
@@ -84,13 +84,16 @@ struct board {
unsigned long id;
char name[DB_BOARD_NAME_LENGTH];
char description[DB_BOARD_DESCR_LENGTH];
- short restricted_posting;
- short restricted_viewing;
- short retention_days;
+ bool restricted_posting;
+ bool restricted_viewing;
+ unsigned short retention_days;
unsigned long last_post_at;
unsigned long post_count;
};
+extern struct struct_field board_fields[];
+extern size_t nboard_fields;
+
struct user_map {
unsigned long id;
char username_key[DB_USERNAME_LENGTH + 1];
@@ -103,11 +106,14 @@ struct db {
struct user_map *user_map;
short nusers;
struct bile *sessions_bile;
+ struct board *boards;
+ short nboards;
};
struct db * db_open(Str255 file, short vrefnum);
struct db * db_create(void);
void db_close(struct db *tdb);
void db_config_save(struct db *tdb);
+void db_board_create(struct db *tdb, struct board *board);
#endif
--- mail.c Mon May 9 15:48:26 2022
+++ mail.c Sat May 14 22:52:48 2022
@@ -52,7 +52,6 @@ struct bile_object_field mail_object_fields[] = {
void mail_free_message_strings(struct private_message *msg);
short mail_save(struct session *s, struct private_message *msg);
-void mail_help(struct session *s);
void mail_read(struct session *s, unsigned long idx);
void mail_delete(struct session *s, unsigned long idx);
void mail_mark_unread(struct session *s, unsigned long idx);
@@ -90,12 +89,12 @@ get_id:
session_printf(s, "{{B}}%s:{{/B}} ", prompt);
tmp = session_field_input(s, 5, 5, start_s, 0);
+ session_output(s, "\r\n", 2);
+ session_flush(s);
if (tmp == NULL || s->ending) {
ret = -1;
goto get_id_done;
}
- session_output(s, "\r\n", 2);
- session_flush(s);
if (sscanf(tmp, "%d", &ret) != 1 || ret < 1 || ret > nmsgs) {
session_printf(s, "{{B}}Invalid message ID{{/B}} (^C to cancel)\r\n");
@@ -113,13 +112,20 @@ get_id_done:
void
mail_menu(struct session *s)
{
- char l[2], arg[32];
- size_t count, nmsgs, id;
- bool done = false;
- char *field;
+ static struct session_menu_option opts[] = {
+ { 'l', "Ll", "List mail messages" },
+ { '#', "#0123456789", "Read mail message [#]" },
+ { 'd', "Dd", "Delete mail message [#]" },
+ { 'u', "Uu", "Mark mail message [#] unread" },
+ { 'c', "Cc", "Compose new mail message" },
+ { 'q', "QqXx", "Return to main menu" },
+ { '?', "?", "List menu options" },
+ };
+ size_t nmsgs, id;
unsigned long *mail_ids = NULL;
- unsigned short c;
- short ret;
+ char c;
+ bool show_help = false;
+ bool done = false;
if (!s->user) {
session_output_string(s, "Mail is not available to guests.\r\n"
@@ -127,56 +133,30 @@ mail_menu(struct session *s)
session_flush(s);
return;
}
-
- session_output_template(s, "{{B}}Private Mail{{/B}} "
- "('{{B}}?{{/B}}' for help)\r\n"
- "{{B}}--------------------{{/B}}\r\n");
- session_flush(s);
- mail_list(s, false, &mail_ids, &nmsgs);
+ session_printf(s, "{{B}}Private Mail{{/B}}\r\n");
+ session_flush(s);
- while (!done) {
- session_output_template(s, "{{B}}Mail>{{/B}} ");
- session_flush(s);
+ mail_list(s, false, &mail_ids, &nmsgs);
-get_menu_option:
- c = session_input_char(s);
- if (s->ending)
- return;
- if (c == '\r' || c == 0 || c > 255)
- goto get_menu_option;
-
- session_printf(s, "%c\r\n", c);
- session_flush(s);
-
+ while (!done) {
+ c = session_menu(s, "Private Mail", "Mail", opts, nitems(opts),
+ show_help);
+ show_help = false;
+
switch (c) {
case 'c':
- case 'C':
- mail_compose(s, arg, NULL, NULL);
+ mail_compose(s, NULL, NULL, NULL);
break;
case 'd':
- case 'D':
id = mail_get_message_id(s, nmsgs, "Message # to delete", -1);
if (id != -1)
mail_delete(s, id);
break;
- case 'h':
- case 'H':
- case '?':
- mail_help(s);
- break;
case 'l':
- case 'L':
mail_list(s, false, &mail_ids, &nmsgs);
break;
- case 'q':
- case 'Q':
- case 'x':
- case 'X':
- done = true;
- break;
case 'u':
- case 'U':
id = mail_get_message_id(s, nmsgs, "Message # to mark unread",
-1);
if (id != -1)
@@ -197,25 +177,16 @@ get_menu_option:
if (id != -1)
mail_read(s, mail_ids[id - 1]);
break;
+ case '?':
+ show_help = true;
+ break;
+ case '#':
+ break;
default:
- session_output_template(s,
- "Invalid option ({{B}}?{{/B}} for help)\r\n");
- session_flush(s);
+ done = true;
+ break;
}
}
-}
-
-void
-mail_help(struct session *s)
-{
- session_output_template(s,
- "{{B}}L{{/B}}: List mail messages\r\n"
- "{{B}}#{{/B}}: Read mail message [#]\r\n"
- "{{B}}D #{{/B}}: Delete mail message [#]\r\n"
- "{{B}}U #{{/B}}: Mark mail message [#] unread\r\n"
- "{{B}}C{{/B}}: Compose new mail message\r\n"
- "{{B}}Q{{/B}}: Return to main menu\r\n");
- session_flush(s);
}
void
--- session.c Thu May 12 17:40:55 2022
+++ session.c Sat May 14 20:06:07 2022
@@ -27,6 +27,7 @@
#include "session.h"
#include "settings.h"
#include "signup.h"
+#include "sysop.h"
#include "user.h"
#include "user_settings.h"
#include "uthread.h"
@@ -216,7 +217,7 @@ get_another_char:
session_flush(s);
break;
}
- sysop_edit_settings(s);
+ sysop_menu(s);
break;
case '?':
/* short menu */
@@ -1260,25 +1261,60 @@ session_who(struct session *s)
session_pause_return(s, 0, NULL);
}
-void
-sysop_edit_settings(struct session *s)
+char
+session_menu(struct session *s, char *title, char *prompt,
+ struct session_menu_option *opts, size_t nopts, bool show_opts)
{
- struct config *new_config;
- short ret;
+ struct session_menu_option *opt;
+ size_t n;
+ short j;
+ unsigned short c;
+
+ if (show_opts) {
+ session_printf(s, "{{B}}%s{{/B}}\r\n", title);
+ session_flush(s);
+ }
- if (!s->user || !s->user->is_sysop)
- return;
-
- ret = struct_editor(s, config_fields, nconfig_fields, &db->config,
- sizeof(struct config), (void *)&new_config, "BBS Settings");
- if (ret != 0) {
- session_printf(s, "No changes made\r\n");
- return;
+print_options:
+ if (show_opts) {
+ for (n = 0; n < nopts; n++) {
+ opt = &opts[n];
+
+ session_printf(s, "{{B}}%c{{/B}}: %s\r\n", opt->key[0],
+ opt->title);
+ session_flush(s);
+ }
}
- memcpy(&db->config, new_config, sizeof(db->config));
- db_config_save(db);
+ for (;;) {
+ session_printf(s, "{{B}}%s>{{/B}} ", prompt);
+ session_flush(s);
- session_printf(s, "Successfully saved changes to BBS Settings\r\n");
- free(new_config);
+get_menu_option:
+ c = session_input_char(s);
+ if (s->ending)
+ return 0;
+ if (c == '\r' || c == 0 || c > 255)
+ goto get_menu_option;
+
+ session_printf(s, "%c\r\n", c);
+ session_flush(s);
+
+ for (n = 0; n < nopts; n++) {
+ opt = &opts[n];
+
+ for (j = 0; ; j++) {
+ if (opt->key[j] == '\0')
+ break;
+ if (opt->key[j] == c) {
+ if (opt->ret == '#')
+ return c; /* return actual number */
+ return opt->ret;
+ }
+ }
+ }
+
+ session_output_string(s, "Invalid option\r\n");
+ session_flush(s);
+ }
}
--- session.h Thu Apr 28 14:02:58 2022
+++ session.h Sat May 14 20:18:01 2022
@@ -97,6 +97,12 @@ struct session {
extern struct session **sessions;
extern short nsessions;
+struct session_menu_option {
+ char ret;
+ char key[15];
+ char title[100];
+};
+
struct session * session_create(char *node, char *via,
struct node_funcs *node_funcs);
void session_close(struct session *session);
@@ -122,5 +128,7 @@ char * session_bar(struct session *s, char *left_str,
void session_pause_return(struct session *s, short enforce, char *msg);
void session_recents(struct session *s);
void session_who(struct session *s);
+char session_menu(struct session *s, char *title, char *prompt,
+ struct session_menu_option *opts, size_t nopts, bool show_opts);
#endif /* __SESSION_H__ */
--- settings.c Thu May 12 16:56:04 2022
+++ settings.c Sun May 15 15:54:54 2022
@@ -42,7 +42,8 @@ void view_editor_save(struct focusable *focusable, Eve
short
struct_editor(struct session *s, struct struct_field *fields,
- size_t nfields, void *data, size_t dsize, void **result, char *title)
+ size_t nfields, void *data, size_t dsize, void **result, char *title,
+ char *prompt)
{
Handle ihandle;
struct struct_field *sf;
@@ -79,6 +80,17 @@ print_options:
sval = (new_data[sf->off] << 8) | new_data[sf->off + 1];
session_printf(s, "%d", sval);
break;
+ case CONFIG_TYPE_LONG:
+ lval = (new_data[sf->off] << 24) |
+ (new_data[sf->off + 1] << 16) |
+ (new_data[sf->off + 2] << 8) |
+ new_data[sf->off + 3];
+ session_printf(s, "%ld", lval);
+ break;
+ case CONFIG_TYPE_BOOLEAN:
+ session_printf(s, "%s",
+ new_data[sf->off] == 0 ? "false" : "true");
+ break;
}
session_output_string(s, "]\r\n");
@@ -89,7 +101,7 @@ print_options:
session_printf(s, "{{B}}?{{/B}}: Print menu of options\r\n");
for (;;) {
- session_output_template(s, "{{B}}Editor>{{/B}} ");
+ session_printf(s, "{{B}}%s>{{/B}} ", prompt);
session_flush(s);
get_menu_option:
@@ -160,8 +172,17 @@ get_input:
any_changes = true;
break;
case CONFIG_TYPE_SHORT:
- sval = (new_data[sf->off] << 8) | new_data[sf->off + 1];
- snprintf(initial, sizeof(initial), "%d", sval);
+ case CONFIG_TYPE_LONG:
+ if (sf->type == CONFIG_TYPE_LONG) {
+ lval = (new_data[sf->off] << 24) |
+ (new_data[sf->off + 1] << 16) |
+ (new_data[sf->off + 2] << 8) |
+ new_data[sf->off + 3];
+ snprintf(initial, sizeof(initial), "%ld", lval);
+ } else {
+ sval = (new_data[sf->off] << 8) | new_data[sf->off + 1];
+ snprintf(initial, sizeof(initial), "%d", sval);
+ }
input = session_field_input(s, 10, 10, initial, 0);
session_output(s, "\r\n", 2);
session_flush(s);
@@ -183,10 +204,46 @@ get_input:
free(input);
goto get_input;
}
- sval = lval;
- new_data[sf->off] = (sval >> 8) & 0xff;
- new_data[sf->off + 1] = sval & 0xff;
+ if (sf->type == CONFIG_TYPE_LONG) {
+ new_data[sf->off] = (lval >> 24) & 0xff;
+ new_data[sf->off + 1] = (lval >> 16) & 0xff;
+ new_data[sf->off + 2] = (lval >> 8) & 0xff;
+ new_data[sf->off + 3] = lval & 0xff;
+ } else {
+ sval = lval;
+ new_data[sf->off] = (sval >> 8) & 0xff;
+ new_data[sf->off + 1] = sval & 0xff;
+ }
any_changes = true;
+ break;
+ case CONFIG_TYPE_BOOLEAN:
+ if (new_data[sf->off])
+ session_output_string(s, "[Y/n] ");
+ else
+ session_output_string(s, "[y/N] ");
+ session_flush(s);
+
+ for (;;) {
+ c = session_input_char(s);
+ if (s->ending)
+ break;
+ if (c == '\r' && new_data[sf->off])
+ c = 'y';
+ else if (c == '\r' && new_data[sf->off] == 0)
+ c = 'n';
+ if (c == 'y' || c == 'Y') {
+ new_data[sf->off] = 1;
+ any_changes = true;
+ session_printf(s, "%c\r\n", c);
+ break;
+ }
+ if (c == 'n' || c == 'N') {
+ new_data[sf->off] = 0;
+ any_changes = true;
+ session_printf(s, "%c\r\n", c);
+ break;
+ }
+ }
break;
}
--- settings.h Tue May 10 15:45:23 2022
+++ settings.h Sun May 15 15:58:58 2022
@@ -21,7 +21,9 @@
enum {
CONFIG_TYPE_STRING,
- CONFIG_TYPE_SHORT
+ CONFIG_TYPE_SHORT,
+ CONFIG_TYPE_LONG,
+ CONFIG_TYPE_BOOLEAN
};
struct struct_field {
@@ -33,7 +35,8 @@ struct struct_field {
};
short struct_editor(struct session *s, struct struct_field *fields,
- size_t nfields, void *data, size_t dsize, void **result, char *title);
+ size_t nfields, void *data, size_t dsize, void **result, char *title,
+ char *prompt);
void view_editor_show(size_t id, char *title);
#endif
--- sysop.c Sun May 15 21:42:53 2022
+++ sysop.c Sun May 15 21:42:53 2022
@@ -0,0 +1,199 @@
+/*
+ * Copyright (c) 2022 joshua stein <jcs@jcs.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "subtext.h"
+#include "session.h"
+#include "sysop.h"
+
+#include <string.h>
+
+void sysop_edit_boards(struct session *s);
+
+void
+sysop_menu(struct session *s)
+{
+ static struct session_menu_option opts[] = {
+ { 'b', "Bb", "Manage Boards" },
+ { 'u', "Uu", "Manage Users" },
+ { 's', "Ss", "Change BBS Settings" },
+ { 'q', "QqXx", "Return to main menu" },
+ { '?', "?", "List menu options" },
+ };
+ char c;
+ bool show_help = true;
+ bool done = false;
+
+ if (!s->user || !s->user->is_sysop)
+ return;
+
+ session_log(s, "Entered sysop menu");
+
+ while (!done) {
+ c = session_menu(s, "Sysop Menu", "Sysop", opts, nitems(opts),
+ show_help);
+ show_help = false;
+
+ switch (c) {
+ case 'b':
+ sysop_edit_boards(s);
+ break;
+ case 's':
+ sysop_edit_settings(s);
+ break;
+ case 'u':
+ break;
+ case '?':
+ show_help = true;
+ break;
+ default:
+ done = true;
+ break;
+ }
+ }
+}
+
+void
+sysop_edit_settings(struct session *s)
+{
+ struct config *new_config;
+ short ret;
+
+ if (!s->user || !s->user->is_sysop)
+ return;
+
+ ret = struct_editor(s, config_fields, nconfig_fields, &db->config,
+ sizeof(struct config), (void *)&new_config, "BBS Settings",
+ "Sysop:Settings");
+ if (ret != 0) {
+ session_printf(s, "No changes made\r\n");
+ return;
+ }
+
+ memcpy(&db->config, new_config, sizeof(db->config));
+ db_config_save(db);
+
+ session_log(s, "Changed BBS settings");
+ session_printf(s, "Successfully saved changes to BBS Settings\r\n");
+ free(new_config);
+}
+
+void
+sysop_edit_boards(struct session *s)
+{
+ static struct session_menu_option opts[] = {
+ { 'n', "Nn", "Create new board" },
+ { 'q', "QqXx", "Return to sysop menu" },
+ { '?', "?", "List menu options" },
+ };
+ struct session_menu_option *dopts = NULL, *opt;
+ struct board *board, *new_board;
+ size_t n;
+ short ret;
+ char c;
+ char prompt[30];
+ bool show_help = true;
+ bool done = false;
+ bool found = false;
+
+ while (!done) {
+ /*
+ * Unfortunately we have to do this every iteration because the
+ * list of boards may change
+ */
+ if (dopts != NULL)
+ free(dopts);
+ dopts = xmalloc(sizeof(opts) +
+ (db->nboards * sizeof(struct session_menu_option)));
+ for (n = 0; n < db->nboards; n++) {
+ board = &db->boards[n];
+ opt = &dopts[n];
+ opt->ret = '0' + board->id;
+ opt->key[0] = '0' + board->id;
+ opt->key[1] = '\0';
+ strlcpy(opt->title, board->name, sizeof(opts[0].title));
+ }
+ memcpy(&dopts[db->nboards], opts, sizeof(opts));
+
+ c = session_menu(s, "Board Editor", "Sysop:Boards", dopts,
+ nitems(opts) + db->nboards, show_help);
+ show_help = false;
+
+ switch (c) {
+ case 'n':
+ board = xmalloczero(sizeof(struct board));
+ board->id = bile_next_id(db->bile, DB_BOARD_RTYPE);
+ board->restricted_posting = false;
+ board->restricted_viewing = false;
+ ret = struct_editor(s, board_fields, nboard_fields,
+ board, sizeof(struct board), (void *)&new_board,
+ "New Board", "Sysop:Boards:New");
+ if (ret != 0) {
+ free(board);
+ continue;
+ }
+ db_board_create(db, new_board);
+ session_log(s, "Created new board %ld: %s", new_board->id,
+ new_board->name);
+ free(board);
+ free(new_board);
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ found = false;
+ for (n = 0; n < db->nboards; n++) {
+ board = &db->boards[n];
+ if (board->id != c - '0')
+ continue;
+ found = true;
+ snprintf(prompt, sizeof(prompt), "Sysop:Boards:%ld",
+ board->id);
+ ret = struct_editor(s, board_fields, nboard_fields,
+ board, sizeof(struct board), (void *)&new_board,
+ "Edit Board", prompt);
+ if (ret != 0)
+ continue;
+ memcpy(&db->boards[n], new_board, sizeof(struct board));
+ if (bile_write(db->bile, DB_BOARD_RTYPE, new_board->id,
+ new_board, sizeof(struct board)) != sizeof(struct board))
+ panic("save of board %ld failed: %d",
+ new_board->id, bile_error(db->bile));
+ session_log(s, "Saved changes to board %ld: %s",
+ new_board->id, new_board->name);
+ free(new_board);
+ break;
+ }
+ if (!found) {
+ session_printf(s, "Invalid board ID\r\n");
+ session_flush(s);
+ }
+ break;
+ case '?':
+ show_help = true;
+ break;
+ default:
+ done = true;
+ break;
+ }
+ }
+}
--- sysop.h Sat May 14 19:48:01 2022
+++ sysop.h Sat May 14 19:48:01 2022
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2022 joshua stein <jcs@jcs.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef __SYSOP_H__
+#define __SYSOP_H__
+
+#include "subtext.h"
+#include "session.h"
+
+void sysop_menu(struct session *s);
+void sysop_edit_settings(struct session *s);
+
+#endif
--- user_settings.c Mon May 9 15:49:26 2022
+++ user_settings.c Sat May 14 21:49:20 2022
@@ -26,25 +26,10 @@
#include "user_settings.h"
#include "util.h"
-void user_settings_help(struct session *s);
void user_settings_renegotiate(struct session *s);
void user_settings_password(struct session *s);
void
-user_settings_help(struct session *s)
-{
- session_output_template(s,
- "{{B}}R{{/B}}: Renegotiate terminal\r\n");
-
- if (s->user)
- session_output_template(s, "{{B}}P{{/B}}: Change password\r\n");
-
- session_output_template(s,
- "{{B}}Q{{/B}}: Return to main menu\r\n");
- session_flush(s);
-}
-
-void
user_settings_renegotiate(struct session *s)
{
unsigned short c;
@@ -194,52 +179,35 @@ user_settings_password(struct session *s)
void
user_settings_menu(struct session *s)
{
+ static struct session_menu_option opts[] = {
+ { 'r', "Rr", "Renegotiate terminal" },
+ { 'p', "Pp", "Change password" },
+ { 'q', "QqXx", "Return to main menu" },
+ { '?', "?", "List menu options" },
+ };
+ char c;
+ bool show_help = true;
bool done = false;
- unsigned short c;
-
+
session_log(s, "User settings menu");
- session_output_template(s, "{{B}}Settings{{/B}}\r\n"
- "{{B}}--------{{/B}}\r\n");
- user_settings_help(s);
-
while (!done) {
- session_output_template(s, "{{B}}Settings>{{/B}} ");
- session_flush(s);
-
-get_another_char:
- c = session_input_char(s);
- if (s->ending)
- break;
- if (c == '\r' || c == 0 || c > 255)
- goto get_another_char;
-
- session_printf(s, "%c\r\n", c);
- session_flush(s);
+ c = session_menu(s, "Settings", "Settings", opts, nitems(opts),
+ show_help);
+ show_help = false;
switch (c) {
- case 'p':
- case 'P':
- user_settings_password(s);
- break;
- case 'q':
- case 'Q':
- case 'x':
- case 'X':
- done = true;
- break;
case 'r':
- case 'R':
user_settings_renegotiate(s);
break;
+ case 'p':
+ user_settings_password(s);
+ break;
case '?':
- case 'H':
- case 'h':
- user_settings_help(s);
+ show_help = true;
break;
default:
- session_output_string(s, "Invalid option\r\n");
- session_flush(s);
+ done = true;
break;
}
}