2006-11-25 13:07:29 -07:00
|
|
|
/*
|
|
|
|
|
|
|
|
Copyright (c) 1987, 1988 X Consortium
|
|
|
|
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining
|
|
|
|
a copy of this software and associated documentation files (the
|
|
|
|
"Software"), to deal in the Software without restriction, including
|
|
|
|
without limitation the rights to use, copy, modify, merge, publish,
|
|
|
|
distribute, sublicense, and/or sell copies of the Software, and to
|
|
|
|
permit persons to whom the Software is furnished to do so, subject to
|
|
|
|
the following conditions:
|
|
|
|
|
|
|
|
The above copyright notice and this permission notice shall be included
|
|
|
|
in all copies or substantial portions of the Software.
|
|
|
|
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
|
|
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
|
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
|
|
IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
|
|
|
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
|
|
|
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
|
|
OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
|
|
|
|
Except as contained in this notice, the name of the X Consortium shall
|
|
|
|
not be used in advertising or otherwise to promote the sale, use or
|
|
|
|
other dealings in this Software without prior written authorization
|
|
|
|
from the X Consortium.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
#include "globals.h"
|
2013-09-28 10:22:59 -06:00
|
|
|
#include "vendor.h" /* vendor-specific defines and data */
|
2006-11-25 13:07:29 -07:00
|
|
|
|
|
|
|
#include <dirent.h>
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
2013-09-28 10:22:59 -06:00
|
|
|
static char error_buf[BUFSIZ]; /* The buffer for error messages. */
|
2006-11-25 13:07:29 -07:00
|
|
|
#endif /* DEBUG */
|
|
|
|
|
2013-09-28 10:22:59 -06:00
|
|
|
static void AddToCurrentSection(Manual * local_manual, char *path);
|
|
|
|
static void InitManual(Manual * l_manual, char *label);
|
|
|
|
static void ReadCurrentSection(Manual * local_manual, char *path);
|
|
|
|
static void ReadMandescFile(SectionList ** section_list, char *path);
|
|
|
|
static void SortAndRemove(Manual * man, int number);
|
2006-11-25 13:07:29 -07:00
|
|
|
static void SortList(SectionList ** list);
|
|
|
|
|
|
|
|
#define SECT_ERROR -1
|
|
|
|
|
|
|
|
#ifndef Byte
|
|
|
|
#define Byte unsigned char
|
|
|
|
#endif
|
2013-09-28 10:22:59 -06:00
|
|
|
|
2006-11-25 13:07:29 -07:00
|
|
|
#ifndef reg
|
|
|
|
#define reg register
|
|
|
|
#endif
|
2013-09-28 10:22:59 -06:00
|
|
|
|
|
|
|
static void sortstrs(Byte * data[], int size, Byte * otherdata[]);
|
|
|
|
static void sortstrs_block(Byte **, Byte **, int, Byte, Byte **, Byte **);
|
|
|
|
static void sortstrs_block_oo(Byte **, Byte **, int, Byte, int *, int *,
|
|
|
|
Byte **, Byte **);
|
|
|
|
|
2006-11-25 13:07:29 -07:00
|
|
|
/* Function Name: Man
|
|
|
|
* Description: Builds a list of all manual directories and files.
|
2013-09-28 10:22:59 -06:00
|
|
|
* Arguments: none.
|
2006-11-25 13:07:29 -07:00
|
|
|
* Returns: the number of manual sections.
|
|
|
|
*/
|
|
|
|
|
|
|
|
int
|
|
|
|
Man(void)
|
|
|
|
{
|
2013-09-28 10:22:59 -06:00
|
|
|
SectionList *list = NULL;
|
2006-11-25 13:07:29 -07:00
|
|
|
|
2013-09-28 10:22:59 -06:00
|
|
|
char *ptr, *lang = NULL, manpath[BUFSIZ], buf[BUFSIZ],
|
|
|
|
*path, *current_label;
|
|
|
|
int sect, num_alloced;
|
|
|
|
|
|
|
|
/*
|
2006-11-25 13:07:29 -07:00
|
|
|
* Get the environment variable MANPATH, and if it doesn't exist then use
|
|
|
|
* SYSMANPATH and LOCALMANPATH.
|
|
|
|
*/
|
|
|
|
|
2013-09-28 10:22:59 -06:00
|
|
|
/* if MANPATH variable ends in ':'. So, should extend it's value to the
|
|
|
|
* default search path.
|
|
|
|
*/
|
2006-11-25 13:07:29 -07:00
|
|
|
|
2013-09-28 10:22:59 -06:00
|
|
|
*manpath = '\0';
|
|
|
|
if ((ptr = getenv("MANPATH")) != NULL)
|
|
|
|
strcpy(manpath, ptr);
|
|
|
|
if (ptr == NULL || streq(ptr, "") || ptr[strlen(ptr) - 1] == ':') {
|
|
|
|
lang = getenv("LANG");
|
2006-11-25 13:07:29 -07:00
|
|
|
#ifdef MANCONF
|
2013-09-28 10:22:59 -06:00
|
|
|
if (!ReadManConfig(manpath + strlen(manpath)))
|
2006-11-25 13:07:29 -07:00
|
|
|
#endif
|
2013-09-28 10:22:59 -06:00
|
|
|
{
|
2006-11-25 13:07:29 -07:00
|
|
|
#ifdef MANCONF
|
2013-09-28 10:22:59 -06:00
|
|
|
if (manpath[strlen(manpath) - 1] != ':')
|
|
|
|
strcat(manpath, ":");
|
2006-11-25 13:07:29 -07:00
|
|
|
#endif
|
2013-09-28 10:22:59 -06:00
|
|
|
strcat(manpath, SYSMANPATH);
|
2006-11-25 13:07:29 -07:00
|
|
|
#ifdef LOCALMANPATH
|
2013-09-28 10:22:59 -06:00
|
|
|
strcat(manpath, ":");
|
|
|
|
strcat(manpath, LOCALMANPATH);
|
2006-11-25 13:07:29 -07:00
|
|
|
#endif
|
2013-09-28 10:22:59 -06:00
|
|
|
}
|
2006-11-25 13:07:29 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Get the list of manual directories in the users MANPATH that we should
|
|
|
|
* open to look for manual pages. The ``mandesc'' file is read here.
|
|
|
|
*/
|
|
|
|
|
2013-09-28 10:22:59 -06:00
|
|
|
for (path = manpath; (ptr = strchr(path, ':')) != NULL; path = ++ptr) {
|
|
|
|
*ptr = '\0';
|
|
|
|
if (lang != NULL) {
|
|
|
|
strcpy(buf, path);
|
|
|
|
strcat(buf, "/");
|
|
|
|
strncat(buf, lang, sizeof(buf) - strlen(path) + 1);
|
|
|
|
buf[sizeof(buf) - strlen(path) + 1] = '\0';
|
|
|
|
ReadMandescFile(&list, buf);
|
|
|
|
}
|
|
|
|
ReadMandescFile(&list, path);
|
|
|
|
}
|
2009-10-24 09:00:51 -06:00
|
|
|
if (lang != NULL) {
|
2013-09-28 10:22:59 -06:00
|
|
|
strcpy(buf, path);
|
|
|
|
strcat(buf, "/");
|
|
|
|
strncat(buf, lang, sizeof(buf) - strlen(path) + 1);
|
|
|
|
buf[sizeof(buf) - strlen(path) + 1] = '\0';
|
|
|
|
ReadMandescFile(&list, buf);
|
2006-11-25 13:07:29 -07:00
|
|
|
}
|
|
|
|
ReadMandescFile(&list, path);
|
2013-09-28 10:22:59 -06:00
|
|
|
|
|
|
|
SortList(&list);
|
|
|
|
|
|
|
|
sect = 0;
|
|
|
|
num_alloced = SECTALLOC;
|
|
|
|
manual = (Manual *) XtMalloc(sizeof(Manual) * num_alloced);
|
|
|
|
InitManual(manual, list->label);
|
|
|
|
manual[sect].flags = list->flags;
|
|
|
|
current_label = NULL;
|
|
|
|
|
|
|
|
while (list != NULL) {
|
|
|
|
SectionList *old_list;
|
|
|
|
|
|
|
|
if (current_label == NULL || streq(list->label, current_label))
|
|
|
|
AddToCurrentSection(manual + sect, list->directory);
|
|
|
|
else {
|
|
|
|
if (manual[sect].nentries == 0) { /* empty section, re-use it. */
|
|
|
|
XtFree(manual[sect].blabel);
|
|
|
|
manual[sect].blabel = list->label;
|
|
|
|
manual[sect].flags = list->flags;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (++sect >= num_alloced) {
|
|
|
|
num_alloced += SECTALLOC;
|
|
|
|
manual = (Manual *) XtRealloc((char *) manual,
|
|
|
|
(sizeof(Manual) * num_alloced));
|
|
|
|
if (manual == NULL)
|
|
|
|
PrintError
|
|
|
|
("Could not allocate memory for manual sections.");
|
|
|
|
}
|
|
|
|
InitManual(manual + sect, list->label);
|
|
|
|
manual[sect].flags = list->flags;
|
|
|
|
}
|
|
|
|
AddToCurrentSection(manual + sect, list->directory);
|
|
|
|
}
|
|
|
|
/* Save label to see if it matches next entry. */
|
|
|
|
current_label = list->label;
|
|
|
|
old_list = list;
|
|
|
|
list = list->next;
|
|
|
|
XtFree((char *) old_list); /* free what you allocate. */
|
2006-11-25 13:07:29 -07:00
|
|
|
}
|
2013-09-28 10:22:59 -06:00
|
|
|
if (manual[sect].nentries != 0)
|
|
|
|
sect++; /* don't forget that last section. */
|
|
|
|
|
|
|
|
SortAndRemove(manual, sect);
|
|
|
|
|
|
|
|
#ifdef notdef /* dump info. */
|
|
|
|
DumpManual(sect);
|
2006-11-25 13:07:29 -07:00
|
|
|
#endif
|
2013-09-28 10:22:59 -06:00
|
|
|
|
2006-11-25 13:07:29 -07:00
|
|
|
/*
|
|
|
|
* realloc manual to be minimum space necessary.
|
|
|
|
*/
|
|
|
|
|
2013-09-28 10:22:59 -06:00
|
|
|
if (sect == 0)
|
|
|
|
PrintError("No manual pages found.");
|
|
|
|
manual = (Manual *) XtRealloc((char *) manual, (sizeof(Manual) * sect));
|
|
|
|
if (manual == NULL)
|
|
|
|
PrintError("Could not allocate memory for manual sections.");
|
2006-11-25 13:07:29 -07:00
|
|
|
|
2013-09-28 10:22:59 -06:00
|
|
|
return (sect); /* return the number of man sections. */
|
|
|
|
}
|
2006-11-25 13:07:29 -07:00
|
|
|
|
|
|
|
/* Function Name: SortList
|
|
|
|
* Description: Sorts the list of sections to search.
|
|
|
|
* Arguments: list - a pointer to the list to sort.
|
|
|
|
* Returns: a sorted list.
|
|
|
|
*
|
|
|
|
* This is the most complicated part of the entire operation.
|
|
|
|
* all sections with the same label must by right next to each other,
|
|
|
|
* but the sections that are in the standard list have to come first.
|
|
|
|
*/
|
|
|
|
|
|
|
|
static void
|
|
|
|
SortList(SectionList ** list)
|
|
|
|
{
|
2013-09-28 10:22:59 -06:00
|
|
|
SectionList *local;
|
|
|
|
SectionList *head, *last, *inner, *old;
|
|
|
|
|
|
|
|
if (*list == NULL)
|
|
|
|
PrintError("No manual sections to read, exiting.");
|
|
|
|
|
|
|
|
/*
|
|
|
|
* First step
|
|
|
|
*
|
2006-11-25 13:07:29 -07:00
|
|
|
* Look for standard list items, and more them to the top of the list.
|
|
|
|
*/
|
|
|
|
|
2013-09-28 10:22:59 -06:00
|
|
|
last = NULL; /* keep Saber happy. */
|
|
|
|
for (local = *list; local->next != NULL; local = local->next) {
|
|
|
|
if (local->flags) {
|
|
|
|
if (local == *list) /* top element is already standard. */
|
|
|
|
break;
|
|
|
|
head = local;
|
2006-11-25 13:07:29 -07:00
|
|
|
|
2013-09-28 10:22:59 -06:00
|
|
|
/* Find end of standard block */
|
|
|
|
for (old = NULL; (local->next != NULL) && (local->flags);
|
|
|
|
old = local, local = local->next);
|
2006-11-25 13:07:29 -07:00
|
|
|
|
2013-09-28 10:22:59 -06:00
|
|
|
if (old != NULL) {
|
|
|
|
last->next = old->next; /* Move the block. */
|
|
|
|
old->next = *list;
|
|
|
|
*list = head;
|
|
|
|
}
|
2006-11-25 13:07:29 -07:00
|
|
|
|
2013-09-28 10:22:59 -06:00
|
|
|
break; /* First step accomplished. */
|
|
|
|
}
|
|
|
|
last = local;
|
2006-11-25 13:07:29 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Second step
|
|
|
|
*
|
|
|
|
* Move items with duplicate labels right next to each other.
|
|
|
|
*
|
|
|
|
* Changed to keep the order of the list entries unchanged.
|
|
|
|
*/
|
|
|
|
|
2013-09-28 10:22:59 -06:00
|
|
|
for (local = *list; local->next != NULL; local = local->next) {
|
|
|
|
head = local;
|
|
|
|
old = inner = local->next;
|
|
|
|
while (inner != NULL) {
|
|
|
|
if (streq(inner->label, local->label)) {
|
|
|
|
if (old != inner) {
|
|
|
|
old->next = inner->next;
|
|
|
|
last = inner->next;
|
|
|
|
inner->next = head->next;
|
|
|
|
head->next = inner;
|
|
|
|
head = inner;
|
|
|
|
old = inner = last;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
head = inner;
|
|
|
|
}
|
|
|
|
old = inner;
|
|
|
|
inner = inner->next;
|
|
|
|
}
|
2006-11-25 13:07:29 -07:00
|
|
|
}
|
2013-09-28 10:22:59 -06:00
|
|
|
}
|
2006-11-25 13:07:29 -07:00
|
|
|
|
|
|
|
/* Function Name: ReadMandescFile
|
2013-09-28 10:22:59 -06:00
|
|
|
* Description: Reads the mandesc file, and adds more sections as
|
2006-11-25 13:07:29 -07:00
|
|
|
* necessary.
|
|
|
|
* Arguments: path - path name if the current search directory.
|
|
|
|
* section_list - pointer to the list of sections.
|
|
|
|
* Returns: TRUE in we should use default sections
|
|
|
|
*/
|
2013-09-28 10:22:59 -06:00
|
|
|
|
2006-11-25 13:07:29 -07:00
|
|
|
static void
|
2013-09-28 10:22:59 -06:00
|
|
|
ReadMandescFile(SectionList ** section_list, char *path)
|
2006-11-25 13:07:29 -07:00
|
|
|
{
|
2013-09-28 10:22:59 -06:00
|
|
|
char mandesc_file[BUFSIZ]; /* full path to the mandesc file. */
|
|
|
|
FILE *descfile;
|
|
|
|
char string[BUFSIZ], local_file[BUFSIZ];
|
|
|
|
Boolean use_defaults = TRUE;
|
|
|
|
char *cp;
|
|
|
|
|
|
|
|
snprintf(mandesc_file, sizeof(mandesc_file), "%s/%s", path, MANDESC);
|
|
|
|
if ((descfile = fopen(mandesc_file, "r")) != NULL) {
|
|
|
|
while (fgets(string, BUFSIZ, descfile) != NULL) {
|
2015-05-10 04:21:18 -06:00
|
|
|
size_t len = strlen(string);
|
|
|
|
|
|
|
|
if (len == 0)
|
|
|
|
continue;
|
|
|
|
if (string[len - 1] == '\n')
|
|
|
|
string[len - 1] = '\0'; /* Strip off the CR. */
|
2013-09-28 10:22:59 -06:00
|
|
|
|
|
|
|
if (streq(string, NO_SECTION_DEFAULTS)) {
|
|
|
|
use_defaults = FALSE;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((cp = strchr(string, '\t')) != NULL) {
|
|
|
|
char *s;
|
|
|
|
|
|
|
|
*cp++ = '\0';
|
|
|
|
strcpy(local_file, MAN);
|
|
|
|
strcat(local_file, string);
|
|
|
|
if ((s = strchr(cp, '\t')) != NULL) {
|
|
|
|
*s++ = '\0';
|
|
|
|
if (streq(s, SUFFIX))
|
|
|
|
AddNewSection(section_list, path, local_file, cp,
|
|
|
|
MSUFFIX);
|
|
|
|
else if (streq(s, FOLD))
|
|
|
|
AddNewSection(section_list, path, local_file, cp,
|
|
|
|
MFOLD);
|
|
|
|
else if (streq(s, FOLDSUFFIX))
|
|
|
|
AddNewSection(section_list, path, local_file, cp,
|
|
|
|
MFOLDSUFFIX);
|
|
|
|
else
|
|
|
|
AddNewSection(section_list, path, local_file, cp,
|
|
|
|
MNULL);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
AddNewSection(section_list, path, local_file, cp, MNULL);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
snprintf(local_file, sizeof(local_file), "%s%c", MAN,
|
|
|
|
string[0]);
|
|
|
|
AddNewSection(section_list, path, local_file, (string + 1),
|
|
|
|
FALSE);
|
2006-11-25 13:07:29 -07:00
|
|
|
#ifdef SEARCHOTHER
|
2013-09-28 10:22:59 -06:00
|
|
|
snprintf(local_file, sizeof(local_file), "%s%c", SEARCHOTHER,
|
|
|
|
string[0]);
|
|
|
|
AddNewSection(section_list, path, local_file, (string + 1),
|
|
|
|
FALSE);
|
2006-11-25 13:07:29 -07:00
|
|
|
#endif
|
2013-09-28 10:22:59 -06:00
|
|
|
}
|
|
|
|
}
|
2006-11-25 13:07:29 -07:00
|
|
|
|
2013-09-28 10:22:59 -06:00
|
|
|
fclose(descfile);
|
|
|
|
}
|
|
|
|
if (use_defaults)
|
|
|
|
AddStandardSections(section_list, path);
|
2006-11-25 13:07:29 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Function Name: AddNewSection
|
|
|
|
* Description: Adds the new section onto the current section list.
|
|
|
|
* Arguments: list - pointer to the section list.
|
|
|
|
* path - the path to the current manual section.
|
|
|
|
* file - the file to save.
|
|
|
|
* label - the current section label.
|
|
|
|
* flags = 1 - add a suffix
|
|
|
|
* = 2 - fold to lower case
|
|
|
|
* Returns: none.
|
|
|
|
*/
|
|
|
|
|
|
|
|
void
|
2013-09-28 10:22:59 -06:00
|
|
|
AddNewSection(SectionList ** list, const char *path, const char *file,
|
|
|
|
const char *label, int flags)
|
2006-11-25 13:07:29 -07:00
|
|
|
{
|
2013-09-28 10:22:59 -06:00
|
|
|
SectionList *local_list, *end;
|
|
|
|
char full_path[BUFSIZ];
|
2006-11-25 13:07:29 -07:00
|
|
|
|
|
|
|
/* Allocate a new list element */
|
|
|
|
|
2013-09-28 10:22:59 -06:00
|
|
|
local_list = (SectionList *) XtMalloc(sizeof(SectionList));
|
2006-11-25 13:07:29 -07:00
|
|
|
|
2013-09-28 10:22:59 -06:00
|
|
|
if (*list != NULL) {
|
|
|
|
for (end = *list; end->next != NULL; end = end->next);
|
|
|
|
end->next = local_list;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
*list = local_list;
|
|
|
|
|
|
|
|
local_list->next = NULL;
|
|
|
|
local_list->label = XtNewString(label);
|
|
|
|
snprintf(full_path, sizeof(full_path), "%s/%s", path, file);
|
|
|
|
local_list->directory = XtNewString(full_path);
|
|
|
|
local_list->flags = flags;
|
|
|
|
}
|
2006-11-25 13:07:29 -07:00
|
|
|
|
|
|
|
/* Function Name: AddToCurrentSection
|
|
|
|
* Description: This function gets the names of the manual page
|
|
|
|
* directories, then closes the directory.
|
|
|
|
* Arguments: local_manual - a pointer to a manual pages structure.
|
|
|
|
* path - the path to this directory.
|
|
|
|
* Returns: none.
|
|
|
|
*/
|
|
|
|
|
|
|
|
static void
|
2013-09-28 10:22:59 -06:00
|
|
|
AddToCurrentSection(Manual * local_manual, char *path)
|
2006-11-25 13:07:29 -07:00
|
|
|
{
|
2013-09-28 10:22:59 -06:00
|
|
|
char temp_path[BUFSIZ];
|
2006-11-25 13:07:29 -07:00
|
|
|
|
|
|
|
#if defined(__OpenBSD__) || defined(__NetBSD__)
|
2013-09-28 10:22:59 -06:00
|
|
|
snprintf(temp_path, sizeof(temp_path), "%s/%s", path, MACHINE);
|
|
|
|
ReadCurrentSection(local_manual, temp_path);
|
2006-11-25 13:07:29 -07:00
|
|
|
#endif
|
2013-09-28 10:22:59 -06:00
|
|
|
ReadCurrentSection(local_manual, path);
|
|
|
|
snprintf(temp_path, sizeof(temp_path), "%s.%s", path,
|
|
|
|
COMPRESSION_EXTENSION);
|
|
|
|
ReadCurrentSection(local_manual, temp_path);
|
2006-11-25 13:07:29 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Function Name: ReadCurrentSection
|
2013-09-28 10:22:59 -06:00
|
|
|
* Description: Actually does the work of adding entries to the
|
2006-11-25 13:07:29 -07:00
|
|
|
* new section
|
|
|
|
* Arguments: local_manual - a pointer to a manual pages structure.
|
|
|
|
* path - the path to this directory.
|
|
|
|
* compressed - Is this a compressed directory?
|
|
|
|
* Returns: TRUE if any entries are found.
|
|
|
|
*/
|
|
|
|
|
|
|
|
static void
|
2013-09-28 10:22:59 -06:00
|
|
|
ReadCurrentSection(Manual * local_manual, char *path)
|
2006-11-25 13:07:29 -07:00
|
|
|
{
|
2013-09-28 10:22:59 -06:00
|
|
|
DIR *dir;
|
|
|
|
register struct dirent *dp;
|
2006-11-25 13:07:29 -07:00
|
|
|
|
2013-09-28 10:22:59 -06:00
|
|
|
register int nentries;
|
|
|
|
register int nalloc;
|
|
|
|
char full_name[BUFSIZ], *ptr;
|
2006-11-25 13:07:29 -07:00
|
|
|
|
2013-09-28 10:22:59 -06:00
|
|
|
if ((dir = opendir(path)) == NULL) {
|
2006-11-25 13:07:29 -07:00
|
|
|
#ifdef DEBUG
|
2013-09-28 10:22:59 -06:00
|
|
|
snprintf(error_buf, sizeof(error_buf), "Can't open directory %s", path);
|
|
|
|
PopupWarning(NULL, error_buf);
|
2006-11-25 13:07:29 -07:00
|
|
|
#endif /* DEBUG */
|
2013-09-28 10:22:59 -06:00
|
|
|
return;
|
|
|
|
}
|
2006-11-25 13:07:29 -07:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Remove the compression extension from the path name.
|
|
|
|
*/
|
|
|
|
|
2013-09-28 10:22:59 -06:00
|
|
|
if ((ptr = strrchr(path, '.')) != NULL) {
|
2006-11-25 13:07:29 -07:00
|
|
|
#if !defined(__SCO__) && !defined(ISC)
|
2013-09-28 10:22:59 -06:00
|
|
|
if (streq(ptr + 1, COMPRESSION_EXTENSION))
|
2006-11-25 13:07:29 -07:00
|
|
|
#else
|
2013-09-28 10:22:59 -06:00
|
|
|
if (strpbrk(ptr + 1, COMPRESSION_EXTENSIONS) != NULL)
|
2006-11-25 13:07:29 -07:00
|
|
|
#endif
|
2013-09-28 10:22:59 -06:00
|
|
|
*ptr = '\0';
|
2006-11-25 13:07:29 -07:00
|
|
|
#ifdef GZIP_EXTENSION
|
2013-09-28 10:22:59 -06:00
|
|
|
else if (streq(ptr + 1, GZIP_EXTENSION))
|
|
|
|
*ptr = '\0';
|
2009-10-24 09:00:51 -06:00
|
|
|
#endif
|
|
|
|
#ifdef BZIP2_EXTENSION
|
2013-09-28 10:22:59 -06:00
|
|
|
else if (streq(ptr + 1, BZIP2_EXTENSION))
|
|
|
|
*ptr = '\0';
|
2009-10-24 09:00:51 -06:00
|
|
|
#endif
|
|
|
|
#ifdef LZMA_EXTENSION
|
2013-09-28 10:22:59 -06:00
|
|
|
else if (streq(ptr + 1, LZMA_EXTENSION))
|
|
|
|
*ptr = '\0';
|
2006-11-25 13:07:29 -07:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2013-09-28 10:22:59 -06:00
|
|
|
nentries = local_manual->nentries;
|
|
|
|
nalloc = local_manual->nalloc;
|
|
|
|
|
|
|
|
while ((dp = readdir(dir)) != NULL) {
|
|
|
|
char *name = dp->d_name;
|
|
|
|
|
|
|
|
if (name[0] == '.')
|
|
|
|
continue;
|
|
|
|
if (strchr(name, '.') == NULL)
|
|
|
|
continue;
|
|
|
|
if (nentries >= nalloc) {
|
|
|
|
nalloc += ENTRYALLOC;
|
|
|
|
local_manual->entries =
|
|
|
|
(char **) XtRealloc((char *) local_manual->entries,
|
|
|
|
nalloc * sizeof(char *));
|
|
|
|
local_manual->entries_less_paths =
|
|
|
|
(char **) XtRealloc((char *) local_manual->entries_less_paths,
|
|
|
|
nalloc * sizeof(char *));
|
|
|
|
}
|
|
|
|
|
|
|
|
snprintf(full_name, sizeof(full_name), "%s/%s", path, name);
|
2006-11-25 13:07:29 -07:00
|
|
|
/*
|
|
|
|
* Remove the compression extension from the entry name.
|
|
|
|
*/
|
|
|
|
|
2013-09-28 10:22:59 -06:00
|
|
|
if ((ptr = strrchr(full_name, '.')) != NULL) {
|
2006-11-25 13:07:29 -07:00
|
|
|
#if !defined(__SCO__) && !defined(ISC)
|
2013-09-28 10:22:59 -06:00
|
|
|
if (streq(ptr + 1, COMPRESSION_EXTENSION))
|
2006-11-25 13:07:29 -07:00
|
|
|
#else
|
2013-09-28 10:22:59 -06:00
|
|
|
if (strpbrk(ptr + 1, COMPRESSION_EXTENSIONS) != NULL)
|
2006-11-25 13:07:29 -07:00
|
|
|
#endif
|
2013-09-28 10:22:59 -06:00
|
|
|
*ptr = '\0';
|
2006-11-25 13:07:29 -07:00
|
|
|
#ifdef GZIP_EXTENSION
|
2013-09-28 10:22:59 -06:00
|
|
|
else if (streq(ptr + 1, GZIP_EXTENSION))
|
|
|
|
*ptr = '\0';
|
2006-11-25 13:07:29 -07:00
|
|
|
#endif
|
2009-10-24 09:00:51 -06:00
|
|
|
#ifdef BZIP2_EXTENSION
|
2013-09-28 10:22:59 -06:00
|
|
|
else if (streq(ptr + 1, BZIP2_EXTENSION))
|
|
|
|
*ptr = '\0';
|
2009-10-24 09:00:51 -06:00
|
|
|
#endif
|
|
|
|
#ifdef LZMA_EXTENSION
|
2013-09-28 10:22:59 -06:00
|
|
|
else if (streq(ptr + 1, LZMA_EXTENSION))
|
|
|
|
*ptr = '\0';
|
2009-10-24 09:00:51 -06:00
|
|
|
#endif
|
2006-11-25 13:07:29 -07:00
|
|
|
#ifdef IGNORE_EXTENSION
|
2013-09-28 10:22:59 -06:00
|
|
|
/* skip files with specified extension - they're not real man pages */
|
|
|
|
else if (streq(ptr + 1, IGNORE_EXTENSION)) {
|
|
|
|
continue;
|
|
|
|
}
|
2006-11-25 13:07:29 -07:00
|
|
|
#endif /* IGNORE_EXTENSION */
|
2013-09-28 10:22:59 -06:00
|
|
|
}
|
|
|
|
local_manual->entries[nentries] = XtNewString(full_name);
|
|
|
|
local_manual->entries_less_paths[nentries] =
|
|
|
|
strrchr(local_manual->entries[nentries], '/');
|
|
|
|
if (local_manual->entries_less_paths[nentries] == NULL)
|
|
|
|
PrintError("Internal error while cataloging manual pages.");
|
|
|
|
++nentries;
|
2006-11-25 13:07:29 -07:00
|
|
|
}
|
2013-09-28 10:22:59 -06:00
|
|
|
|
|
|
|
local_manual->nentries = nentries;
|
|
|
|
local_manual->nalloc = nalloc;
|
|
|
|
|
|
|
|
closedir(dir);
|
2006-11-25 13:07:29 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Function Name: SortAndRemove
|
|
|
|
* Description: This function sorts all the entry names and
|
|
|
|
* then removes all the duplicate entries.
|
|
|
|
* Arguments: man - a pointer to the manual structure.
|
|
|
|
* number - the number of manual sections.
|
|
|
|
* Returns: an improved manual stucure
|
|
|
|
*/
|
|
|
|
|
|
|
|
static void
|
2013-09-28 10:22:59 -06:00
|
|
|
SortAndRemove(Manual * man, int number)
|
2006-11-25 13:07:29 -07:00
|
|
|
{
|
2013-09-28 10:22:59 -06:00
|
|
|
int i;
|
|
|
|
char *l1, *l2, **s1;
|
|
|
|
|
|
|
|
for (i = 0; i < number; man++, i++) { /* sort each section */
|
|
|
|
register int i2 = 0;
|
|
|
|
|
2006-11-25 13:07:29 -07:00
|
|
|
#ifdef DEBUG
|
2013-09-28 10:22:59 -06:00
|
|
|
printf("sorting section %d - %s\n", i, man->blabel);
|
2006-11-25 13:07:29 -07:00
|
|
|
#endif /* DEBUG */
|
|
|
|
|
2013-09-28 10:22:59 -06:00
|
|
|
s1 = (char **) malloc(man->nentries * sizeof(char *));
|
|
|
|
|
|
|
|
/* temporarily remove suffixes of entries, preventing them from */
|
|
|
|
/* being used in alphabetic comparison ie sccs-delta.1 vs sccs.1 */
|
|
|
|
for (i2 = 0; i2 < man->nentries; i2++)
|
|
|
|
if ((s1[i2] = strrchr(man->entries_less_paths[i2], '.')) != NULL)
|
|
|
|
*s1[i2] = '\0';
|
2006-11-25 13:07:29 -07:00
|
|
|
|
2013-09-28 10:22:59 -06:00
|
|
|
sortstrs((Byte **) man->entries_less_paths, man->nentries,
|
|
|
|
(Byte **) man->entries);
|
2006-11-25 13:07:29 -07:00
|
|
|
|
2013-09-28 10:22:59 -06:00
|
|
|
/* put back suffixes */
|
|
|
|
for (i2 = 0; i2 < man->nentries; i2++)
|
|
|
|
if (s1[i2] != NULL)
|
|
|
|
*s1[i2] = '.';
|
|
|
|
|
|
|
|
free(s1);
|
2006-11-25 13:07:29 -07:00
|
|
|
|
|
|
|
#ifdef DEBUG
|
2013-09-28 10:22:59 -06:00
|
|
|
printf("removing from section %d.\n", i);
|
2006-11-25 13:07:29 -07:00
|
|
|
#endif /* DEBUG */
|
2013-09-28 10:22:59 -06:00
|
|
|
|
|
|
|
{
|
|
|
|
register int j, k, nent, nentm1;
|
|
|
|
int j2;
|
|
|
|
|
|
|
|
nent = man->nentries;
|
|
|
|
nentm1 = nent - 1;
|
|
|
|
j = 0;
|
|
|
|
l2 = man->entries_less_paths[j++];
|
|
|
|
if (l2 == NULL)
|
|
|
|
PrintError
|
|
|
|
("Internal error while removing duplicate manual pages.");
|
|
|
|
while (j < nentm1) {
|
|
|
|
l1 = l2;
|
|
|
|
l2 = man->entries_less_paths[j++];
|
|
|
|
if (l2 == NULL)
|
|
|
|
PrintError
|
|
|
|
("Internal error while removing duplicate manual pages.");
|
|
|
|
if (streq(l1, l2)) {
|
|
|
|
j2 = j - 1;
|
|
|
|
k = j2;
|
|
|
|
while (j < nent) {
|
|
|
|
man->entries_less_paths[k] = man->entries_less_paths[j];
|
|
|
|
man->entries[k++] = man->entries[j++];
|
|
|
|
}
|
|
|
|
j = j2;
|
|
|
|
--man->nentries;
|
|
|
|
--nent;
|
|
|
|
--nentm1;
|
2006-11-25 13:07:29 -07:00
|
|
|
}
|
2013-09-28 10:22:59 -06:00
|
|
|
}
|
|
|
|
}
|
2006-11-25 13:07:29 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2013-09-28 10:22:59 -06:00
|
|
|
******* Replacement for qsort to keep
|
|
|
|
******* identical entries in order
|
|
|
|
|
|
|
|
A somewhat ugly hack of something that was once simpler...
|
|
|
|
*/
|
2006-11-25 13:07:29 -07:00
|
|
|
/*
|
2013-09-28 10:22:59 -06:00
|
|
|
Sort an array of pointers to strings, keeping it
|
|
|
|
in ascending order by (1) string comparison and
|
|
|
|
(2) original entry order in the pointer array.
|
|
|
|
|
|
|
|
This is a modified radix exchange algorithm.
|
|
|
|
|
|
|
|
In case there's insufficient memory for a temporary copy
|
|
|
|
of the pointer array, the original order of identical strings
|
|
|
|
isn't preserved.
|
|
|
|
*/
|
|
|
|
|
|
|
|
static void
|
|
|
|
sortstrs(Byte * data[], int size, Byte * otherdata[])
|
2006-11-25 13:07:29 -07:00
|
|
|
{
|
2013-09-28 10:22:59 -06:00
|
|
|
Byte **sp, **ep;
|
|
|
|
Byte **othersp, **otherep;
|
|
|
|
int *origorder;
|
|
|
|
|
|
|
|
origorder = (int *) calloc(size, sizeof(int));
|
|
|
|
if (origorder) {
|
|
|
|
reg int i;
|
|
|
|
|
|
|
|
for (i = 0; i < size; ++i)
|
|
|
|
origorder[i] = i;
|
2006-11-25 13:07:29 -07:00
|
|
|
}
|
2013-09-28 10:22:59 -06:00
|
|
|
|
|
|
|
sp = data;
|
|
|
|
ep = &data[size - 1];
|
|
|
|
othersp = otherdata;
|
|
|
|
otherep = &otherdata[size - 1];
|
|
|
|
if (origorder) {
|
|
|
|
sortstrs_block_oo(sp, ep, 0, 0x80, origorder, &origorder[size - 1],
|
|
|
|
othersp, otherep);
|
|
|
|
free(origorder);
|
2006-11-25 13:07:29 -07:00
|
|
|
}
|
2013-09-28 10:22:59 -06:00
|
|
|
else
|
|
|
|
sortstrs_block(sp, ep, 0, 0x80, othersp, otherep);
|
2006-11-25 13:07:29 -07:00
|
|
|
}
|
|
|
|
|
2013-09-28 10:22:59 -06:00
|
|
|
|
|
|
|
|
2006-11-25 13:07:29 -07:00
|
|
|
/*---------------------------------*/
|
|
|
|
/* Sort 1 block of data on 1 bit */
|
|
|
|
/*---------------------------------*/
|
2013-09-28 10:22:59 -06:00
|
|
|
|
2006-11-25 13:07:29 -07:00
|
|
|
static void
|
2013-09-28 10:22:59 -06:00
|
|
|
sortstrs_block(Byte ** start, Byte ** end, int offset, Byte mask,
|
|
|
|
Byte ** otherstart, Byte ** otherend)
|
2006-11-25 13:07:29 -07:00
|
|
|
{
|
2013-09-28 10:22:59 -06:00
|
|
|
reg Byte **sp, **ep;
|
|
|
|
reg Byte m;
|
|
|
|
reg int off;
|
|
|
|
reg Byte *t;
|
|
|
|
reg int curstrlen;
|
|
|
|
int maxstrlen;
|
|
|
|
Byte **othersp, **otherep;
|
|
|
|
|
|
|
|
|
|
|
|
#define newstring(ptr) \
|
2006-11-25 13:07:29 -07:00
|
|
|
{ \
|
|
|
|
t = *ptr; \
|
|
|
|
curstrlen = 0; \
|
|
|
|
while ( *t++ ) ++ curstrlen; \
|
|
|
|
if ( curstrlen > maxstrlen ) maxstrlen = curstrlen; \
|
|
|
|
t = *ptr; \
|
|
|
|
}
|
2013-09-28 10:22:59 -06:00
|
|
|
|
|
|
|
|
|
|
|
maxstrlen = 0;
|
|
|
|
sp = start;
|
|
|
|
ep = end;
|
|
|
|
off = offset;
|
|
|
|
m = mask;
|
|
|
|
othersp = otherstart;
|
|
|
|
otherep = otherend;
|
|
|
|
|
|
|
|
while (1) {
|
|
|
|
newstring(sp)
|
|
|
|
while (((sp != ep) && ((curstrlen < off) || ((t[off] & m) == 0)))) {
|
|
|
|
++sp;
|
|
|
|
++othersp;
|
|
|
|
newstring(sp)
|
|
|
|
}
|
|
|
|
if (sp == ep)
|
|
|
|
break;
|
|
|
|
|
|
|
|
newstring(ep);
|
|
|
|
while (((sp != ep) && (curstrlen >= off) && ((t[off] & m) != 0))) {
|
|
|
|
--ep;
|
|
|
|
--otherep;
|
|
|
|
newstring(ep)
|
|
|
|
}
|
|
|
|
if (sp == ep)
|
|
|
|
break;
|
|
|
|
|
|
|
|
t = *sp;
|
|
|
|
*sp = *ep;
|
|
|
|
*ep = t;
|
|
|
|
|
|
|
|
t = *othersp;
|
|
|
|
*othersp = *otherep;
|
|
|
|
*otherep = t;
|
2006-11-25 13:07:29 -07:00
|
|
|
}
|
2013-09-28 10:22:59 -06:00
|
|
|
|
|
|
|
t = *sp;
|
|
|
|
if ((curstrlen < off) || ((t[off] & m) == 0)) {
|
|
|
|
if (ep != end) {
|
|
|
|
++ep;
|
|
|
|
++otherep;
|
|
|
|
}
|
2006-11-25 13:07:29 -07:00
|
|
|
}
|
2013-09-28 10:22:59 -06:00
|
|
|
else {
|
|
|
|
if (sp != start) {
|
|
|
|
--sp;
|
|
|
|
--othersp;
|
|
|
|
}
|
2006-11-25 13:07:29 -07:00
|
|
|
}
|
2013-09-28 10:22:59 -06:00
|
|
|
|
|
|
|
m >>= 1;
|
|
|
|
if (m == 0) {
|
|
|
|
m = 0x80;
|
|
|
|
if (++off >= maxstrlen)
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sp != start)
|
|
|
|
sortstrs_block(start, sp, off, m, otherstart, othersp);
|
|
|
|
if (ep != end)
|
|
|
|
sortstrs_block(ep, end, off, m, otherep, otherend);
|
2006-11-25 13:07:29 -07:00
|
|
|
}
|
|
|
|
|
2013-09-28 10:22:59 -06:00
|
|
|
|
|
|
|
|
2006-11-25 13:07:29 -07:00
|
|
|
/*-----------------------------------------------------------------*/
|
|
|
|
/* Sort 1 block of data on 1 bit; check for out-of-order entries */
|
|
|
|
/*-----------------------------------------------------------------*/
|
2013-09-28 10:22:59 -06:00
|
|
|
|
2006-11-25 13:07:29 -07:00
|
|
|
static void
|
2013-09-28 10:22:59 -06:00
|
|
|
sortstrs_block_oo(Byte ** start, Byte ** end, int offset, Byte mask,
|
|
|
|
int *ostart, int *oend, Byte ** otherstart, Byte ** otherend)
|
2006-11-25 13:07:29 -07:00
|
|
|
{
|
2013-09-28 10:22:59 -06:00
|
|
|
reg Byte **sp, **ep;
|
|
|
|
reg int *osp, *oep;
|
|
|
|
reg Byte m;
|
|
|
|
reg int off;
|
|
|
|
reg Byte *t;
|
|
|
|
reg int u;
|
|
|
|
reg int curstrlen;
|
|
|
|
int maxstrlen;
|
|
|
|
Byte **othersp, **otherep;
|
|
|
|
|
|
|
|
|
2006-11-25 13:07:29 -07:00
|
|
|
#define newstring(ptr) \
|
|
|
|
{ \
|
|
|
|
t = *ptr; \
|
|
|
|
curstrlen = 0; \
|
|
|
|
while ( *t++ ) ++ curstrlen; \
|
|
|
|
if ( curstrlen > maxstrlen ) maxstrlen = curstrlen; \
|
|
|
|
t = *ptr; \
|
|
|
|
}
|
2013-09-28 10:22:59 -06:00
|
|
|
|
|
|
|
|
|
|
|
maxstrlen = 0;
|
|
|
|
sp = start;
|
|
|
|
ep = end;
|
|
|
|
osp = ostart;
|
|
|
|
oep = oend;
|
|
|
|
off = offset;
|
|
|
|
m = mask;
|
|
|
|
othersp = otherstart;
|
|
|
|
otherep = otherend;
|
|
|
|
|
|
|
|
while (1) {
|
|
|
|
newstring(sp)
|
|
|
|
while (((sp != ep) && ((curstrlen < off) || ((t[off] & m) == 0)))) {
|
|
|
|
++sp;
|
|
|
|
++osp;
|
|
|
|
++othersp;
|
|
|
|
newstring(sp)
|
|
|
|
}
|
|
|
|
if (sp == ep)
|
|
|
|
break;
|
|
|
|
|
|
|
|
newstring(ep);
|
|
|
|
while (((sp != ep) && (curstrlen >= off) && ((t[off] & m) != 0))) {
|
|
|
|
--ep;
|
|
|
|
--oep;
|
|
|
|
--otherep;
|
|
|
|
newstring(ep)
|
|
|
|
}
|
|
|
|
if (sp == ep)
|
|
|
|
break;
|
|
|
|
|
|
|
|
t = *sp;
|
|
|
|
*sp = *ep;
|
|
|
|
*ep = t;
|
|
|
|
|
|
|
|
t = *othersp;
|
|
|
|
*othersp = *otherep;
|
|
|
|
*otherep = t;
|
|
|
|
|
|
|
|
u = *osp;
|
|
|
|
*osp = *oep;
|
|
|
|
*oep = u;
|
2006-11-25 13:07:29 -07:00
|
|
|
}
|
2013-09-28 10:22:59 -06:00
|
|
|
|
|
|
|
t = *sp;
|
|
|
|
if ((curstrlen < off) || ((t[off] & m) == 0)) {
|
|
|
|
if (ep != end) {
|
|
|
|
++ep;
|
|
|
|
++oep;
|
|
|
|
++otherep;
|
|
|
|
}
|
2006-11-25 13:07:29 -07:00
|
|
|
}
|
2013-09-28 10:22:59 -06:00
|
|
|
else {
|
|
|
|
if (sp != start) {
|
|
|
|
--sp;
|
|
|
|
--osp;
|
|
|
|
--othersp;
|
2006-11-25 13:07:29 -07:00
|
|
|
}
|
2013-09-28 10:22:59 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
m >>= 1;
|
|
|
|
if (m == 0) {
|
|
|
|
m = 0x80;
|
|
|
|
if (++off >= maxstrlen) { /* Finished sorting block of strings: *//* Restore duplicates to original order */
|
|
|
|
reg Byte **cp;
|
|
|
|
reg int *ocp;
|
|
|
|
Byte **othercp;
|
|
|
|
|
|
|
|
if (sp != start) {
|
|
|
|
cp = start;
|
|
|
|
ocp = ostart;
|
|
|
|
othercp = otherstart;
|
|
|
|
while (cp != sp) {
|
|
|
|
if (*ocp > *(ocp + 1)) {
|
|
|
|
t = *(cp + 1);
|
|
|
|
*(cp + 1) = *cp;
|
|
|
|
*cp = t;
|
|
|
|
|
|
|
|
t = *(othercp + 1);
|
|
|
|
*(othercp + 1) = *othercp;
|
|
|
|
*othercp = t;
|
|
|
|
|
|
|
|
u = *(ocp + 1);
|
|
|
|
*(ocp + 1) = *ocp;
|
|
|
|
*ocp = u;
|
|
|
|
|
|
|
|
if (cp != start) {
|
|
|
|
--cp;
|
|
|
|
--ocp;
|
|
|
|
--othercp;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
++cp;
|
|
|
|
++ocp;
|
|
|
|
++othercp;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (ep != end) {
|
|
|
|
cp = ep;
|
|
|
|
ocp = oep;
|
|
|
|
othercp = otherep;
|
|
|
|
while (cp != end) {
|
|
|
|
if (*ocp > *(ocp + 1)) {
|
|
|
|
t = *(cp + 1);
|
|
|
|
*(cp + 1) = *cp;
|
|
|
|
*cp = t;
|
|
|
|
|
|
|
|
t = *(othercp + 1);
|
|
|
|
*(othercp + 1) = *othercp;
|
|
|
|
*othercp = t;
|
|
|
|
|
|
|
|
u = *(ocp + 1);
|
|
|
|
*(ocp + 1) = *ocp;
|
|
|
|
*ocp = u;
|
|
|
|
|
|
|
|
if (cp != ep) {
|
|
|
|
--cp;
|
|
|
|
--ocp;
|
|
|
|
--othercp;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
++cp;
|
|
|
|
++ocp;
|
|
|
|
++othercp;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return;
|
2006-11-25 13:07:29 -07:00
|
|
|
}
|
|
|
|
}
|
2013-09-28 10:22:59 -06:00
|
|
|
|
|
|
|
if (sp != start)
|
|
|
|
sortstrs_block_oo(start, sp, off, m, ostart, osp, otherstart, othersp);
|
|
|
|
if (ep != end)
|
|
|
|
sortstrs_block_oo(ep, end, off, m, oep, oend, otherep, otherend);
|
2006-11-25 13:07:29 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Function Name: InitManual
|
|
|
|
* Description: Initializes this manual section.
|
|
|
|
* Arguments: l_manual - local copy of the manual structure.
|
|
|
|
* label - the button label for this section.
|
|
|
|
* Returns: none.
|
|
|
|
*/
|
|
|
|
|
|
|
|
static void
|
2013-09-28 10:22:59 -06:00
|
|
|
InitManual(Manual * l_manual, char *label)
|
2006-11-25 13:07:29 -07:00
|
|
|
{
|
2013-09-28 10:22:59 -06:00
|
|
|
bzero(l_manual, sizeof(Manual)); /* clear it. */
|
|
|
|
l_manual->blabel = label; /* set label. */
|
2006-11-25 13:07:29 -07:00
|
|
|
}
|
2013-09-28 10:22:59 -06:00
|
|
|
|
2006-11-25 13:07:29 -07:00
|
|
|
#if defined(DEBUG)
|
|
|
|
|
|
|
|
/* Function Name: DumpManual
|
|
|
|
* Description: Debugging function that dumps the entire manual page
|
|
|
|
* structure.
|
|
|
|
* Arguments: number - the number of sections.
|
|
|
|
* Returns: none.
|
|
|
|
*/
|
|
|
|
|
|
|
|
void
|
|
|
|
DumpManual(int number)
|
|
|
|
{
|
2013-09-28 10:22:59 -06:00
|
|
|
register int i, j;
|
|
|
|
|
|
|
|
for (i = 0; i < number; i++) {
|
|
|
|
printf("label: %s\n", manual[i].blabel);
|
|
|
|
for (j = 0; j < manual[i].nentries; j++)
|
|
|
|
printf("%s\n", manual[i].entries[j]);
|
|
|
|
}
|
2006-11-25 13:07:29 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* DEBUG */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef MANCONF
|
|
|
|
|
|
|
|
#if defined(MANCONFIGSTYLE_FreeBSD)
|
|
|
|
|
|
|
|
/* Function Name: ReadManConfig
|
|
|
|
* Description: Reads man.conf file used by FreeBSD man
|
|
|
|
* Argument: manpath - char array to return path in.
|
|
|
|
* Returns: TRUE if read was successful.
|
|
|
|
*/
|
|
|
|
|
|
|
|
Bool
|
|
|
|
ReadManConfig(char manpath[])
|
|
|
|
{
|
2013-09-28 10:22:59 -06:00
|
|
|
FILE *fp;
|
|
|
|
char line[BUFSIZ];
|
|
|
|
char *path;
|
|
|
|
Bool firstpath = TRUE;
|
|
|
|
|
|
|
|
if (!(fp = fopen(MANCONF, "r")))
|
|
|
|
return (FALSE);
|
|
|
|
|
|
|
|
while (fgets(line, sizeof(line), fp)) {
|
|
|
|
path = strtok(line, " \t\n");
|
|
|
|
if (!path || *path == '#')
|
|
|
|
continue;
|
|
|
|
if (strcmp(path, "MANPATH_MAP") == 0)
|
|
|
|
path = strtok((char *) NULL, " \t\n");
|
|
|
|
else if (strcmp(path, "MANDATORY_MANPATH") != 0 &&
|
|
|
|
strcmp(path, "OPTIONAL_MANPATH") != 0)
|
|
|
|
return (FALSE);
|
|
|
|
path = strtok((char *) NULL, " \t\n");
|
|
|
|
if (!path || *path == '#')
|
|
|
|
return FALSE;
|
|
|
|
if (firstpath) {
|
|
|
|
strcpy(manpath, path);
|
|
|
|
firstpath = FALSE;
|
|
|
|
}
|
|
|
|
else if (!strstr(manpath, path)) {
|
|
|
|
strcat(manpath, ":");
|
|
|
|
strcat(manpath, path);
|
|
|
|
}
|
2006-11-25 13:07:29 -07:00
|
|
|
}
|
2013-09-28 10:22:59 -06:00
|
|
|
fclose(fp);
|
|
|
|
return (!firstpath);
|
2006-11-25 13:07:29 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-09-28 10:22:59 -06:00
|
|
|
#elif defined(MANCONFIGSTYLE_Linux) /* not FreeBSD */
|
2006-11-25 13:07:29 -07:00
|
|
|
|
|
|
|
/* Function Name: ReadManConfig
|
|
|
|
* Description: Reads man.conf file used by Linux man
|
|
|
|
* Argument: manpath - char array to return path in.
|
|
|
|
* Returns: TRUE if read was successful.
|
|
|
|
*/
|
|
|
|
|
|
|
|
Bool
|
|
|
|
ReadManConfig(char manpath[])
|
|
|
|
{
|
2013-09-28 10:22:59 -06:00
|
|
|
FILE *fp;
|
|
|
|
char line[BUFSIZ];
|
|
|
|
char *path;
|
|
|
|
Bool firstpath = TRUE;
|
|
|
|
|
|
|
|
if (!(fp = fopen(MANCONF, "r")))
|
|
|
|
return (FALSE);
|
|
|
|
|
|
|
|
while (fgets(line, sizeof(line), fp)) {
|
|
|
|
path = strtok(line, " \t\n");
|
|
|
|
if (!path || *path == '#' || (strcmp(path, "MANPATH") != 0))
|
|
|
|
continue;
|
|
|
|
path = strtok((char *) NULL, " \t\n");
|
|
|
|
if (!path || *path == '#')
|
|
|
|
return FALSE;
|
|
|
|
if (firstpath) {
|
|
|
|
strcpy(manpath, path);
|
|
|
|
firstpath = FALSE;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
strcat(manpath, ":");
|
|
|
|
strcat(manpath, path);
|
|
|
|
}
|
2006-11-25 13:07:29 -07:00
|
|
|
}
|
2013-09-28 10:22:59 -06:00
|
|
|
fclose(fp);
|
|
|
|
return (!firstpath);
|
2006-11-25 13:07:29 -07:00
|
|
|
}
|
|
|
|
|
2013-09-28 10:22:59 -06:00
|
|
|
#elif defined(MANCONFIGSTYLE_OpenBSD) /* not FreeBSD or Linux */
|
2006-11-25 13:07:29 -07:00
|
|
|
|
|
|
|
/* Function Name: ReadManConfig
|
|
|
|
* Description: Reads man.conf file used by Open/NetBSD
|
|
|
|
* Argument: manpath - char array to return path in.
|
|
|
|
* Returns: TRUE if read was successful.
|
|
|
|
*
|
2013-09-28 10:22:59 -06:00
|
|
|
* This version expands the glob pattern that can be found
|
2006-11-25 13:07:29 -07:00
|
|
|
* in man.conf
|
|
|
|
*/
|
|
|
|
#include <glob.h>
|
|
|
|
|
|
|
|
Bool
|
|
|
|
ReadManConfig(char manpath[])
|
|
|
|
{
|
2013-09-28 10:22:59 -06:00
|
|
|
FILE *fp;
|
|
|
|
char line[BUFSIZ];
|
|
|
|
char *path;
|
|
|
|
Bool firstpath = TRUE;
|
|
|
|
glob_t gs;
|
|
|
|
int i;
|
|
|
|
|
2006-11-25 13:07:29 -07:00
|
|
|
if (!(fp = fopen(MANCONF, "r")))
|
2013-09-28 10:22:59 -06:00
|
|
|
return (FALSE);
|
|
|
|
|
2006-11-25 13:07:29 -07:00
|
|
|
while (fgets(line, sizeof(line), fp)) {
|
2013-09-28 10:22:59 -06:00
|
|
|
path = strtok(line, " \t\n");
|
|
|
|
if (!path || *path == '#')
|
|
|
|
continue;
|
|
|
|
if (strcmp(path, "_default")) {
|
|
|
|
/* for now */
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
memset(&gs, 0, sizeof(glob_t));
|
|
|
|
while ((path = strtok((char *) NULL, " \t\n"))) {
|
|
|
|
if (glob(path, GLOB_BRACE, NULL, &gs) < 0) {
|
|
|
|
fclose(fp);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
} /* while */
|
|
|
|
for (i = 0; i < gs.gl_pathc; i++) {
|
|
|
|
|
|
|
|
if (firstpath) {
|
|
|
|
strcpy(manpath, gs.gl_pathv[i]);
|
|
|
|
firstpath = FALSE;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
strcat(manpath, ":");
|
|
|
|
strcat(manpath, gs.gl_pathv[i]);
|
|
|
|
}
|
|
|
|
} /* for */
|
|
|
|
globfree(&gs);
|
2006-11-25 13:07:29 -07:00
|
|
|
}
|
|
|
|
fclose(fp);
|
2013-09-28 10:22:59 -06:00
|
|
|
return (!firstpath);
|
2006-11-25 13:07:29 -07:00
|
|
|
}
|
|
|
|
|
2013-09-28 10:22:59 -06:00
|
|
|
#elif defined(MANCONFIGSTYLE_BSD) /* not FreeBSD, Linux, or OpenBSD */
|
2006-11-25 13:07:29 -07:00
|
|
|
|
|
|
|
/* Function Name: ReadManConfig
|
|
|
|
* Description: Reads man.conf file used by BSD 4.4
|
|
|
|
* Argument: manpath - char array to return path in.
|
|
|
|
* Returns: TRUE if read was successful.
|
|
|
|
*/
|
|
|
|
|
|
|
|
Bool
|
2013-09-28 10:22:59 -06:00
|
|
|
ReadManConfig(char manpath[])
|
|
|
|
{
|
|
|
|
FILE *fp;
|
|
|
|
char line[BUFSIZ];
|
|
|
|
char *path;
|
|
|
|
Bool firstpath = TRUE;
|
2006-11-25 13:07:29 -07:00
|
|
|
|
2013-09-28 10:22:59 -06:00
|
|
|
if (!(fp = fopen(MANCONF, "r")))
|
|
|
|
return (FALSE);
|
2006-11-25 13:07:29 -07:00
|
|
|
|
2013-09-28 10:22:59 -06:00
|
|
|
while (fgets(line, sizeof(line), fp)) {
|
|
|
|
path = strtok(line, " \t\n");
|
|
|
|
if (!path || *path == '#' || strcmp(path, "_default"))
|
|
|
|
continue;
|
|
|
|
while ((path = strtok((char *) NULL, " \t\n"))) {
|
|
|
|
if (firstpath) {
|
|
|
|
strcpy(manpath, path);
|
|
|
|
firstpath = FALSE;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
strcat(manpath, ":");
|
|
|
|
strcat(manpath, path);
|
|
|
|
}
|
|
|
|
}
|
2006-11-25 13:07:29 -07:00
|
|
|
}
|
2013-09-28 10:22:59 -06:00
|
|
|
fclose(fp);
|
|
|
|
return (!firstpath);
|
2006-11-25 13:07:29 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
#else /* not BSD */
|
|
|
|
|
|
|
|
#error "MANCONF defined (in vendor.h) for unknown operating system."
|
|
|
|
|
|
|
|
#endif /* MANCONFIGSTYLE == FreeBSD ... BSD */
|
|
|
|
|
|
|
|
#endif /* MANCONF */
|