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