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