comparison nnchat.c @ 268:d04ea4395e9e

Move username and password prompting into the Curses interface, also move Curses initialization to earlier phase.
author Matti Hamalainen <ccr@tnsp.org>
date Fri, 03 Jun 2011 12:48:46 +0300
parents 5175ed15ffa4
children 4d106ad65f26
comparison
equal deleted inserted replaced
267:5175ed15ffa4 268:d04ea4395e9e
342 } 342 }
343 343
344 return 0; 344 return 0;
345 } 345 }
346 346
347 347 enum {
348 void printMsgV(BOOL addStamp, BOOL logOnly, const char *fmt, va_list ap) 348 LOG_FILE = 1,
349 LOG_WINDOW = 2,
350 LOG_STAMP = 4
351 };
352
353 void printMsgV(int flags, const char *fmt, va_list ap)
349 { 354 {
350 char tmpStr[128], buf[8192]; 355 char tmpStr[128], buf[8192];
351 356
352 getTimeStamp(tmpStr, sizeof(tmpStr), "½17½[½11½%H:%M:%S½17½]½0½ "); 357 getTimeStamp(tmpStr, sizeof(tmpStr), "½17½[½11½%H:%M:%S½17½]½0½ ");
353 358
354 vsnprintf(buf, sizeof(buf), fmt, ap); 359 vsnprintf(buf, sizeof(buf), fmt, ap);
355 360
356 if (optLogFile) { 361 if (optLogFile && (flags & LOG_FILE)) {
357 if (addStamp) printFile(optLogFile, tmpStr); 362 if (flags & LOG_STAMP) printFile(optLogFile, tmpStr);
358 printFile(optLogFile, buf); 363 printFile(optLogFile, buf);
359 fflush(optLogFile); 364 fflush(optLogFile);
360 } 365 }
361 366
362 if (!optDaemon && !logOnly) { 367 if (!optDaemon && (flags & LOG_WINDOW)) {
363 if (addStamp) printWin(mainWin, tmpStr); 368 if (flags & LOG_STAMP) printWin(mainWin, tmpStr);
364 printWin(mainWin, buf); 369 printWin(mainWin, buf);
365 wrefresh(mainWin); 370 wrefresh(mainWin);
366 } 371 }
367 } 372 }
368 373
369 void printMsg(const char *fmt, ...) 374 void printMsg(const char *fmt, ...)
370 { 375 {
371 va_list ap; 376 va_list ap;
372 377
373 va_start(ap, fmt); 378 va_start(ap, fmt);
374 printMsgV(TRUE, FALSE, fmt, ap); 379 printMsgV(LOG_STAMP | LOG_WINDOW | LOG_FILE, fmt, ap);
375 va_end(ap); 380 va_end(ap);
376 } 381 }
377 382
378 void printMsgC(const char *fmt, ...) 383 void printMsgC(const char *fmt, ...)
379 { 384 {
380 va_list ap; 385 va_list ap;
381 386
382 va_start(ap, fmt); 387 va_start(ap, fmt);
383 printMsgV(FALSE, FALSE, fmt, ap); 388 printMsgV(LOG_WINDOW | LOG_FILE, fmt, ap);
384 va_end(ap); 389 va_end(ap);
385 } 390 }
386 391
387 void printMsgQ(BOOL logOnly, const char *fmt, ...) 392 void printMsgQ(BOOL logOnly, const char *fmt, ...)
388 { 393 {
389 va_list ap; 394 va_list ap;
390 395
391 va_start(ap, fmt); 396 va_start(ap, fmt);
392 printMsgV(TRUE, logOnly, fmt, ap); 397 printMsgV(logOnly ? (LOG_STAMP | LOG_FILE) : (LOG_STAMP | LOG_WINDOW | LOG_FILE), fmt, ap);
393 va_end(ap); 398 va_end(ap);
394 } 399 }
395 400
396 401
397 char *errorMessages = NULL; 402 char *errorMessages = NULL;
400 { 405 {
401 char *tmp; 406 char *tmp;
402 va_list ap2; 407 va_list ap2;
403 408
404 va_copy(ap2, ap); 409 va_copy(ap2, ap);
405 printMsgV(TRUE, FALSE, fmt, ap); 410 printMsgV(LOG_STAMP | LOG_WINDOW | LOG_FILE, fmt, ap);
406 411
407 tmp = th_strdup_vprintf(fmt, ap2); 412 tmp = th_strdup_vprintf(fmt, ap2);
408 413
409 if (errorMessages != NULL) { 414 if (errorMessages != NULL) {
410 char *tmp2 = th_strdup_printf("%s%s", errorMessages, tmp); 415 char *tmp2 = th_strdup_printf("%s%s", errorMessages, tmp);
431 } 436 }
432 437
433 void messageFunc(struct _nn_conn_t *conn, const char *fmt, va_list ap) 438 void messageFunc(struct _nn_conn_t *conn, const char *fmt, va_list ap)
434 { 439 {
435 (void) conn; 440 (void) conn;
436 printMsgV(TRUE, FALSE, fmt, ap); 441 printMsgV(LOG_STAMP | LOG_WINDOW | LOG_FILE, fmt, ap);
437 } 442 }
438 443
439 444
440 BOOL checkIgnoreList(const char *name) 445 BOOL checkIgnoreList(const char *name)
441 { 446 {
1022 fclose(optLogFile); 1027 fclose(optLogFile);
1023 optLogFile = NULL; 1028 optLogFile = NULL;
1024 } 1029 }
1025 } 1030 }
1026 1031
1027 char *promptRequester(const char *info, BOOL allowEmpty) 1032 char *promptRequester(WINDOW *win, const char *info, BOOL allowEmpty)
1028 { 1033 {
1029 char tmpBuf[512], *ptr; 1034 char tmpBuf[512], *ptr;
1030 ssize_t pos; 1035 ssize_t pos;
1031 1036
1032 fputs(info, stdout); 1037 waddstr(win, info);
1033 fgets(tmpBuf, sizeof(tmpBuf), stdin); 1038 wgetnstr(win, tmpBuf, sizeof(tmpBuf) - 1);
1034 1039
1035 for (pos = strlen(tmpBuf) - 1; pos > 0 && (tmpBuf[pos] == '\n' || tmpBuf[pos] == '\r' || th_isspace(tmpBuf[pos])); pos--) 1040 for (pos = strlen(tmpBuf) - 1; pos > 0 && (tmpBuf[pos] == '\n' || tmpBuf[pos] == '\r' || th_isspace(tmpBuf[pos])); pos--)
1036 tmpBuf[pos] = 0; 1041 tmpBuf[pos] = 0;
1037 1042
1038 ptr = trimLeft(tmpBuf); 1043 ptr = trimLeft(tmpBuf);
1139 if (optUserNameCmd != NULL) { 1144 if (optUserNameCmd != NULL) {
1140 optUserName = optUserNameCmd; 1145 optUserName = optUserNameCmd;
1141 optPassword = optPasswordCmd; 1146 optPassword = optPasswordCmd;
1142 } 1147 }
1143 1148
1144 /* Check if we have username and password */
1145 if (optUserName == NULL || optPassword == NULL) {
1146 printf("\nYou can avoid this prompt by issuing '/save' after logging in.\n\n");
1147 optUserName = promptRequester("NN username: ", FALSE);
1148 optPassword = promptRequester("NN password: ", TRUE);
1149 if (optUserName == NULL || optPassword == NULL) {
1150 THERR("User/pass not specified, get some --help\n");
1151 return -1;
1152 }
1153 }
1154
1155 if (!argsOK) 1149 if (!argsOK)
1156 return -2; 1150 return -2;
1157 1151
1158 /* Allocate userhash */ 1152 /* Allocate userhash */
1159 if ((nnUsers = nn_userhash_new()) == NULL) { 1153 if ((nnUsers = nn_userhash_new()) == NULL) {
1174 THERR("Could not initialize network subsystem.\n"); 1168 THERR("Could not initialize network subsystem.\n");
1175 goto err_exit; 1169 goto err_exit;
1176 } else 1170 } else
1177 networkInit = TRUE; 1171 networkInit = TRUE;
1178 1172
1179 /* Okay ... */
1180 THMSG(1, "Trying to resolve host '%s' ...\n", optServer);
1181 tmpHost = gethostbyname(optServer);
1182 if (tmpHost == NULL) {
1183 THERR("Could not resolve hostname: %s.\n", strerror(h_errno));
1184 goto err_exit;
1185 }
1186 THMSG(2, "True hostname: %s\n", tmpHost->h_name);
1187
1188 /* To emulate the official client, we first make a request for
1189 * policy file, even though we don't use it for anything...
1190 */
1191 conn = nn_conn_open((struct in_addr *) tmpHost->h_addr, 843);
1192 if (!nn_conn_check(conn)) {
1193 THERR("Policy file request connection setup failed!\n");
1194 goto err_exit;
1195 }
1196
1197 tmpStr = "<policy-file-request/>";
1198 if (nn_conn_send_buf(conn, tmpStr, strlen(tmpStr) + 1) == FALSE) {
1199 THERR("Failed to send policy file request.\n");
1200 goto err_exit;
1201 } else {
1202 int cres = nn_conn_pull(conn);
1203 if (cres == 0) {
1204 THMSG(2, "Probe got: %s\n", conn->buf);
1205 } else {
1206 THMSG(2, "Could not get policy probe.\n");
1207 }
1208 }
1209 nn_conn_close(conn);
1210
1211 /* Okay, now do the proper connection ... */
1212 conn = nn_conn_open((struct in_addr *) tmpHost->h_addr, optPort);
1213 if (!nn_conn_check(conn)) {
1214 THERR("Main connection setup failed!\n");
1215 goto err_exit;
1216 }
1217
1218 conn->errfunc = errorFunc;
1219 conn->msgfunc = messageFunc;
1220
1221 THMSG(1, "Connected, logging in as '%s', site '%s'.\n", optUserName, optSite);
1222 optUserNameEnc = nn_dblencode_str(optUserName);
1223 tmpStr = nn_dblencode_str(optSite);
1224 nn_conn_send_msg(conn, optUserNameEnc, "%%2Flogin%%20%%2Dsite%%20%s%%20%%2Dpassword%%20%s", tmpStr, optPassword);
1225 th_free(tmpStr);
1226
1227 /* Initialize NCurses */ 1173 /* Initialize NCurses */
1228 if (!optDaemon) { 1174 if (!optDaemon) {
1229 if (LINES < 0 || LINES > 1000) LINES = 24; 1175 if (LINES < 0 || LINES > 1000) LINES = 24;
1230 if (COLS < 0 || COLS > 1000) COLS = 80; 1176 if (COLS < 0 || COLS > 1000) COLS = 80;
1231 initscr(); 1177 initscr();
1232 raw(); 1178 raw();
1233 keypad(stdscr, TRUE); 1179 keypad(stdscr, TRUE);
1234 noecho(); 1180 echo();
1235 meta(stdscr, TRUE); 1181 meta(stdscr, TRUE);
1236 timeout(SET_DELAY); 1182 timeout(SET_DELAY);
1237 curVis = curs_set(0); 1183 curVis = curs_set(1);
1238 1184
1239 if (has_colors()) { 1185 if (has_colors()) {
1240 start_color(); 1186 start_color();
1241 1187
1242 init_pair( 1, COLOR_RED, COLOR_BLACK); 1188 init_pair( 1, COLOR_RED, COLOR_BLACK);
1260 cursesInit = TRUE; 1206 cursesInit = TRUE;
1261 1207
1262 if (!initializeWindows()) 1208 if (!initializeWindows())
1263 goto err_exit; 1209 goto err_exit;
1264 1210
1211 updateStatus(insertMode);
1212 }
1213
1214 /* Check if we have username and password */
1215 if (cursesInit && (optUserName == NULL || optPassword == NULL)) {
1216 printWin(editWin, "You can avoid this prompt by issuing '/save' after logging in.\n");
1217 optUserName = promptRequester(editWin, "NN username: ", FALSE);
1218 optPassword = promptRequester(editWin, "NN password: ", TRUE);
1219 }
1220
1221 if (optUserName == NULL || optPassword == NULL) {
1222 errorMsg("Username and/or password not specified.\n");
1223 goto err_exit;
1224 }
1225
1226 /* Okay ... */
1227 printMsg("Trying to resolve host '%s' ...\n", optServer);
1228 tmpHost = gethostbyname(optServer);
1229 if (tmpHost == NULL) {
1230 errorMsg("Could not resolve hostname: %s.\n", strerror(h_errno));
1231 goto err_exit;
1232 }
1233 printMsg("True hostname: %s\n", tmpHost->h_name);
1234
1235 /* To emulate the official client, we first make a request for
1236 * policy file, even though we don't use it for anything...
1237 */
1238 conn = nn_conn_open((struct in_addr *) tmpHost->h_addr, 843);
1239 if (!nn_conn_check(conn)) {
1240 errorMsg("Policy file request connection setup failed!\n");
1241 goto err_exit;
1242 }
1243
1244 tmpStr = "<policy-file-request/>";
1245 if (nn_conn_send_buf(conn, tmpStr, strlen(tmpStr) + 1) == FALSE) {
1246 errorMsg("Failed to send policy file request.\n");
1247 goto err_exit;
1248 } else {
1249 int cres = nn_conn_pull(conn);
1250 if (cres == 0) {
1251 printMsg("Probe got: %s\n", conn->buf);
1252 } else {
1253 printMsg("Could not get policy probe.\n");
1254 }
1255 }
1256 nn_conn_close(conn);
1257
1258 /* Okay, now do the proper connection ... */
1259 conn = nn_conn_open((struct in_addr *) tmpHost->h_addr, optPort);
1260 if (!nn_conn_check(conn)) {
1261 errorMsg("Main connection setup failed!\n");
1262 goto err_exit;
1263 }
1264
1265 conn->errfunc = errorFunc;
1266 conn->msgfunc = messageFunc;
1267
1268 /* Log in */
1269 optUserNameEnc = nn_dblencode_str(optUserName);
1270 tmpStr = nn_dblencode_str(optSite);
1271 nn_conn_send_msg(conn, optUserNameEnc, "%%2Flogin%%20%%2Dsite%%20%s%%20%%2Dpassword%%20%s", tmpStr, optPassword);
1272 th_free(tmpStr);
1273
1274 /* Initialize random numbers */
1275 prevTime = time(NULL);
1276 srandom((int) prevTime);
1277
1278 if (cursesInit) {
1279 noecho();
1280 curVis = curs_set(0);
1265 nn_editbuf_clear(editBuf); 1281 nn_editbuf_clear(editBuf);
1266 printEditBuf("", editBuf); 1282 printEditBuf("", editBuf);
1267 updateStatus(insertMode); 1283 updateStatus(insertMode);
1268 } 1284 }
1269
1270 /* Initialize random numbers */
1271 prevTime = time(NULL);
1272 srandom((int) prevTime);
1273 1285
1274 /* Enter mainloop */ 1286 /* Enter mainloop */
1275 while (!isError && !exitProg) { 1287 while (!isError && !exitProg) {
1276 int cres = nn_conn_pull(conn); 1288 int cres = nn_conn_pull(conn);
1277 if (cres == 0) { 1289 if (cres == 0) {
1588 nn_ringbuf_free(backBuf); 1600 nn_ringbuf_free(backBuf);
1589 nn_editbuf_free(editBuf); 1601 nn_editbuf_free(editBuf);
1590 for (histPos = 0; histPos <= SET_MAX_HISTORY; histPos++) 1602 for (histPos = 0; histPos <= SET_MAX_HISTORY; histPos++)
1591 nn_editbuf_free(histBuf[histPos]); 1603 nn_editbuf_free(histBuf[histPos]);
1592 1604
1605 #ifdef __WIN32
1606 if (errorMessages || isError) {
1607 char *tmp = promptRequester(editWin, "Press enter to quit.\n", FALSE);
1608 th_free(tmp);
1609 }
1610 #endif
1611
1593 if (cursesInit) { 1612 if (cursesInit) {
1594 if (curVis != ERR) 1613 if (curVis != ERR)
1595 curs_set(curVis); 1614 curs_set(curVis);
1596 closeWindows(); 1615 closeWindows();
1597 endwin(); 1616 endwin();
1598 THMSG(1, "NCurses deinitialized.\n"); 1617 THMSG(1, "NCurses deinitialized.\n");
1599 } 1618 }
1600 1619
1620 #ifndef __WIN32
1601 if (errorMessages) 1621 if (errorMessages)
1602 THERR("%s", errorMessages); 1622 THERR("%s", errorMessages);
1603
1604 if (isError) {
1605 #ifdef __WIN32
1606 char *tmp = promptRequester("Press enter to quit.\n", FALSE);
1607 th_free(tmp);
1608 #else
1609 THMSG(1, "Error exit.\n");
1610 #endif 1623 #endif
1611 }
1612 1624
1613 th_free(optUserNameEnc); 1625 th_free(optUserNameEnc);
1614 1626
1615 nn_conn_close(conn); 1627 nn_conn_close(conn);
1616 1628