[Uim] reliability fix: uim-fep.c

Iwata iwata at quasiquote.org
Thu Mar 29 09:57:02 EEST 2007


Hi,

I wrote a patch same as r4437 (mkdir ~/.uim.d/fep).
This patch includes replacing atoi -> strtonum.

Thanks.


diff -rN -u old-uim/configure.ac new-uim/configure.ac
--- old-uim/configure.ac	Thu Mar 29 15:52:57 2007
+++ new-uim/configure.ac	Thu Mar 29 15:52:57 2007
@@ -347,7 +347,7 @@
 AC_CHECK_FUNCS([asprintf vasprintf])
 # C99 functions
 AC_CHECK_FUNCS([snprintf vsnprintf])
-AC_REPLACE_FUNCS([getpeereid strsep setenv unsetenv strlcpy strlcat])
+AC_REPLACE_FUNCS([getpeereid strsep setenv unsetenv strlcpy strlcat strtonum])
 AC_CHECK_FUNCS([getpid stat mkdir chmod])
 AC_CHECK_FUNCS([execv execvp])
 AC_CHECK_FUNCS([isascii])
diff -rN -u old-uim/fep/uim-fep.c new-uim/fep/uim-fep.c
--- old-uim/fep/uim-fep.c	Thu Mar 29 15:52:57 2007
+++ new-uim/fep/uim-fep.c	Thu Mar 29 15:52:57 2007
@@ -223,6 +223,58 @@
   return engine;
 }
 
