Print this page
4956 zonecfg won't use a valid pager

@@ -20,10 +20,11 @@
  */
 
 /*
  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
  * Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
+ * Copyright 2014 Gary Mills
  */
 
 /*
  * zonecfg is a lex/yacc based command interpreter used to manage zone
  * configurations.  The lexer (see zonecfg_lex.l) builds up tokens, which

@@ -906,10 +907,107 @@
         }
         /* NOTREACHED */
         return (NULL);
 }
 
+/* Copied almost verbatim from libtnfctl/prb_findexec.c */
+static const char *
+exec_cat(const char *s1, const char *s2, char *si)
+{
+        char               *s;
+        /* number of characters in s2 */
+        int                      cnt = PATH_MAX + 1;
+
+        s = si;
+        while (*s1 && *s1 != ':') {
+                if (cnt > 0) {
+                        *s++ = *s1++;
+                        cnt--;
+                } else
+                        s1++;
+        }
+        if (si != s && cnt > 0) {
+                *s++ = '/';
+                cnt--;
+        }
+        while (*s2 && cnt > 0) {
+                *s++ = *s2++;
+                cnt--;
+        }
+        *s = '\0';
+        return (*s1 ? ++s1 : NULL);
+}
+
+/* Determine that a name exists in PATH */
+/* Copied with changes from libtnfctl/prb_findexec.c */
+static int
+path_find(const char *name, char *ret_path)
+{
+        const char       *pathstr;
+        char            fname[PATH_MAX + 2];
+        const char       *cp;
+        struct stat      stat_buf;
+
+        if (*name == '\0') {
+                return (-1);
+        }
+        if ((pathstr = getenv("PATH")) == NULL) {
+                if (geteuid() == 0 || getuid() == 0)
+                        pathstr = "/usr/sbin:/usr/bin";
+                else
+                        pathstr = "/usr/bin:";
+        }
+        cp = strchr(name, '/') ? (const char *) "" : pathstr;
+
+        do {
+                cp = exec_cat(cp, name, fname);
+                if (stat(fname, &stat_buf) != -1) {
+                        /* successful find of the file */
+                        if (ret_path != NULL)
+                                (void) strncpy(ret_path, fname, PATH_MAX + 2);
+                        return (0);
+                }
+        } while (cp != NULL);
+
+        return (-1);
+}
+
+static FILE *
+pager_open(void) {
+        FILE *newfp;
+        char *pager, *space;
+
+        if ((pager = getenv("PAGER")) == NULL)
+                pager = PAGER;
+
+        space = strchr(pager, ' ');
+        if (space)
+                *space = '\0';
+        if (path_find(pager, NULL) == 0) {
+                if (space)
+                        *space = ' ';
+                if ((newfp = popen(pager, "w")) == NULL)
+                        zerr(gettext("PAGER open failed (%s)."),
+                            strerror(errno));
+                return (newfp);
+        } else {
+                zerr(gettext("PAGER %s does not exist (%s)."),
+                    pager, strerror(errno));
+        }
+        return (NULL);
+}
+
+static void
+pager_close(FILE *fp) {
+        int status;
+
+        status = pclose(fp);
+        if (status == -1)
+                zerr(gettext("PAGER close failed (%s)."),
+                    strerror(errno));
+}
+
 /*
  * Called with verbose TRUE when help is explicitly requested, FALSE for
  * unexpected errors.
  */
 

@@ -917,34 +1015,19 @@
 usage(boolean_t verbose, uint_t flags)
 {
         FILE *fp = verbose ? stdout : stderr;
         FILE *newfp;
         boolean_t need_to_close = B_FALSE;
-        char *pager, *space;
         int i;
-        struct stat statbuf;
 
         /* don't page error output */
         if (verbose && interactive_mode) {
-                if ((pager = getenv("PAGER")) == NULL)
-                        pager = PAGER;
-
-                space = strchr(pager, ' ');
-                if (space)
-                        *space = '\0';
-                if (stat(pager, &statbuf) == 0) {
-                        if (space)
-                                *space = ' ';
-                        if ((newfp = popen(pager, "w")) != NULL) {
+                if ((newfp = pager_open()) != NULL) {
                                 need_to_close = B_TRUE;
                                 fp = newfp;
                         }
-                } else {
-                        zerr(gettext("PAGER %s does not exist (%s)."),
-                            pager, strerror(errno));
                 }
-        }
 
         if (flags & HELP_META) {
                 (void) fprintf(fp, gettext("More help is available for the "
                     "following:\n"));
                 (void) fprintf(fp, "\n\tcommands ('%s commands')\n",

@@ -1272,11 +1355,11 @@
                     pt_to_str(PT_LOCKED));
                 (void) fprintf(fp, "\t%s\t\t%s, %s\n", rt_to_str(RT_ADMIN),
                     pt_to_str(PT_USER), pt_to_str(PT_AUTHS));
         }
         if (need_to_close)
-                (void) pclose(fp);
+                (void) pager_close(fp);
 }
 
 static void
 zone_perror(char *prefix, int err, boolean_t set_saw)
 {

@@ -5341,40 +5424,26 @@
 void
 info_func(cmd_t *cmd)
 {
         FILE *fp = stdout;
         boolean_t need_to_close = B_FALSE;
-        char *pager, *space;
         int type;
         int res1, res2;
         uint64_t swap_limit;
         uint64_t locked_limit;
-        struct stat statbuf;
 
         assert(cmd != NULL);
 
         if (initialize(B_TRUE) != Z_OK)
                 return;
 
         /* don't page error output */
         if (interactive_mode) {
-                if ((pager = getenv("PAGER")) == NULL)
-                        pager = PAGER;
-                space = strchr(pager, ' ');
-                if (space)
-                        *space = '\0';
-                if (stat(pager, &statbuf) == 0) {
-                        if (space)
-                                *space = ' ';
-                        if ((fp = popen(pager, "w")) != NULL)
+                if ((fp = pager_open()) != NULL)
                                 need_to_close = B_TRUE;
                         else
                                 fp = stdout;
-                } else {
-                        zerr(gettext("PAGER %s does not exist (%s)."),
-                            pager, strerror(errno));
-                }
 
                 setbuf(fp, NULL);
         }
 
         if (!global_scope) {

@@ -5560,11 +5629,11 @@
                     B_TRUE);
         }
 
 cleanup:
         if (need_to_close)
-                (void) pclose(fp);
+                (void) pager_close(fp);
 }
 
 /*
  * Helper function for verify-- checks that a required string property
  * exists.