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