1185377Ssam/*
2187831Ssam * Copyright (c) 1985, 1993, 1994
3185377Ssam *	The Regents of the University of California.  All rights reserved.
4185377Ssam *
5185377Ssam * Redistribution and use in source and binary forms, with or without
6185377Ssam * modification, are permitted provided that the following conditions
7185377Ssam * are met:
8185377Ssam * 1. Redistributions of source code must retain the above copyright
9185377Ssam *    notice, this list of conditions and the following disclaimer.
10185377Ssam * 2. Redistributions in binary form must reproduce the above copyright
11185377Ssam *    notice, this list of conditions and the following disclaimer in the
12185377Ssam *    documentation and/or other materials provided with the distribution.
13185377Ssam * 3. All advertising materials mentioning features or use of this software
14185377Ssam *    must display the following acknowledgement:
15185377Ssam *	This product includes software developed by the University of
16185377Ssam *	California, Berkeley and its contributors.
17185907Ssam * 4. Neither the name of the University nor the names of its contributors
18185377Ssam *    may be used to endorse or promote products derived from this software
19185377Ssam *    without specific prior written permission.
20185377Ssam *
21185377Ssam * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22185377Ssam * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23185377Ssam * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24185377Ssam * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25185377Ssam * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26185377Ssam * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27185377Ssam * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28185377Ssam * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29185377Ssam * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30185377Ssam * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31185377Ssam * SUCH DAMAGE.
32185377Ssam */
33185377Ssam
34185377Ssam#include "ftp_locl.h"
35185377SsamRCSID("$Id$");
36185377Ssam
37185377Ssamvoid
38185377Ssamdomacro(int argc, char **argv)
39185377Ssam{
40185377Ssam	int i, j, count = 2, loopflg = 0;
41185377Ssam	char *cp1, *cp2, line2[200];
42185377Ssam	struct cmd *c;
43185377Ssam
44185377Ssam	if (argc < 2 && !another(&argc, &argv, "macro name")) {
45185377Ssam		printf("Usage: %s macro_name.\n", argv[0]);
46185377Ssam		code = -1;
47185377Ssam		return;
48185377Ssam	}
49185377Ssam	for (i = 0; i < macnum; ++i) {
50185377Ssam		if (!strncmp(argv[1], macros[i].mac_name, 9)) {
51185377Ssam			break;
52185377Ssam		}
53185377Ssam	}
54185377Ssam	if (i == macnum) {
55185377Ssam		printf("'%s' macro not found.\n", argv[1]);
56185377Ssam		code = -1;
57185377Ssam		return;
58185377Ssam	}
59185377Ssam	strlcpy(line2, line, sizeof(line2));
60185377SsamTOP:
61185377Ssam	cp1 = macros[i].mac_start;
62185377Ssam	while (cp1 != macros[i].mac_end) {
63185377Ssam		while (isspace((unsigned char)*cp1)) {
64185377Ssam			cp1++;
65185377Ssam		}
66185377Ssam		cp2 = line;
67185377Ssam		while (*cp1 != '\0') {
68185377Ssam		      size_t len;
69185377Ssam		      switch(*cp1) {
70185377Ssam		   	    case '\\':
71185377Ssam				if (line + sizeof(line) - 2 < cp2)
72185377Ssam				    goto out;
73185377Ssam				*cp2++ = *++cp1;
74185380Ssam				 break;
75185380Ssam			    case '$':
76185380Ssam				 if (isdigit((unsigned char)*(cp1+1))) {
77185380Ssam				    j = 0;
78185380Ssam				    while (isdigit((unsigned char)*++cp1)) {
79185380Ssam					  j = 10*j +  *cp1 - '0';
80185380Ssam				    }
81185380Ssam				    cp1--;
82185380Ssam				    if (argc - 2 >= j) {
83185380Ssam					len = sizeof(line) - (cp2 - line) - 1;
84185380Ssam					if (strlcpy(cp2, argv[j+1], len) >= len)
85185380Ssam					    goto out;
86185380Ssam					cp2 += strlen(argv[j+1]);
87185380Ssam				    }
88185380Ssam				    break;
89185380Ssam				 }
90185380Ssam				 if (*(cp1+1) == 'i') {
91185380Ssam					loopflg = 1;
92185380Ssam					cp1++;
93185380Ssam					if (count < argc) {
94185380Ssam					   len = sizeof(line) - (cp2 - line) - 1;
95185380Ssam					   if (strlcpy(cp2, argv[count], len) >= len)
96185380Ssam					       goto out;
97185380Ssam					   cp2 += strlen(argv[count]);
98185380Ssam					}
99185380Ssam					break;
100185380Ssam				}
101185380Ssam				/* intentional drop through */
102185380Ssam			    default:
103185380Ssam				if (line + sizeof(line) - 2 < cp2)
104185380Ssam				    goto out;
105185380Ssam				*cp2++ = *cp1;
106185380Ssam				break;
107185377Ssam		      }
108185377Ssam		      if (*cp1 != '\0') {
109185377Ssam			 cp1++;
110185377Ssam		      }
111185377Ssam		}
112185377Ssam	out:
113185377Ssam		*cp2 = '\0';
114185377Ssam		makeargv();
115185377Ssam		c = getcmd(margv[0]);
116185377Ssam		if (c == (struct cmd *)-1) {
117185377Ssam			printf("?Ambiguous command\n");
118185377Ssam			code = -1;
119185377Ssam		}
120185377Ssam		else if (c == 0) {
121185380Ssam			printf("?Invalid command\n");
122185380Ssam			code = -1;
123185380Ssam		}
124185380Ssam		else if (c->c_conn && !connected) {
125185377Ssam			printf("Not connected.\n");
126185377Ssam			code = -1;
127185377Ssam		}
128185377Ssam		else {
129185377Ssam			if (verbose) {
130185377Ssam				printf("%s\n",line);
131185377Ssam			}
132185377Ssam			(*c->c_handler)(margc, margv);
133185380Ssam			if (bell && c->c_bell) {
134185380Ssam				putchar('\007');
135185380Ssam			}
136185380Ssam			strlcpy(line, line2, sizeof(line));
137185377Ssam			makeargv();
138185377Ssam			argc = margc;
139185377Ssam			argv = margv;
140185377Ssam		}
141185377Ssam		if (cp1 != macros[i].mac_end) {
142185377Ssam			cp1++;
143185377Ssam		}
144185377Ssam	}
145185377Ssam	if (loopflg && ++count < argc) {
146185377Ssam		goto TOP;
147185377Ssam	}
148185377Ssam}
149185377Ssam