cdesktopenv/cde/programs/dthelp/parser.ccdf/helpcomp/helpcomp.c

480 lines
12 KiB
C

/*
* CDE - Common Desktop Environment
*
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
*
* These libraries and programs are free software; you can
* redistribute them and/or modify them under the terms of the GNU
* Lesser General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* These libraries and programs are distributed in the hope that
* they will be useful, but WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with these librararies and programs; if not, write
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
* Floor, Boston, MA 02110-1301 USA
*/
/* Copyright 1992 Hewlett-Packard Co. */
static char *version = "$XConsortium: helpcomp.c /main/3 1995/11/08 11:10:34 rswiston $";
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <stdlib.h>
#include <dirent.h>
#include <sys/stat.h>
typedef char LineBuff[BUFSIZ];
typedef char FileBuff[BUFSIZ];
typedef char *FileName;
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
static char *prog_name;
static char fileNamePrefix[] = "hc";
static FileName newHvFileName, newHtFileName,
topicFileName, topicZFileName;
/* issues an error message, cleans up temp files and exits */
void
ErrorExit(const char *who, const char *how)
{
fprintf(stderr, "%s -> %s: %s\n", prog_name, who, how);
if (newHvFileName) unlink(newHvFileName);
if (newHtFileName) unlink(newHtFileName);
if (topicFileName) unlink(topicFileName);
if (topicZFileName) unlink(topicZFileName);
exit(1);
}
/* converts errno into a string and calls ErrorExit() */
void
ErrorIntExit(const char *who, const int how)
{
ErrorExit(who, strerror(how));
}
/* copies a file by name to another file by name */
int
CopyFile(const char *toName, const char *fromName)
{
int toFile, fromFile;
int bytesRead;
FileBuff fileBuff;
toFile = open(toName, O_WRONLY|O_CREAT, 0666);
if (toFile < 0)
{
ErrorIntExit(toName, errno);
}
fromFile = open(fromName, O_RDONLY);
if (fromFile < 0)
{
ErrorIntExit(fromName, errno);
}
while ((bytesRead = read(fromFile, fileBuff, sizeof(fileBuff))) > 0)
{
if (write(toFile, fileBuff, bytesRead) != bytesRead)
{
ErrorIntExit(toName, errno);
}
if (bytesRead < sizeof(fileBuff))
break;
}
close(fromFile);
close(toFile);
if (bytesRead < 0)
return 1;
return 0;
}
/*
* Here's the idea:
*
* Open the old .hv file and a temp file to contain the new .hv file.
*
* Copy lines from the old to the new up to and including the line
* "# Topic Locations".
*
* Then, iteratively look for lines containing the string ".filename:",
* copying lines from the old .hv to the new until such a line is found.
* Copy the found line to the new .hv as well.
*
* If the file name specified after the found string specifies a new
* file, finish writing the last open .ht if one exists (i.e., we are
* not in the first pass through the loop. Close the previous old .ht
* file and the previous new .ht file and move the new one to replace
* the old one. Open the recent .ht file specified and open a temp file
* to contain the new .ht file.
*
* Read the next line from the old .hv file to get the offset into the
* file of the next topic. Subtract the current offset from the next
* offset to get the size of the current topic. Read that many bytes
* from the old .ht file into a newly created topic file. Close the topic
* file and execute compress(1) on it. Attempt to open the topic file
* this time with a .Z extension. If possible, the topic was compressed.
* If not possible, reopen the topic file as an uncompressed topic.
*
* Append either a 0x0 (compressed) or 0xff (uncompressed) byte to the
* new .ht file followed by three bytes holding the size of the topic
* determined by fstat'ing the open topic file. The three bytes are
* computed using div/mod rather than right shift and mask to avoid byte
* sex problems.
*
* Append the contents of the topic file to the new .ht file.
*
* Continue opening, compressing and appending compressed topic files
* until a blank line is found in the old .hv file.
*
* When the blank line is found, copy the remaining lines of the old .hv
* file to the new .hv file. When finished, move the new .hv file to
* replace the old one.
*/
int
main(int argc, char **argv)
{
char *pc;
FILE *oldHvFile, *newHvFile;
int oldHtFile, newHtFile, topicZFile;
FileName oldHvFileName;
LineBuff lineBuff, string1, string2, lastString2, command;
FileBuff fileBuff;
int oldOffset, newOffset;
int bytesToRead, bytesRead, totalBytes, zFileSize;
unsigned char zTmp[4];
int doBreak, firstPass, result;
struct stat statBuf;
pc = strrchr(argv[0], '/');
if (pc) pc++;
else pc = argv[0];
prog_name = malloc(strlen(pc) + 1);
if (!prog_name)
{
fprintf(stderr, "%s: could not copy the program name (no memory)", pc);
return 1;
}
strcpy(prog_name, pc);
if (argc != 2)
{
fprintf(stderr, "usage: %s <help volume base name>\n", prog_name);
return 1;
}
oldHvFileName = malloc(strlen(argv[1]) + 3 + 1); /* add ".hv" and null */
if (!oldHvFileName)
{
ErrorExit("malloc", "could not create a temporary file name");
}
strcpy(oldHvFileName, argv[1]);
strcat(oldHvFileName, ".hv");
oldHvFile = fopen(oldHvFileName, "r");
if (!oldHvFile)
{
ErrorIntExit(oldHvFileName, errno);
}
newHvFileName = tempnam(NULL, fileNamePrefix);
if (!newHvFileName)
{
ErrorExit("tempnam", "could not create a temporary file name");
}
newHvFile = fopen(newHvFileName, "w");
if (!newHvFile)
{
ErrorIntExit(newHvFileName, errno);
}
do {
if (!fgets(lineBuff, sizeof(lineBuff), oldHvFile))
{
ErrorExit(oldHvFileName, "premature end of input file");
}
fputs(lineBuff, newHvFile);
}
while (strncmp(lineBuff, "# Topic Locations", sizeof("# Topic Locations") - 1));
firstPass = 1;
topicFileName = tempnam(NULL, fileNamePrefix);
if (!topicFileName)
{
ErrorExit("tempnam", "could not create a temporary file name");
}
strcpy(command, "compress ");
strcat(command, topicFileName);
topicZFileName = malloc(strlen(topicFileName) + 2 + 1); /* add ".Z" and null */
if (!topicZFileName)
{
ErrorExit("malloc", "could not create a temporary file name");
}
strcpy(topicZFileName, topicFileName);
strcat(topicZFileName, ".Z");
newHtFileName = tempnam(NULL, fileNamePrefix);
if (!newHtFileName)
{
ErrorExit("tempnam", "could not create a temporary file name");
}
newHtFile = open(newHtFileName, O_WRONLY|O_CREAT, 0666);
if (!newHtFile)
{
ErrorIntExit(newHtFileName, errno);
}
totalBytes = 0;
doBreak = 0;
result = 0;
while (1)
{
if (!fgets(lineBuff, sizeof(lineBuff), oldHvFile))
{
ErrorExit(oldHvFileName, "premature end of input file");
}
if (*lineBuff != '\n')
{
char *pc;
fputs(lineBuff, newHvFile);
sscanf(lineBuff, "%s %s", string1, string2);
pc = strrchr(string1, '.');
if (!pc || (strcmp(pc, ".filename:") != 0))
continue;
if (firstPass)
{
firstPass = 0;
oldOffset = 0;
strcpy(lastString2, string2);
if ((oldHtFile = open(string2, O_RDONLY)) < 0)
{
ErrorIntExit(string2, errno);
}
}
}
else
{
doBreak = 1;
string2[0] = 0;
}
if (strcmp(string2, lastString2) != 0)
{
topicZFile = open(topicFileName, O_WRONLY|O_CREAT, 0666);
if (topicZFile < 0)
{
ErrorIntExit(topicFileName, errno);
}
while (bytesRead = read(oldHtFile, fileBuff, sizeof(fileBuff)))
{
if (write(topicZFile, fileBuff, bytesRead) != bytesRead)
{
ErrorIntExit(string2, errno);
}
if (bytesRead < sizeof(fileBuff))
break;
}
close(topicZFile);
system(command);
zTmp[0] = 0;
if ((topicZFile = open(topicZFileName, O_RDONLY)) < 0)
{
zTmp[0] = ~0;
topicZFile = open(topicFileName, O_RDONLY);
}
if (topicZFile < 0)
{
char *who;
who = (char *) malloc(strlen(topicFileName) +
strlen(topicZFileName) +
sizeof(" or "));
strcpy(who, topicFileName);
strcat(who, " or ");
strcat(who, topicZFileName);
ErrorIntExit(who, errno);
}
if (fstat(topicZFile, &statBuf) < 0)
{
ErrorIntExit(topicZFileName, errno);
}
zFileSize = statBuf.st_size;
zTmp[3] = zFileSize % 256;
zFileSize /= 256;
zTmp[2] = zFileSize % 256;
zFileSize /= 256;
zTmp[1] = zFileSize % 256;
if (write(newHtFile, zTmp, 4) != 4)
{
ErrorIntExit(newHtFileName, errno);
}
while (bytesRead = read(topicZFile, fileBuff, sizeof(fileBuff)))
{
if (write(newHtFile, fileBuff, bytesRead) != bytesRead)
{
ErrorIntExit(string2, errno);
}
if (bytesRead < sizeof(fileBuff))
break;
}
close(topicZFile);
unlink(topicFileName);
unlink(topicZFileName);
unlink(lastString2);
result = CopyFile(lastString2, newHtFileName);
unlink(newHtFileName);
if (doBreak || result)
break;
newHtFile = open(newHtFileName, O_WRONLY|O_CREAT, 0666);
if (!newHtFile)
{
ErrorIntExit(newHtFileName, errno);
}
totalBytes = 0;
strcpy(lastString2, string2);
oldOffset = 0;
if ((oldHtFile = open(string2, O_RDONLY)) < 0)
{
ErrorIntExit(string2, errno);
}
}
if (!fgets(lineBuff, sizeof(lineBuff), oldHvFile))
{
ErrorIntExit(oldHvFileName, errno);
}
sscanf(lineBuff, "%s %d", string1, &newOffset);
if (newOffset != oldOffset)
{
bytesToRead = newOffset - oldOffset;
topicZFile = open(topicFileName, O_WRONLY|O_CREAT, 0666);
if (topicZFile < 0)
{
ErrorIntExit(topicFileName, errno);
}
while (bytesRead = read(oldHtFile,
fileBuff,
MIN(bytesToRead, sizeof(fileBuff))))
{
if (write(topicZFile, fileBuff, bytesRead) != bytesRead)
{
ErrorIntExit(topicFileName, errno);
}
if ((bytesToRead -= bytesRead) == 0)
break;
}
close(topicZFile);
system(command);
zTmp[0] = 0;
if ((topicZFile = open(topicZFileName, O_RDONLY)) < 0)
{
zTmp[0] = ~0;
topicZFile = open(topicFileName, O_RDONLY);
}
if (topicZFile < 0)
{
char *who;
who = (char *) malloc(strlen(topicFileName) +
strlen(topicZFileName) +
sizeof(" or "));
strcpy(who, topicFileName);
strcat(who, " or ");
strcat(who, topicZFileName);
ErrorIntExit(who, errno);
}
if (fstat(topicZFile, &statBuf) < 0)
{
ErrorIntExit(topicZFileName, errno);
}
zFileSize = statBuf.st_size;
zTmp[3] = zFileSize % 256;
zFileSize /= 256;
zTmp[2] = zFileSize % 256;
zFileSize /= 256;
zTmp[1] = zFileSize % 256;
if (write(newHtFile, zTmp, 4) != 4)
{
ErrorIntExit(newHtFileName, errno);
}
totalBytes += statBuf.st_size + 4;
while (bytesRead = read(topicZFile, fileBuff, sizeof(fileBuff)))
{
if (write(newHtFile, fileBuff, bytesRead) != bytesRead)
{
ErrorIntExit(newHtFileName, errno);
}
if (bytesRead < sizeof(fileBuff))
break;
}
close(topicZFile);
unlink(topicFileName);
unlink(topicZFileName);
fprintf(newHvFile, "%s\t%d\n", string1, totalBytes);
oldOffset = newOffset;
}
else
fputs(lineBuff, newHvFile);
}
if (result)
{
ErrorExit(lastString2, "bad file copy");
}
putc('\n', newHvFile);
while (!feof(oldHvFile))
{
fgets(lineBuff, sizeof(lineBuff), oldHvFile);
if (feof(oldHvFile))
break;
fputs(lineBuff, newHvFile);
}
fclose(oldHvFile);
fclose(newHvFile);
unlink(oldHvFileName);
result = CopyFile(oldHvFileName, newHvFileName);
if (result)
{
ErrorExit(oldHvFileName, "bad file copy");
}
unlink(newHvFileName);
return 0;
}