1 /* @(#)take.c	1.25 18/08/25 Copyright 1984-2018 J. Schilling */
2 #include <schily/mconfig.h>
3 #ifndef lint
4 static	UConst char sccsid[] =
5 	"@(#)take.c	1.25 18/08/25 Copyright 1984-2018 J. Schilling";
6 #endif
7 /*
8  *	Routines that implement a set of take buffers
9  *	and take care of backing up unused buffers into a file
10  *
11  *	Copyright (c) 1984-2018 J. Schilling
12  */
13 /*
14  * The contents of this file are subject to the terms of the
15  * Common Development and Distribution License, Version 1.0 only
16  * (the "License").  You may not use this file except in compliance
17  * with the License.
18  *
19  * See the file CDDL.Schily.txt in this distribution for details.
20  * A copy of the CDDL is also available via the Internet at
21  * http://www.opensource.org/licenses/cddl1.txt
22  *
23  * When distributing Covered Code, include this CDDL HEADER in each
24  * file and include the License file CDDL.Schily.txt from this distribution.
25  */
26 
27 #include "ved.h"
28 
29 #define	MAXTAKEBUFS 32
30 
31 /*
32  * XXX eigentlich MAXFN - "vedT" - "." - sizeof (pid)
33  * XXX Bei altem UNIX:	14 - 4 - 1 - 5 == 4
34  * XXX Bei DOS:		8 - 4 == 4
35  * XXX richtigen Algorithmus finden!!!!!
36  */
37 #define	TAKENAMESIZE 17
38 
39 typedef struct {
40 	Uchar	*name;			/* The take name used in ved	*/
41 	Uchar	*pathname;		/* Related take file path name	*/
42 }  take_t;
43 
44 LOCAL	take_t	takebufs[MAXTAKEBUFS];	/* the names of take buffers	    */
45 LOCAL	int	maxbuf;			/* # of take buffers currently in use */
46 LOCAL	int	curbuf;			/* index of current take buffer	    */
47 LOCAL	Uchar	*curpath;		/* pathname of current take buffer  */
48 EXPORT	char	TAKEBUF[] = "TAKE BUF";
49 
50 EXPORT	void	settakename	__PR((ewin_t *wp, Uchar* name));
51 LOCAL	BOOL	settpath	__PR((Uchar* name, int idx));
52 LOCAL	int	checktake	__PR((Uchar* name));
53 EXPORT	Uchar	*findtake	__PR((ewin_t *wp, Uchar* name));
54 EXPORT	void	backuptake	__PR((ewin_t *wp));
55 EXPORT	void	loadtake	__PR((ewin_t *wp));
56 LOCAL	void	newtake		__PR((Uchar* name));
57 LOCAL	void	oldtake		__PR((ewin_t *wp, int idx));
58 EXPORT	void	deletetake	__PR((void));
59 EXPORT	int	fcopy		__PR((ewin_t *wp, FILE * from, FILE * to, epos_t size,
60 						char *fromname, char *toname));
61 LOCAL	void	toomany_tbufs	__PR((ewin_t *wp));
62 
63 /*
64  * Set the name of the current take buffer
65  */
66 EXPORT void
settakename(wp,name)67 settakename(wp, name)
68 	ewin_t	*wp;
69 	Uchar	*name;
70 {
71 	int	idx;
72 	Uchar	*p;
73 	Uchar	tname[TAKENAMESIZE];
74 
75 	snprintf(C tname, sizeof (tname), "%s", name);
76 	p = tname;
77 	while (*p) {
78 		/*
79 		 * Do not allow white space in the take buffer name
80 		 */
81 		if (white(*p++)) {
82 			writeerr(wp, "BAD BUFFER NAME");
83 			return;
84 		}
85 	}
86 	idx = checktake(tname);
87 	if (idx >= 0) {
88 		/*
89 		 * A take buffer with this name already exists.
90 		 */
91 		if (curbuf == idx)
92 			return;
93 		backuptake(wp);
94 		oldtake(wp, idx);
95 		writetake(wp, tname);
96 		return;
97 	}
98 
99 	if (maxbuf >= MAXTAKEBUFS) {
100 		/*
101 		 * We will not allow to open another take buffer.
102 		 */
103 		toomany_tbufs(wp);
104 		return;
105 	}
106 	/*
107 	 * Need to create a new take buffer
108 	 */
109 	backuptake(wp);
110 	newtake(tname);
111 	writetake(wp, tname);
112 }
113 
114 /*
115  * Set the name of the current take buffer
116  */
117 LOCAL BOOL
settpath(name,idx)118 settpath(name, idx)
119 	Uchar	*name;
120 	int	idx;
121 {
122 	Uchar	tpath[FNAMESIZE];
123 	Uchar	*p;
124 
125 	p = (Uchar *)malloc(strlen(C name)+1);
126 	if (p == NULL)
127 		return (FALSE);
128 
129 	strcpy(C p, C name);
130 	takebufs[idx].name = p;
131 
132 	takepath(tpath, sizeof (tpath), name);
133 	p = (Uchar *)malloc(strlen(C tpath)+1);
134 	if (p == NULL)
135 		return (FALSE);
136 
137 	strcpy(C p, C tpath);
138 	takebufs[idx].pathname = p;
139 
140 	return (TRUE);
141 }
142 
143 /*
144  * Check if a named take buffer exists
145  */
146 LOCAL int
checktake(name)147 checktake(name)
148 	Uchar	*name;
149 {
150 	int i;
151 
152 	for (i = 0; i < maxbuf; i++)
153 		if (streql(C name, C takebufs[i].name))
154 			return (i);
155 	return (-1);
156 }
157 
158 /*
159  * Get the path name of a take buffer for the execute commands.
160  * An empty name is translated into the current take buffer path.
161  * This allows to use \ for the current take buffer.
162  * If the named take bufer does not exist, create it - it may be loaded later.
163  */
164 EXPORT Uchar *
findtake(wp,name)165 findtake(wp, name)
166 	ewin_t	*wp;
167 	Uchar	*name;
168 {
169 	int idx;
170 
171 	if (*name == 0)
172 		return (curpath);
173 	if ((idx = checktake(name)) >= 0)
174 		return (takebufs[idx].pathname);
175 
176 	if (maxbuf >= MAXTAKEBUFS) {
177 		/*
178 		 * We will not allow to open another take buffer.
179 		 */
180 		toomany_tbufs(wp);
181 		return ((Uchar *)0);
182 	}
183 	settpath(name, maxbuf);
184 	return (takebufs[maxbuf++].pathname);
185 }
186 
187 /*
188  * Backup the current take file to its named take backup
189  */
190 EXPORT void
backuptake(wp)191 backuptake(wp)
192 	ewin_t *wp;
193 {
194 	FILE	*f;
195 
196 	if (maxbuf) {				/* Paranoia */
197 		if ((f = opensyserr(wp, curpath, "ctwub")) == NULL)
198 			return;
199 		stmpfmodes(curpath);
200 		fcopy(wp, takefile, f, takesize, TAKEBUF, TAKEBUF);
201 		fclose(f);
202 	}
203 }
204 
205 /*
206  * Reload the current take file from its named take backup
207  */
208 EXPORT void
loadtake(wp)209 loadtake(wp)
210 	ewin_t	*wp;
211 {
212 	if (maxbuf) 				/* Paranoia */
213 		oldtake(wp, curbuf);
214 }
215 
216 /*
217  * Create a new named take buffer
218  */
219 LOCAL void
newtake(name)220 newtake(name)
221 	Uchar	*name;
222 {
223 	settpath(name, maxbuf);
224 	takesize = 0;
225 	curbuf = maxbuf;
226 	curpath = takebufs[maxbuf++].pathname;
227 }
228 
229 /*
230  * Reload the current take file from a specific named take backup
231  */
232 LOCAL void
oldtake(wp,idx)233 oldtake(wp, idx)
234 	ewin_t	*wp;
235 	int	idx;
236 {
237 	FILE	*f;
238 
239 	if (maxbuf == 0)			/* Paranoia */
240 		return;
241 	curbuf = idx;
242 	curpath = takebufs[idx].pathname;
243 	if ((f = opensyserr(wp, curpath, "rub")) == NULL)
244 		return;
245 	takesize = filesize(f);
246 	fcopy(wp, f, takefile, takesize, TAKEBUF, TAKEBUF);
247 	fclose(f);
248 }
249 
250 /*
251  * Delete all named take buffers
252  */
253 EXPORT void
deletetake()254 deletetake()
255 {
256 	int i;
257 
258 	for (i = 0; i < maxbuf; i++) {
259 		if (takebufs[i].pathname[0] != '\0')
260 			unlink(C takebufs[i].pathname);
261 	}
262 }
263 
264 /*
265  * Copy one open file into another empty file
266  */
267 EXPORT int
fcopy(wp,from,to,size,fromname,toname)268 fcopy(wp, from, to, size, fromname, toname)
269 	ewin_t 	*wp;
270 	FILE	*from;
271 	FILE	*to;
272 	epos_t 	size;
273 	char 	*fromname;
274 	char	*toname;
275 {
276 	Uchar	buf[BUFSIZ < 8192 ? 8192 : BUFSIZ];
277 	int	amount;
278 	int	result;
279 
280 	lseek(fdown(from), (off_t)0, SEEK_SET);
281 	lseek(fdown(to), (off_t)0, SEEK_SET);
282 	while (size > 0) {
283 		amount = min(size, sizeof (buf));
284 		if ((result = readsyserr(wp, from, buf, amount, UC fromname)) <= 0)
285 			return (result);
286 		if ((amount = writesyserr(wp, to, buf, result, UC toname)) != result)
287 			return (amount);
288 		size -= amount;
289 	}
290 	return (0);
291 }
292 
293 LOCAL void
toomany_tbufs(wp)294 toomany_tbufs(wp)
295 	ewin_t	*wp;
296 {
297 	writeerr(wp, "TOO MANY TAKE BUFFERS");
298 }
299