/****************************************************************************** * This file is part of TinTin++ * * * * Copyright 2004-2019 Igor van den Hoven * * * * TinTin++ 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 3 of the License, or * * (at your option) any later version. * * * * This program 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 TinTin++. If not, see https://www.gnu.org/licenses. * ******************************************************************************/ /****************************************************************************** * (T)he K(I)cki(N) (T)ickin D(I)kumud Clie(N)t * * * * coded by Igor van den Hoven 2004 * ******************************************************************************/ #include "tintin.h" int hex_digit(char *str) { if (isdigit((int) *str)) { return *str - '0'; } else { return toupper((int) *str) - 'A' + 10; } } unsigned long long hex_number_64bit(char *str) { unsigned long long len, mul, val = 0; for (len = 0 ; len < 16 ; len++) { if (!isxdigit((int) str[len])) { break; } } for (mul = 1 ; len > 0 ; mul *= 16) { val += mul * hex_digit(str + --len); } return val; } int hex_number_8bit(char *str) { int value = 0; if (str) { if (isdigit((int) *str)) { value += 16 * (*str - '0'); } else { value += 16 * (toupper((int) *str) - 'A' + 10); } str++; } if (str) { if (isdigit((int) *str)) { value += *str - '0'; } else { value += toupper((int) *str) - 'A' + 10; } str++; } return value; } int oct_number(char *str) { int value = 0; if (str) { if (isdigit((int) *str)) { value += 8 * (*str - '0'); } str++; } if (str) { if (isdigit((int) *str)) { value += *str - '0'; } str++; } return value; } int unicode_16_bit(char *str, char *out) { int val = 0; unsigned char *pto = (unsigned char *) out; if (isdigit((int) *str)) { val += 4096 * (*str - '0'); } else { val += 4096 * (toupper((int) *str) - 'A' + 10); } str++; if (isdigit((int) *str)) { val += 256 * (*str - '0'); } else { val += 256 * (toupper((int) *str) - 'A' + 10); } str++; if (isdigit((int) *str)) { val += 16 * (*str - '0'); } else { val += 16 * (toupper((int) *str) - 'A' + 10); } str++; if (isdigit((int) *str)) { val += (*str - '0'); } else { val += (toupper((int) *str) - 'A' + 10); } str++; if (val < 128) { *pto++ = val; *pto++ = 0; return 1; } else if (val < 4096) { *pto++ = 192 + val / 64; *pto++ = 128 + val % 64; *pto++ = 0; return 2; } else { *pto++ = 224 + val / 4096; *pto++ = 128 + val / 64 % 64; *pto++ = 128 + val % 64; *pto++ = 0; return 3; } } int unicode_21_bit(char *str, char *out) { int val = 0; unsigned char *pto = (unsigned char *) out; if (str) { if (isdigit((int) *str)) { val += 1048576 * (*str - '0'); } else { val += 1048576 * (toupper((int) *str) - 'A' + 10); } str++; } if (str) { if (isdigit((int) *str)) { val += 65536 * (*str - '0'); } else { val += 65536 * (toupper((int) *str) - 'A' + 10); } str++; } if (str) { if (isdigit((int) *str)) { val += 4096 * (*str - '0'); } else { val += 4096 * (toupper((int) *str) - 'A' + 10); } str++; } if (str) { if (isdigit((int) *str)) { val += 256 * (*str - '0'); } else { val += 256 * (toupper((int) *str) - 'A' + 10); } str++; } if (str) { if (isdigit((int) *str)) { val += 16 * (*str - '0'); } else { val += 16 * (toupper((int) *str) - 'A' + 10); } str++; } if (str) { if (isdigit((int) *str)) { val += (*str - '0'); } else { val += (toupper((int) *str) - 'A' + 10); } str++; } if (val < 128) { *pto++ = val; return 1; } else if (val < 4096) { *pto++ = 192 + val / 64; *pto++ = 128 + val % 64; *pto++ = 0; return 2; } else if (val < 65536) { *pto++ = 224 + val / 4096; *pto++ = 128 + val / 64 % 64; *pto++ = 128 + val % 64; *pto++ = 0; return 3; } else if (val < 1114112) { *pto++ = 240 + val / 262144; *pto++ = 128 + val / 4096 % 64; *pto++ = 128 + val / 64 % 64; *pto++ = 128 + val % 64; *pto++ = 0; return 4; } else { *pto++ = 239; *pto++ = 191; *pto++ = 189; *pto++ = 0; return 3; } } unsigned long long utime() { struct timeval now_time; gettimeofday(&now_time, NULL); if (gtd->utime >= now_time.tv_sec * 1000000ULL + now_time.tv_usec) { gtd->utime++; } else { gtd->utime = now_time.tv_sec * 1000000ULL + now_time.tv_usec; } return gtd->utime; } void seed_rand(struct session *ses, unsigned long long seed) { ses->rand = seed % 4294967291ULL; ses->rkey = seed % 5; } unsigned long long generate_rand(struct session *ses) { static unsigned long long primes[] = {26196137413795067, 1062272168593625449, 5189794811, 237506310434573, 212938855558633 }; if (ses->rkey % 3 == 1) { ses->rand += 316595909ULL + primes[++ses->rkey % 5]; } else { ses->rand += primes[++ses->rkey % 5]; } return (unsigned int) ses->rand; // ses->rand = (ses->rand + 260854879ULL) % 4294967291ULL; // return ses->rand % 1000000000ULL; } /* uint32_t lcg_rand(uint32_t *state) { return *state = (uint64_t)*state * 279470273u % 0xfffffffb; } ses->rand = 6364136223846793005ULL * ses->rand + 1ULL; return ses->rand; } */ char *capitalize(char *str) { static char outbuf[BUFFER_SIZE]; int cnt; for (cnt = 0 ; str[cnt] != 0 ; cnt++) { outbuf[cnt] = toupper((int) str[cnt]); } outbuf[cnt] = 0; return outbuf; } char *ntos(long long number) { static char outbuf[10][NUMBER_SIZE]; static int cnt; cnt = (cnt + 1) % 10; sprintf(outbuf[cnt], "%lld", number); return outbuf[cnt]; } char *indent_one(int len) { static char outbuf[10][STACK_SIZE]; static int cnt; cnt = (cnt + 1) % 10; memset(outbuf[cnt], ' ', UMAX(1, len)); outbuf[cnt][len] = 0; return outbuf[cnt]; } char *indent(int len) { static char outbuf[10][STACK_SIZE]; static int cnt; cnt = (cnt + 1) % 10; memset(outbuf[cnt], ' ', UMAX(1, len * 5)); outbuf[cnt][len * 5] = 0; return outbuf[cnt]; } int cat_sprintf(char *dest, char *fmt, ...) { char buf[STRING_SIZE]; int size; va_list args; va_start(args, fmt); size = vsprintf(buf, fmt, args); va_end(args); strcat(dest, buf); return size; } void ins_sprintf(char *dest, char *fmt, ...) { char buf[STRING_SIZE], tmp[STRING_SIZE]; va_list args; va_start(args, fmt); vsprintf(buf, fmt, args); va_end(args); strcpy(tmp, dest); strcpy(dest, buf); strcat(dest, tmp); } int str_suffix(char *str1, char *str2) { int len1, len2; len1 = strlen(str1); len2 = strlen(str2); if (len1 >= len2) { if (!strcasecmp(str1 + len1 - len2, str2)) { return FALSE; } } return TRUE; } void socket_printf(struct session *ses, size_t length, char *format, ...) { size_t size; char buf[STRING_SIZE]; va_list args; va_start(args, format); size = vsprintf(buf, format, args); va_end(args); if (size != length && HAS_BIT(ses->telopts, TELOPT_FLAG_DEBUG)) { tintin_printf(ses, "DEBUG TELNET: socket_printf size difference: %d vs %d", size, length); } if (HAS_BIT(ses->flags, SES_FLAG_CONNECTED)) { write_line_mud(ses, buf, length); } } void telnet_printf(struct session *ses, int length, char *format, ...) { size_t size; char buf[STRING_SIZE]; va_list args; va_start(args, format); size = vsprintf(buf, format, args); va_end(args); if (length != -1 && size != length && HAS_BIT(ses->telopts, TELOPT_FLAG_DEBUG)) { tintin_printf(ses, "DEBUG TELNET: telnet_printf size difference: %d vs %d", size, length); } if (HAS_BIT(ses->flags, SES_FLAG_CONNECTED)) { SET_BIT(ses->telopts, TELOPT_FLAG_TELNET); write_line_mud(ses, buf, size); DEL_BIT(ses->telopts, TELOPT_FLAG_TELNET); } }