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