static void resize_curses_msgwin(struct gamewin *gw) { int linecount; char **lines; struct win_msgwin *wmw = (struct win_msgwin *)gw->extra; layout_curses_msgwin(wmw, &linecount, &lines, 1); free_wrap(lines); gw->win = newdialog(wmw->layout_height, wmw->layout_width, wmw->context == krc_notification ? 2 : 1, NULL); }
static void draw_curses_msgwin(struct gamewin *gw) { int i; int linecount; char **lines; struct win_msgwin *wmw = (struct win_msgwin *)gw->extra; layout_curses_msgwin(wmw, &linecount, &lines, 0); for (i = 0; i < linecount; i++) mvwaddstr(gw->win, 1 + i, 2, lines[i]); wnoutrefresh(gw->win); free_wrap(lines); }
int network_motd(void) { char errmsg[256]; char motdmsg[4096]; int fd = -1; if (settings.show_motd == MOTD_TRUE) { fd = connect_server(MOTD_SERVER, MOTD_PORT, FALSE, errmsg, sizeof errmsg); if (fd == -1) fd = connect_server(MOTD_SERVER, MOTD_PORT, TRUE, errmsg, sizeof errmsg); errmsg[sizeof errmsg - 1] = '\0'; if (fd == -1) { strcpy(motdmsg, "Could not connect to <" MOTD_SERVER "> to " "receive a Message of the Day: "); strcat(motdmsg, errmsg); } else { /* We want to receive until the connection closes (which causes either EPIPE on abnormal shutdown, or 0 on normal shutdown). So continue until we get an error message other than EINTR or the buffer fills (indicating a malicious connection; I'm not planning on sending malicious packets from motd.nethack4.org, especially as I wrote this code and so know it wouldn't work, but it's worth allowing for the possibility that someone else intercepts the connection). */ int recvlen = 0; int rv; while (recvlen < sizeof motdmsg && (((rv = recv(fd, motdmsg + recvlen, (sizeof motdmsg) - recvlen, 0))) > 0 || errno == EINTR)) recvlen += rv < 0 ? 0 : rv; if (recvlen >= sizeof motdmsg) recvlen = -1 + sizeof motdmsg; motdmsg[recvlen] = '\0'; } close(fd); } else if (settings.show_motd == MOTD_FALSE) { return 1; } else { /* It's a bad idea to do network connections without asking the user for permission first. (Arguably we could make an exception for connection-only mode, but that connects to localhost, which is not quite the same thing as connecting to the Internet, so I'd rather make absolutely sure we aren't doing connections unsolicited.) Note that nothing is sent (other than the fact that the connection exists); the nethack4 binary just creates the connection, then reads from it. */ strcpy(motdmsg, "The Message of the Day system connects to the " "Internet to receive gameplay tips and announcements (such " "as tournament information or release announcements). Do you " "want to turn it on? (You can change this later with the " "\x0enetwork_motd\x0f option.)"); } /* SI/SO in the output indicate bold text. This isn't implemented yet. Also strip out all other unprintable characters for security reasons. We just use the ASCII space-to-tilde range for printables; we're not expecting any control characters but SI/SO, not even newlines. */ char *f, *t; f = t = motdmsg; while (*f) { if (*f >= ' ' && *f <= '~') *(t++) = *f; f++; } *t = '\0'; int outcount; char **outlines; wrap_text(COLNO-6, motdmsg, &outcount, &outlines); struct nh_menulist menu; int i; init_menulist(&menu); for (i = 0; i < outcount; i++) add_menu_txt(&menu, outlines[i], MI_TEXT); free_wrap(outlines); if (settings.show_motd == MOTD_ASK) { add_menu_txt(&menu, "", MI_TEXT); add_menu_item(&menu, 1, "Yes, I'd like announcements and gameplay tips", 'y', FALSE); add_menu_item(&menu, 2, "No, please don't connect to the MotD server", 'n', FALSE); curses_display_menu(&menu, "Message of the Day", PICK_ONE, PLHINT_ANYWHERE, &i, curses_menu_callback); if (i == 1) { curses_set_option("networkmotd", (union nh_optvalue){.e = MOTD_TRUE});
static void curses_print_message_core(int turn, const char *msg, nh_bool canblock) { int hsize, vsize, maxlen; nh_bool died; if (!msghistory) alloc_hist_array(); if (turn != prevturn) start_of_turn_curline = last_redraw_curline = curline; if (turn < prevturn) /* going back in time can happen during replay */ prune_messages(turn); if (!*msg) return; /* empty message. done. */ if (action > prevaction) { /* re-enable output if it was stopped and start a new line */ stopprint = FALSE; newline(); } prevturn = turn; prevaction = action; store_message(turn, msg); if (stopprint) return; /* * generally we want to put as many messages on one line as possible to * maximize space usage. A new line is begun after each player turn or if * more() is called via pause_messages(). "You die" also deserves its own line. * * If the message area is only one line high, space for "--More--" must be * reserved at the end of the line, otherwise --More-- is shown on a new line. */ getmaxyx(msgwin, vsize, hsize); maxlen = hsize; if (maxlen >= COLNO) maxlen = COLNO - 1; if (vsize == 1) maxlen -= 8; /* for "--More--" */ died = !strncmp(msg, "You die", 7); if (strlen(msglines[curline]) + strlen(msg) + 1 < maxlen && !died) { if (msglines[curline][0]) strcat(msglines[curline], " "); strcat(msglines[curline], msg); } else { int idx, output_count; char **output; wrap_text(maxlen, msg, &output_count, &output); for (idx = 0; idx < output_count; idx++) { if (strlen(msglines[curline]) > 0) fresh_message_line(canblock); if (stopprint) break; /* may get set in more() */ strcpy(msglines[curline], output[idx]); } free_wrap(output); } draw_msgwin(); }