/* * 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 #include #include #include #include #include #include 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 \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; }