Merge Irssi 0.8.16-rc1
[silc.git] / apps / irssi / src / core / misc.c
index 93612d6bb5ab7704f786fa2dc51fd21e5ee4fbf7..7c930e3f61955fbb75bdd52b3c880a6e1c195a07 100644 (file)
     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 this program; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+    You should have received a copy of the GNU General Public License along
+    with this program; if not, write to the Free Software Foundation, Inc.,
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */
 
 #include "module.h"
 #include "misc.h"
-#include "pidwait.h"
 
-#include <errno.h>
 #ifdef HAVE_REGEX_H
 #  include <regex.h>
 #endif
-#include <pwd.h>
 
 typedef struct {
        int condition;
@@ -90,6 +87,16 @@ int g_input_add(GIOChannel *source, int condition,
                                function, data);
 }
 
+/* easy way to bypass glib polling of io channel internal buffer */
+int g_input_add_poll(int fd, int priority, int condition,
+                    GInputFunction function, void *data)
+{
+       GIOChannel *source = g_io_channel_unix_new(fd);
+       int ret = g_input_add_full(source, priority, condition, function, data);
+       g_io_channel_unref(source);
+       return ret;
+}
+
 int g_timeval_cmp(const GTimeVal *tv1, const GTimeVal *tv2)
 {
        if (tv1->tv_sec < tv2->tv_sec)
@@ -174,37 +181,6 @@ int strarray_find(char **array, const char *item)
        return -1;
 }
 
-int execute(const char *cmd)
-{
-       char **args;
-#ifndef WIN32
-       int pid;
-#endif
-
-       g_return_val_if_fail(cmd != NULL, -1);
-
-#ifndef WIN32
-       pid = fork();
-       if (pid == -1) return FALSE;
-       if (pid != 0) {
-               pidwait_add(pid);
-               return pid;
-       }
-
-       args = g_strsplit(cmd, " ", -1);
-       execvp(args[0], args);
-       g_strfreev(args);
-
-       _exit(99);
-       return -1;
-#else
-       args = g_strsplit(cmd, " ", -1);
-       _spawnvp(_P_DETACH, args[0], args);
-       g_strfreev(args);
-       return 0;
-#endif
-}
-
 GSList *gslist_find_string(GSList *list, const char *key)
 {
        for (list = list; list != NULL; list = list->next)
@@ -340,7 +316,7 @@ char *stristr(const char *data, const char *key)
        ((unsigned char) (c) < 128 && \
        (i_isspace(c) || i_ispunct(c)))
 
-char *strstr_full_case(const char *data, const char *key, int icase)
+static char *strstr_full_case(const char *data, const char *key, int icase)
 {
        const char *start, *max;
        int keylen, datalen, pos, match;
@@ -449,25 +425,20 @@ int mkpath(const char *path, int mode)
        return 0;
 }
 
-/* Get home directory */
-const char *get_home_dir(void)
-{
-       struct passwd *pw = getpwuid(getuid());
-       if (!pw) {
-        if (g_getenv("HOME"))
-          return g_getenv("HOME");
-        else
-          return ".";
-       }
-       return pw->pw_dir;
-}
-
 /* convert ~/ to $HOME */
 char *convert_home(const char *path)
 {
-       return *path == '~' && (*(path+1) == '/' || *(path+1) == '\0') ?
-               g_strconcat((char *)get_home_dir, path+1, NULL) :
-               g_strdup(path);
+       const char *home;
+
+       if (*path == '~' && (*(path+1) == '/' || *(path+1) == '\0')) {
+               home = g_get_home_dir();
+               if (home == NULL)
+                       home = ".";
+
+               return g_strconcat(home, path+1, NULL);
+       } else {
+               return g_strdup(path);
+       }
 }
 
 int g_istr_equal(gconstpointer v, gconstpointer v2)
@@ -598,24 +569,38 @@ int dec2octal(int decimal)
        return octal;
 }
 
+/* string -> uoff_t */
+uoff_t str_to_uofft(const char *str)
+{
+       uoff_t ret;
+
+       ret = 0;
+       while (*str != '\0') {
+               ret = ret*10 + (*str - '0');
+               str++;
+       }
+
+       return ret;
+}
+
 /* convert all low-ascii (<32) to ^<A..> combinations */
