xref: /plan9/sys/src/ape/cmd/pax/replace.c (revision 9a747e4fd48b9f4522c70c07e8f882a15030f964)
1*9a747e4fSDavid du Colombier /* $Source: /u/mark/src/pax/RCS/replace.c,v $
2*9a747e4fSDavid du Colombier  *
3*9a747e4fSDavid du Colombier  * $Revision: 1.2 $
4*9a747e4fSDavid du Colombier  *
5*9a747e4fSDavid du Colombier  * replace.c - regular expression pattern replacement functions
6*9a747e4fSDavid du Colombier  *
7*9a747e4fSDavid du Colombier  * DESCRIPTION
8*9a747e4fSDavid du Colombier  *
9*9a747e4fSDavid du Colombier  *	These routines provide for regular expression file name replacement
10*9a747e4fSDavid du Colombier  *	as required by pax.
11*9a747e4fSDavid du Colombier  *
12*9a747e4fSDavid du Colombier  * AUTHORS
13*9a747e4fSDavid du Colombier  *
14*9a747e4fSDavid du Colombier  *	Mark H. Colburn, NAPS International
15*9a747e4fSDavid du Colombier  *
16*9a747e4fSDavid du Colombier  * Sponsored by The USENIX Association for public distribution.
17*9a747e4fSDavid du Colombier  *
18*9a747e4fSDavid du Colombier  * Copyright (c) 1989 Mark H. Colburn.
19*9a747e4fSDavid du Colombier  * All rights reserved.
20*9a747e4fSDavid du Colombier  *
21*9a747e4fSDavid du Colombier  * Redistribution and use in source and binary forms are permitted
22*9a747e4fSDavid du Colombier  * provided that the above copyright notice is duplicated in all such
23*9a747e4fSDavid du Colombier  * forms and that any documentation, advertising materials, and other
24*9a747e4fSDavid du Colombier  * materials related to such distribution and use acknowledge that the
25*9a747e4fSDavid du Colombier  * software was developed * by Mark H. Colburn and sponsored by The
26*9a747e4fSDavid du Colombier  * USENIX Association.
27*9a747e4fSDavid du Colombier  *
28*9a747e4fSDavid du Colombier  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
29*9a747e4fSDavid du Colombier  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
30*9a747e4fSDavid du Colombier  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
31*9a747e4fSDavid du Colombier  *
32*9a747e4fSDavid du Colombier  * $Log:	replace.c,v $
33*9a747e4fSDavid du Colombier  * Revision 1.2  89/02/12  10:05:59  mark
34*9a747e4fSDavid du Colombier  * 1.2 release fixes
35*9a747e4fSDavid du Colombier  *
36*9a747e4fSDavid du Colombier  * Revision 1.1  88/12/23  18:02:36  mark
37*9a747e4fSDavid du Colombier  * Initial revision
38*9a747e4fSDavid du Colombier  *
39*9a747e4fSDavid du Colombier  */
40*9a747e4fSDavid du Colombier 
41*9a747e4fSDavid du Colombier #ifndef lint
42*9a747e4fSDavid du Colombier static char *ident = "$Id: replace.c,v 1.2 89/02/12 10:05:59 mark Exp $";
43*9a747e4fSDavid du Colombier static char *copyright = "Copyright (c) 1989 Mark H. Colburn.\nAll rights reserved.\n";
44*9a747e4fSDavid du Colombier #endif /* not lint */
45*9a747e4fSDavid du Colombier 
46*9a747e4fSDavid du Colombier /* Headers */
47*9a747e4fSDavid du Colombier 
48*9a747e4fSDavid du Colombier #include "pax.h"
49*9a747e4fSDavid du Colombier 
50*9a747e4fSDavid du Colombier 
51*9a747e4fSDavid du Colombier /* add_replstr - add a replacement string to the replacement string list
52*9a747e4fSDavid du Colombier  *
53*9a747e4fSDavid du Colombier  * DESCRIPTION
54*9a747e4fSDavid du Colombier  *
55*9a747e4fSDavid du Colombier  *	Add_replstr adds a replacement string to the replacement string
56*9a747e4fSDavid du Colombier  *	list which is applied each time a file is about to be processed.
57*9a747e4fSDavid du Colombier  *
58*9a747e4fSDavid du Colombier  * PARAMETERS
59*9a747e4fSDavid du Colombier  *
60*9a747e4fSDavid du Colombier  *	char	*pattern	- A regular expression which is to be parsed
61*9a747e4fSDavid du Colombier  */
62*9a747e4fSDavid du Colombier 
63*9a747e4fSDavid du Colombier #ifdef __STDC__
64*9a747e4fSDavid du Colombier 
add_replstr(char * pattern)65*9a747e4fSDavid du Colombier void add_replstr(char *pattern)
66*9a747e4fSDavid du Colombier 
67*9a747e4fSDavid du Colombier #else
68*9a747e4fSDavid du Colombier 
69*9a747e4fSDavid du Colombier void add_replstr(pattern)
70*9a747e4fSDavid du Colombier char           *pattern;
71*9a747e4fSDavid du Colombier 
72*9a747e4fSDavid du Colombier #endif
73*9a747e4fSDavid du Colombier {
74*9a747e4fSDavid du Colombier     char           *p;
75*9a747e4fSDavid du Colombier     char            sep;
76*9a747e4fSDavid du Colombier     Replstr        *rptr;
77*9a747e4fSDavid du Colombier     int             len;
78*9a747e4fSDavid du Colombier 
79*9a747e4fSDavid du Colombier     if ((len = strlen(pattern)) < 4) {
80*9a747e4fSDavid du Colombier 	warn("Replacement string not added",
81*9a747e4fSDavid du Colombier 		 "Malformed substitution syntax");
82*9a747e4fSDavid du Colombier 	return;
83*9a747e4fSDavid du Colombier     }
84*9a747e4fSDavid du Colombier     if ((rptr = (Replstr *) malloc(sizeof(Replstr))) == (Replstr *)NULL) {
85*9a747e4fSDavid du Colombier 	warn("Replacement string not added", "No space");
86*9a747e4fSDavid du Colombier 	return;
87*9a747e4fSDavid du Colombier     }
88*9a747e4fSDavid du Colombier 
89*9a747e4fSDavid du Colombier     /* First character is the delimeter... */
90*9a747e4fSDavid du Colombier     sep = *pattern;
91*9a747e4fSDavid du Colombier 
92*9a747e4fSDavid du Colombier     /* Get trailing g and/or p */
93*9a747e4fSDavid du Colombier     p = pattern + len - 1;
94*9a747e4fSDavid du Colombier     while (*p != sep) {
95*9a747e4fSDavid du Colombier 	if (*p == 'g') {
96*9a747e4fSDavid du Colombier             rptr->global = 1;
97*9a747e4fSDavid du Colombier 	} else if (*p == 'p') {
98*9a747e4fSDavid du Colombier 	    rptr->print = 1;
99*9a747e4fSDavid du Colombier 	} else {
100*9a747e4fSDavid du Colombier 	    warn(p, "Invalid RE modifier");
101*9a747e4fSDavid du Colombier 	}
102*9a747e4fSDavid du Colombier 	p--;
103*9a747e4fSDavid du Colombier     }
104*9a747e4fSDavid du Colombier 
105*9a747e4fSDavid du Colombier     if (*p != sep) {
106*9a747e4fSDavid du Colombier 	warn("Replacement string not added", "Bad delimeters");
107*9a747e4fSDavid du Colombier 	free(rptr);
108*9a747e4fSDavid du Colombier 	return;
109*9a747e4fSDavid du Colombier     }
110*9a747e4fSDavid du Colombier     /* strip off leading and trailing delimeter */
111*9a747e4fSDavid du Colombier     *p = '\0';
112*9a747e4fSDavid du Colombier     pattern++;
113*9a747e4fSDavid du Colombier 
114*9a747e4fSDavid du Colombier     /* find the separating '/' in the pattern */
115*9a747e4fSDavid du Colombier     p = pattern;
116*9a747e4fSDavid du Colombier     while (*p) {
117*9a747e4fSDavid du Colombier 	if (*p == sep) {
118*9a747e4fSDavid du Colombier 	    break;
119*9a747e4fSDavid du Colombier 	}
120*9a747e4fSDavid du Colombier 	if (*p == '\\' && *(p + 1) != '\0') {
121*9a747e4fSDavid du Colombier 	    p++;
122*9a747e4fSDavid du Colombier 	}
123*9a747e4fSDavid du Colombier 	p++;
124*9a747e4fSDavid du Colombier     }
125*9a747e4fSDavid du Colombier     if (*p != sep) {
126*9a747e4fSDavid du Colombier 	warn("Replacement string not added", "Bad delimeters");
127*9a747e4fSDavid du Colombier 	free(rptr);
128*9a747e4fSDavid du Colombier 	return;
129*9a747e4fSDavid du Colombier     }
130*9a747e4fSDavid du Colombier     *p++ = '\0';
131*9a747e4fSDavid du Colombier 
132*9a747e4fSDavid du Colombier     /*
133*9a747e4fSDavid du Colombier      * Now pattern points to 'old' and p points to 'new' and both are '\0'
134*9a747e4fSDavid du Colombier      * terminated
135*9a747e4fSDavid du Colombier      */
136*9a747e4fSDavid du Colombier     if ((rptr->comp = regcomp(pattern)) == (regexp *)NULL) {
137*9a747e4fSDavid du Colombier 	warn("Replacement string not added", "Invalid RE");
138*9a747e4fSDavid du Colombier 	free(rptr);
139*9a747e4fSDavid du Colombier 	return;
140*9a747e4fSDavid du Colombier     }
141*9a747e4fSDavid du Colombier     rptr->replace = p;
142*9a747e4fSDavid du Colombier     rptr->next = (Replstr *)NULL;
143*9a747e4fSDavid du Colombier     if (rplhead == (Replstr *)NULL) {
144*9a747e4fSDavid du Colombier 	rplhead = rptr;
145*9a747e4fSDavid du Colombier 	rpltail = rptr;
146*9a747e4fSDavid du Colombier     } else {
147*9a747e4fSDavid du Colombier 	rpltail->next = rptr;
148*9a747e4fSDavid du Colombier 	rpltail = rptr;
149*9a747e4fSDavid du Colombier     }
150*9a747e4fSDavid du Colombier }
151*9a747e4fSDavid du Colombier 
152*9a747e4fSDavid du Colombier 
153*9a747e4fSDavid du Colombier 
154*9a747e4fSDavid du Colombier /* rpl_name - possibly replace a name with a regular expression
155*9a747e4fSDavid du Colombier  *
156*9a747e4fSDavid du Colombier  * DESCRIPTION
157*9a747e4fSDavid du Colombier  *
158*9a747e4fSDavid du Colombier  *	The string name is searched for in the list of regular expression
159*9a747e4fSDavid du Colombier  *	substituions.  If the string matches any of the regular expressions
160*9a747e4fSDavid du Colombier  *	then the string is modified as specified by the user.
161*9a747e4fSDavid du Colombier  *
162*9a747e4fSDavid du Colombier  * PARAMETERS
163*9a747e4fSDavid du Colombier  *
164*9a747e4fSDavid du Colombier  *	char	*name	- name to search for and possibly modify
165*9a747e4fSDavid du Colombier  */
166*9a747e4fSDavid du Colombier 
167*9a747e4fSDavid du Colombier #ifdef __STDC__
168*9a747e4fSDavid du Colombier 
rpl_name(char * name)169*9a747e4fSDavid du Colombier void rpl_name(char *name)
170*9a747e4fSDavid du Colombier 
171*9a747e4fSDavid du Colombier #else
172*9a747e4fSDavid du Colombier 
173*9a747e4fSDavid du Colombier void rpl_name(name)
174*9a747e4fSDavid du Colombier char           *name;
175*9a747e4fSDavid du Colombier 
176*9a747e4fSDavid du Colombier #endif
177*9a747e4fSDavid du Colombier {
178*9a747e4fSDavid du Colombier     int             found = 0;
179*9a747e4fSDavid du Colombier     int             ret;
180*9a747e4fSDavid du Colombier     Replstr        *rptr;
181*9a747e4fSDavid du Colombier     char            buff[PATH_MAX + 1];
182*9a747e4fSDavid du Colombier     char            buff1[PATH_MAX + 1];
183*9a747e4fSDavid du Colombier     char            buff2[PATH_MAX + 1];
184*9a747e4fSDavid du Colombier     char           *p;
185*9a747e4fSDavid du Colombier     char           *b;
186*9a747e4fSDavid du Colombier 
187*9a747e4fSDavid du Colombier     strcpy(buff, name);
188*9a747e4fSDavid du Colombier     for (rptr = rplhead; !found && rptr != (Replstr *)NULL; rptr = rptr->next) {
189*9a747e4fSDavid du Colombier 	do {
190*9a747e4fSDavid du Colombier 	    if ((ret = regexec(rptr->comp, buff)) != 0) {
191*9a747e4fSDavid du Colombier 		p = buff;
192*9a747e4fSDavid du Colombier 		b = buff1;
193*9a747e4fSDavid du Colombier 		while (p < rptr->comp->startp[0]) {
194*9a747e4fSDavid du Colombier 		    *b++ = *p++;
195*9a747e4fSDavid du Colombier 		}
196*9a747e4fSDavid du Colombier 		p = rptr->replace;
197*9a747e4fSDavid du Colombier 		while (*p) {
198*9a747e4fSDavid du Colombier 		    *b++ = *p++;
199*9a747e4fSDavid du Colombier 		}
200*9a747e4fSDavid du Colombier 		strcpy(b, rptr->comp->endp[0]);
201*9a747e4fSDavid du Colombier 		found = 1;
202*9a747e4fSDavid du Colombier 		regsub(rptr->comp, buff1, buff2);
203*9a747e4fSDavid du Colombier 		strcpy(buff, buff2);
204*9a747e4fSDavid du Colombier 	    }
205*9a747e4fSDavid du Colombier 	} while (ret && rptr->global);
206*9a747e4fSDavid du Colombier 	if (found) {
207*9a747e4fSDavid du Colombier 	    if (rptr->print) {
208*9a747e4fSDavid du Colombier 		fprintf(stderr, "%s >> %s\n", name, buff);
209*9a747e4fSDavid du Colombier 	    }
210*9a747e4fSDavid du Colombier 	    strcpy(name, buff);
211*9a747e4fSDavid du Colombier 	}
212*9a747e4fSDavid du Colombier     }
213*9a747e4fSDavid du Colombier }
214*9a747e4fSDavid du Colombier 
215*9a747e4fSDavid du Colombier 
216*9a747e4fSDavid du Colombier /* get_disposition - get a file disposition
217*9a747e4fSDavid du Colombier  *
218*9a747e4fSDavid du Colombier  * DESCRIPTION
219*9a747e4fSDavid du Colombier  *
220*9a747e4fSDavid du Colombier  *	Get a file disposition from the user.  If the user enters 'y'
221*9a747e4fSDavid du Colombier  *	the the file is processed, anything else and the file is ignored.
222*9a747e4fSDavid du Colombier  *	If the user enters EOF, then the PAX exits with a non-zero return
223*9a747e4fSDavid du Colombier  *	status.
224*9a747e4fSDavid du Colombier  *
225*9a747e4fSDavid du Colombier  * PARAMETERS
226*9a747e4fSDavid du Colombier  *
227*9a747e4fSDavid du Colombier  *	char	*mode	- string signifying the action to be taken on file
228*9a747e4fSDavid du Colombier  *	char	*name	- the name of the file
229*9a747e4fSDavid du Colombier  *
230*9a747e4fSDavid du Colombier  * RETURNS
231*9a747e4fSDavid du Colombier  *
232*9a747e4fSDavid du Colombier  *	Returns 1 if the file should be processed, 0 if it should not.
233*9a747e4fSDavid du Colombier  */
234*9a747e4fSDavid du Colombier 
235*9a747e4fSDavid du Colombier #ifdef __STDC__
236*9a747e4fSDavid du Colombier 
get_disposition(char * mode,char * name)237*9a747e4fSDavid du Colombier int get_disposition(char *mode, char *name)
238*9a747e4fSDavid du Colombier 
239*9a747e4fSDavid du Colombier #else
240*9a747e4fSDavid du Colombier 
241*9a747e4fSDavid du Colombier int get_disposition(mode, name)
242*9a747e4fSDavid du Colombier char	*mode;
243*9a747e4fSDavid du Colombier char	*name;
244*9a747e4fSDavid du Colombier 
245*9a747e4fSDavid du Colombier #endif
246*9a747e4fSDavid du Colombier {
247*9a747e4fSDavid du Colombier     char	ans[2];
248*9a747e4fSDavid du Colombier     char	buf[PATH_MAX + 10];
249*9a747e4fSDavid du Colombier 
250*9a747e4fSDavid du Colombier     if (f_disposition) {
251*9a747e4fSDavid du Colombier 	sprintf(buf, "%s %s? ", mode, name);
252*9a747e4fSDavid du Colombier 	if (nextask(buf, ans, sizeof(ans)) == -1 || ans[0] == 'q') {
253*9a747e4fSDavid du Colombier 	    exit(0);
254*9a747e4fSDavid du Colombier 	}
255*9a747e4fSDavid du Colombier 	if (strlen(ans) == 0 || ans[0] != 'y') {
256*9a747e4fSDavid du Colombier 	    return(1);
257*9a747e4fSDavid du Colombier 	}
258*9a747e4fSDavid du Colombier     }
259*9a747e4fSDavid du Colombier     return(0);
260*9a747e4fSDavid du Colombier }
261*9a747e4fSDavid du Colombier 
262*9a747e4fSDavid du Colombier 
263*9a747e4fSDavid du Colombier /* get_newname - prompt the user for a new filename
264*9a747e4fSDavid du Colombier  *
265*9a747e4fSDavid du Colombier  * DESCRIPTION
266*9a747e4fSDavid du Colombier  *
267*9a747e4fSDavid du Colombier  *	The user is prompted with the name of the file which is currently
268*9a747e4fSDavid du Colombier  *	being processed.  The user may choose to rename the file by
269*9a747e4fSDavid du Colombier  *	entering the new file name after the prompt; the user may press
270*9a747e4fSDavid du Colombier  *	carriage-return/newline, which will skip the file or the user may
271*9a747e4fSDavid du Colombier  *	type an 'EOF' character, which will cause the program to stop.
272*9a747e4fSDavid du Colombier  *
273*9a747e4fSDavid du Colombier  * PARAMETERS
274*9a747e4fSDavid du Colombier  *
275*9a747e4fSDavid du Colombier  *	char	*name		- filename, possibly modified by user
276*9a747e4fSDavid du Colombier  *	int	size		- size of allowable new filename
277*9a747e4fSDavid du Colombier  *
278*9a747e4fSDavid du Colombier  * RETURNS
279*9a747e4fSDavid du Colombier  *
280*9a747e4fSDavid du Colombier  *	Returns 0 if successfull, or -1 if an error occurred.
281*9a747e4fSDavid du Colombier  *
282*9a747e4fSDavid du Colombier  */
283*9a747e4fSDavid du Colombier 
284*9a747e4fSDavid du Colombier #ifdef __STDC__
285*9a747e4fSDavid du Colombier 
get_newname(char * name,int size)286*9a747e4fSDavid du Colombier int get_newname(char *name, int size)
287*9a747e4fSDavid du Colombier 
288*9a747e4fSDavid du Colombier #else
289*9a747e4fSDavid du Colombier 
290*9a747e4fSDavid du Colombier int get_newname(name, size)
291*9a747e4fSDavid du Colombier char	*name;
292*9a747e4fSDavid du Colombier int	size;
293*9a747e4fSDavid du Colombier 
294*9a747e4fSDavid du Colombier #endif
295*9a747e4fSDavid du Colombier {
296*9a747e4fSDavid du Colombier     char	buf[PATH_MAX + 10];
297*9a747e4fSDavid du Colombier 
298*9a747e4fSDavid du Colombier     if (f_interactive) {
299*9a747e4fSDavid du Colombier 	sprintf(buf, "rename %s? ", name);
300*9a747e4fSDavid du Colombier 	if (nextask(buf, name, size) == -1) {
301*9a747e4fSDavid du Colombier 	    exit(0);
302*9a747e4fSDavid du Colombier 	}
303*9a747e4fSDavid du Colombier 	if (strlen(name) == 0) {
304*9a747e4fSDavid du Colombier 	    return(1);
305*9a747e4fSDavid du Colombier 	}
306*9a747e4fSDavid du Colombier     }
307*9a747e4fSDavid du Colombier     return(0);
308*9a747e4fSDavid du Colombier }
309