On linux do not include X11/Xlocale.h but locale.h, this prevents
[oweals/cde.git] / cde / programs / dthelp / parser.ccdf / helpcomp / helpcomp.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /* Copyright 1992     Hewlett-Packard Co. */
24 static char *version = "$XConsortium: helpcomp.c /main/3 1995/11/08 11:10:34 rswiston $";
25
26 #include <stdio.h>
27 #include <string.h>
28 #include <fcntl.h>
29 #include <errno.h>
30 #include <malloc.h>
31 #include <dirent.h>
32 #include <sys/stat.h>
33
34 typedef char  LineBuff[BUFSIZ];
35 typedef char  FileBuff[BUFSIZ];
36 typedef char *FileName;
37
38 #define MIN(a,b) (((a) < (b)) ? (a) : (b))
39
40 static char     *prog_name;
41 static char      fileNamePrefix[] = "hc";
42 static FileName  newHvFileName, newHtFileName,
43                  topicFileName, topicZFileName;
44
45
46 /* issues an error message, cleans up temp files and exits */
47 void
48 ErrorExit(const char *who, const char *how)
49 {
50 fprintf(stderr, "%s -> %s: %s\n", prog_name, who, how);
51
52 if (newHvFileName)  unlink(newHvFileName);
53 if (newHtFileName)  unlink(newHtFileName);
54 if (topicFileName)  unlink(topicFileName);
55 if (topicZFileName) unlink(topicZFileName);
56
57 exit(1);
58 }
59
60
61 /* converts errno into a string and calls ErrorExit() */
62 void
63 ErrorIntExit(const char *who, const int how)
64 {
65 ErrorExit(who, strerror(how));
66 }
67
68
69 /* copies a file by name to another file by name */
70 int
71 CopyFile(const char *toName, const char *fromName)
72 {
73 int      toFile, fromFile;
74 int      bytesRead;
75 FileBuff fileBuff;
76
77 toFile = open(toName, O_WRONLY|O_CREAT, 0666);
78 if (toFile < 0)
79     {
80     ErrorIntExit(toName, errno);
81     }
82
83 fromFile = open(fromName, O_RDONLY);
84 if (fromFile < 0)
85     {
86     ErrorIntExit(fromName, errno);
87     }
88
89 while ((bytesRead = read(fromFile, fileBuff, sizeof(fileBuff))) > 0)
90     {
91     if (write(toFile, fileBuff, bytesRead) != bytesRead)
92         {
93         ErrorIntExit(toName, errno);
94         }
95     if (bytesRead < sizeof(fileBuff))
96         break;
97     }
98
99 close(fromFile);
100 close(toFile);
101
102 if (bytesRead < 0)
103     return 1;
104
105 return 0;
106 }
107
108
109 /*
110  * Here's the idea:
111  *
112  * Open the old .hv file and a temp file to contain the new .hv file.
113  *
114  * Copy lines from the old to the new up to and including the line
115  * "# Topic Locations".
116  *
117  * Then, iteratively look for lines containing the string ".filename:",
118  * copying lines from the old .hv to the new until such a line is found.
119  * Copy the found line to the new .hv as well.
120  *
121  * If the file name specified after the found string specifies a new
122  * file, finish writing the last open .ht if one exists (i.e., we are
123  * not in the first pass through the loop.  Close the previous old .ht
124  * file and the previous new .ht file and move the new one to replace
125  * the old one.  Open the recent .ht file specified and open a temp file
126  * to contain the new .ht file.
127  *
128  * Read the next line from the old .hv file to get the offset into the
129  * file of the next topic.  Subtract the current offset from the next
130  * offset to get the size of the current topic.  Read that many bytes
131  * from the old .ht file into a newly created topic file.  Close the topic
132  * file and execute compress(1) on it.  Attempt to open the topic file
133  * this time with a .Z extension.  If possible, the topic was compressed.
134  * If not possible, reopen the topic file as an uncompressed topic.
135  *
136  * Append either a 0x0 (compressed) or 0xff (uncompressed) byte to the
137  * new .ht file followed by three bytes holding the size of the topic
138  * determined by fstat'ing the open topic file.  The three bytes are
139  * computed using div/mod rather than right shift and mask to avoid byte
140  * sex problems.
141  * 
142  * Append the contents of the topic file to the new .ht file.
143  *
144  * Continue opening, compressing and appending compressed topic files
145  * until a blank line is found in the old .hv file.
146  *
147  * When the blank line is found, copy the remaining lines of the old .hv
148  * file to the new .hv file.  When finished, move the new .hv file to 
149  * replace the old one.
150 */
151 int
152 main(int argc, char **argv)
153 {
154 char         *pc;
155 FILE         *oldHvFile, *newHvFile;
156 int           oldHtFile,  newHtFile, topicZFile;
157 FileName      oldHvFileName;
158 LineBuff      lineBuff, string1, string2, lastString2, command;
159 FileBuff      fileBuff;
160 int           oldOffset, newOffset;
161 int           bytesToRead, bytesRead, totalBytes, zFileSize;
162 unsigned char zTmp[4];
163 int           doBreak, firstPass, result;
164 struct stat   statBuf;
165
166 pc = strrchr(argv[0], '/');
167 if (pc) pc++;
168 else pc = argv[0];
169 prog_name = malloc(strlen(pc) + 1);
170 if (!prog_name)
171     {
172     fprintf(stderr, "%s: could not copy the program name (no memory)", pc);
173     return 1;
174     }
175 strcpy(prog_name, pc);
176
177 if (argc != 2)
178     {
179     fprintf(stderr, "usage: %s <help volume base name>\n", prog_name);
180     return 1;
181     }
182
183 oldHvFileName = malloc(strlen(argv[1]) + 3 + 1); /* add ".hv" and null */
184 if (!oldHvFileName)
185     {
186     ErrorExit("malloc", "could not create a temporary file name");
187     }
188 strcpy(oldHvFileName, argv[1]);
189 strcat(oldHvFileName, ".hv");
190 oldHvFile = fopen(oldHvFileName, "r");
191 if (!oldHvFile)
192     {
193     ErrorIntExit(oldHvFileName, errno);
194     }
195
196 newHvFileName = tempnam(NULL, fileNamePrefix);
197 if (!newHvFileName)
198     {
199     ErrorExit("tempnam", "could not create a temporary file name");
200     }
201 newHvFile = fopen(newHvFileName, "w");
202 if (!newHvFile)
203     {
204     ErrorIntExit(newHvFileName, errno);
205     }
206
207 do  {
208     if (!fgets(lineBuff, sizeof(lineBuff), oldHvFile))
209         {
210         ErrorExit(oldHvFileName, "premature end of input file");
211         }
212     fputs(lineBuff, newHvFile);
213     }
214 while (strncmp(lineBuff, "# Topic Locations", sizeof("# Topic Locations") - 1));
215
216
217 firstPass = 1;
218
219 topicFileName = tempnam(NULL, fileNamePrefix);
220 if (!topicFileName)
221     {
222     ErrorExit("tempnam", "could not create a temporary file name");
223     }
224 strcpy(command, "compress ");
225 strcat(command, topicFileName);
226
227 topicZFileName = malloc(strlen(topicFileName) + 2 + 1); /* add ".Z" and null */
228 if (!topicZFileName)
229     {
230     ErrorExit("malloc", "could not create a temporary file name");
231     }
232 strcpy(topicZFileName, topicFileName);
233 strcat(topicZFileName, ".Z");
234
235 newHtFileName = tempnam(NULL, fileNamePrefix);
236 if (!newHtFileName)
237     {
238     ErrorExit("tempnam", "could not create a temporary file name");
239     }
240 newHtFile = open(newHtFileName, O_WRONLY|O_CREAT, 0666);
241 if (!newHtFile)
242     {
243     ErrorIntExit(newHtFileName, errno);
244     }
245 totalBytes = 0;
246
247 doBreak = 0;
248 result  = 0;
249 while (1)
250     {
251     if (!fgets(lineBuff, sizeof(lineBuff), oldHvFile))
252         {
253         ErrorExit(oldHvFileName, "premature end of input file");
254         }
255     if (*lineBuff != '\n')
256         {
257         char *pc;
258
259         fputs(lineBuff, newHvFile);
260         sscanf(lineBuff, "%s %s", string1, string2);
261         pc = strrchr(string1, '.');
262         if (!pc || (strcmp(pc, ".filename:") != 0))
263             continue;
264         if (firstPass)
265             {
266             firstPass = 0;
267             oldOffset = 0;
268             strcpy(lastString2, string2);
269             if ((oldHtFile = open(string2, O_RDONLY)) < 0)
270                 {
271                 ErrorIntExit(string2, errno);
272                 }
273             }
274         }
275     else
276         {
277         doBreak = 1;
278         string2[0] = 0;
279         }
280     if (strcmp(string2, lastString2) != 0)
281         {
282         topicZFile = open(topicFileName, O_WRONLY|O_CREAT, 0666);
283         if (topicZFile < 0)
284             {
285             ErrorIntExit(topicFileName, errno);
286             }
287         while (bytesRead = read(oldHtFile, fileBuff, sizeof(fileBuff)))
288             {
289             if (write(topicZFile, fileBuff, bytesRead) != bytesRead)
290                 {
291                 ErrorIntExit(string2, errno);
292                 }
293             if (bytesRead < sizeof(fileBuff))
294                 break;
295             }
296         close(topicZFile);
297         system(command);
298
299         zTmp[0] = 0;
300         if ((topicZFile = open(topicZFileName, O_RDONLY)) < 0)
301             {
302             zTmp[0] = ~0;
303             topicZFile = open(topicFileName, O_RDONLY);
304             }
305         if (topicZFile < 0)
306             {
307             char *who;
308
309             who = (char *) malloc(strlen(topicFileName)  +
310                                   strlen(topicZFileName) +
311                                   sizeof(" or "));
312             strcpy(who, topicFileName);
313             strcat(who, " or ");
314             strcat(who, topicZFileName);
315             ErrorIntExit(who, errno);
316             }
317
318         if (fstat(topicZFile, &statBuf) < 0)
319             {
320             ErrorIntExit(topicZFileName, errno);
321             }
322
323         zFileSize = statBuf.st_size;
324
325         zTmp[3] = zFileSize % 256;
326         zFileSize /= 256;
327         zTmp[2] = zFileSize % 256;
328         zFileSize /= 256;
329         zTmp[1] = zFileSize % 256;
330         if (write(newHtFile, zTmp, 4) != 4)
331             {
332             ErrorIntExit(newHtFileName, errno);
333             }
334
335         while (bytesRead = read(topicZFile, fileBuff, sizeof(fileBuff)))
336             {
337             if (write(newHtFile, fileBuff, bytesRead) != bytesRead)
338                 {
339                 ErrorIntExit(string2, errno);
340                 }
341             if (bytesRead < sizeof(fileBuff))
342                 break;
343             }
344         close(topicZFile);
345         unlink(topicFileName);
346         unlink(topicZFileName);
347
348         unlink(lastString2);
349         result = CopyFile(lastString2, newHtFileName);
350         unlink(newHtFileName);
351
352         if (doBreak || result)
353             break;
354
355         newHtFile = open(newHtFileName, O_WRONLY|O_CREAT, 0666);
356         if (!newHtFile)
357             {
358             ErrorIntExit(newHtFileName, errno);
359             }
360         totalBytes = 0;
361
362         strcpy(lastString2, string2);
363         oldOffset = 0;
364         if ((oldHtFile = open(string2, O_RDONLY)) < 0)
365             {
366             ErrorIntExit(string2, errno);
367             }
368         }
369     if (!fgets(lineBuff, sizeof(lineBuff), oldHvFile))
370         {
371         ErrorIntExit(oldHvFileName, errno);
372         }
373     sscanf(lineBuff, "%s %d", string1, &newOffset);
374     if (newOffset != oldOffset)
375         {
376         bytesToRead = newOffset - oldOffset;
377         topicZFile = open(topicFileName, O_WRONLY|O_CREAT, 0666);
378         if (topicZFile < 0)
379             {
380             ErrorIntExit(topicFileName, errno);
381             }
382         while (bytesRead = read(oldHtFile,
383                                 fileBuff,
384                                 MIN(bytesToRead, sizeof(fileBuff))))
385             {
386             if (write(topicZFile, fileBuff, bytesRead) != bytesRead)
387                 {
388                 ErrorIntExit(topicFileName, errno);
389                 }
390             if ((bytesToRead -= bytesRead) == 0)
391                 break;
392             }
393         close(topicZFile);
394         system(command);
395
396         zTmp[0] = 0;
397         if ((topicZFile = open(topicZFileName, O_RDONLY)) < 0)
398             {
399             zTmp[0] = ~0;
400             topicZFile = open(topicFileName, O_RDONLY);
401             }
402         if (topicZFile < 0)
403             {
404             char *who;
405
406             who = (char *) malloc(strlen(topicFileName)  +
407                                   strlen(topicZFileName) +
408                                   sizeof(" or "));
409             strcpy(who, topicFileName);
410             strcat(who, " or ");
411             strcat(who, topicZFileName);
412             ErrorIntExit(who, errno);
413             }
414
415         if (fstat(topicZFile, &statBuf) < 0)
416             {
417             ErrorIntExit(topicZFileName, errno);
418             }
419
420         zFileSize = statBuf.st_size;
421
422         zTmp[3] = zFileSize % 256;
423         zFileSize /= 256;
424         zTmp[2] = zFileSize % 256;
425         zFileSize /= 256;
426         zTmp[1] = zFileSize % 256;
427         if (write(newHtFile, zTmp, 4) != 4)
428             {
429             ErrorIntExit(newHtFileName, errno);
430             }
431
432         totalBytes += statBuf.st_size + 4;
433
434         while (bytesRead = read(topicZFile, fileBuff, sizeof(fileBuff)))
435             {
436             if (write(newHtFile, fileBuff, bytesRead) != bytesRead)
437                 {
438                 ErrorIntExit(newHtFileName, errno);
439                 }
440             if (bytesRead < sizeof(fileBuff))
441                 break;
442             }
443         close(topicZFile);
444         unlink(topicFileName);
445         unlink(topicZFileName);
446
447         fprintf(newHvFile, "%s\t%d\n", string1, totalBytes);
448         oldOffset = newOffset;
449         }
450     else
451         fputs(lineBuff, newHvFile);
452     }
453
454 if (result)
455     {
456     ErrorExit(lastString2, "bad file copy");
457     }
458
459 putc('\n', newHvFile);
460 while (!feof(oldHvFile))
461     {
462     fgets(lineBuff, sizeof(lineBuff), oldHvFile);
463     if (feof(oldHvFile))
464         break;
465     fputs(lineBuff, newHvFile);
466     }
467 fclose(oldHvFile);
468 fclose(newHvFile);
469
470 unlink(oldHvFileName);
471 result = CopyFile(oldHvFileName, newHvFileName);
472 if (result)
473     {
474     ErrorExit(oldHvFileName, "bad file copy");
475     }
476 unlink(newHvFileName);
477
478 return 0;
479 }