5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2005 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; version 2 of the License.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
20 * These are general utility functions that doesn't belong to any specific
27 /* Gets line from a buffer. Stops reading when a newline or EOF occurs.
28 This doesn't remove the newline sign from the destination buffer. The
29 argument begin is returned and should be passed again for the function. */
31 int silc_gets(char *dest, int destlen, const char *src, int srclen, int begin)
36 memset(dest, 0, destlen);
42 for ( ; start <= srclen; i++, start++) {
59 /* Checks line for illegal characters. Return -1 when illegal character
60 were found. This is used to check for bad lines when reading data from
61 for example a configuration file. */
63 int silc_check_line(char *buf)
65 /* Illegal characters in line */
66 if (strchr(buf, '#')) return -1;
67 if (strchr(buf, '\'')) return -1;
68 if (strchr(buf, '\\')) return -1;
69 if (strchr(buf, '\r')) return -1;
70 if (strchr(buf, '\a')) return -1;
71 if (strchr(buf, '\b')) return -1;
72 if (strchr(buf, '\f')) return -1;
81 /* Returns time as string. If the the `timeval' is non-zero that
82 value is returned as string. If it is zero the current time of the
83 local machine is returned. */
85 const char *silc_get_time(SilcUInt32 timeval)
93 curtime = (time_t)timeval;
94 return_time = ctime(&curtime);
95 return_time[strlen(return_time) - 1] = '\0';
97 return (const char *)return_time;
100 /* Converts string to capital characters. */
102 SilcBool silc_to_upper(const char *string, char *dest, SilcUInt32 dest_size)
106 if (strlen(string) > dest_size)
109 for (i = 0; i < strlen(string); i++)
110 dest[i] = toupper(string[i]);
115 /* Converts string to lower letter characters. */
117 SilcBool silc_to_lower(const char *string, char *dest, SilcUInt32 dest_size)
121 if (strlen(string) > dest_size)
124 for (i = 0; i < strlen(string); i++)
125 dest[i] = tolower(string[i]);
130 /* Parse userfqdn string which is in user@fqdn format. */
132 int silc_parse_userfqdn(const char *string,
133 char *user, SilcUInt32 user_size,
134 char *fqdn, SilcUInt32 fqdn_size)
138 if (!string || (!user && !fqdn))
141 if (string[0] == '@') {
143 memset(user, 0, user_size);
144 silc_strncat(user, user_size, string, strlen(string));
150 if (strchr(string, '@')) {
151 tlen = strcspn(string, "@");
154 memset(user, 0, user_size);
155 silc_strncat(user, user_size, string, tlen);
159 memset(fqdn, 0, fqdn_size);
160 silc_strncat(fqdn, fqdn_size, string + tlen + 1,
161 strlen(string) - tlen - 1);
168 memset(user, 0, user_size);
169 silc_strncat(user, user_size, string, strlen(string));
175 /* Parses command line. At most `max_args' is taken. Rest of the line
176 will be allocated as the last argument if there are more than `max_args'
177 arguments in the line. Note that the command name is counted as one
178 argument and is saved. */
180 void silc_parse_command_line(unsigned char *buffer,
181 unsigned char ***parsed,
182 SilcUInt32 **parsed_lens,
183 SilcUInt32 **parsed_types,
184 SilcUInt32 *parsed_num,
189 const char *cp = buffer;
192 *parsed = silc_calloc(1, sizeof(**parsed));
193 *parsed_lens = silc_calloc(1, sizeof(**parsed_lens));
195 /* Get the command first */
196 len = strcspn(cp, " ");
197 tmp = silc_calloc(strlen(cp) + 1, sizeof(*tmp));
200 silc_to_upper(cp, tmp, strlen(cp));
201 (*parsed)[0] = silc_calloc(len + 1, sizeof(char));
202 memcpy((*parsed)[0], tmp, len);
204 (*parsed_lens)[0] = len;
210 /* Parse arguments */
211 if (strchr(cp, ' ') || strlen(cp) != 0) {
212 for (i = 1; i < max_args; i++) {
214 if (i != max_args - 1)
215 len = strcspn(cp, " ");
218 while (len && cp[len - 1] == ' ')
223 *parsed = silc_realloc(*parsed, sizeof(**parsed) * (argc + 1));
224 *parsed_lens = silc_realloc(*parsed_lens,
225 sizeof(**parsed_lens) * (argc + 1));
226 (*parsed)[argc] = silc_calloc(len + 1, sizeof(char));
227 memcpy((*parsed)[argc], cp, len);
228 (*parsed_lens)[argc] = len;
240 /* Save argument types. Protocol defines all argument types but
241 this implementation makes sure that they are always in correct
242 order hence this simple code. */
243 *parsed_types = silc_calloc(argc, sizeof(**parsed_types));
244 for (i = 0; i < argc; i++)
245 (*parsed_types)[i] = i;
250 /* Formats arguments to a string and returns it after allocating memory
251 for it. It must be remembered to free it later. */
253 char *silc_format(char *fmt, ...)
258 memset(buf, 0, sizeof(buf));
260 vsnprintf(buf, sizeof(buf) - 1, fmt, args);
266 /* Renders ID to suitable to print for example to log file. */
268 static char rid[256];
269 #define _PUT_STRING(__d__, __s__) \
271 int __sp = sizeof(__d__) - 1 - strlen(__d__); \
272 if (__sp < strlen(__s__)) { \
274 strncat(__d__, __s__, (sizeof(__d__) - 1) - strlen(__d__)); \
276 strncat(__d__, __s__, strlen(__s__)); \
280 char *silc_id_render(void *id, SilcUInt16 type)
283 unsigned char tmps[2];
286 memset(rid, 0, sizeof(rid));
290 SilcServerID *server_id = (SilcServerID *)id;
291 if (server_id->ip.data_len > 4) {
293 struct sockaddr_in6 ipv6;
294 memset(&ipv6, 0, sizeof(ipv6));
295 ipv6.sin6_family = AF_INET6;
296 memmove(&ipv6.sin6_addr, server_id->ip.data, sizeof(ipv6.sin6_addr));
297 if (!getnameinfo((struct sockaddr *)&ipv6, sizeof(ipv6),
298 tmp, sizeof(tmp) - 1, NULL, 0, NI_NUMERICHOST))
299 _PUT_STRING(rid, tmp);
303 memmove(&ipv4.s_addr, server_id->ip.data, 4);
304 cp = inet_ntoa(ipv4);
306 _PUT_STRING(rid, cp);
309 memset(tmp, 0, sizeof(tmp));
310 snprintf(tmp, sizeof(tmp) - 1, ",%d,", ntohs(server_id->port));
311 _PUT_STRING(rid, tmp);
312 SILC_PUT16_MSB(server_id->rnd, tmps);
313 memset(tmp, 0, sizeof(tmp));
314 snprintf(tmp, sizeof(tmp) - 1, "[%02x %02x]", tmps[0], tmps[1]);
315 _PUT_STRING(rid, tmp);
320 SilcClientID *client_id = (SilcClientID *)id;
321 if (client_id->ip.data_len > 4) {
323 struct sockaddr_in6 ipv6;
324 memset(&ipv6, 0, sizeof(ipv6));
325 ipv6.sin6_family = AF_INET6;
326 memmove(&ipv6.sin6_addr, client_id->ip.data, sizeof(ipv6.sin6_addr));
327 if (!getnameinfo((struct sockaddr *)&ipv6, sizeof(ipv6),
328 tmp, sizeof(tmp) - 1, NULL, 0, NI_NUMERICHOST))
329 _PUT_STRING(rid, tmp);
333 memmove(&ipv4.s_addr, client_id->ip.data, 4);
334 cp = inet_ntoa(ipv4);
336 _PUT_STRING(rid, cp);
339 memset(tmp, 0, sizeof(tmp));
340 snprintf(tmp, sizeof(tmp) - 1, ",%02x,", client_id->rnd);
341 _PUT_STRING(rid, tmp);
342 memset(tmp, 0, sizeof(tmp));
343 snprintf(tmp, sizeof(tmp) - 1, "[%02x %02x %02x %02x...]",
344 client_id->hash[0], client_id->hash[1],
345 client_id->hash[2], client_id->hash[3]);
346 _PUT_STRING(rid, tmp);
349 case SILC_ID_CHANNEL:
351 SilcChannelID *channel_id = (SilcChannelID *)id;
352 if (channel_id->ip.data_len > 4) {
354 struct sockaddr_in6 ipv6;
355 memset(&ipv6, 0, sizeof(ipv6));
356 ipv6.sin6_family = AF_INET6;
357 memmove(&ipv6.sin6_addr, channel_id->ip.data, sizeof(ipv6.sin6_addr));
358 if (!getnameinfo((struct sockaddr *)&ipv6, sizeof(ipv6),
359 tmp, sizeof(tmp) - 1, NULL, 0, NI_NUMERICHOST))
360 _PUT_STRING(rid, tmp);
364 memmove(&ipv4.s_addr, channel_id->ip.data, 4);
365 cp = inet_ntoa(ipv4);
367 _PUT_STRING(rid, cp);
370 memset(tmp, 0, sizeof(tmp));
371 snprintf(tmp, sizeof(tmp) - 1, ",%d,", ntohs(channel_id->port));
372 _PUT_STRING(rid, tmp);
373 SILC_PUT16_MSB(channel_id->rnd, tmps);
374 memset(tmp, 0, sizeof(tmp));
375 snprintf(tmp, sizeof(tmp) - 1, "[%02x %02x]", tmps[0], tmps[1]);
376 _PUT_STRING(rid, tmp);
385 /* Compares two strings. Strings may include wildcards '*' and '?'.
386 Returns TRUE if strings match. */
388 int silc_string_compare(char *string1, char *string2)
393 char *tmpstr1, *tmpstr2;
395 if (!string1 || !string2)
398 slen1 = strlen(string1);
399 slen2 = strlen(string2);
401 /* See if they are same already */
402 if (!strncmp(string1, string2, slen2) && slen2 == slen1)
406 if (!strchr(string1, '*'))
409 /* Take copies of the original strings as we will change them */
410 tmpstr1 = silc_calloc(slen1 + 1, sizeof(char));
411 memcpy(tmpstr1, string1, slen1);
412 tmpstr2 = silc_calloc(slen2 + 1, sizeof(char));
413 memcpy(tmpstr2, string2, slen2);
415 for (i = 0; i < slen1; i++) {
417 /* * wildcard. Only one * wildcard is possible. */
418 if (tmpstr1[i] == '*')
419 if (!strncmp(tmpstr1, tmpstr2, i)) {
420 memset(tmpstr2, 0, slen2);
421 strncpy(tmpstr2, tmpstr1, i);
426 if (tmpstr1[i] == '?') {
427 if (!strncmp(tmpstr1, tmpstr2, i)) {
428 if (!(slen1 < i + 1))
429 if (tmpstr1[i + 1] != '?' &&
430 tmpstr1[i + 1] != tmpstr2[i + 1])
433 if (!(slen1 < slen2))
439 /* if using *, remove it */
440 if (strchr(tmpstr1, '*'))
441 *strchr(tmpstr1, '*') = 0;
443 if (!strcmp(tmpstr1, tmpstr2)) {
444 memset(tmpstr1, 0, slen1);
445 memset(tmpstr2, 0, slen2);
451 memset(tmpstr1, 0, slen1);
452 memset(tmpstr2, 0, slen2);
458 /* Basic has function to hash strings. May be used with the SilcHashTable.
459 Note that this lowers the characters of the string (with tolower()) so
460 this is used usually with nicknames, channel and server names to provide
461 case insensitive keys. */
463 SilcUInt32 silc_hash_string(void *key, void *user_context)
465 char *s = (char *)key;
469 h = (h << 4) + tolower(*s);
470 if ((g = h & 0xf0000000)) {
480 /* Hash UTF-8 string */
482 SilcUInt32 silc_hash_utf8_string(void *key, void *user_context)
484 unsigned char *s = (unsigned char *)key;
489 if ((g = h & 0xf0000000)) {
499 /* Basic hash function to hash integers. May be used with the SilcHashTable. */
501 SilcUInt32 silc_hash_uint(void *key, void *user_context)
503 return SILC_PTR_TO_32(key);
506 /* Basic hash funtion to hash pointers. May be used with the SilcHashTable. */
508 SilcUInt32 silc_hash_ptr(void *key, void *user_context)
510 return SILC_PTR_TO_32(key);
513 /* Hash a ID. The `user_context' is the ID type. */
515 SilcUInt32 silc_hash_id(void *key, void *user_context)
517 SilcIdType id_type = (SilcIdType)SILC_PTR_TO_32(user_context);
524 SilcClientID *id = (SilcClientID *)key;
526 /* The client ID is hashed by hashing the hash of the ID
527 (which is a truncated MD5 hash of the nickname) so that we
528 can access the entry from the cache with both Client ID but
529 with just a hash from the ID as well. */
530 return silc_hash_client_id_hash(id->hash, NULL);
535 SilcServerID *id = (SilcServerID *)key;
537 h = id->port * id->rnd;
538 for (i = 0; i < id->ip.data_len; i++)
544 case SILC_ID_CHANNEL:
546 SilcChannelID *id = (SilcChannelID *)key;
548 h = id->port * id->rnd;
549 for (i = 0; i < id->ip.data_len; i++)
562 /* Hash Client ID's hash. */
564 SilcUInt32 silc_hash_client_id_hash(void *key, void *user_context)
567 unsigned char *hash = key;
570 for (i = 0; i < CLIENTID_HASH_LEN; i++) {
571 h = (h << 4) + hash[i];
572 if ((g = h & 0xf0000000)) {
581 /* Hash binary data. The `user_context' is the data length. */
583 SilcUInt32 silc_hash_data(void *key, void *user_context)
585 SilcUInt32 len = SILC_PTR_TO_32(user_context), h = 0;
586 unsigned char *data = (unsigned char *)key;
589 h = (data[0] * data[len - 1] + 1) * len;
590 for (i = 0; i < len; i++)
596 /* Hash public key of any type. */
598 SilcUInt32 silc_hash_public_key(void *key, void *user_context)
600 SilcPublicKey public_key = key;
605 pk = silc_pkcs_public_key_encode(public_key, &pk_len);
609 hash = silc_hash_data(pk, SILC_32_TO_PTR(pk_len));
615 /* Compares two strings. It may be used as SilcHashTable comparison
618 SilcBool silc_hash_string_compare(void *key1, void *key2, void *user_context)
620 return !strcasecmp((char *)key1, (char *)key2);
623 /* Compares two ID's. May be used as SilcHashTable comparison function.
624 The Client ID's compares only the hash of the Client ID not any other
625 part of the Client ID. Other ID's are fully compared. */
627 SilcBool silc_hash_id_compare(void *key1, void *key2, void *user_context)
629 SilcIdType id_type = (SilcIdType)SILC_PTR_TO_32(user_context);
630 return (id_type == SILC_ID_CLIENT ?
631 SILC_ID_COMPARE_HASH((SilcClientID *)key1, (SilcClientID *)key2) :
632 SILC_ID_COMPARE_TYPE(key1, key2, id_type));
635 /* Compares two ID's. Compares full IDs. */
637 SilcBool silc_hash_id_compare_full(void *key1, void *key2, void *user_context)
639 SilcIdType id_type = (SilcIdType)SILC_PTR_TO_32(user_context);
640 return SILC_ID_COMPARE_TYPE(key1, key2, id_type);
643 /* Compare two Client ID's entirely and not just the hash from the ID. */
645 SilcBool silc_hash_client_id_compare(void *key1, void *key2,
648 return SILC_ID_COMPARE_TYPE(key1, key2, SILC_ID_CLIENT);
651 /* Compares binary data. May be used as SilcHashTable comparison function. */
653 SilcBool silc_hash_data_compare(void *key1, void *key2, void *user_context)
655 SilcUInt32 len = SILC_PTR_TO_32(user_context);
656 return !memcmp(key1, key2, len);
659 /* Compares UTF-8 string. */
661 SilcBool silc_hash_utf8_compare(void *key1, void *key2, void *user_context)
663 int l1 = strlen((char *)key1);
664 int l2 = strlen((char *)key2);
667 return !memcmp(key1, key2, l2);
670 /* Compares two SILC Public keys. It may be used as SilcHashTable
671 comparison function. */
673 SilcBool silc_hash_public_key_compare(void *key1, void *key2,
676 return silc_pkcs_public_key_compare(key1, key2);
679 /* Parses mode mask and returns the mode as string. */
681 char *silc_client_chmode(SilcUInt32 mode, const char *cipher, const char *hmac)
688 memset(string, 0, sizeof(string));
690 if (mode & SILC_CHANNEL_MODE_PRIVATE)
691 strncat(string, "p", 1);
693 if (mode & SILC_CHANNEL_MODE_SECRET)
694 strncat(string, "s", 1);
696 if (mode & SILC_CHANNEL_MODE_PRIVKEY)
697 strncat(string, "k", 1);
699 if (mode & SILC_CHANNEL_MODE_INVITE)
700 strncat(string, "i", 1);
702 if (mode & SILC_CHANNEL_MODE_TOPIC)
703 strncat(string, "t", 1);
705 if (mode & SILC_CHANNEL_MODE_ULIMIT)
706 strncat(string, "l", 1);
708 if (mode & SILC_CHANNEL_MODE_PASSPHRASE)
709 strncat(string, "a", 1);
711 if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)
712 strncat(string, "f", 1);
714 if (mode & SILC_CHANNEL_MODE_CHANNEL_AUTH)
715 strncat(string, "C", 1);
717 if (mode & SILC_CHANNEL_MODE_SILENCE_USERS)
718 strncat(string, "m", 1);
720 if (mode & SILC_CHANNEL_MODE_SILENCE_OPERS)
721 strncat(string, "M", 1);
723 if (mode & SILC_CHANNEL_MODE_CIPHER)
724 strncat(string, "c", 1);
726 if (mode & SILC_CHANNEL_MODE_HMAC)
727 strncat(string, "h", 1);
729 if (mode & SILC_CHANNEL_MODE_CIPHER) {
730 if (strlen(cipher) + strlen(string) + 1< sizeof(string)) {
731 strncat(string, " ", 1);
732 strncat(string, cipher, strlen(cipher));
736 if (mode & SILC_CHANNEL_MODE_HMAC) {
737 if (strlen(hmac) + strlen(string) + 1< sizeof(string)) {
738 strncat(string, " ", 1);
739 strncat(string, hmac, strlen(hmac));
743 /* Rest of mode is ignored */
745 return strdup(string);
748 /* Parses channel user mode mask and returns te mode as string */
750 char *silc_client_chumode(SilcUInt32 mode)
757 memset(string, 0, sizeof(string));
759 if (mode & SILC_CHANNEL_UMODE_CHANFO)
760 strncat(string, "f", 1);
762 if (mode & SILC_CHANNEL_UMODE_CHANOP)
763 strncat(string, "o", 1);
765 if (mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES)
766 strncat(string, "b", 1);
768 if (mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS)
769 strncat(string, "u", 1);
771 if (mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS)
772 strncat(string, "r", 1);
774 if (mode & SILC_CHANNEL_UMODE_QUIET)
775 strncat(string, "q", 1);
777 return strdup(string);
780 /* Parses channel user mode and returns it as special mode character. */
782 char *silc_client_chumode_char(SilcUInt32 mode)
789 memset(string, 0, sizeof(string));
791 if (mode & SILC_CHANNEL_UMODE_CHANFO)
792 strncat(string, "*", 1);
794 if (mode & SILC_CHANNEL_UMODE_CHANOP)
795 strncat(string, "@", 1);
797 if (mode & SILC_CHANNEL_UMODE_QUIET)
798 strncat(string, "&", 1);
800 return strdup(string);
803 /* Creates fingerprint from data, usually used with SHA1 digests */
805 char *silc_fingerprint(const unsigned char *data, SilcUInt32 data_len)
807 char fingerprint[64], *cp;
810 memset(fingerprint, 0, sizeof(fingerprint));
812 for (i = 0; i < data_len; i++) {
813 snprintf(cp, sizeof(fingerprint), "%02X", data[i]);
816 if ((i + 1) % 2 == 0)
817 snprintf(cp++, sizeof(fingerprint), " ");
819 if ((i + 1) % 10 == 0)
820 snprintf(cp++, sizeof(fingerprint), " ");
823 if ((i + 1) % 2 == 0)
825 if ((i + 1) % 10 == 0)
828 return strdup(fingerprint);
831 /* Return TRUE if the `data' is ASCII string. */
833 SilcBool silc_string_is_ascii(const unsigned char *data, SilcUInt32 data_len)
837 for (i = 0; i < data_len; i++) {
838 if (!isascii(data[i]))
845 /* Parses SILC protocol style version string. */
847 SilcBool silc_parse_version_string(const char *version,
848 SilcUInt32 *protocol_version,
849 char **protocol_version_string,
850 SilcUInt32 *software_version,
851 char **software_version_string,
852 char **vendor_version)
855 int maj = 0, min = 0;
857 if (!strstr(version, "SILC-"))
860 cp = (char *)version + 5;
864 /* Take protocol version */
867 if (!strchr(cp, '.'))
869 cp = strchr(cp, '.') + 1;
874 memset(buf, 0, sizeof(buf));
875 snprintf(buf, sizeof(buf) - 1, "%d%d", maj, min);
876 if (protocol_version)
877 *protocol_version = atoi(buf);
878 memset(buf, 0, sizeof(buf));
879 snprintf(buf, sizeof(buf) - 1, "%d.%d", maj, min);
880 if (protocol_version_string)
881 *protocol_version_string = strdup(buf);
883 /* Take software version */
887 if (!strchr(cp, '-'))
889 cp = strchr(cp, '-') + 1;
894 if (strchr(cp, '.')) {
895 cp = strchr(cp, '.') + 1;
900 memset(buf, 0, sizeof(buf));
901 snprintf(buf, sizeof(buf) - 1, "%d%d", maj, min);
902 if (software_version)
903 *software_version = atoi(buf);
904 memset(buf, 0, sizeof(buf));
905 snprintf(buf, sizeof(buf) - 1, "%d.%d", maj, min);
906 if (software_version_string)
907 *software_version_string = strdup(buf);
909 /* Take vendor string */
911 if (strchr(cp, '.')) {
912 cp = strchr(cp, '.') + 1;
913 if (cp && *cp && vendor_version)
914 *vendor_version = strdup(cp);
920 /* Converts version string x.x into number representation. */
922 SilcUInt32 silc_version_to_num(const char *version)
924 int maj = 0, min = 0;
930 cp = (char *)version;
932 cp = strchr(cp, '.');
936 memset(buf, 0, sizeof(buf));
937 snprintf(buf, sizeof(buf) - 1, "%d%d", maj, min);
938 return (SilcUInt32)atoi(buf);
941 /* Displays input prompt on command line and takes input data from user */
943 char *silc_get_input(const char *prompt, SilcBool echo_off)
951 #ifdef HAVE_TERMIOS_H
953 struct termios to_old;
955 fd = open("/dev/tty", O_RDONLY);
957 fprintf(stderr, "silc: %s\n", strerror(errno));
961 signal(SIGINT, SIG_IGN);
963 /* Get terminal info */
967 /* Echo OFF, and assure we can prompt and get input */
968 to.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
969 to.c_lflag |= ICANON;
971 tcsetattr(fd, TCSANOW, &to);
973 memset(input, 0, sizeof(input));
975 printf("%s", prompt);
978 if ((read(fd, input, sizeof(input))) < 0) {
979 fprintf(stderr, "silc: %s\n", strerror(errno));
980 tcsetattr(fd, TCSANOW, &to_old);
984 if (strlen(input) <= 1) {
985 tcsetattr(fd, TCSANOW, &to_old);
989 if (strchr(input, '\n'))
990 *strchr(input, '\n') = '\0';
992 /* Restore old terminfo */
993 tcsetattr(fd, TCSANOW, &to_old);
994 signal(SIGINT, SIG_DFL);
996 ret = silc_memdup(input, strlen(input));
997 memset(input, 0, sizeof(input));
998 #endif /* HAVE_TERMIOS_H */
1001 fd = open("/dev/tty", O_RDONLY);
1003 fprintf(stderr, "silc: %s\n", strerror(errno));
1007 memset(input, 0, sizeof(input));
1009 printf("%s", prompt);
1012 if ((read(fd, input, sizeof(input))) < 0) {
1013 fprintf(stderr, "silc: %s\n", strerror(errno));
1017 if (strlen(input) <= 1)
1020 if (strchr(input, '\n'))
1021 *strchr(input, '\n') = '\0';
1023 return strdup(input);
1027 #endif /* SILC_UNIX */
1030 /* Return mode list */
1032 SilcBool silc_get_mode_list(SilcBuffer mode_list, SilcUInt32 mode_list_count,
1037 if (silc_buffer_len(mode_list) / 4 != mode_list_count)
1040 *list = silc_calloc(mode_list_count, sizeof(**list));
1042 for (i = 0; i < mode_list_count; i++) {
1043 SILC_GET32_MSB((*list)[i], mode_list->data);
1044 silc_buffer_pull(mode_list, 4);
1047 silc_buffer_push(mode_list, mode_list->data - mode_list->head);
1052 /* Status message structure. Messages are defined below. */
1055 const char *message;
1056 } SilcStatusMessage;
1058 #define STAT(x) SILC_STATUS_ERR_##x
1059 static const SilcStatusMessage silc_status_messages[] = {
1061 { STAT(NO_SUCH_NICK), "There was no such nickname" },
1062 { STAT(NO_SUCH_CHANNEL), "There was no such channel" },
1063 { STAT(NO_SUCH_SERVER), "There was no such server" },
1064 { STAT(INCOMPLETE_INFORMATION), "Incomplete registration information" },
1065 { STAT(NO_RECIPIENT), "No recipient given" },
1066 { STAT(UNKNOWN_COMMAND), "Unknown command" },
1067 { STAT(WILDCARDS), "Wilcrads not allowed" },
1068 { STAT(NO_CLIENT_ID), "No Client ID given" },
1069 { STAT(NO_CHANNEL_ID), "No Channel ID given" },
1070 { STAT(NO_SERVER_ID), "No Server ID given" },
1071 { STAT(BAD_CLIENT_ID), "Bad Client ID" },
1072 { STAT(BAD_CHANNEL_ID), "Bad Channel ID" },
1073 { STAT(NO_SUCH_CLIENT_ID), "There is no such client" },
1074 { STAT(NO_SUCH_CHANNEL_ID),"There is no such channel" },
1075 { STAT(NICKNAME_IN_USE), "Nickname already exists" },
1076 { STAT(NOT_ON_CHANNEL), "You are not on that channel" },
1077 { STAT(USER_NOT_ON_CHANNEL),"They are not on the channel" },
1078 { STAT(USER_ON_CHANNEL), "User already on the channel" },
1079 { STAT(NOT_REGISTERED), "You have not registered" },
1080 { STAT(NOT_ENOUGH_PARAMS), "Not enough parameters" },
1081 { STAT(TOO_MANY_PARAMS), "Too many parameters" },
1082 { STAT(PERM_DENIED), "Permission denied" },
1083 { STAT(BANNED_FROM_SERVER),"You are not allowed to connect" },
1084 { STAT(BAD_PASSWORD), "Cannot join channel. Incorrect password" },
1085 { STAT(CHANNEL_IS_FULL), "Cannot join channel. Channel is full" },
1086 { STAT(NOT_INVITED), "Cannot join channel. You have not been invited" },
1087 { STAT(BANNED_FROM_CHANNEL), "Cannot join channel. You have been banned" },
1088 { STAT(UNKNOWN_MODE), "Unknown mode" },
1089 { STAT(NOT_YOU), "Cannot change mode for other users" },
1090 { STAT(NO_CHANNEL_PRIV), "Permission denied. You are not channel operator" },
1091 { STAT(NO_CHANNEL_FOPRIV),"Permission denied. You are not channel founder" },
1092 { STAT(NO_SERVER_PRIV), "Permission denied. You are not server operator" },
1093 { STAT(NO_ROUTER_PRIV), "Permission denied. You are not SILC operator" },
1094 { STAT(BAD_NICKNAME), "Bad nickname" },
1095 { STAT(BAD_CHANNEL), "Bad channel name" },
1096 { STAT(AUTH_FAILED), "Authentication failed" },
1097 { STAT(UNKNOWN_ALGORITHM), "Unsupported algorithm" },
1098 { STAT(NO_SUCH_SERVER_ID), "No such Server ID" },
1099 { STAT(RESOURCE_LIMIT), "No more free resources" },
1100 { STAT(NO_SUCH_SERVICE), "Service doesn't exist" },
1101 { STAT(NOT_AUTHENTICATED), "You have not been authenticated" },
1102 { STAT(BAD_SERVER_ID), "Server ID is not valid" },
1103 { STAT(KEY_EXCHANGE_FAILED), "Key exchange failed" },
1104 { STAT(BAD_VERSION), "Bad version" },
1105 { STAT(TIMEDOUT), "Service timed out" },
1106 { STAT(UNSUPPORTED_PUBLIC_KEY), "Unsupported public key type" },
1107 { STAT(OPERATION_ALLOWED), "Operation is not allowed" },
1108 { STAT(BAD_SERVER), "Bad server name" },
1109 { STAT(BAD_USERNAME), "Bad user name" },
1114 /* Returns status message string */
1116 const char *silc_get_status_message(unsigned char status)
1120 for (i = 0; silc_status_messages[i].message; i++) {
1121 if (silc_status_messages[i].status == status)
1125 if (silc_status_messages[i].message == NULL)
1128 return silc_status_messages[i].message;
1131 static const char *packet_name[] = {
1142 "PRIVATE MESSAGE KEY",
1148 "CONNECTION AUTH REQUEST",
1163 /* Returns packet type name */
1165 const char *silc_get_packet_name(unsigned char type)
1167 if (type >= SILC_PACKET_MAX)
1169 if (type >= SILC_PACKET_PRIVATE)
1170 return "PRIVATE RANGE";
1171 if (type > (sizeof(packet_name) / sizeof(*packet_name)))
1173 return packet_name[type];
1176 static const char *command_name[] = {
1207 /* Returns command name */
1209 const char *silc_get_command_name(unsigned char command)
1211 if (command >= SILC_COMMAND_RESERVED)
1213 if (command >= SILC_COMMAND_PRIVATE)
1214 return "PRIVATE RANGE";
1215 if (command > (sizeof(command_name) / sizeof(*command_name)))
1217 return command_name[command];
1220 /* Return TRUE if `smaller' is smaller than `bigger'. */
1222 SilcBool silc_compare_timeval(struct timeval *smaller,
1223 struct timeval *bigger)
1225 if ((smaller->tv_sec < bigger->tv_sec) ||
1226 ((smaller->tv_sec == bigger->tv_sec) &&
1227 (smaller->tv_usec < bigger->tv_usec)))