/***************************************************************************** * * $Id: input.c,v 1.29 2007/08/25 18:32:08 mbse Exp $ * Purpose ...............: Input functions, also for some utils. * ***************************************************************************** * Copyright (C) 1997-2007 * * Michiel Broek FIDO: 2:280/2802 * Beekmansbos 10 * 1971 BV IJmuiden * the Netherlands * * This file is part of MBSE BBS. * * This BBS is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2, or (at your option) any * later version. * * MBSE BBS is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with MBSE BBS; see the file COPYING. If not, write to the Free * Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *****************************************************************************/ #include "../config.h" #include "../lib/mbselib.h" #include "../lib/mbse.h" #include "../lib/users.h" #include "input.h" #include "timeout.h" #include "language.h" #include "term.h" #include "ttyio.h" extern int cols; extern int rows; void CheckScreen(void) { struct winsize ws; if (ioctl(1, TIOCGWINSZ, &ws) != -1 && (ws.ws_col > 0) && (ws.ws_row > 0)) { if (ws.ws_col != 80) ws.ws_col = 80; if (ws.ws_row < 24) ws.ws_row = 24; if ((ws.ws_col != cols) || (ws.ws_row != rows)) { cols = ws.ws_col; rows = ws.ws_row; Syslog('+', "User screensize changed to %dx%d", cols, rows); } } } /* * Wait for a character for a maximum of wtime * 10 mSec. */ int Waitchar(unsigned char *ch, int wtime) { int i, rc = TIMEOUT; for (i = 0; i < wtime; i++) { CheckScreen(); rc = GETCHAR(0); if (tty_status == STAT_SUCCESS) { *ch = (unsigned char)rc; return 1; } if (tty_status != STAT_TIMEOUT) { return rc; } msleep(10); } return rc; } int Escapechar(unsigned char *ch) { int rc; unsigned char c; /* * Escape character, if nothing follows within * 50 mSec, the user really pressed . */ if ((rc = Waitchar(ch, 5)) == TIMEOUT) { return rc; } if (*ch == '[') { /* * Start of CSI sequence. If nothing follows, * return immediatly. */ if ((rc = Waitchar(ch, 5)) == TIMEOUT) { return rc; } /* * Test for the most important keys. Note * that only the cursor movement keys are * guaranteed to work with PC-clients. */ c = *ch; if (c == 'A') c = KEY_UP; else if (c == 'B') c = KEY_DOWN; else if (c == 'C') c = KEY_RIGHT; else if (c == 'D') c = KEY_LEFT; else if ((c == 'H') || (c == 0)) c = KEY_HOME; else if ((c == '4') || (c == 'K') || (c == 'F') || (c == 101) || (c == 144)) c = KEY_END; else if ((c == '2') || (c == 'L')) { Waitchar(ch, 5); /* Eat following ~ char */ c = KEY_INS; } else if (c == '3') { Waitchar(ch, 5); /* Eat following ~ char */ c = KEY_DEL; } else if ((c == '5') || (c == 'I')) { Waitchar(ch, 5); /* Eat following ~ char */ c = KEY_PGUP; } else if ((c == '6') || (c == 'G')) { Waitchar(ch, 5); /* Eat following ~ char */ c = KEY_PGDN; } else if (c == '1') { if ((rc = Waitchar(ch, 5)) == TIMEOUT) { c = KEY_HOME; } else { c = *ch; Waitchar(ch, 5); /* Eat following ~ char */ switch (c) { case '1' : c = KEY_F1; break; case '2' : c = KEY_F2; break; case '3' : c = KEY_F3; break; case '4' : c = KEY_F4; break; case '5' : c = KEY_F5; break; case '7' : c = KEY_F6; break; case '8' : c = KEY_F7; break; case '9' : c = KEY_F8; break; } } } memcpy(ch, &c, sizeof(unsigned char)); return rc; } return -1; } /* * This next function will detect the grey keys on the keyboard for * VT100, VT220, Xterm, PC-ANSI, and Linux console. Works with * several terminals on serial lines (tested 1200 bps). * If for example cursur keys are detected, this function returns * a translated value. */ unsigned char Readkey(void) { unsigned char ch = 0; int rc = TIMEOUT; while (rc == TIMEOUT) { rc = Waitchar(&ch, 5); /* * If the character is not an Escape character, * then this function is finished. */ if ((rc == 1) && (ch != KEY_ESCAPE)) { return ch; } if ((rc == 1) && (ch == KEY_ESCAPE)) { rc = Escapechar(&ch); if (rc == 1) { return ch; } else { return KEY_ESCAPE; } } } return rc; } /* * Read the (locked) speed from the tty */ int Speed(void) { speed_t mspeed; mspeed = cfgetospeed(&tbufs); #ifdef CBAUD switch (mspeed & CBAUD) { #else switch (mspeed) { #endif case B0: return 0; #if defined(B50) case B50: return 50; #endif #if defined(B75) case B75: return 75; #endif #if defined(B110) case B110: return 110; #endif #if defined(B134) case B134: return 134; #endif #if defined(B150) case B150: return 150; #endif #if defined(B200) case B200: return 200; #endif #if defined(B300) case B300: return 300; #endif #if defined(B600) case B600: return 600; #endif #if defined(B1200) case B1200: return 1200; #endif #if defined(B1800) case B1800: return 1800; #endif #if defined(B2400) case B2400: return 2400; #endif #if defined(B4800) case B4800: return 4800; #endif #if defined(B9600) case B9600: return 9600; #endif #if defined(B19200) case B19200: return 19200; #endif #if defined(B38400) case B38400: return 38400; #endif #if defined(B57600) case B57600: return 57600; #endif #if defined(B115200) case B115200: return 115200; #endif #if defined(B230400) case B230400: return 203400; #endif #if defined(B460800) case B460800: return 460800; #endif #if defined(B500000) case B500000: return 500000; #endif #if defined(B576000) case B576000: return 576000; #endif #if defined(B921600) case B921600: return 921600; #endif #if defined(B1000000) case B1000000: return 1000000; #endif #if defined(B1152000) case B1152000: return 1152000; #endif #if defined(B1500000) case B1500000: return 1500000; #endif #if defined(B2000000) case B2000000: return 2000000; #endif #if defined(B2500000) case B2500000: return 2500000; #endif #if defined(B3000000) case B3000000: return 3000000; #endif #if defined(B3500000) case B3500000: return 3500000; #endif #if defined(B4000000) case B4000000: return 4000000; #endif default: return 9600; } } int traduce(char *ch) { int i; for (i = 0; i < 81; i++){ if ( Language(35)[i] == '\0' ) break; if ( *ch == Language(35)[i] ){ if ( Language(36)[i] != '\0'){ *ch = ( Language(36)[i] ); } return TRUE; } } for (i = 0; i < 81; i++){ if ( Language(33)[i] == '\0' ) break; if ( *ch == Language(33)[i] ){ if ( Language(34)[i] != '\0'){ *ch = ( Language(34)[i] ); } return TRUE; } } return FALSE; } void BackErase(void) { PUTCHAR('\b'); PUTCHAR(' '); PUTCHAR('\b'); } /* * Get a character string with cursor position */ void GetstrP(char *sStr, int iMaxLen, int Position) { unsigned char ch = 0; int iPos = Position; FLUSHIN(); alarm_on(); while (ch != KEY_ENTER) { ch = Readkey(); if ((ch == KEY_BACKSPACE) || (ch == KEY_DEL) || (ch == KEY_RUBOUT)) { if (iPos > 0) { BackErase(); sStr[--iPos] = '\0'; } else PUTCHAR('\007'); /* if 13 < DEL < 127 , should not output again */ } else if ((ch > 31 && ch < 127) || traduce((char *)&ch)) { if (iPos <= iMaxLen) { iPos++; snprintf(sStr + strlen(sStr), 5, "%c", ch); PUTCHAR(ch); } else { PUTCHAR('\007'); } } } PUTCHAR('\r'); PUTCHAR('\n'); } /* * Get a character string */ void GetstrC(char *sStr, int iMaxlen) { unsigned char ch = 0; int iPos = 0; FLUSHIN(); strcpy(sStr, ""); alarm_on(); while (ch != 13) { ch = Readkey(); if ((ch == 8) || (ch == KEY_DEL) || (ch == 127)) { if (iPos > 0) { BackErase(); sStr[--iPos] = '\0'; } else PUTCHAR('\007'); } if ((ch > 31) && (ch < 127)) { if (iPos <= iMaxlen) { iPos++; snprintf(sStr + strlen(sStr), 5, "%c", ch); PUTCHAR(ch); } else PUTCHAR('\007'); } } PUTCHAR('\r'); PUTCHAR('\n'); } /* * get a string, don't allow spaces (for Unix accounts) */ void GetstrU(char *sStr, int iMaxlen) { unsigned char ch = 0; int iPos = 0; FLUSHIN(); strcpy(sStr, ""); alarm_on(); while (ch != 13) { ch = Readkey(); if ((ch == 8) || (ch == KEY_DEL) || (ch == 127)) { if (iPos > 0) { BackErase(); sStr[--iPos] = '\0'; } else PUTCHAR('\007'); } if (isalnum(ch) || (ch == '@') || (ch == '.') || (ch == '-') || (ch == '_')) { if (iPos <= iMaxlen) { iPos++; snprintf(sStr + strlen(sStr), 5, "%c", ch); PUTCHAR(ch); } else PUTCHAR('\007'); } } PUTCHAR('\r'); PUTCHAR('\n'); } /* * Get a phone number, only allow digits, + and - characters. */ void GetPhone(char *sStr, int iMaxlen) { unsigned char ch = 0; int iPos = 0; FLUSHIN(); strcpy(sStr, ""); alarm_on(); while (ch != 13) { ch = Readkey(); if ((ch == 8) || (ch == KEY_DEL) || (ch == 127)) { if (iPos > 0) { BackErase(); sStr[--iPos]='\0'; } else PUTCHAR('\007'); } if ((ch >= '0' && ch <= '9') || (ch == '-') || (ch == '+')) { if (iPos <= iMaxlen) { iPos++; snprintf(sStr + strlen(sStr), 5, "%c", ch); PUTCHAR(ch); } else PUTCHAR('\007'); } } PUTCHAR('\r'); PUTCHAR('\n'); } /* * Get a number, allow digits, spaces, minus sign, points and comma's */ void Getnum(char *sStr, int iMaxlen) { unsigned char ch = 0; int iPos = 0; FLUSHIN(); strcpy(sStr, ""); alarm_on(); while (ch != 13) { ch = Readkey(); if ((ch == 8) || (ch == KEY_DEL) || (ch == 127)) { if (iPos > 0) { BackErase(); sStr[--iPos]='\0'; } else PUTCHAR('\007'); } if ((ch >= '0' && ch <= '9') || (ch == '-') || (ch == ' ') || (ch == ',') || (ch == '.')) { if (iPos <= iMaxlen) { iPos++; snprintf(sStr + strlen(sStr), 5, "%c", ch); PUTCHAR(ch); } else PUTCHAR('\007'); } } PUTCHAR('\r'); PUTCHAR('\n'); } /* * This function gets the date from the user checking the length and * putting two minus signs in the right places */ void GetDate(char *sStr, int iMaxlen) { unsigned char ch = 0; int iPos = 0; FLUSHIN(); strcpy(sStr, ""); alarm_on(); while (ch != 13) { ch = Readkey(); if ((ch == 8) || (ch == KEY_DEL) || (ch == 127)) { if (iPos > 0) BackErase(); else PUTCHAR('\007'); if (iPos == 3 || iPos == 6) { BackErase(); --iPos; } sStr[--iPos]='\0'; } if (ch >= '0' && ch <= '9') { if (iPos < iMaxlen) { iPos++; snprintf(sStr + strlen(sStr), 5, "%c", ch); PUTCHAR(ch); if (iPos == 2 || iPos == 5) { PUTCHAR('-'); snprintf(sStr + strlen(sStr), 2, "-"); iPos++; } } else PUTCHAR('\007'); } } PUTCHAR('\r'); PUTCHAR('\n'); } /* * Get a string, capitalize only if set in config. */ void Getname(char *sStr, int iMaxlen) { unsigned char ch = 0; int iPos = 0, iNewPos = 0; fflush(stdout); strcpy(sStr, ""); alarm_on(); while (ch != 13) { fflush(stdout); ch = Readkey(); if ((ch == 8) || (ch == KEY_DEL) || (ch == 127)) { if (iPos > 0) { printf("\b \b"); sStr[--iPos]='\0'; } else putchar('\007'); } if (ch > 31 && (ch < 127)) { if (iPos < iMaxlen) { iPos++; if (iPos == 1 && CFG.iCapUserName) ch = toupper(ch); if (ch == 32) { iNewPos = iPos; iNewPos++; } if (iNewPos == iPos && CFG.iCapUserName) ch = toupper(ch); else if (CFG.iCapUserName) ch = tolower(ch); if (iPos == 1 && CFG.iCapUserName) ch = toupper(ch); snprintf(sStr + strlen(sStr), 5, "%c", ch); printf("%c", ch); } else putchar('\007'); } } printf("\n"); } /* * Get a Fidonet style username, always capitalize. * Also used for Location Names. */ void GetnameNE(char *sStr, int iMaxlen) { unsigned char ch = 0; int iPos = 0, iNewPos = 0; fflush(stdout); strcpy(sStr, ""); alarm_on(); while (ch != 13) { fflush(stdout); ch = Readkey(); if ((ch == 8) || (ch == KEY_DEL) || (ch == 127)) { if (iPos > 0) { printf("\b \b"); sStr[--iPos]='\0'; } else putchar('\007'); } if ((ch > 31) && (ch < 127)) { if (iPos < iMaxlen) { iPos++; if (iPos == 1) ch = toupper(ch); if (ch == 32) { iNewPos = iPos; iNewPos++; } if (iNewPos == iPos) ch = toupper(ch); else ch = tolower(ch); if (iPos == 1) ch = toupper(ch); snprintf(sStr + strlen(sStr), 5, "%c", ch); printf("%c", ch); } else putchar('\007'); } } printf("\n"); } /* * Open up /dev/tty to get the password from the user * because this is done in raw mode, it makes life a bit * more difficult. * This function gets a password from a user, upto Max_passlen */ void Getpass(char *theword) { unsigned char c = 0; int counter = 0; char password[Max_passlen+1]; alarm_on(); /* * Till the user presses ENTER or reaches the maximum length allowed */ while ((c != 13) && (counter < Max_passlen )) { fflush(stdout); c = Readkey(); /* Reads a character from the raw device */ if (((c == 8) || (c == KEY_DEL) || (c == 127)) && (counter != 0 )) { /* If its a BACKSPACE */ counter--; password[counter] = '\0'; printf("\x008 \x008"); continue; } /* Backtrack to fix the BACKSPACE */ if (((c == 8) || (c == KEY_DEL) || (c == 127)) && (counter == 0) ) { printf("\x007"); continue; } /* Don't Backtrack as we are at the begining of the passwd field */ if (((isalnum(c)) || (ispunct(c)))) { password[counter] = c; counter++; printf("%c", CFG.iPasswd_Char); } /* Allow alphanumeric and punctuation, but not CTRL characters or spaces */ } password[counter] = '\0'; /* Make sure the string has a NULL at the end */ strcpy(theword,password); } void Pause() { int i, x; char *string; string = malloc(81); /* Press (Enter) to continue: */ snprintf(string, 81, "\r%s", (char *) Language(375)); colour(CFG.CRColourF, CFG.CRColourB); PUTSTR(string); do { alarm_on(); i = Readkey(); } while ((i != '\r') && (i != '\n')); x = strlen(string); for(i = 0; i < x; i++) PUTCHAR('\b'); for(i = 0; i < x; i++) PUTCHAR(' '); for(i = 0; i < x; i++) PUTCHAR('\b'); free(string); }