Home | History | Annotate | Line # | Download | only in dist
      1 /* $OpenBSD$ */
      2 
      3 /*
      4  * Copyright (c) 2009 Nicholas Marriott <nicholas.marriott (at) gmail.com>
      5  *
      6  * Permission to use, copy, modify, and distribute this software for any
      7  * purpose with or without fee is hereby granted, provided that the above
      8  * copyright notice and this permission notice appear in all copies.
      9  *
     10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
     11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     14  * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
     15  * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
     16  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     17  */
     18 
     19 #include <sys/types.h>
     20 
     21 #include <stdlib.h>
     22 #include <string.h>
     23 
     24 #include "tmux.h"
     25 
     26 /*
     27  * Show environment.
     28  */
     29 
     30 static enum cmd_retval	cmd_show_environment_exec(struct cmd *,
     31 			    struct cmdq_item *);
     32 
     33 static char	*cmd_show_environment_escape(struct environ_entry *);
     34 static void	 cmd_show_environment_print(struct cmd *, struct cmdq_item *,
     35 		     struct environ_entry *);
     36 
     37 const struct cmd_entry cmd_show_environment_entry = {
     38 	.name = "show-environment",
     39 	.alias = "showenv",
     40 
     41 	.args = { "hgst:", 0, 1, NULL },
     42 	.usage = "[-hgs] " CMD_TARGET_SESSION_USAGE " [variable]",
     43 
     44 	.target = { 't', CMD_FIND_SESSION, CMD_FIND_CANFAIL },
     45 
     46 	.flags = CMD_AFTERHOOK,
     47 	.exec = cmd_show_environment_exec
     48 };
     49 
     50 static char *
     51 cmd_show_environment_escape(struct environ_entry *envent)
     52 {
     53 	const char	*value = envent->value;
     54 	char		 c, *out, *ret;
     55 
     56 	out = ret = xmalloc(strlen(value) * 2 + 1); /* at most twice the size */
     57 	while ((c = *value++) != '\0') {
     58 		/* POSIX interprets $ ` " and \ in double quotes. */
     59 		if (c == '$' || c == '`' || c == '"' || c == '\\')
     60 			*out++ = '\\';
     61 		*out++ = c;
     62 	}
     63 	*out = '\0';
     64 
     65 	return (ret);
     66 }
     67 
     68 static void
     69 cmd_show_environment_print(struct cmd *self, struct cmdq_item *item,
     70     struct environ_entry *envent)
     71 {
     72 	struct args	*args = cmd_get_args(self);
     73 	char		*escaped;
     74 
     75 	if (!args_has(args, 'h') && (envent->flags & ENVIRON_HIDDEN))
     76 		return;
     77 	if (args_has(args, 'h') && (~envent->flags & ENVIRON_HIDDEN))
     78 		return;
     79 
     80 	if (!args_has(args, 's')) {
     81 		if (envent->value != NULL)
     82 			cmdq_print(item, "%s=%s", envent->name, envent->value);
     83 		else
     84 			cmdq_print(item, "-%s", envent->name);
     85 		return;
     86 	}
     87 
     88 	if (envent->value != NULL) {
     89 		escaped = cmd_show_environment_escape(envent);
     90 		cmdq_print(item, "%s=\"%s\"; export %s;", envent->name, escaped,
     91 		    envent->name);
     92 		free(escaped);
     93 	} else
     94 		cmdq_print(item, "unset %s;", envent->name);
     95 }
     96 
     97 static enum cmd_retval
     98 cmd_show_environment_exec(struct cmd *self, struct cmdq_item *item)
     99 {
    100 	struct args		*args = cmd_get_args(self);
    101 	struct cmd_find_state	*target = cmdq_get_target(item);
    102 	struct environ		*env;
    103 	struct environ_entry	*envent;
    104 	const char		*tflag, *name = args_string(args, 0);
    105 
    106 	if ((tflag = args_get(args, 't')) != NULL) {
    107 		if (target->s == NULL) {
    108 			cmdq_error(item, "no such session: %s", tflag);
    109 			return (CMD_RETURN_ERROR);
    110 		}
    111 	}
    112 
    113 	if (args_has(args, 'g'))
    114 		env = global_environ;
    115 	else {
    116 		if (target->s == NULL) {
    117 			tflag = args_get(args, 't');
    118 			if (tflag != NULL)
    119 				cmdq_error(item, "no such session: %s", tflag);
    120 			else
    121 				cmdq_error(item, "no current session");
    122 			return (CMD_RETURN_ERROR);
    123 		}
    124 		env = target->s->environ;
    125 	}
    126 
    127 	if (name != NULL) {
    128 		envent = environ_find(env, name);
    129 		if (envent == NULL) {
    130 			cmdq_error(item, "unknown variable: %s", name);
    131 			return (CMD_RETURN_ERROR);
    132 		}
    133 		cmd_show_environment_print(self, item, envent);
    134 		return (CMD_RETURN_NORMAL);
    135 	}
    136 
    137 	envent = environ_first(env);
    138 	while (envent != NULL) {
    139 		cmd_show_environment_print(self, item, envent);
    140 		envent = environ_next(envent);
    141 	}
    142 	return (CMD_RETURN_NORMAL);
    143 }
    144