2 * Copyright (C) 1998 Peter Zelezny.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19 #define __APPLE_API_STRICT_CONFORMANCE
21 #define _FILE_OFFSET_BITS 64
26 #include <sys/types.h>
28 #include <sys/types.h>
31 #include <sys/utsname.h>
44 #if defined (USING_FREEBSD) || defined (__APPLE__)
45 #include <sys/sysctl.h>
58 int current_mem_usage
;
67 struct mem_block
*next
;
70 struct mem_block
*mroot
= NULL
;
73 xchat_malloc (int size
, char *file
, int line
)
76 struct mem_block
*new;
78 current_mem_usage
+= size
;
82 printf ("Out of memory! (%d)\n", current_mem_usage
);
86 new = malloc (sizeof (struct mem_block
));
91 new->file
= strdup (file
);
94 printf ("%s:%d Malloc'ed %d bytes, now \033[35m%d\033[m\n", file
, line
,
95 size
, current_mem_usage
);
101 xchat_realloc (char *old
, int len
, char *file
, int line
)
105 ret
= xchat_malloc (len
, file
, line
);
109 xchat_dfree (old
, file
, line
);
115 xchat_strdup (char *str
, char *file
, int line
)
118 struct mem_block
*new;
121 size
= strlen (str
) + 1;
122 current_mem_usage
+= size
;
126 printf ("Out of memory! (%d)\n", current_mem_usage
);
131 new = malloc (sizeof (struct mem_block
));
136 new->file
= strdup (file
);
139 printf ("%s:%d strdup (\"%-.40s\") size: %d, total: \033[35m%d\033[m\n",
140 file
, line
, str
, size
, current_mem_usage
);
146 xchat_mem_list (void)
148 struct mem_block
*cur
, *p
;
159 if (p
->line
== cur
->line
&&
160 strcmp (p
->file
, cur
->file
) == 0)
169 cur
->total
= cur
->size
;
170 totals
= g_slist_prepend (totals
, cur
);
175 fprintf (stderr
, "file line size num total\n");
180 fprintf (stderr
, "%-15.15s %6d %6d %6d %6d\n", cur
->file
, cur
->line
,
181 cur
->size
, cur
->total
/cur
->size
, cur
->total
);
187 xchat_dfree (void *buf
, char *file
, int line
)
189 struct mem_block
*cur
, *last
;
193 printf ("%s:%d \033[33mTried to free NULL\033[m\n", file
, line
);
208 printf ("%s:%d \033[31mTried to free unknown block %lx!\033[m\n",
209 file
, line
, (unsigned long) buf
);
214 current_mem_usage
-= cur
->size
;
215 printf ("%s:%d Free'ed %d bytes, usage now \033[35m%d\033[m\n",
216 file
, line
, cur
->size
, current_mem_usage
);
218 last
->next
= cur
->next
;
225 #define malloc(n) xchat_malloc(n, __FILE__, __LINE__)
226 #define realloc(n, m) xchat_realloc(n, m, __FILE__, __LINE__)
227 #define free(n) xchat_dfree(n, __FILE__, __LINE__)
228 #define strdup(n) xchat_strdup(n, __FILE__, __LINE__)
230 #endif /* MEMORY_DEBUG */
233 file_part (char *file
)
235 char *filepart
= file
;
256 path_part (char *file
, char *path
, int pathlen
)
259 char *filepart
= file_part (file
);
262 safe_strcpy (path
, file
, pathlen
);
266 char * /* like strstr(), but nocase */
267 nocasestrstr (const char *s
, const char *wanted
)
269 register const int len
= strlen (wanted
);
273 while (rfc_tolower(*s
) != rfc_tolower(*wanted
) || strncasecmp (s
, wanted
, len
))
280 errorstring (int err
)
287 return _("Remote host closed socket");
291 case WSAECONNREFUSED
:
292 return _("Connection refused");
294 case WSAEHOSTUNREACH
:
295 return _("No route to host");
297 return _("Connection timed out");
298 case WSAEADDRNOTAVAIL
:
299 return _("Cannot assign that address");
301 return _("Connection reset by peer");
304 /* can't use strerror() on Winsock errors! */
305 if (err
>= WSABASEERR
)
307 static char tbuf
[384];
310 osvi
.dwOSVersionInfoSize
= sizeof (OSVERSIONINFO
);
311 GetVersionEx (&osvi
);
313 /* FormatMessage works on WSA*** errors starting from Win2000 */
314 if (osvi
.dwMajorVersion
>= 5)
316 if (FormatMessageA (FORMAT_MESSAGE_FROM_SYSTEM
|
317 FORMAT_MESSAGE_IGNORE_INSERTS
|
318 FORMAT_MESSAGE_MAX_WIDTH_MASK
,
320 MAKELANGID (LANG_NEUTRAL
, SUBLANG_DEFAULT
),
321 tbuf
, sizeof (tbuf
), NULL
))
326 tbuf
[sizeof (tbuf
) - 1] = 0;
329 tbuf
[len
- 2] = 0; /* remove the cr-lf */
331 /* now convert to utf8 */
332 utf
= g_locale_to_utf8 (tbuf
, -1, 0, 0, 0);
335 safe_strcpy (tbuf
, utf
, sizeof (tbuf
));
340 } /* ! if (osvi.dwMajorVersion >= 5) */
342 /* fallback to error number */
343 sprintf (tbuf
, "%s %d", _("Error"), err
);
345 } /* ! if (err >= WSABASEERR) */
348 return strerror (err
);
352 waitline (int sok
, char *buf
, int bufsize
, int use_recv
)
360 if (recv (sok
, &buf
[i
], 1, 0) < 1)
364 if (read (sok
, &buf
[i
], 1) < 1)
367 if (buf
[i
] == '\n' || bufsize
== i
+ 1)
376 /* checks for "~" in a file and expands */
379 expand_homedir (char *file
)
387 if (file
[1] != '\0' && file
[1] != '/')
390 if (strchr(user
,'/') != NULL
)
391 *(strchr(user
,'/')) = '\0';
392 if ((pw
= getpwnam(user
+ 1)) == NULL
)
398 user
= strchr(file
, '/') != NULL
? strchr(file
,'/') : file
;
399 ret
= malloc(strlen(user
) + strlen(pw
->pw_dir
) + 1);
400 strcpy(ret
, pw
->pw_dir
);
405 ret
= malloc (strlen (file
) + strlen (g_get_home_dir ()) + 1);
406 sprintf (ret
, "%s%s", g_get_home_dir (), file
+ 1);
411 return strdup (file
);
415 strip_color (const char *text
, int len
, int flags
)
422 new_str
= g_malloc (len
+ 2);
423 strip_color2 (text
, len
, new_str
, flags
);
425 if (flags
& STRIP_ESCMARKUP
)
427 char *esc
= g_markup_escape_text (new_str
, -1);
435 /* CL: strip_color2 strips src and writes the output at dst; pass the same pointer
436 in both arguments to strip in place. */
438 strip_color2 (const char *src
, int len
, char *dst
, int flags
)
440 int rcol
= 0, bgcol
= 0;
443 if (len
== -1) len
= strlen (src
);
446 if (rcol
> 0 && (isdigit ((unsigned char)*src
) ||
447 (*src
== ',' && isdigit ((unsigned char)src
[1]) && !bgcol
)))
449 if (src
[1] != ',') rcol
--;
460 case '\003': /*ATTR_COLOR: */
461 if (!(flags
& STRIP_COLOR
)) goto pass_char
;
464 case HIDDEN_CHAR
: /* CL: invisible text (for event formats only) */ /* this takes care of the topic */
465 if (!(flags
& STRIP_HIDDEN
)) goto pass_char
;
467 case '\007': /*ATTR_BEEP: */
468 case '\017': /*ATTR_RESET: */
469 case '\026': /*ATTR_REVERSE: */
470 case '\002': /*ATTR_BOLD: */
471 case '\037': /*ATTR_UNDERLINE: */
472 case '\035': /*ATTR_ITALICS: */
473 if (!(flags
& STRIP_ATTRIB
)) goto pass_char
;
484 return (int) (dst
- start
);
488 strip_hidden_attribute (char *src
, char *dst
)
491 while (*src
!= '\000')
493 if (*src
!= HIDDEN_CHAR
)
503 #if defined (USING_LINUX) || defined (USING_FREEBSD) || defined (__APPLE__)
506 get_cpu_info (double *mhz
, int *cpus
)
517 fh
= open ("/proc/cpuinfo", O_RDONLY
); /* linux 2.2+ only */
526 if (waitline (fh
, buf
, sizeof buf
, FALSE
) < 0)
528 if (!strncmp (buf
, "cycle frequency [Hz]\t:", 22)) /* alpha */
530 *mhz
= atoi (buf
+ 23) / 1000000;
531 } else if (!strncmp (buf
, "cpu MHz\t\t:", 10)) /* i386 */
533 *mhz
= atof (buf
+ 11) + 0.5;
534 } else if (!strncmp (buf
, "clock\t\t:", 8)) /* PPC */
536 *mhz
= atoi (buf
+ 9);
537 } else if (!strncmp (buf
, "processor\t", 10))
561 sysctl(mib
, 2, &ncpu
, &len
, NULL
, 0);
564 sysctlbyname("machdep.tsc_freq", &freq
, &len
, NULL
, 0);
567 *mhz
= (freq
/ 1000000);
573 unsigned long long freq
;
584 sysctl(mib
, 2, &ncpu
, &len
, NULL
, 0);
587 sysctlbyname("hw.cpufrequency", &freq
, &len
, NULL
, 0);
590 *mhz
= (freq
/ 1000000);
603 int result
, data
, dataSize
;
605 if (RegOpenKeyEx (HKEY_LOCAL_MACHINE
, "Hardware\\Description\\System\\"
606 "CentralProcessor\\0", 0, KEY_QUERY_VALUE
, &hKey
) == ERROR_SUCCESS
)
608 dataSize
= sizeof (data
);
609 result
= RegQueryValueEx (hKey
, "~MHz", 0, 0, (LPBYTE
)&data
, &dataSize
);
611 if (result
== ERROR_SUCCESS
)
614 return 0; /* fails on Win9x */
620 static char verbuf
[64];
625 osvi
.dwOSVersionInfoSize
= sizeof (OSVERSIONINFO
);
626 GetVersionEx (&osvi
);
632 double cpuspeed
= ( mhz
> 1000 ) ? mhz
/ 1000 : mhz
;
633 const char *cpuspeedstr
= ( mhz
> 1000 ) ? "GHz" : "MHz";
634 sprintf (verbuf
, "Windows %ld.%ld [i%d86/%.2f%s]",
635 osvi
.dwMajorVersion
, osvi
.dwMinorVersion
, si
.wProcessorLevel
,
636 cpuspeed
, cpuspeedstr
);
638 sprintf (verbuf
, "Windows %ld.%ld [i%d86]",
639 osvi
.dwMajorVersion
, osvi
.dwMinorVersion
, si
.wProcessorLevel
);
649 #if defined (USING_LINUX) || defined (USING_FREEBSD) || defined (__APPLE__)
654 static char *buf
= NULL
;
663 #if defined (USING_LINUX) || defined (USING_FREEBSD) || defined (__APPLE__)
664 get_cpu_info (&mhz
, &cpus
);
667 double cpuspeed
= ( mhz
> 1000 ) ? mhz
/ 1000 : mhz
;
668 const char *cpuspeedstr
= ( mhz
> 1000 ) ? "GHz" : "MHz";
670 (cpus
== 1) ? "%s %s [%s/%.2f%s]" : "%s %s [%s/%.2f%s/SMP]",
671 un
.sysname
, un
.release
, un
.machine
,
672 cpuspeed
, cpuspeedstr
);
676 (cpus
== 1) ? "%s %s [%s]" : "%s %s [%s/SMP]",
677 un
.sysname
, un
.release
, un
.machine
);
685 buf_get_line (char *ibuf
, char **buf
, int *position
, int len
)
687 int pos
= *position
, spos
= pos
;
692 while (ibuf
[pos
++] != '\n')
705 int match(const char *mask
, const char *string
)
707 register const char *m
= mask
, *s
= string
;
709 const char *bm
, *bs
; /* Will be reg anyway on a decent CPU/compiler */
711 /* Process the "head" of the mask, if any */
712 while ((ch
= *m
++) && (ch
!= '*'))
716 if (*m
== '?' || *m
== '*')
719 if (rfc_tolower(*s
) != rfc_tolower(ch
))
728 /* We got a star: quickly find if/where we match the next char */
730 bm
= m
; /* Next try rollback here */
739 continue; /* while */
741 if (*m
== '?' || *m
== '*')
744 goto break_while
; /* C is structured ? */
748 return 1; /* mask ends with '*', we got it */
749 ch
= rfc_tolower(ch
);
750 while (rfc_tolower(*s
++) != ch
)
753 bs
= s
; /* Next try start from here */
755 /* Check the rest of the "chunk" */
763 if (*m
== '?' || *m
== '*')
766 if (rfc_tolower(*s
) != rfc_tolower(ch
))
789 for_files (char *dirname
, char *mask
, void callback (char *file
))
795 dir
= opendir (dirname
);
798 while ((ent
= readdir (dir
)))
800 if (strcmp (ent
->d_name
, ".") && strcmp (ent
->d_name
, ".."))
802 if (match (mask
, ent
->d_name
))
804 buf
= malloc (strlen (dirname
) + strlen (ent
->d_name
) + 2);
805 sprintf (buf
, "%s/%s", dirname
, ent
->d_name
);
816 tolowerStr (char *str)
820 *str = rfc_tolower (*str);
827 char *code
, *country
;
831 country_compare (const void *a
, const void *b
)
833 return strcasecmp (a
, ((domain_t
*)b
)->code
);
836 static const domain_t domain
[] =
838 {"AC", N_("Ascension Island") },
839 {"AD", N_("Andorra") },
840 {"AE", N_("United Arab Emirates") },
841 {"AF", N_("Afghanistan") },
842 {"AG", N_("Antigua and Barbuda") },
843 {"AI", N_("Anguilla") },
844 {"AL", N_("Albania") },
845 {"AM", N_("Armenia") },
846 {"AN", N_("Netherlands Antilles") },
847 {"AO", N_("Angola") },
848 {"AQ", N_("Antarctica") },
849 {"AR", N_("Argentina") },
850 {"ARPA", N_("Reverse DNS") },
851 {"AS", N_("American Samoa") },
852 {"AT", N_("Austria") },
853 {"ATO", N_("Nato Fiel") },
854 {"AU", N_("Australia") },
855 {"AW", N_("Aruba") },
856 {"AX", N_("Aland Islands") },
857 {"AZ", N_("Azerbaijan") },
858 {"BA", N_("Bosnia and Herzegovina") },
859 {"BB", N_("Barbados") },
860 {"BD", N_("Bangladesh") },
861 {"BE", N_("Belgium") },
862 {"BF", N_("Burkina Faso") },
863 {"BG", N_("Bulgaria") },
864 {"BH", N_("Bahrain") },
865 {"BI", N_("Burundi") },
866 {"BIZ", N_("Businesses"), },
867 {"BJ", N_("Benin") },
868 {"BM", N_("Bermuda") },
869 {"BN", N_("Brunei Darussalam") },
870 {"BO", N_("Bolivia") },
871 {"BR", N_("Brazil") },
872 {"BS", N_("Bahamas") },
873 {"BT", N_("Bhutan") },
874 {"BV", N_("Bouvet Island") },
875 {"BW", N_("Botswana") },
876 {"BY", N_("Belarus") },
877 {"BZ", N_("Belize") },
878 {"CA", N_("Canada") },
879 {"CC", N_("Cocos Islands") },
880 {"CD", N_("Democratic Republic of Congo") },
881 {"CF", N_("Central African Republic") },
882 {"CG", N_("Congo") },
883 {"CH", N_("Switzerland") },
884 {"CI", N_("Cote d'Ivoire") },
885 {"CK", N_("Cook Islands") },
886 {"CL", N_("Chile") },
887 {"CM", N_("Cameroon") },
888 {"CN", N_("China") },
889 {"CO", N_("Colombia") },
890 {"COM", N_("Internic Commercial") },
891 {"CR", N_("Costa Rica") },
892 {"CS", N_("Serbia and Montenegro") },
894 {"CV", N_("Cape Verde") },
895 {"CX", N_("Christmas Island") },
896 {"CY", N_("Cyprus") },
897 {"CZ", N_("Czech Republic") },
898 {"DE", N_("Germany") },
899 {"DJ", N_("Djibouti") },
900 {"DK", N_("Denmark") },
901 {"DM", N_("Dominica") },
902 {"DO", N_("Dominican Republic") },
903 {"DZ", N_("Algeria") },
904 {"EC", N_("Ecuador") },
905 {"EDU", N_("Educational Institution") },
906 {"EE", N_("Estonia") },
907 {"EG", N_("Egypt") },
908 {"EH", N_("Western Sahara") },
909 {"ER", N_("Eritrea") },
910 {"ES", N_("Spain") },
911 {"ET", N_("Ethiopia") },
912 {"EU", N_("European Union") },
913 {"FI", N_("Finland") },
915 {"FK", N_("Falkland Islands") },
916 {"FM", N_("Micronesia") },
917 {"FO", N_("Faroe Islands") },
918 {"FR", N_("France") },
919 {"GA", N_("Gabon") },
920 {"GB", N_("Great Britain") },
921 {"GD", N_("Grenada") },
922 {"GE", N_("Georgia") },
923 {"GF", N_("French Guiana") },
924 {"GG", N_("British Channel Isles") },
925 {"GH", N_("Ghana") },
926 {"GI", N_("Gibraltar") },
927 {"GL", N_("Greenland") },
928 {"GM", N_("Gambia") },
929 {"GN", N_("Guinea") },
930 {"GOV", N_("Government") },
931 {"GP", N_("Guadeloupe") },
932 {"GQ", N_("Equatorial Guinea") },
933 {"GR", N_("Greece") },
934 {"GS", N_("S. Georgia and S. Sandwich Isles") },
935 {"GT", N_("Guatemala") },
937 {"GW", N_("Guinea-Bissau") },
938 {"GY", N_("Guyana") },
939 {"HK", N_("Hong Kong") },
940 {"HM", N_("Heard and McDonald Islands") },
941 {"HN", N_("Honduras") },
942 {"HR", N_("Croatia") },
943 {"HT", N_("Haiti") },
944 {"HU", N_("Hungary") },
945 {"ID", N_("Indonesia") },
946 {"IE", N_("Ireland") },
947 {"IL", N_("Israel") },
948 {"IM", N_("Isle of Man") },
949 {"IN", N_("India") },
950 {"INFO", N_("Informational") },
951 {"INT", N_("International") },
952 {"IO", N_("British Indian Ocean Territory") },
955 {"IS", N_("Iceland") },
956 {"IT", N_("Italy") },
957 {"JE", N_("Jersey") },
958 {"JM", N_("Jamaica") },
959 {"JO", N_("Jordan") },
960 {"JP", N_("Japan") },
961 {"KE", N_("Kenya") },
962 {"KG", N_("Kyrgyzstan") },
963 {"KH", N_("Cambodia") },
964 {"KI", N_("Kiribati") },
965 {"KM", N_("Comoros") },
966 {"KN", N_("St. Kitts and Nevis") },
967 {"KP", N_("North Korea") },
968 {"KR", N_("South Korea") },
969 {"KW", N_("Kuwait") },
970 {"KY", N_("Cayman Islands") },
971 {"KZ", N_("Kazakhstan") },
973 {"LB", N_("Lebanon") },
974 {"LC", N_("Saint Lucia") },
975 {"LI", N_("Liechtenstein") },
976 {"LK", N_("Sri Lanka") },
977 {"LR", N_("Liberia") },
978 {"LS", N_("Lesotho") },
979 {"LT", N_("Lithuania") },
980 {"LU", N_("Luxembourg") },
981 {"LV", N_("Latvia") },
982 {"LY", N_("Libya") },
983 {"MA", N_("Morocco") },
984 {"MC", N_("Monaco") },
985 {"MD", N_("Moldova") },
986 {"MED", N_("United States Medical") },
987 {"MG", N_("Madagascar") },
988 {"MH", N_("Marshall Islands") },
989 {"MIL", N_("Military") },
990 {"MK", N_("Macedonia") },
992 {"MM", N_("Myanmar") },
993 {"MN", N_("Mongolia") },
994 {"MO", N_("Macau") },
995 {"MP", N_("Northern Mariana Islands") },
996 {"MQ", N_("Martinique") },
997 {"MR", N_("Mauritania") },
998 {"MS", N_("Montserrat") },
999 {"MT", N_("Malta") },
1000 {"MU", N_("Mauritius") },
1001 {"MV", N_("Maldives") },
1002 {"MW", N_("Malawi") },
1003 {"MX", N_("Mexico") },
1004 {"MY", N_("Malaysia") },
1005 {"MZ", N_("Mozambique") },
1006 {"NA", N_("Namibia") },
1007 {"NC", N_("New Caledonia") },
1008 {"NE", N_("Niger") },
1009 {"NET", N_("Internic Network") },
1010 {"NF", N_("Norfolk Island") },
1011 {"NG", N_("Nigeria") },
1012 {"NI", N_("Nicaragua") },
1013 {"NL", N_("Netherlands") },
1014 {"NO", N_("Norway") },
1015 {"NP", N_("Nepal") },
1016 {"NR", N_("Nauru") },
1017 {"NU", N_("Niue") },
1018 {"NZ", N_("New Zealand") },
1019 {"OM", N_("Oman") },
1020 {"ORG", N_("Internic Non-Profit Organization") },
1021 {"PA", N_("Panama") },
1022 {"PE", N_("Peru") },
1023 {"PF", N_("French Polynesia") },
1024 {"PG", N_("Papua New Guinea") },
1025 {"PH", N_("Philippines") },
1026 {"PK", N_("Pakistan") },
1027 {"PL", N_("Poland") },
1028 {"PM", N_("St. Pierre and Miquelon") },
1029 {"PN", N_("Pitcairn") },
1030 {"PR", N_("Puerto Rico") },
1031 {"PS", N_("Palestinian Territory") },
1032 {"PT", N_("Portugal") },
1033 {"PW", N_("Palau") },
1034 {"PY", N_("Paraguay") },
1035 {"QA", N_("Qatar") },
1036 {"RE", N_("Reunion") },
1037 {"RO", N_("Romania") },
1038 {"RPA", N_("Old School ARPAnet") },
1039 {"RU", N_("Russian Federation") },
1040 {"RW", N_("Rwanda") },
1041 {"SA", N_("Saudi Arabia") },
1042 {"SB", N_("Solomon Islands") },
1043 {"SC", N_("Seychelles") },
1044 {"SD", N_("Sudan") },
1045 {"SE", N_("Sweden") },
1046 {"SG", N_("Singapore") },
1047 {"SH", N_("St. Helena") },
1048 {"SI", N_("Slovenia") },
1049 {"SJ", N_("Svalbard and Jan Mayen Islands") },
1050 {"SK", N_("Slovak Republic") },
1051 {"SL", N_("Sierra Leone") },
1052 {"SM", N_("San Marino") },
1053 {"SN", N_("Senegal") },
1054 {"SO", N_("Somalia") },
1055 {"SR", N_("Suriname") },
1056 {"ST", N_("Sao Tome and Principe") },
1057 {"SU", N_("Former USSR") },
1058 {"SV", N_("El Salvador") },
1059 {"SY", N_("Syria") },
1060 {"SZ", N_("Swaziland") },
1061 {"TC", N_("Turks and Caicos Islands") },
1062 {"TD", N_("Chad") },
1063 {"TF", N_("French Southern Territories") },
1064 {"TG", N_("Togo") },
1065 {"TH", N_("Thailand") },
1066 {"TJ", N_("Tajikistan") },
1067 {"TK", N_("Tokelau") },
1068 {"TL", N_("East Timor") },
1069 {"TM", N_("Turkmenistan") },
1070 {"TN", N_("Tunisia") },
1071 {"TO", N_("Tonga") },
1072 {"TP", N_("East Timor") },
1073 {"TR", N_("Turkey") },
1074 {"TT", N_("Trinidad and Tobago") },
1075 {"TV", N_("Tuvalu") },
1076 {"TW", N_("Taiwan") },
1077 {"TZ", N_("Tanzania") },
1078 {"UA", N_("Ukraine") },
1079 {"UG", N_("Uganda") },
1080 {"UK", N_("United Kingdom") },
1081 {"US", N_("United States of America") },
1082 {"UY", N_("Uruguay") },
1083 {"UZ", N_("Uzbekistan") },
1084 {"VA", N_("Vatican City State") },
1085 {"VC", N_("St. Vincent and the Grenadines") },
1086 {"VE", N_("Venezuela") },
1087 {"VG", N_("British Virgin Islands") },
1088 {"VI", N_("US Virgin Islands") },
1089 {"VN", N_("Vietnam") },
1090 {"VU", N_("Vanuatu") },
1091 {"WF", N_("Wallis and Futuna Islands") },
1092 {"WS", N_("Samoa") },
1093 {"YE", N_("Yemen") },
1094 {"YT", N_("Mayotte") },
1095 {"YU", N_("Yugoslavia") },
1096 {"ZA", N_("South Africa") },
1097 {"ZM", N_("Zambia") },
1098 {"ZW", N_("Zimbabwe") },
1102 country (char *hostname
)
1107 if (!hostname
|| !*hostname
|| isdigit ((unsigned char) hostname
[strlen (hostname
) - 1]))
1108 return _("Unknown");
1109 if ((p
= strrchr (hostname
, '.')))
1114 dom
= bsearch (p
, domain
, sizeof (domain
) / sizeof (domain_t
),
1115 sizeof (domain_t
), country_compare
);
1118 return _("Unknown");
1120 return _(dom
->country
);
1124 country_search (char *pattern
, void *ud
, void (*print
)(void *, char *, ...))
1126 const domain_t
*dom
;
1129 for (i
= 0; i
< sizeof (domain
) / sizeof (domain_t
); i
++)
1132 if (match (pattern
, dom
->country
) || match (pattern
, _(dom
->country
)))
1134 print (ud
, "%s = %s\n", dom
->code
, _(dom
->country
));
1139 /* I think gnome1.0.x isn't necessarily linked against popt, ah well! */
1140 /* !!! For now use this inlined function, or it would break fe-text building */
1141 /* .... will find a better solution later. */
1142 /*#ifndef USE_GNOME*/
1144 /* this is taken from gnome-libs 1.2.4 */
1145 #define POPT_ARGV_ARRAY_GROW_DELTA 5
1147 int my_poptParseArgvString(const char * s
, int * argcPtr
, char *** argvPtr
) {
1148 char * buf
, * bufStart
, * dst
;
1151 int argvAlloced
= POPT_ARGV_ARRAY_GROW_DELTA
;
1152 char ** argv
= malloc(sizeof(*argv
) * argvAlloced
);
1153 const char ** argv2
;
1157 buflen
= strlen(s
) + 1;
1158 /* bufStart = buf = alloca(buflen);*/
1159 bufStart
= buf
= malloc (buflen
);
1160 memset(buf
, '\0', buflen
);
1166 if (quote
== *src
) {
1176 if (*src
!= quote
) *buf
++ = '\\';
1179 /*} else if (isspace((unsigned char) *src)) {*/
1180 } else if (*src
== ' ') {
1183 if (argc
== argvAlloced
) {
1184 argvAlloced
+= POPT_ARGV_ARRAY_GROW_DELTA
;
1185 argv
= realloc(argv
, sizeof(*argv
) * argvAlloced
);
1189 } else switch (*src
) {
1209 if (strlen(argv
[argc
])) {
1213 dst
= malloc((argc
+ 1) * sizeof(*argv
) + (buf
- bufStart
));
1214 argv2
= (void *) dst
;
1215 dst
+= (argc
+ 1) * sizeof(*argv
);
1216 memcpy((void *)argv2
, argv
, argc
* sizeof(*argv
));
1218 memcpy(dst
, bufStart
, buf
- bufStart
);
1220 for (i
= 0; i
< argc
; i
++) {
1221 argv2
[i
] = dst
+ (argv
[i
] - bufStart
);
1226 *argvPtr
= (char **)argv2
; /* XXX don't change the API */
1235 util_exec (const char *cmd
)
1242 if (my_poptParseArgvString (cmd
, &argc
, &argv
) != 0)
1251 /* Now close all open file descriptors except stdin, stdout and stderr */
1252 for (fd
= 3; fd
< 1024; fd
++) close(fd
);
1253 execvp (argv
[0], argv
);
1261 spawnvp (_P_DETACH
, argv
[0], argv
);
1268 util_execv (char * const argv
[])
1278 /* Now close all open file descriptors except stdin, stdout and stderr */
1279 for (fd
= 3; fd
< 1024; fd
++) close(fd
);
1280 execv (argv
[0], argv
);
1287 spawnv (_P_DETACH
, argv
[0], argv
);
1293 make_ping_time (void)
1296 struct timeval timev
;
1297 gettimeofday (&timev
, 0);
1300 g_get_current_time (&timev
);
1302 return (timev
.tv_sec
- 50000) * 1000000 + timev
.tv_usec
;
1306 /************************************************************************
1307 * This technique was borrowed in part from the source code to
1308 * ircd-hybrid-5.3 to implement case-insensitive string matches which
1309 * are fully compliant with Section 2.2 of RFC 1459, the copyright
1310 * of that code being (C) 1990 Jarkko Oikarinen and under the GPL.
1312 * A special thanks goes to Mr. Okarinen for being the one person who
1313 * seems to have ever noticed this section in the original RFC and
1314 * written code for it. Shame on all the rest of you (myself included).
1316 * --+ Dagmar d'Surreal
1320 rfc_casecmp (const char *s1
, const char *s2
)
1322 register unsigned char *str1
= (unsigned char *) s1
;
1323 register unsigned char *str2
= (unsigned char *) s2
;
1326 while ((res
= rfc_tolower (*str1
) - rfc_tolower (*str2
)) == 0)
1337 rfc_ncasecmp (char *str1
, char *str2
, int n
)
1339 register unsigned char *s1
= (unsigned char *) str1
;
1340 register unsigned char *s2
= (unsigned char *) str2
;
1343 while ((res
= rfc_tolower (*s1
) - rfc_tolower (*s2
)) == 0)
1348 if (n
== 0 || (*s1
== '\0' && *s2
== '\0'))
1354 const unsigned char rfc_tolowertab
[] =
1355 { 0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa,
1356 0xb, 0xc, 0xd, 0xe, 0xf, 0x10, 0x11, 0x12, 0x13, 0x14,
1357 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
1359 ' ', '!', '"', '#', '$', '%', '&', 0x27, '(', ')',
1360 '*', '+', ',', '-', '.', '/',
1361 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
1362 ':', ';', '<', '=', '>', '?',
1363 '@', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',
1364 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's',
1365 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~',
1367 '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',
1368 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's',
1369 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~',
1371 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
1372 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
1373 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99,
1374 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
1375 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9,
1376 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
1377 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9,
1378 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
1379 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9,
1380 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
1381 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9,
1382 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
1383 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
1384 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
1385 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9,
1386 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
1389 /*static unsigned char touppertab[] =
1390 { 0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa,
1391 0xb, 0xc, 0xd, 0xe, 0xf, 0x10, 0x11, 0x12, 0x13, 0x14,
1392 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
1394 ' ', '!', '"', '#', '$', '%', '&', 0x27, '(', ')',
1395 '*', '+', ',', '-', '.', '/',
1396 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
1397 ':', ';', '<', '=', '>', '?',
1398 '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
1399 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
1400 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^',
1402 '`', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
1403 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
1404 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^',
1406 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
1407 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
1408 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99,
1409 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
1410 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9,
1411 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
1412 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9,
1413 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
1414 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9,
1415 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
1416 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9,
1417 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
1418 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
1419 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
1420 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9,
1421 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
1425 rename_utf8 (char *oldname, char *newname)
1430 fso = xchat_filename_from_utf8 (oldname, -1, 0, 0, 0);
1433 fsn = xchat_filename_from_utf8 (newname, -1, 0, 0, 0);
1440 res = rename (fso, fsn);
1449 unlink_utf8 (char *fname)
1454 fs = xchat_filename_from_utf8 (fname, -1, 0, 0, 0);
1464 file_exists_utf8 (char *fname
)
1469 fs
= xchat_filename_from_utf8 (fname
, -1, 0, 0, 0);
1473 res
= access (fs
, F_OK
);
1481 copy_file (char *dl_src
, char *dl_dest
, int permissions
) /* FS encoding */
1483 int tmp_src
, tmp_dest
;
1484 gboolean ok
= FALSE
;
1486 int return_tmp
, return_tmp2
;
1488 if ((tmp_src
= open (dl_src
, O_RDONLY
| OFLAGS
)) == -1)
1490 fprintf (stderr
, "Unable to open() file '%s' (%s) !", dl_src
,
1496 open (dl_dest
, O_WRONLY
| O_CREAT
| O_TRUNC
| OFLAGS
, permissions
)) < 0)
1499 fprintf (stderr
, "Unable to create file '%s' (%s) !", dl_src
,
1506 return_tmp
= read (tmp_src
, dl_tmp
, sizeof (dl_tmp
));
1516 fprintf (stderr
, "download_move_to_completed_dir(): "
1517 "error reading while moving file to save directory (%s)",
1522 return_tmp2
= write (tmp_dest
, dl_tmp
, return_tmp
);
1524 if (return_tmp2
< 0)
1526 fprintf (stderr
, "download_move_to_completed_dir(): "
1527 "error writing while moving file to save directory (%s)",
1532 if (return_tmp
< sizeof (dl_tmp
))
1544 /* Takes care of moving a file from a temporary download location to a completed location. Now in UTF-8. */
1546 move_file_utf8 (char *src_dir
, char *dst_dir
, char *fname
, int dccpermissions
)
1551 char *src_fs
; /* FileSystem encoding */
1554 /* if dcc_dir and dcc_completed_dir are the same then we are done */
1555 if (0 == strcmp (src_dir
, dst_dir
) ||
1557 return; /* Already in "completed dir" */
1559 snprintf (src
, sizeof (src
), "%s/%s", src_dir
, fname
);
1560 snprintf (dst
, sizeof (dst
), "%s/%s", dst_dir
, fname
);
1562 /* already exists in completed dir? Append a number */
1563 if (file_exists_utf8 (dst
))
1567 snprintf (dst
, sizeof (dst
), "%s/%s.%d", dst_dir
, fname
, i
);
1568 if (!file_exists_utf8 (dst
))
1573 /* convert UTF-8 to filesystem encoding */
1574 src_fs
= xchat_filename_from_utf8 (src
, -1, 0, 0, 0);
1577 dst_fs
= xchat_filename_from_utf8 (dst
, -1, 0, 0, 0);
1584 /* first try a simple rename move */
1585 res
= rename (src_fs
, dst_fs
);
1587 if (res
== -1 && (errno
== EXDEV
|| errno
== EPERM
))
1589 /* link failed because either the two paths aren't on the */
1590 /* same filesystem or the filesystem doesn't support hard */
1591 /* links, so we have to do a copy. */
1592 if (copy_file (src_fs
, dst_fs
, dccpermissions
))
1601 mkdir_utf8 (char *dir
)
1605 dir
= xchat_filename_from_utf8 (dir
, -1, 0, 0, 0);
1612 ret
= mkdir (dir
, S_IRUSR
| S_IWUSR
| S_IXUSR
);
1619 /* separates a string according to a 'sep' char, then calls the callback
1620 function for each token found */
1623 token_foreach (char *str
, char sep
,
1624 int (*callback
) (char *str
, void *ud
), void *ud
)
1626 char t
, *start
= str
;
1630 if (*str
== sep
|| *str
== 0)
1634 if (callback (start
, ud
) < 1)
1648 /* chars $00-$7f can never be embedded in utf-8 */
1656 /* 31 bit string hash functions */
1659 str_hash (const char *key
)
1661 const char *p
= key
;
1665 for (p
+= 1; *p
!= '\0'; p
++)
1666 h
= (h
<< 5) - h
+ *p
;
1672 str_ihash (const unsigned char *key
)
1674 const char *p
= key
;
1675 guint32 h
= rfc_tolowertab
[(guint
)*p
];
1678 for (p
+= 1; *p
!= '\0'; p
++)
1679 h
= (h
<< 5) - h
+ rfc_tolowertab
[(guint
)*p
];
1684 /* features: 1. "src" must be valid, NULL terminated UTF-8 */
1685 /* 2. "dest" will be left with valid UTF-8 - no partial chars! */
1688 safe_strcpy (char *dest
, const char *src
, int bytes_left
)
1694 mbl
= g_utf8_skip
[*((unsigned char *)src
)];
1696 if (bytes_left
< (mbl
+ 1)) /* can't fit with NULL? */
1702 if (mbl
== 1) /* one byte char */
1706 break; /* it all fit */
1711 else /* multibyte char */
1713 memcpy (dest
, src
, mbl
);