1 /*****************************************************************************/
2 /* */
3 /* (C) Copyright 1992-1997 Alberto Pasquale */
4 /* */
5 /* A L L R I G H T S R E S E R V E D */
6 /* */
7 /*****************************************************************************/
8 /* */
9 /* This source code is NOT in the public domain and it CANNOT be used or */
10 /* distributed without written permission from the author. */
11 /* */
12 /*****************************************************************************/
13 /* */
14 /* How to contact the author: Alberto Pasquale of 2:332/504@fidonet */
15 /* Viale Verdi 106 */
16 /* 41100 Modena */
17 /* Italy */
18 /* */
19 /*****************************************************************************/
20
21 // Edit.Cpp
22
23
24 #ifdef __OS2__
25 #define INCL_DOS
26 #include <os2.h>
27 #endif
28
29 #include <apgenlib.hpp>
30 #include <time.h>
31 #include <stdio.h>
32 #include <string.h>
33 #include <ctype.h>
34 #include <stdlib.h>
35 #include "edit.hpp"
36 #include "defines.hpp"
37 #include "misc.hpp"
38 #include "cfgdata.hpp"
39 #include "data.hpp"
40 #include "crc16.hpp"
41 #include "parse.hpp"
42
43
EDIT(char * BeforeCmd,char * AfterCmd)44 EDIT::EDIT (char *BeforeCmd, char *AfterCmd)
45 {
46 EDIT::BeforeCmd = BeforeCmd;
47 EDIT::AfterCmd = AfterCmd;
48
49 old_name = new char[PATH_MAX];
50 diff_name = new char[PATH_MAX];
51 new_name = new char[PATH_MAX];
52 }
53
54
~EDIT(void)55 EDIT::~EDIT (void)
56 {
57 delete[] new_name;
58 delete[] diff_name;
59 delete[] old_name;
60 }
61
62
DoEdit(void)63 int EDIT::DoEdit (void)
64 { /* Actually put the new lines in here */
65 char line[LINESIZE];
66 word official_crc = 0;
67 int i, j;
68
69 int ErrorFull = 0, ErrorRead = 0;
70 word calc_crc = 0;
71 BOOL first_add = TRUE;
72
73 while ((fgets (line, LINESIZE, Diff)) != NULL) {
74 if (line[0] == 0x1A) // ^Z
75 break;
76 switch (line[0]) {
77 case ';':
78 continue;
79
80 case 'D':
81 j = atoi (line+1);
82 for (i = 0; i < j; i++)
83 ErrorRead |= (fgets (line, LINESIZE, Old) == NULL);
84 break;
85
86 case 'A':
87 j = atoi (line+1);
88 for (i = 0; i < j; i++) {
89 ErrorRead |= (fgets (line, LINESIZE, Diff) == NULL);
90 if (!first_add)
91 calc_crc = crcstr (line, calc_crc);
92 else {
93 first_add = FALSE;
94 char *ptr = strrchr (line, ':');
95 if (!ptr) {
96 vprintlogrsp (MsgLogRsp, "Error: Cannot find new CRC !\n");
97 return -1;
98 }
99 official_crc = (word) atoi (ptr+1);
100 }
101 ErrorFull |= (fputs (line, New) == EOF);
102 }
103 break;
104
105 case 'C':
106 j = atoi (line+1);
107 for (i = 0; i < j; i++) {
108 ErrorRead |= (fgets (line, sizeof (line), Old) == NULL);
109 calc_crc = crcstr (line, calc_crc);
110 ErrorFull |= (fputs (line, New) == EOF);
111 }
112 break;
113
114 default:
115 vprintlogrsp (MsgLogRsp, "Spurious line: %.200s", line);
116 break;
117 }
118
119 if (ErrorRead || ErrorFull || Break)
120 break;
121 }
122
123 fprintf (New, "%c", '\x1A'); // terminating ^Z
124
125 if (ErrorRead) {
126 vprintlogrsp (MsgLogRsp, "Read Error\n");
127 errorlevel = READ_ON_DIFF;
128 return -1;
129 } else
130 if (ErrorFull) {
131 errorlevel = DISK_FULL;
132 return -1;
133 } else
134 if (Break) {
135 errorlevel = USER_BREAK;
136 return -1;
137 }
138
139 if (calc_crc != official_crc) {
140 vprintlogrsp (MsgLogRsp, "\nCRC ERROR: actual/expected CRC: %05hu/%05hu !\n\n", calc_crc, official_crc);
141 errorlevel = CRC_ON_DIFF; /* crc error */
142 if (!nocrcexit)
143 return -1;
144 }
145
146 return 0; /* ok */
147 }
148
149
Open(void)150 int EDIT::Open (void)
151 {
152 char first_line[LINESIZE];
153 char *ptr;
154
155 strcpy (old_name, NodeList);
156 SetDay3 (old_name, ListDay);
157
158 strcpy (new_name, NodeList);
159 SetDay3 (new_name, DiffDay);
160
161 strcpy (diff_name, NodeDiff);
162 SetDay3 (diff_name, DiffDay);
163
164 Old = New = Diff = NULL;
165
166 if (BeforeCmd)
167 RunCmd (BeforeCmd, RCf, "ld", old_name, diff_name);
168
169 vprintlogrsp (MsgLogRsp, "Applying \"%s\" to \"%s\"\n", diff_name, old_name);
170
171 if ((Old = fopen (old_name, "rb")) == NULL) {
172 vprintlogrsp (MsgLogRsp, "Error opening \"%s\" !\n", old_name);
173 return -1;
174 }
175 setvbuf (Old, NULL, _IOFBF, BufSize);
176
177 if (fgets (first_line, LINESIZE, Old) == NULL) {
178 vprintlogrsp (MsgLogRsp, "Read Error on Old List file !\n");
179 return -1;
180 }
181 rewind (Old);
182
183 if ((ptr = strrchr (first_line, ':')) == NULL) {
184 vprintlogrsp (MsgLogRsp, "Error: Cannot find old day/crc in Old List file !\n");
185 return 1;
186 }
187
188 word list_old_crc = (word) atoi (ptr+1); // get crc of old list
189
190 if ((Diff = fopen (diff_name, "rb")) == NULL) {
191 vprintlogrsp (MsgLogRsp, "Error opening \"%s\" !\n", diff_name);
192 return -1;
193 }
194 setvbuf (Diff, NULL, _IOFBF, BufSize);
195
196 if (fgets (first_line, LINESIZE, Diff) == NULL) {
197 vprintlogrsp (MsgLogRsp, "Read Error on Diff file !\n");
198 return -1;
199 }
200
201 if ((ptr = strrchr (first_line, ':')) == NULL) {
202 vprintlogrsp (MsgLogRsp, "Error: Cannot find old day/crc in Diff file !\n");
203 return 1;
204 }
205
206 word diff_old_crc = (word) atoi (ptr+1); // get crc req for old list
207
208 do
209 ptr--;
210 while ((ptr > first_line) && isspace (*ptr));
211 while ((ptr > first_line) && IsDigit (*ptr))
212 ptr--;
213
214 int diff_old_day = atoi (ptr); // get day of old list
215
216 if (diff_old_day != ListDay) {
217 vprintlogrsp (MsgLogRsp, "Error: Diff %03d requires List %03d, not existing %03d !\n", DiffDay, diff_old_day, ListDay);
218 return 1;
219 }
220
221 if (diff_old_crc != list_old_crc) {
222 vprintlogrsp (MsgLogRsp, "Error: Diff %03d requires List %03d with crc %05hu, not %05hu !\n", DiffDay, diff_old_day, diff_old_crc, list_old_crc);
223 return 1;
224 }
225
226 if ((New = fopen (new_name, "wb")) == NULL) {
227 vprintlogrsp (MsgLogRsp, "Can't open \"%s\" !\n", new_name);
228 return -1;
229 }
230 setvbuf (New, NULL, _IOFBF, BufSize);
231
232 return 0;
233 }
234
235
Close(BOOL Ok)236 void EDIT::Close (BOOL Ok)
237 {
238 time_t difftime = 0;
239
240 if (Old)
241 fclose (Old);
242 if (Diff) {
243 difftime = DosFileTime (fileno (Diff));
244 fclose (Diff);
245 }
246 if (New && Ok) {
247 if (fclose (New) == EOF) {
248 errorlevel = DISK_FULL;
249 Ok = FALSE;
250 } else {
251 if (!touchf (new_name, difftime))
252 vprintlogrsp (MsgLogRsp, "Error setting date and time of \"%s\"\n", new_name);
253 }
254 }
255
256 if (errorlevel == DISK_FULL)
257 vprintlogrsp (MsgLogRsp, "Disk Full\n");
258
259 if ((!Ok) && New) {
260 vprintlog ("Erasing \"%s\"\n", new_name);
261 KillWriteFile (New, new_name);
262 if (Break)
263 myexit (USER_BREAK);
264 } else
265 if (Ok) {
266 vprintlog ("Erasing \"%s\" and \"%s\"\n", old_name, diff_name);
267 EraseFile (old_name);
268 EraseFile (diff_name);
269 if (AfterCmd)
270 RunCmd (AfterCmd, RCf, "l", new_name);
271 }
272 }
273
274
Apply(char * NodeList,int ListDay,char * NodeDiff,int DiffDay)275 int EDIT::Apply (char *NodeList, int ListDay, char *NodeDiff, int DiffDay)
276 {
277 EDIT::NodeList = NodeList;
278 EDIT::NodeDiff = NodeDiff;
279 EDIT::ListDay = ListDay;
280 EDIT::DiffDay = DiffDay;
281
282 int ret; // 0 = success, -1 = error, 1 = day mismatch
283
284 ret = Open ();
285
286 if (ret == 0)
287 ret = DoEdit ();
288
289 Close (ret ? FALSE : TRUE);
290
291 return ret;
292 }
293
294
295