xref: /freebsd/crypto/heimdal/appl/ftp/ftp/domacro.c (revision 61e21613)
1 /*
2  * Copyright (c) 1985, 1993, 1994
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *	This product includes software developed by the University of
16  *	California, Berkeley and its contributors.
17  * 4. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33 
34 #include "ftp_locl.h"
35 RCSID("$Id$");
36 
37 void
38 domacro(int argc, char **argv)
39 {
40 	int i, j, count = 2, loopflg = 0;
41 	char *cp1, *cp2, line2[200];
42 	struct cmd *c;
43 
44 	if (argc < 2 && !another(&argc, &argv, "macro name")) {
45 		printf("Usage: %s macro_name.\n", argv[0]);
46 		code = -1;
47 		return;
48 	}
49 	for (i = 0; i < macnum; ++i) {
50 		if (!strncmp(argv[1], macros[i].mac_name, 9)) {
51 			break;
52 		}
53 	}
54 	if (i == macnum) {
55 		printf("'%s' macro not found.\n", argv[1]);
56 		code = -1;
57 		return;
58 	}
59 	strlcpy(line2, line, sizeof(line2));
60 TOP:
61 	cp1 = macros[i].mac_start;
62 	while (cp1 != macros[i].mac_end) {
63 		while (isspace((unsigned char)*cp1)) {
64 			cp1++;
65 		}
66 		cp2 = line;
67 		while (*cp1 != '\0') {
68 		      size_t len;
69 		      switch(*cp1) {
70 		   	    case '\\':
71 				if (line + sizeof(line) - 2 < cp2)
72 				    goto out;
73 				*cp2++ = *++cp1;
74 				 break;
75 			    case '$':
76 				 if (isdigit((unsigned char)*(cp1+1))) {
77 				    j = 0;
78 				    while (isdigit((unsigned char)*++cp1)) {
79 					  j = 10*j +  *cp1 - '0';
80 				    }
81 				    cp1--;
82 				    if (argc - 2 >= j) {
83 					len = sizeof(line) - (cp2 - line) - 1;
84 					if (strlcpy(cp2, argv[j+1], len) >= len)
85 					    goto out;
86 					cp2 += strlen(argv[j+1]);
87 				    }
88 				    break;
89 				 }
90 				 if (*(cp1+1) == 'i') {
91 					loopflg = 1;
92 					cp1++;
93 					if (count < argc) {
94 					   len = sizeof(line) - (cp2 - line) - 1;
95 					   if (strlcpy(cp2, argv[count], len) >= len)
96 					       goto out;
97 					   cp2 += strlen(argv[count]);
98 					}
99 					break;
100 				}
101 				/* intentional drop through */
102 			    default:
103 				if (line + sizeof(line) - 2 < cp2)
104 				    goto out;
105 				*cp2++ = *cp1;
106 				break;
107 		      }
108 		      if (*cp1 != '\0') {
109 			 cp1++;
110 		      }
111 		}
112 	out:
113 		*cp2 = '\0';
114 		makeargv();
115 		c = getcmd(margv[0]);
116 		if (c == (struct cmd *)-1) {
117 			printf("?Ambiguous command\n");
118 			code = -1;
119 		}
120 		else if (c == 0) {
121 			printf("?Invalid command\n");
122 			code = -1;
123 		}
124 		else if (c->c_conn && !connected) {
125 			printf("Not connected.\n");
126 			code = -1;
127 		}
128 		else {
129 			if (verbose) {
130 				printf("%s\n",line);
131 			}
132 			(*c->c_handler)(margc, margv);
133 			if (bell && c->c_bell) {
134 				putchar('\007');
135 			}
136 			strlcpy(line, line2, sizeof(line));
137 			makeargv();
138 			argc = margc;
139 			argv = margv;
140 		}
141 		if (cp1 != macros[i].mac_end) {
142 			cp1++;
143 		}
144 	}
145 	if (loopflg && ++count < argc) {
146 		goto TOP;
147 	}
148 }
149