1 /*
2  * alias.c -- define and undefine aliases
3  *
4  * Yet Another FTP Client
5  * Copyright (C) 1998-2001, Martin Hedenfalk <mhe@stacken.kth.se>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version. See COPYING for more details.
11  */
12 
13 #include "syshdr.h"
14 #include "alias.h"
15 #include "linklist.h"
16 #include "gvars.h"
17 #include "cmd.h"
18 #include "commands.h"
19 #include "strq.h"
20 
alias_searchfunc(alias * ap,const char * name)21 static int alias_searchfunc(alias *ap, const char *name)
22 {
23 	return strcmp(ap->name, name);
24 }
25 
alias_create(void)26 alias *alias_create(void)
27 {
28 	alias *ap = (alias *)xmalloc(sizeof(alias));
29 	return ap;
30 }
31 
alias_destroy(alias * ap)32 void alias_destroy(alias *ap)
33 {
34 	if(!ap)
35 		return;
36 	alias_clear(ap);
37 	free(ap);
38 }
39 
alias_clear(alias * ap)40 void alias_clear(alias *ap)
41 {
42 	free(ap->name);
43 	ap->name = 0;
44 	args_destroy(ap->value);
45 	ap->value = 0;
46 }
47 
alias_search(const char * name)48 alias *alias_search(const char *name)
49 {
50 	listitem *li;
51 	alias *ap = 0;
52 	alias *r = 0;
53 
54 	li = gvAliases->first;
55 	while(li) {
56 		ap = (alias *)li->data;
57 
58 		/* compare only strlen(name) chars, allowing aliases
59 		 * to be shortened, as long as they're not ambiguous
60 		 */
61 		if(strncmp(((alias *)li->data)->name, name, strlen(name)) == 0) {
62 			/* is this an exact match? */
63 			if(strlen(name) == strlen(ap->name))
64 				return ap;
65 
66 			if(r)
67 				r = ALIAS_AMBIGUOUS;
68 			else
69 				r = ap;
70 		}
71 		li = li->next;
72 	}
73 	return r;
74 }
75 
alias_define(const char * name,args_t * args)76 void alias_define(const char *name, args_t *args)
77 {
78 	alias *ap;
79 	cmd_t *cp;
80 	listitem *li;
81 
82 	li = list_search(gvAliases, (listsearchfunc)alias_searchfunc, name);
83 	ap = li ? li->data : 0;
84 
85 	if(!ap) {
86 		ap = alias_create();
87 		list_additem(gvAliases, ap);
88 	} else
89 		alias_clear(ap); /* overwrite if already defined */
90 
91 	ap->name = xstrdup(name);
92 
93 	/* special handling of '!', execute shell command */
94 	if(args->argv[0][0] == '!' && strlen(args->argv[0]) > 1) {
95 		strpull(args->argv[0], 1);
96 		args_push_front(args, "!");
97 	}
98 
99 	/* warn if strange alias */
100 	if(strcmp(ap->name, args->argv[0]) != 0) {
101 		cp = find_cmd(ap->name);
102 		if(cp && cp != CMD_AMBIGUOUS && strcmp(ap->name, cp->cmd) == 0)
103 			fprintf(stderr, _("warning: alias '%s' shadows a command with"
104 							  " the same name\n"),
105 				   ap->name);
106 	}
107 	cp = find_cmd(args->argv[0]);
108 	if(!cp)
109 		fprintf(stderr,
110 				_("warning: alias '%s' points to a non-existing command\n"),
111 			   ap->name);
112 	else if(cp == CMD_AMBIGUOUS)
113 		fprintf(stderr, _("warning: alias '%s' is ambiguous\n"), ap->name);
114 
115 	ap->value = args;
116 }
117 
cmd_alias(int argc,char ** argv)118 void cmd_alias(int argc, char **argv)
119 {
120 	alias *ap;
121 	listitem *li = 0;
122 
123 	OPT_HELP_NEW(_("Define an alias."), "alias [options]  [name [value]]",
124     _("without arguments, prints all defined aliases\n"
125     "with only [name] argument, prints that alias' value\n"
126     "with [name] and [value] arguments, define [name] to be [value]\n"));
127 
128 	maxargs(optind + 1);
129 
130 	/* gvAliases created in main.c */
131 
132 	li = gvAliases->first;
133 
134 	if(argc < optind + 1) {  /* print all alias bindings */
135 		if(!li)
136 			fprintf(stderr, _("No aliases defined.\n"));
137 		else {
138 			while(li) {
139 				char *f;
140 				f = args_cat2(((alias *)li->data)->value, 0);
141 				printf("%s = '%s'\n", ((alias *)li->data)->name, f);
142 				free(f);
143 				li = li->next;
144 			}
145 		}
146 		return;
147 	}
148 
149 	ap = alias_search(argv[optind]);
150 
151 	if(argc == optind + 1) {  /* print one alias binding */
152 		if(!ap)
153 			fprintf(stderr, _("No such alias '%s'.\n"), argv[optind]);
154 		else if(ap == ALIAS_AMBIGUOUS)
155 			fprintf(stderr, _("Ambiguous alias '%s'.\n"), argv[optind]);
156 		else {
157 			char *f;
158 			f = args_cat2(ap->value, 0);
159 			printf("%s = '%s'\n", ap->name, f);
160 			free(f);
161 		}
162 		return;
163 	}
164 
165 	/* define a new alias ... */
166 
167 	{
168 		args_t *args;
169 
170 		args = args_create();
171 		args_push_back(args, argv[optind + 1]);
172 /*		args_init2(args, argc, argv, 3);*/
173 		alias_define(argv[optind], args);
174 	}
175 }
176 
cmd_unalias(int argc,char ** argv)177 void cmd_unalias(int argc, char **argv)
178 {
179 	int i;
180 	listitem *lip;
181 
182   OPT_HELP_NEW(_("Undefine an alias."), "unalias [options] <alias>", "");
183 
184 	minargs(optind);
185 
186 	if(list_numitem(gvAliases) == 0) {
187 		fprintf(stderr, _("No aliases defined.\n"));
188 		return;
189 	}
190 
191 	if(strcmp(argv[optind], "*") == 0)
192 		list_clear(gvAliases);
193 	else {
194 		for(i=optind; i<argc; i++) {
195 			lip = list_search(gvAliases, (listsearchfunc)alias_searchfunc,
196 							  argv[i]);
197 			if(!lip) {
198 				fprintf(stderr, _("No such alias '%s'.\n"), argv[i]);
199 				continue;
200 			}
201 			list_delitem(gvAliases, lip);
202 		}
203 	}
204 }
205