-char *show_lowascii(const char *channel)
+char *show_lowascii(const char *str)
 {
-       char *str, *p;
+       char *ret, *p;
 
-       str = p = g_malloc(strlen(channel)*2+1);
-       while (*channel != '\0') {
-               if ((unsigned char) *channel >= 32)
-                       *p++ = *channel;
+       ret = p = g_malloc(strlen(str)*2+1);
+       while (*str != '\0') {
+               if ((unsigned char) *str >= 32)
+                       *p++ = *str;
                else {
                        *p++ = '^';
-                       *p++ = *channel + 'A'-1;
+                       *p++ = *str + 'A'-1;
                }
-               channel++;
+               str++;
        }
        *p = '\0';
 
-       return str;
+       return ret;
 }
 
 /* Get time in human readable form with localtime() + asctime() */
@@ -771,16 +756,213 @@ int expand_escape(const char **data)
                 /* control character (\cA = ^A) */
                 (*data)++;
                return i_toupper(**data) - 64;
-       default:
-               if (!i_isdigit(**data))
-                       return -1;
-
+       case '0': case '1': case '2': case '3':
+       case '4': case '5': case '6': case '7':
                 /* octal */
+               digit[1] = digit[2] = digit[3] = '\0';
                 digit[0] = (*data)[0];
-                digit[1] = (*data)[1];
-               digit[2] = (*data)[2];
-                digit[3] = '\0';
-               *data += 2;
+               if ((*data)[1] >= '0' && (*data)[1] <= '7') {
+                       ++*data;
+                       digit[1] = **data;
+                       if ((*data)[1] >= '0' && (*data)[1] <= '7') {
+                               ++*data;
+                               digit[2] = **data;
+                       }
+               }
                return strtol(digit, NULL, 8);
+       default:
+               return -1;
+       }
+}
+
+/* Escape all '"', "'" and '\' chars with '\' */
+char *escape_string(const char *str)
+{
+       char *ret, *p;
+
+       p = ret = g_malloc(strlen(str)*2+1);
+       while (*str != '\0') {
+               if (*str == '"' || *str == '\'' || *str == '\\')
+                       *p++ = '\\';
+               *p++ = *str++;
+       }
+       *p = '\0';
+
+       return ret;
+}
+
+int strocpy(char *dest, const char *src, size_t dstsize)
+{
+       if (dstsize == 0)
+               return -1;
+
+       while (*src != '\0' && dstsize > 1) {
+               *dest++ = *src++;
+               dstsize--;
        }
+
+       *dest++ = '\0';
+       return *src == '\0' ? 0 : -1;
+}
+
+int nearest_power(int num)
+{
+       int n = 1;
+
+       while (n < num) n <<= 1;
+       return n;
+}
+
+int parse_time_interval(const char *time, int *msecs)
+{
+       const char *desc;
+       int number, sign, len, ret, digits;
+
+       *msecs = 0;
+
+       /* max. return value is around 24 days */
+       number = 0; sign = 1; ret = TRUE; digits = FALSE;
+       while (i_isspace(*time))
+               time++;
+       if (*time == '-') {
+               sign = -sign;
+               time++;
+               while (i_isspace(*time))
+                       time++;
+       }
+       for (;;) {
+               if (i_isdigit(*time)) {
+                       number = number*10 + (*time - '0');
+                       time++;
+                       digits = TRUE;
+                       continue;
+               }
+
+               if (!digits)
+                       return FALSE;
+
+               /* skip punctuation */
+               while (*time != '\0' && i_ispunct(*time) && *time != '-')
+                       time++;
+
+               /* get description */
+               for (len = 0, desc = time; i_isalpha(*time); time++)
+                       len++;
+
+               while (i_isspace(*time))
+                       time++;
+
+               if (len == 0) {
+                       if (*time != '\0')
+                               return FALSE;
+                       *msecs += number * 1000; /* assume seconds */
+                       *msecs *= sign;
+                       return TRUE;
+               }
+
+               if (g_ascii_strncasecmp(desc, "days", len) == 0) {
+                       if (number > 24) {
+                               /* would overflow */
+                               return FALSE;
+                       }
+                       *msecs += number * 1000*3600*24;
+               } else if (g_ascii_strncasecmp(desc, "hours", len) == 0)
+                       *msecs += number * 1000*3600;
+               else if (g_ascii_strncasecmp(desc, "minutes", len) == 0 ||
+                        g_ascii_strncasecmp(desc, "mins", len) == 0)
+                       *msecs += number * 1000*60;
+               else if (g_ascii_strncasecmp(desc, "seconds", len) == 0 ||
+                        g_ascii_strncasecmp(desc, "secs", len) == 0)
+                       *msecs += number * 1000;
+               else if (g_ascii_strncasecmp(desc, "milliseconds", len) == 0 ||
+                        g_ascii_strncasecmp(desc, "millisecs", len) == 0 ||
+                        g_ascii_strncasecmp(desc, "mseconds", len) == 0 ||
+                        g_ascii_strncasecmp(desc, "msecs", len) == 0)
+                       *msecs += number;
+               else {
+                       ret = FALSE;
+               }
+
+               /* skip punctuation */
+               while (*time != '\0' && i_ispunct(*time) && *time != '-')
+                       time++;
+
+               if (*time == '\0')
+                       break;
+
+               number = 0;
+               digits = FALSE;
+       }
+
+       *msecs *= sign;
+       return ret;
+}
+
+int parse_size(const char *size, int *bytes)
+{
+       const char *desc;
+       int number, len;
+
+       *bytes = 0;
+
+       /* max. return value is about 1.6 years */
+       number = 0;
+       while (*size != '\0') {
+               if (i_isdigit(*size)) {
+                       number = number*10 + (*size - '0');
+                       size++;
+                       continue;
+               }
+
+               /* skip punctuation */
+               while (*size != '\0' && i_ispunct(*size))
+                       size++;
+
+               /* get description */
+               for (len = 0, desc = size; i_isalpha(*size); size++)
+                       len++;
+
+               if (len == 0) {
+                       if (number == 0) {
+                               /* "0" - allow it */
+                               return TRUE;
+                       }
+
+                       *bytes += number*1024; /* assume kilobytes */
+                       return FALSE;
+               }
+
+               if (g_ascii_strncasecmp(desc, "gbytes", len) == 0)
+                       *bytes += number * 1024*1024*1024;
+               if (g_ascii_strncasecmp(desc, "mbytes", len) == 0)
+                       *bytes += number * 1024*1024;
+               if (g_ascii_strncasecmp(desc, "kbytes", len) == 0)
+                       *bytes += number * 1024;
+               if (g_ascii_strncasecmp(desc, "bytes", len) == 0)
+                       *bytes += number;
+
+               /* skip punctuation */
+               while (*size != '\0' && i_ispunct(*size))
+                       size++;
+       }
+
+       return TRUE;
+}
+
+char *ascii_strup(char *str)
+{
+       char *s;
+
+       for (s = str; *s; s++)
+               *s = g_ascii_toupper (*s);
+       return str;
+}
+
+char *ascii_strdown(char *str)
+{
+       char *s;
+
+       for (s = str; *s; s++)
+               *s = g_ascii_tolower (*s);
+       return str;
 }