+static uim_bool
+check_dir(const char *dir)
+{
+  struct stat st;
+
+  if (dir == NULL)
+    return UIM_FALSE;
+
+  if (stat(dir, &st) < 0)
+    return (mkdir(dir, 0700) < 0) ? UIM_FALSE : UIM_TRUE;
+  else {
+    mode_t mode = S_IFDIR | S_IRUSR | S_IWUSR | S_IXUSR;
+    return ((st.st_mode & mode) == mode) ? UIM_TRUE : UIM_FALSE;
+  }
+}
+
+static char *
+get_ud_path(void)
+{
+  char *path, *home = NULL;
+  struct passwd *pw;
+
+  pw = getpwuid(getuid());
+  if (pw)
+    home = pw->pw_dir;
+
+  if (!home && !uim_helper_is_setugid())
+    home = getenv("HOME");
+
+  if (!home)
+    return NULL;
+
+  if (asprintf(&path, "%s/.uim.d", home) == -1)
+    return NULL; /* XXX: fatal */
+
+  if (!check_dir(path)) {
+    free(path);
+    return NULL;
+  }
+  free(path);
+
+  if (asprintf(&path, "%s/.uim.d/fep", home) == -1)
+    return NULL; /* XXX: fatal */
+
+  if (!check_dir(path)) {
+    free(path);
+    return NULL;
+  }
+
+  return path;
+}
+
 int main(int argc, char **argv)
 {
   /* command will be execed on pty */
@@ -230,7 +282,7 @@
   char *engine;
   char *sock_path = NULL; /* Socket for backtick */
   int gnu_screen = FALSE;
-  char *env_buf;
+  char pid_str[30];
   struct attribute_tag attr_uim = {
     FALSE,     /* underline */
     FALSE,     /* standout */
@@ -241,10 +293,11 @@
   };
   FILE *fp;
   const char *suffix = NULL;
-  const char *tmp_dir;
+  const char *uim_dir;
   const char *sty_str;
   const char *win_str;
   struct stat stat_buf;
+  const char *errstr;
 
   int op;
 
@@ -332,7 +385,11 @@
         break;
 
       case 'w':
-        g_opt.statusline_width = atoi(optarg);
+        g_opt.statusline_width = strtonum(optarg, 1, 10000, &errstr);
+	if (errstr) {
+	  printf("'%s': %s", optarg, errstr);
+	  return EXIT_FAILURE;
+	}
         if (g_opt.statusline_width <= 0) {
           usage();
           return EXIT_FAILURE;
@@ -408,8 +465,9 @@
   tcgetattr(g_win_in, &s_save_tios);
   setupterm(NULL, g_win_out, NULL);
 
-  if ((tmp_dir = getenv("TMP")) == NULL) {
-    tmp_dir = "/tmp";
+  if ((uim_dir = get_ud_path()) == NULL) {
+    sendline("uim-fep cannot make directory");
+    return EXIT_FAILURE;
   }
 
   sty_str = getenv("STY");
@@ -419,65 +477,62 @@
       puts("STY and WINDOW are not defined");
       return EXIT_FAILURE;
     }
-    snprintf(s_path_getmode, sizeof(s_path_getmode), "%s/uim-fep-getmode-%s-%s", tmp_dir, sty_str, win_str);
-    snprintf(s_path_setmode, sizeof(s_path_setmode), "%s/uim-fep-setmode-%s-%s", tmp_dir, sty_str, win_str);
+    snprintf(s_path_getmode, sizeof(s_path_getmode), "%s/getmode-%s-%s", uim_dir, sty_str, win_str);
+    snprintf(s_path_setmode, sizeof(s_path_setmode), "%s/setmode-%s-%s", uim_dir, sty_str, win_str);
     if (stat(s_path_getmode, &stat_buf) == 0 || stat(s_path_setmode, &stat_buf) == 0) {
       char msg[100];
-      snprintf(msg, 100, "uim-fep is already running on window %s", win_str);
+      snprintf(msg, sizeof(msg), "uim-fep is already running on window %s", win_str);
       sendline(msg);
       return EXIT_FAILURE;
     }
     if (suffix != NULL) {
-      snprintf(s_path_getmode, sizeof(s_path_getmode), "%s/uim-fep-getmode-%s", tmp_dir, suffix);
-      snprintf(s_path_setmode, sizeof(s_path_setmode), "%s/uim-fep-setmode-%s", tmp_dir, suffix);
+      snprintf(s_path_getmode, sizeof(s_path_getmode), "%s/getmode-%s", uim_dir, suffix);
+      snprintf(s_path_setmode, sizeof(s_path_setmode), "%s/setmode-%s", uim_dir, suffix);
     } else {
-      snprintf(s_path_getmode, sizeof(s_path_getmode), "%s/uim-fep-getmode-%s-%s-screen", tmp_dir, sty_str, win_str);
-      snprintf(s_path_setmode, sizeof(s_path_setmode), "%s/uim-fep-setmode-%s-%s-screen", tmp_dir, sty_str, win_str);
+      snprintf(s_path_getmode, sizeof(s_path_getmode), "%s/getmode-%s-%s-screen", uim_dir, sty_str, win_str);
+      snprintf(s_path_setmode, sizeof(s_path_setmode), "%s/setmode-%s-%s-screen", uim_dir, sty_str, win_str);
     }
   } else {
     if (sty_str != NULL && win_str != NULL) {
-      snprintf(s_path_getmode, sizeof(s_path_getmode), "%s/uim-fep-getmode-%s-%s-screen", tmp_dir, sty_str, win_str);
-      snprintf(s_path_setmode, sizeof(s_path_setmode), "%s/uim-fep-setmode-%s-%s-screen", tmp_dir, sty_str, win_str);
+      snprintf(s_path_getmode, sizeof(s_path_getmode), "%s/getmode-%s-%s-screen", uim_dir, sty_str, win_str);
+      snprintf(s_path_setmode, sizeof(s_path_setmode), "%s/setmode-%s-%s-screen", uim_dir, sty_str, win_str);
       if (stat(s_path_getmode, &stat_buf) == 0 || stat(s_path_setmode, &stat_buf) == 0) {
         printf("uim-fep is already running on window %s as filter\n", win_str);
         return EXIT_FAILURE;
       }
       if (suffix != NULL) {
-        snprintf(s_path_getmode, sizeof(s_path_getmode), "%s/uim-fep-getmode-%s", tmp_dir, suffix);
-        snprintf(s_path_setmode, sizeof(s_path_setmode), "%s/uim-fep-setmode-%s", tmp_dir, suffix);
+        snprintf(s_path_getmode, sizeof(s_path_getmode), "%s/getmode-%s", uim_dir, suffix);
+        snprintf(s_path_setmode, sizeof(s_path_setmode), "%s/setmode-%s", uim_dir, suffix);
       } else {
-        snprintf(s_path_getmode, sizeof(s_path_getmode), "%s/uim-fep-getmode-%s-%s", tmp_dir, sty_str, win_str);
-        snprintf(s_path_setmode, sizeof(s_path_setmode), "%s/uim-fep-setmode-%s-%s", tmp_dir, sty_str, win_str);
+        snprintf(s_path_getmode, sizeof(s_path_getmode), "%s/getmode-%s-%s", uim_dir, sty_str, win_str);
+        snprintf(s_path_setmode, sizeof(s_path_setmode), "%s/setmode-%s-%s", uim_dir, sty_str, win_str);
       }
     } else {
       if (suffix != NULL) {
-        snprintf(s_path_getmode, sizeof(s_path_getmode), "%s/uim-fep-getmode-%s", tmp_dir, suffix);
-        snprintf(s_path_setmode, sizeof(s_path_setmode), "%s/uim-fep-setmode-%s", tmp_dir, suffix);
+        snprintf(s_path_getmode, sizeof(s_path_getmode), "%s/getmode-%s", uim_dir, suffix);
+        snprintf(s_path_setmode, sizeof(s_path_setmode), "%s/setmode-%s", uim_dir, suffix);
       } else {
         int file_suffix = 1;
         int pid = getpid();
 
-        snprintf(s_path_getmode, sizeof(s_path_getmode), "%s/uim-fep-getmode-%d", tmp_dir, pid);
-        snprintf(s_path_setmode, sizeof(s_path_setmode), "%s/uim-fep-setmode-%d", tmp_dir, pid);
+        snprintf(s_path_getmode, sizeof(s_path_getmode), "%s/getmode-%d", uim_dir, pid);
+        snprintf(s_path_setmode, sizeof(s_path_setmode), "%s/setmode-%d", uim_dir, pid);
         while (stat(s_path_getmode, &stat_buf) == 0 || stat(s_path_setmode, &stat_buf) == 0) {
-          snprintf(s_path_getmode, sizeof(s_path_getmode), "%s/uim-fep-getmode-%d-%d", tmp_dir, pid, file_suffix);
-          snprintf(s_path_setmode, sizeof(s_path_setmode), "%s/uim-fep-setmode-%d-%d", tmp_dir, pid, file_suffix);
+          snprintf(s_path_getmode, sizeof(s_path_getmode), "%s/getmode-%d-%d", uim_dir, pid, file_suffix);
+          snprintf(s_path_setmode, sizeof(s_path_setmode), "%s/setmode-%d-%d", uim_dir, pid, file_suffix);
           file_suffix++;
         }
       }
     }
   }
 
-  env_buf = malloc(30);
-  snprintf(env_buf, 30, "UIM_FEP_PID=%d", getpid());
-  putenv(env_buf);
+  snprintf(pid_str, sizeof(pid_str), "%d", getpid());
+  setenv("UIM_FEP_PID", pid_str, 1);
 
   if ((fp = fopen(s_path_getmode, "wt")) != NULL) {
     fclose(fp);
     unlink(s_path_getmode);
-    env_buf = malloc(strlen("UIM_FEP_GETMODE=") + strlen(s_path_getmode) + 1);
-    sprintf(env_buf, "UIM_FEP_GETMODE=%s", s_path_getmode);
-    putenv(env_buf);
+    setenv("UIM_FEP_GETMODE", s_path_getmode, 1);
   } else {
     s_path_getmode[0] = '\0';
   }
@@ -485,9 +540,7 @@
   unlink(s_path_setmode);
   if (mkfifo(s_path_setmode, 0600) != -1) {
     unlink(s_path_setmode);
-    env_buf = malloc(strlen("UIM_FEP_SETMODE=") + strlen(s_path_setmode) + 1);
-    sprintf(env_buf, "UIM_FEP_SETMODE=%s", s_path_setmode);
-    putenv(env_buf);
+    setenv("UIM_FEP_SETMODE", s_path_setmode, 1);
   } else {
     s_path_setmode[0] = '\0';
     s_setmode_fd = -1;
@@ -730,6 +783,7 @@
   int nfd;
   char *_clear_screen = cut_padding(clear_screen);
   char *_clr_eos = cut_padding(clr_eos);
+  const char *errstr;
 
   if (g_win_in > s_master) {
     if (g_win_in > s_setmode_fd) {
@@ -830,8 +884,10 @@
 
         for (start = end; start > 0 && isdigit((unsigned char)buf[start - 1]); --start);
         buf[end + 1] = '\0';
-        mode = atoi(&buf[start]);
-        if (mode != uim_get_current_mode(g_context)) {
+        mode = strtonum(&buf[start], 0, uim_get_nr_modes(g_context) - 1, &errstr);
+	if (errstr) {
+	  debug2(("'%s': %s\n", &buf[start], errstr));
+	} else if (mode != uim_get_current_mode(g_context)) {
           debug2(("mode change %d\n", mode));
           uim_set_mode(g_context, mode);
           /* callbacks_set_mode(uim_get_current_mode(g_context)); */
diff -rN -u old-uim/replace/Makefile.am new-uim/replace/Makefile.am
--- old-uim/replace/Makefile.am	Thu Mar 29 15:52:57 2007
+++ new-uim/replace/Makefile.am	Thu Mar 29 15:52:57 2007
@@ -1,2 +1,2 @@
 noinst_LTLIBRARIES = libreplace.la
-libreplace_la_SOURCES = strsep.c getpeereid.c setenv.c os_dep.h strlcpy.c strlcat.c fake-rfc2553.c fake-rfc2553.h
+libreplace_la_SOURCES = strsep.c getpeereid.c setenv.c os_dep.h strlcpy.c strlcat.c fake-rfc2553.c fake-rfc2553.h bsd-asprintf.c strtonum.c
diff -rN -u old-uim/replace/bsd-asprintf.c new-uim/replace/bsd-asprintf.c
--- old-uim/replace/bsd-asprintf.c	Thu Jan  1 09:00:00 1970
+++ new-uim/replace/bsd-asprintf.c	Thu Mar 29 15:52:57 2007
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2004 Darren Tucker.
+ *
+ * Based originally on asprintf.c from OpenBSD:
+ * Copyright (c) 1997 Todd C. Miller <Todd.Miller at courtesan.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <config.h>
+
+#ifndef HAVE_VASPRINTF
+
+#include <errno.h>
+#include <stdarg.h>
+#include <stdlib.h>
+
+#ifndef VA_COPY
+# ifdef HAVE_VA_COPY
+#  define VA_COPY(dest, src) va_copy(dest, src)
+# else
+#  ifdef HAVE___VA_COPY
+#   define VA_COPY(dest, src) __va_copy(dest, src)
+#  else
+#   define VA_COPY(dest, src) (dest) = (src)
+#  endif
+# endif
+#endif
+
+#define INIT_SZ	128
+
+int vasprintf(char **str, const char *fmt, va_list ap)
+{
+	int ret = -1;
+	va_list ap2;
+	char *string, *newstr;
+	size_t len;
+
+	VA_COPY(ap2, ap);
+	if ((string = malloc(INIT_SZ)) == NULL)
+		goto fail;
+
+	ret = vsnprintf(string, INIT_SZ, fmt, ap2);
+	if (ret >= 0 && ret < INIT_SZ) { /* succeeded with initial alloc */
+		*str = string;
+	} else if (ret == INT_MAX) { /* shouldn't happen */
+		goto fail;
+	} else {	/* bigger than initial, realloc allowing for nul */
+		len = (size_t)ret + 1;
+		if ((newstr = realloc(string, len)) == NULL) {
+			free(string);
+			goto fail;
+		} else {
+			va_end(ap2);
+			VA_COPY(ap2, ap);
+			ret = vsnprintf(newstr, len, fmt, ap2);
+			if (ret >= 0 && (size_t)ret < len) {
+				*str = newstr;
+			} else { /* failed with realloc'ed string, give up */
+				free(newstr);
+				goto fail;
+			}
+		}
+	}
+	va_end(ap2);
+	return (ret);
+
+fail:
+	*str = NULL;
+	errno = ENOMEM;
+	va_end(ap2);
+	return (-1);
+}
+#endif
+
+#ifndef HAVE_ASPRINTF
+int asprintf(char **str, const char *fmt, ...)
+{
+	va_list ap;
+	int ret;
+	
+	*str = NULL;
+	va_start(ap, fmt);
+	ret = vasprintf(str, fmt, ap);
+	va_end(ap);
+
+	return ret;
+}
+#endif
diff -rN -u old-uim/replace/os_dep.h new-uim/replace/os_dep.h
--- old-uim/replace/os_dep.h	Thu Mar 29 15:52:57 2007
+++ new-uim/replace/os_dep.h	Thu Mar 29 15:52:57 2007
@@ -47,6 +47,9 @@
 #if HAVE_SYS_TYPES_H
 #include <sys/types.h>
 #endif
+#if HAVE_STDARG_H
+#include <stdarg.h>
+#endif
 #include <limits.h>
 
 #ifdef __cplusplus
@@ -85,6 +88,21 @@
 #endif
 
 #include "fake-rfc2553.h"
+
+#ifndef HAVE_VASPRINTF
+#define vasprintf	uim_vasprintf
+int vasprintf(char **ret, const char *format, va_list ap);
+#endif
+
+#ifndef HAVE_ASPRINTF
+#define asprintf	uim_asprintf
+int asprintf(char **ret, const char *format, ...);
+#endif
+
+#ifndef HAVE_STRTONUM
+#define strtonum	uim_strtonum
+long long strtonum(const char *numstr, long long minval, long long maxval, const char **errstrp)
+#endif
 
 #ifdef __cplusplus
 }
diff -rN -u old-uim/replace/strtonum.c new-uim/replace/strtonum.c
--- old-uim/replace/strtonum.c	Thu Jan  1 09:00:00 1970
+++ new-uim/replace/strtonum.c	Thu Mar 29 15:52:57 2007
@@ -0,0 +1,72 @@
+/*	$OpenBSD: strtonum.c,v 1.6 2004/08/03 19:38:01 millert Exp $	*/
+
+/*
+ * Copyright (c) 2004 Ted Unangst and Todd Miller
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* OPENBSD ORIGINAL: lib/libc/stdlib/strtonum.c */
+
+#include <config.h>
+
+#ifndef HAVE_STRTONUM
+#include <stdlib.h>
+#include <limits.h>
+#include <errno.h>
+
+#define INVALID 	1
+#define TOOSMALL 	2
+#define TOOLARGE 	3
+
+long long
+strtonum(const char *numstr, long long minval, long long maxval,
+    const char **errstrp)
+{
+	long long ll = 0;
+	char *ep;
+	int error = 0;
+	struct errval {
+		const char *errstr;
+		int err;
+	} ev[4] = {
+		{ NULL,		0 },
+		{ "invalid",	EINVAL },
+		{ "too small",	ERANGE },
+		{ "too large",	ERANGE },
+	};
+
+	ev[0].err = errno;
+	errno = 0;
+	if (minval > maxval)
+		error = INVALID;
+	else {
+		ll = strtoll(numstr, &ep, 10);
+		if (numstr == ep || *ep != '\0')
+			error = INVALID;
+		else if ((ll == LLONG_MIN && errno == ERANGE) || ll < minval)
+			error = TOOSMALL;
+		else if ((ll == LLONG_MAX && errno == ERANGE) || ll > maxval)
+			error = TOOLARGE;
+	}
+	if (errstrp != NULL)
+		*errstrp = ev[error].errstr;
+	errno = ev[error].err;
+	if (error)
+		ll = 0;
+
+	return (ll);
+}
+
+#endif /* HAVE_STRTONUM */



More information about the uim mailing list