man.c revision 1abf7346
11abf7346Smrg/* $XConsortium: man.c,v 1.30 94/04/17 20:43:56 rws Exp $ */ 21abf7346Smrg/* $XdotOrg: $ */ 31abf7346Smrg/* 41abf7346Smrg 51abf7346SmrgCopyright (c) 1987, 1988 X Consortium 61abf7346Smrg 71abf7346SmrgPermission is hereby granted, free of charge, to any person obtaining 81abf7346Smrga copy of this software and associated documentation files (the 91abf7346Smrg"Software"), to deal in the Software without restriction, including 101abf7346Smrgwithout limitation the rights to use, copy, modify, merge, publish, 111abf7346Smrgdistribute, sublicense, and/or sell copies of the Software, and to 121abf7346Smrgpermit persons to whom the Software is furnished to do so, subject to 131abf7346Smrgthe following conditions: 141abf7346Smrg 151abf7346SmrgThe above copyright notice and this permission notice shall be included 161abf7346Smrgin all copies or substantial portions of the Software. 171abf7346Smrg 181abf7346SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 191abf7346SmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 201abf7346SmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 211abf7346SmrgIN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR 221abf7346SmrgOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 231abf7346SmrgARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 241abf7346SmrgOTHER DEALINGS IN THE SOFTWARE. 251abf7346Smrg 261abf7346SmrgExcept as contained in this notice, the name of the X Consortium shall 271abf7346Smrgnot be used in advertising or otherwise to promote the sale, use or 281abf7346Smrgother dealings in this Software without prior written authorization 291abf7346Smrgfrom the X Consortium. 301abf7346Smrg 311abf7346Smrg*/ 321abf7346Smrg/* $XFree86: xc/programs/xman/man.c,v 1.8 2003/04/09 20:31:31 herrb Exp $ */ 331abf7346Smrg 341abf7346Smrg 351abf7346Smrg#include "globals.h" 361abf7346Smrg#include "vendor.h" /* vendor-specific defines and data */ 371abf7346Smrg 381abf7346Smrg#ifndef X_NOT_POSIX 391abf7346Smrg#include <dirent.h> 401abf7346Smrg#else 411abf7346Smrg#ifdef SYSV 421abf7346Smrg#include <dirent.h> 431abf7346Smrg#else 441abf7346Smrg#ifdef USG 451abf7346Smrg#include <dirent.h> 461abf7346Smrg#else 471abf7346Smrg#include <sys/dir.h> 481abf7346Smrg#ifndef dirent 491abf7346Smrg#define dirent direct 501abf7346Smrg#endif 511abf7346Smrg#endif 521abf7346Smrg#endif 531abf7346Smrg#endif 541abf7346Smrg 551abf7346Smrg#ifdef DEBUG 561abf7346Smrgstatic char error_buf[BUFSIZ]; /* The buffer for error messages. */ 571abf7346Smrg#endif /* DEBUG */ 581abf7346Smrg 591abf7346Smrgstatic void AddToCurrentSection(Manual * local_manual, char * path); 601abf7346Smrgstatic void InitManual(Manual * l_manual, char * label); 611abf7346Smrgstatic void ReadCurrentSection(Manual * local_manual, char * path); 621abf7346Smrgstatic void ReadMandescFile(SectionList ** section_list, char * path); 631abf7346Smrgstatic void SortAndRemove(Manual *man, int number); 641abf7346Smrgstatic void SortList(SectionList ** list); 651abf7346Smrg 661abf7346Smrg#define SECT_ERROR -1 671abf7346Smrg 681abf7346Smrg#ifndef Byte 691abf7346Smrg#define Byte unsigned char 701abf7346Smrg#endif 711abf7346Smrg 721abf7346Smrg#ifndef reg 731abf7346Smrg#define reg register 741abf7346Smrg#endif 751abf7346Smrg 761abf7346Smrgstatic void sortstrs (Byte *data[], int size, Byte *otherdata[]); 771abf7346Smrgstatic void sortstrs_block (Byte **, Byte **, int, Byte, Byte **, Byte **); 781abf7346Smrgstatic void sortstrs_block_oo (Byte **, Byte **, int, Byte, int *, int *, Byte **, Byte **); 791abf7346Smrg 801abf7346Smrg/* Function Name: Man 811abf7346Smrg * Description: Builds a list of all manual directories and files. 821abf7346Smrg * Arguments: none. 831abf7346Smrg * Returns: the number of manual sections. 841abf7346Smrg */ 851abf7346Smrg 861abf7346Smrgint 871abf7346SmrgMan(void) 881abf7346Smrg{ 891abf7346Smrg SectionList *list = NULL; 901abf7346Smrg char *ptr, *lang = 0, manpath[BUFSIZ], buf[BUFSIZ], *path, *current_label; 911abf7346Smrg int sect, num_alloced; 921abf7346Smrg 931abf7346Smrg/* 941abf7346Smrg * Get the environment variable MANPATH, and if it doesn't exist then use 951abf7346Smrg * SYSMANPATH and LOCALMANPATH. 961abf7346Smrg */ 971abf7346Smrg 981abf7346Smrg /* if MANPATH variable ends in ':'. So, should extend it's value to the 991abf7346Smrg * default search path. 1001abf7346Smrg */ 1011abf7346Smrg 1021abf7346Smrg *manpath = '\0'; 1031abf7346Smrg if ((ptr = getenv("MANPATH")) != NULL) 1041abf7346Smrg strcpy(manpath, ptr); 1051abf7346Smrg if (ptr == NULL || streq(ptr , "") || ptr[strlen(ptr) - 1] == ':') { 1061abf7346Smrg lang = getenv("LANG"); 1071abf7346Smrg#ifdef MANCONF 1081abf7346Smrg if (!ReadManConfig(manpath + strlen(manpath))) 1091abf7346Smrg#endif 1101abf7346Smrg { 1111abf7346Smrg#ifdef MANCONF 1121abf7346Smrg if (manpath[strlen(manpath) - 1] != ':') 1131abf7346Smrg strcat(manpath, ":"); 1141abf7346Smrg#endif 1151abf7346Smrg strcat(manpath, SYSMANPATH); 1161abf7346Smrg#ifdef LOCALMANPATH 1171abf7346Smrg strcat(manpath, ":"); 1181abf7346Smrg strcat(manpath, LOCALMANPATH); 1191abf7346Smrg#endif 1201abf7346Smrg } 1211abf7346Smrg } 1221abf7346Smrg 1231abf7346Smrg/* 1241abf7346Smrg * Get the list of manual directories in the users MANPATH that we should 1251abf7346Smrg * open to look for manual pages. The ``mandesc'' file is read here. 1261abf7346Smrg */ 1271abf7346Smrg 1281abf7346Smrg for ( path = manpath ; (ptr = index(path , ':')) != NULL ; path = ++ptr) { 1291abf7346Smrg *ptr = '\0'; 1301abf7346Smrg if (lang != 0) { 1311abf7346Smrg strcpy(buf, path); 1321abf7346Smrg strcat(buf, "/"); 1331abf7346Smrg strncat(buf, lang, sizeof(buf) - strlen(path) + 1); 1341abf7346Smrg buf[sizeof(buf) - strlen(path) + 1] = '\0'; 1351abf7346Smrg ReadMandescFile(&list, buf); 1361abf7346Smrg } 1371abf7346Smrg ReadMandescFile(&list, path); 1381abf7346Smrg } 1391abf7346Smrg if (lang != 0) { 1401abf7346Smrg strcpy(buf, path); 1411abf7346Smrg strcat(buf, "/"); 1421abf7346Smrg strncat(buf, lang, sizeof(buf) - strlen(path) + 1); 1431abf7346Smrg buf[sizeof(buf) - strlen(path) + 1] = '\0'; 1441abf7346Smrg ReadMandescFile(&list, buf); 1451abf7346Smrg } 1461abf7346Smrg ReadMandescFile(&list, path); 1471abf7346Smrg 1481abf7346Smrg SortList(&list); 1491abf7346Smrg 1501abf7346Smrg sect = 0; 1511abf7346Smrg num_alloced = SECTALLOC; 1521abf7346Smrg manual = (Manual *) XtMalloc( sizeof(Manual) * num_alloced ); 1531abf7346Smrg InitManual( manual, list->label ); 1541abf7346Smrg manual[sect].flags = list->flags; 1551abf7346Smrg current_label = NULL; 1561abf7346Smrg 1571abf7346Smrg while ( list != NULL ) { 1581abf7346Smrg SectionList * old_list; 1591abf7346Smrg 1601abf7346Smrg if ( current_label == NULL || streq(list->label, current_label) ) 1611abf7346Smrg AddToCurrentSection( manual + sect, list->directory); 1621abf7346Smrg else { 1631abf7346Smrg if (manual[sect].nentries == 0) { /* empty section, re-use it. */ 1641abf7346Smrg XtFree(manual[sect].blabel); 1651abf7346Smrg manual[sect].blabel = list->label; 1661abf7346Smrg manual[sect].flags = list->flags; 1671abf7346Smrg } 1681abf7346Smrg else { 1691abf7346Smrg if ( ++sect >= num_alloced ) { 1701abf7346Smrg num_alloced += SECTALLOC; 1711abf7346Smrg manual = (Manual *) XtRealloc ( (char *) manual, 1721abf7346Smrg (sizeof(Manual) * num_alloced)); 1731abf7346Smrg if (manual == NULL) 1741abf7346Smrg PrintError("Could not allocate memory for manual sections."); 1751abf7346Smrg } 1761abf7346Smrg InitManual( manual + sect, list->label ); 1771abf7346Smrg manual[sect].flags = list->flags; 1781abf7346Smrg } 1791abf7346Smrg AddToCurrentSection( manual + sect, list->directory); 1801abf7346Smrg } 1811abf7346Smrg /* Save label to see if it matches next entry. */ 1821abf7346Smrg current_label = list->label; 1831abf7346Smrg old_list = list; 1841abf7346Smrg list = list->next; 1851abf7346Smrg XtFree((char *) old_list); /* free what you allocate. */ 1861abf7346Smrg } 1871abf7346Smrg if (manual[sect].nentries != 0) 1881abf7346Smrg sect++; /* don't forget that last section. */ 1891abf7346Smrg 1901abf7346Smrg SortAndRemove(manual, sect); 1911abf7346Smrg 1921abf7346Smrg#ifdef notdef /* dump info. */ 1931abf7346Smrg DumpManual(sect); 1941abf7346Smrg#endif 1951abf7346Smrg 1961abf7346Smrg/* 1971abf7346Smrg * realloc manual to be minimum space necessary. 1981abf7346Smrg */ 1991abf7346Smrg 2001abf7346Smrg if (sect == 0) 2011abf7346Smrg PrintError("No manual pages found."); 2021abf7346Smrg manual = (Manual *) XtRealloc( (char *) manual, (sizeof(Manual) * sect)); 2031abf7346Smrg if (manual == NULL) 2041abf7346Smrg PrintError("Could not allocate memory for manual sections."); 2051abf7346Smrg 2061abf7346Smrg return(sect); /* return the number of man sections. */ 2071abf7346Smrg} 2081abf7346Smrg 2091abf7346Smrg/* Function Name: SortList 2101abf7346Smrg * Description: Sorts the list of sections to search. 2111abf7346Smrg * Arguments: list - a pointer to the list to sort. 2121abf7346Smrg * Returns: a sorted list. 2131abf7346Smrg * 2141abf7346Smrg * This is the most complicated part of the entire operation. 2151abf7346Smrg * all sections with the same label must by right next to each other, 2161abf7346Smrg * but the sections that are in the standard list have to come first. 2171abf7346Smrg */ 2181abf7346Smrg 2191abf7346Smrgstatic void 2201abf7346SmrgSortList(SectionList ** list) 2211abf7346Smrg{ 2221abf7346Smrg SectionList * local; 2231abf7346Smrg SectionList *head, *last, *inner, *old; 2241abf7346Smrg 2251abf7346Smrg if (*list == NULL) 2261abf7346Smrg PrintError("No manual sections to read, exiting."); 2271abf7346Smrg 2281abf7346Smrg/* 2291abf7346Smrg * First step 2301abf7346Smrg * 2311abf7346Smrg * Look for standard list items, and more them to the top of the list. 2321abf7346Smrg */ 2331abf7346Smrg 2341abf7346Smrg last = NULL; /* keep Saber happy. */ 2351abf7346Smrg for ( local = *list ; local->next != NULL ; local = local->next) { 2361abf7346Smrg if ( local->flags ) { 2371abf7346Smrg if ( local == *list ) /* top element is already standard. */ 2381abf7346Smrg break; 2391abf7346Smrg head = local; 2401abf7346Smrg 2411abf7346Smrg /* Find end of standard block */ 2421abf7346Smrg for (old = 0 ; (local->next != NULL) && (local->flags) 2431abf7346Smrg ; old = local, local = local->next); 2441abf7346Smrg 2451abf7346Smrg if (old != 0) { 2461abf7346Smrg last->next = old->next; /* Move the block. */ 2471abf7346Smrg old->next = *list; 2481abf7346Smrg *list = head; 2491abf7346Smrg } 2501abf7346Smrg 2511abf7346Smrg break; /* First step accomplished. */ 2521abf7346Smrg } 2531abf7346Smrg last = local; 2541abf7346Smrg } 2551abf7346Smrg 2561abf7346Smrg/* 2571abf7346Smrg * Second step 2581abf7346Smrg * 2591abf7346Smrg * Move items with duplicate labels right next to each other. 2601abf7346Smrg * 2611abf7346Smrg * Changed to keep the order of the list entries unchanged. 2621abf7346Smrg */ 2631abf7346Smrg 2641abf7346Smrg for (local = *list; local->next != NULL; local = local->next) { 2651abf7346Smrg head = local; 2661abf7346Smrg old = inner = local->next; 2671abf7346Smrg while (inner != NULL) { 2681abf7346Smrg if (streq(inner->label, local->label)) { 2691abf7346Smrg if (old != inner) { 2701abf7346Smrg old->next = inner->next; 2711abf7346Smrg last = inner->next; 2721abf7346Smrg inner->next = head->next; 2731abf7346Smrg head->next = inner; 2741abf7346Smrg head = inner; 2751abf7346Smrg old = inner = last; 2761abf7346Smrg continue; 2771abf7346Smrg } 2781abf7346Smrg else 2791abf7346Smrg head = inner; 2801abf7346Smrg } 2811abf7346Smrg old = inner; 2821abf7346Smrg inner = inner->next; 2831abf7346Smrg } 2841abf7346Smrg } 2851abf7346Smrg} 2861abf7346Smrg 2871abf7346Smrg/* Function Name: ReadMandescFile 2881abf7346Smrg * Description: Reads the mandesc file, and adds more sections as 2891abf7346Smrg * necessary. 2901abf7346Smrg * Arguments: path - path name if the current search directory. 2911abf7346Smrg * section_list - pointer to the list of sections. 2921abf7346Smrg * Returns: TRUE in we should use default sections 2931abf7346Smrg */ 2941abf7346Smrg 2951abf7346Smrgstatic void 2961abf7346SmrgReadMandescFile(SectionList ** section_list, char * path) 2971abf7346Smrg{ 2981abf7346Smrg char mandesc_file[BUFSIZ]; /* full path to the mandesc file. */ 2991abf7346Smrg FILE * descfile; 3001abf7346Smrg char string[BUFSIZ], local_file[BUFSIZ]; 3011abf7346Smrg Boolean use_defaults = TRUE; 3021abf7346Smrg char *cp; 3031abf7346Smrg 3041abf7346Smrg snprintf(mandesc_file, sizeof(mandesc_file), "%s/%s", path, MANDESC); 3051abf7346Smrg if ( (descfile = fopen(mandesc_file, "r")) != NULL) { 3061abf7346Smrg while ( fgets(string, BUFSIZ, descfile) != NULL) { 3071abf7346Smrg string[strlen(string)-1] = '\0'; /* Strip off the CR. */ 3081abf7346Smrg 3091abf7346Smrg if ( streq(string, NO_SECTION_DEFAULTS) ) { 3101abf7346Smrg use_defaults = FALSE; 3111abf7346Smrg continue; 3121abf7346Smrg } 3131abf7346Smrg 3141abf7346Smrg if ((cp = index(string,'\t')) != NULL) { 3151abf7346Smrg char *s; 3161abf7346Smrg *cp++ = '\0'; 3171abf7346Smrg strcpy(local_file, MAN); 3181abf7346Smrg strcat(local_file, string); 3191abf7346Smrg if ((s = index(cp,'\t')) != NULL) { 3201abf7346Smrg *s++ = '\0'; 3211abf7346Smrg if (streq(s, SUFFIX)) 3221abf7346Smrg AddNewSection(section_list, path, local_file, cp, MSUFFIX); 3231abf7346Smrg else if (streq(s, FOLD)) 3241abf7346Smrg AddNewSection(section_list, path, local_file, cp, MFOLD); 3251abf7346Smrg else if (streq(s, FOLDSUFFIX)) 3261abf7346Smrg AddNewSection(section_list, path, local_file, cp, MFOLDSUFFIX); 3271abf7346Smrg else 3281abf7346Smrg AddNewSection(section_list, path, local_file, cp, MNULL); 3291abf7346Smrg } else 3301abf7346Smrg AddNewSection(section_list, path, local_file, cp, MNULL); 3311abf7346Smrg } else { 3321abf7346Smrg snprintf(local_file, sizeof(local_file), "%s%c", MAN, string[0]); 3331abf7346Smrg AddNewSection(section_list, path, local_file, (string + 1), FALSE ); 3341abf7346Smrg#ifdef SEARCHOTHER 3351abf7346Smrg snprintf(local_file, sizeof(local_file), "%s%c", SEARCHOTHER, string[0]); 3361abf7346Smrg AddNewSection(section_list, path, local_file, (string + 1), FALSE); 3371abf7346Smrg#endif 3381abf7346Smrg } 3391abf7346Smrg } 3401abf7346Smrg 3411abf7346Smrg fclose(descfile); 3421abf7346Smrg } 3431abf7346Smrg if (use_defaults) 3441abf7346Smrg AddStandardSections(section_list, path); 3451abf7346Smrg} 3461abf7346Smrg 3471abf7346Smrg/* Function Name: AddNewSection 3481abf7346Smrg * Description: Adds the new section onto the current section list. 3491abf7346Smrg * Arguments: list - pointer to the section list. 3501abf7346Smrg * path - the path to the current manual section. 3511abf7346Smrg * file - the file to save. 3521abf7346Smrg * label - the current section label. 3531abf7346Smrg * flags = 1 - add a suffix 3541abf7346Smrg * = 2 - fold to lower case 3551abf7346Smrg * Returns: none. 3561abf7346Smrg */ 3571abf7346Smrg 3581abf7346Smrgvoid 3591abf7346SmrgAddNewSection( 3601abf7346SmrgSectionList **list, 3611abf7346Smrgchar * path, char * file, char * label, 3621abf7346Smrgint flags) 3631abf7346Smrg{ 3641abf7346Smrg SectionList * local_list, * end; 3651abf7346Smrg char full_path[BUFSIZ]; 3661abf7346Smrg 3671abf7346Smrg/* Allocate a new list element */ 3681abf7346Smrg 3691abf7346Smrg local_list = (SectionList *) XtMalloc(sizeof(SectionList)); 3701abf7346Smrg 3711abf7346Smrg if (*list != NULL) { 3721abf7346Smrg for ( end = *list ; end->next != NULL ; end = end->next ); 3731abf7346Smrg end->next = local_list; 3741abf7346Smrg } 3751abf7346Smrg else 3761abf7346Smrg *list = local_list; 3771abf7346Smrg 3781abf7346Smrg local_list->next = NULL; 3791abf7346Smrg local_list->label = StrAlloc(label); 3801abf7346Smrg snprintf(full_path, sizeof(full_path), "%s/%s", path, file); 3811abf7346Smrg local_list->directory = StrAlloc(full_path); 3821abf7346Smrg local_list->flags = flags; 3831abf7346Smrg} 3841abf7346Smrg 3851abf7346Smrg/* Function Name: AddToCurrentSection 3861abf7346Smrg * Description: This function gets the names of the manual page 3871abf7346Smrg * directories, then closes the directory. 3881abf7346Smrg * Arguments: local_manual - a pointer to a manual pages structure. 3891abf7346Smrg * path - the path to this directory. 3901abf7346Smrg * Returns: none. 3911abf7346Smrg */ 3921abf7346Smrg 3931abf7346Smrgstatic void 3941abf7346SmrgAddToCurrentSection(Manual * local_manual, char * path) 3951abf7346Smrg{ 3961abf7346Smrg char temp_path[BUFSIZ]; 3971abf7346Smrg 3981abf7346Smrg#if defined(__OpenBSD__) || defined(__NetBSD__) 3991abf7346Smrg snprintf(temp_path, sizeof(temp_path), "%s/%s", path, MACHINE); 4001abf7346Smrg ReadCurrentSection(local_manual, temp_path); 4011abf7346Smrg#endif 4021abf7346Smrg ReadCurrentSection(local_manual, path); 4031abf7346Smrg snprintf(temp_path, sizeof(temp_path), "%s.%s", path, COMPRESSION_EXTENSION); 4041abf7346Smrg ReadCurrentSection(local_manual, temp_path); 4051abf7346Smrg} 4061abf7346Smrg 4071abf7346Smrg/* Function Name: ReadCurrentSection 4081abf7346Smrg * Description: Actually does the work of adding entries to the 4091abf7346Smrg * new section 4101abf7346Smrg * Arguments: local_manual - a pointer to a manual pages structure. 4111abf7346Smrg * path - the path to this directory. 4121abf7346Smrg * compressed - Is this a compressed directory? 4131abf7346Smrg * Returns: TRUE if any entries are found. 4141abf7346Smrg */ 4151abf7346Smrg 4161abf7346Smrgstatic void 4171abf7346SmrgReadCurrentSection(Manual * local_manual, char * path) 4181abf7346Smrg{ 4191abf7346Smrg DIR * dir; 4201abf7346Smrg 4211abf7346Smrg register struct dirent *dp; 4221abf7346Smrg 4231abf7346Smrg register int nentries; 4241abf7346Smrg register int nalloc; 4251abf7346Smrg char full_name[BUFSIZ], *ptr; 4261abf7346Smrg 4271abf7346Smrg if((dir = opendir(path)) == NULL) { 4281abf7346Smrg#ifdef DEBUG 4291abf7346Smrg snprintf(error_buf, sizeof(error_buf), "Can't open directory %s", path); 4301abf7346Smrg PopupWarning(NULL, error_buf); 4311abf7346Smrg#endif /* DEBUG */ 4321abf7346Smrg return; 4331abf7346Smrg } 4341abf7346Smrg 4351abf7346Smrg/* 4361abf7346Smrg * Remove the compression extension from the path name. 4371abf7346Smrg */ 4381abf7346Smrg 4391abf7346Smrg if ( (ptr = rindex(path, '.')) != NULL) { 4401abf7346Smrg#if !defined(__SCO__) && !defined(ISC) 4411abf7346Smrg if (streq(ptr + 1, COMPRESSION_EXTENSION)) 4421abf7346Smrg#else 4431abf7346Smrg if (strpbrk(ptr + 1, COMPRESSION_EXTENSIONS) != NULL) 4441abf7346Smrg#endif 4451abf7346Smrg *ptr = '\0'; 4461abf7346Smrg#ifdef GZIP_EXTENSION 4471abf7346Smrg else if (streq(ptr + 1, GZIP_EXTENSION)) 4481abf7346Smrg *ptr = '\0'; 4491abf7346Smrg#endif 4501abf7346Smrg } 4511abf7346Smrg 4521abf7346Smrg nentries = local_manual->nentries; 4531abf7346Smrg nalloc = local_manual->nalloc; 4541abf7346Smrg 4551abf7346Smrg while( (dp = readdir(dir)) != NULL ) { 4561abf7346Smrg char * name = dp->d_name; 4571abf7346Smrg if (name[0] == '.') 4581abf7346Smrg continue; 4591abf7346Smrg#ifndef CRAY 4601abf7346Smrg if (index(name, '.') == NULL) 4611abf7346Smrg continue; 4621abf7346Smrg#endif 4631abf7346Smrg if( nentries >= nalloc ) { 4641abf7346Smrg nalloc += ENTRYALLOC; 4651abf7346Smrg local_manual->entries =(char **) XtRealloc((char *)local_manual->entries, 4661abf7346Smrg nalloc * sizeof(char *)); 4671abf7346Smrg local_manual->entries_less_paths = 4681abf7346Smrg (char **) XtRealloc((char *)local_manual->entries_less_paths, 4691abf7346Smrg nalloc * sizeof(char *)); 4701abf7346Smrg } 4711abf7346Smrg 4721abf7346Smrg snprintf(full_name, sizeof(full_name), "%s/%s", path, name); 4731abf7346Smrg/* 4741abf7346Smrg * Remove the compression extension from the entry name. 4751abf7346Smrg */ 4761abf7346Smrg 4771abf7346Smrg if ( (ptr = rindex(full_name, '.')) != NULL) { 4781abf7346Smrg#if !defined(__SCO__) && !defined(ISC) 4791abf7346Smrg if (streq(ptr + 1, COMPRESSION_EXTENSION)) 4801abf7346Smrg#else 4811abf7346Smrg if (strpbrk(ptr + 1, COMPRESSION_EXTENSIONS) != NULL) 4821abf7346Smrg#endif 4831abf7346Smrg *ptr = '\0'; 4841abf7346Smrg#ifdef GZIP_EXTENSION 4851abf7346Smrg else if (streq(ptr + 1, GZIP_EXTENSION)) 4861abf7346Smrg *ptr = '\0'; 4871abf7346Smrg#endif 4881abf7346Smrg#ifdef IGNORE_EXTENSION 4891abf7346Smrg /* skip files with specified extension - they're not real man pages */ 4901abf7346Smrg else if (streq(ptr + 1, IGNORE_EXTENSION)) { 4911abf7346Smrg continue; 4921abf7346Smrg } 4931abf7346Smrg#endif /* IGNORE_EXTENSION */ 4941abf7346Smrg } 4951abf7346Smrg local_manual->entries[nentries] = StrAlloc(full_name); 4961abf7346Smrg local_manual->entries_less_paths[nentries] = 4971abf7346Smrg rindex(local_manual->entries[nentries], '/'); 4981abf7346Smrg if ( local_manual->entries_less_paths[nentries] == NULL ) 4991abf7346Smrg PrintError("Internal error while cataloging manual pages."); 5001abf7346Smrg ++ nentries; 5011abf7346Smrg } 5021abf7346Smrg 5031abf7346Smrg local_manual->nentries = nentries; 5041abf7346Smrg local_manual->nalloc = nalloc; 5051abf7346Smrg 5061abf7346Smrg closedir(dir); 5071abf7346Smrg} 5081abf7346Smrg 5091abf7346Smrg/* Function Name: SortAndRemove 5101abf7346Smrg * Description: This function sorts all the entry names and 5111abf7346Smrg * then removes all the duplicate entries. 5121abf7346Smrg * Arguments: man - a pointer to the manual structure. 5131abf7346Smrg * number - the number of manual sections. 5141abf7346Smrg * Returns: an improved manual stucure 5151abf7346Smrg */ 5161abf7346Smrg 5171abf7346Smrgstatic void 5181abf7346SmrgSortAndRemove(Manual *man, int number) 5191abf7346Smrg{ 5201abf7346Smrg int i; 5211abf7346Smrg char *l1, *l2, **s1; 5221abf7346Smrg 5231abf7346Smrg for ( i = 0; i < number; man++, i++) { /* sort each section */ 5241abf7346Smrg register int i2 = 0; 5251abf7346Smrg 5261abf7346Smrg#ifdef DEBUG 5271abf7346Smrg printf("sorting section %d - %s\n", i, man->blabel); 5281abf7346Smrg#endif /* DEBUG */ 5291abf7346Smrg 5301abf7346Smrg s1 = (char **)malloc(man->nentries * sizeof(char *)); 5311abf7346Smrg 5321abf7346Smrg /* temporarily remove suffixes of entries, preventing them from */ 5331abf7346Smrg /* being used in alpabetic comparison ie sccs-delta.1 vs sccs.1 */ 5341abf7346Smrg for (i2=0; i2<man->nentries; i2++) 5351abf7346Smrg if ((s1[i2] = rindex(man->entries_less_paths[i2], '.')) != NULL) 5361abf7346Smrg *s1[i2] = '\0'; 5371abf7346Smrg 5381abf7346Smrg sortstrs ( (Byte **)man->entries_less_paths, man->nentries, (Byte **)man->entries ); 5391abf7346Smrg 5401abf7346Smrg /* put back suffixes */ 5411abf7346Smrg for (i2=0; i2<man->nentries; i2++) 5421abf7346Smrg if (s1[i2] != NULL) *s1[i2] = '.'; 5431abf7346Smrg 5441abf7346Smrg free(s1); 5451abf7346Smrg 5461abf7346Smrg#ifdef DEBUG 5471abf7346Smrg printf("removing from section %d.\n", i); 5481abf7346Smrg#endif /* DEBUG */ 5491abf7346Smrg 5501abf7346Smrg { 5511abf7346Smrg register int j, k, nent, nentm1; 5521abf7346Smrg int j2; 5531abf7346Smrg nent = man -> nentries; 5541abf7346Smrg nentm1 = nent - 1; 5551abf7346Smrg j = 0; 5561abf7346Smrg l2 = man->entries_less_paths[j++]; 5571abf7346Smrg if ( l2 == NULL ) 5581abf7346Smrg PrintError("Internal error while removing duplicate manual pages."); 5591abf7346Smrg while ( j < nentm1 ) 5601abf7346Smrg { 5611abf7346Smrg l1 = l2; 5621abf7346Smrg l2 = man->entries_less_paths[j++]; 5631abf7346Smrg if ( l2 == NULL ) 5641abf7346Smrg PrintError("Internal error while removing duplicate manual pages." 5651abf7346Smrg ); 5661abf7346Smrg if ( streq(l1,l2) ) 5671abf7346Smrg { 5681abf7346Smrg j2 = j-1; 5691abf7346Smrg k = j2; 5701abf7346Smrg while ( j < nent ) 5711abf7346Smrg { 5721abf7346Smrg man -> entries_less_paths[k] = man -> entries_less_paths[j]; 5731abf7346Smrg man -> entries[k++] = man -> entries[j++]; 5741abf7346Smrg } 5751abf7346Smrg j = j2; 5761abf7346Smrg -- man -> nentries; 5771abf7346Smrg -- nent; 5781abf7346Smrg -- nentm1; 5791abf7346Smrg } 5801abf7346Smrg } 5811abf7346Smrg } 5821abf7346Smrg } 5831abf7346Smrg} 5841abf7346Smrg 5851abf7346Smrg /* 5861abf7346Smrg ******* Replacement for qsort to keep 5871abf7346Smrg ******* identical entries in order 5881abf7346Smrg 5891abf7346Smrg A somewhat ugly hack of something that was once simpler... 5901abf7346Smrg */ 5911abf7346Smrg /* 5921abf7346Smrg Sort an array of pointers to strings, keeping it 5931abf7346Smrg in ascending order by (1) string comparison and 5941abf7346Smrg (2) original entry order in the pointer array. 5951abf7346Smrg 5961abf7346Smrg This is a modified radix exchange algorithm. 5971abf7346Smrg 5981abf7346Smrg In case there's insufficient memory for a temporary copy 5991abf7346Smrg of the pointer array, the original order of identical strings 6001abf7346Smrg isn't preserved. 6011abf7346Smrg */ 6021abf7346Smrg 6031abf7346Smrgstatic void 6041abf7346Smrgsortstrs (Byte *data[], int size, Byte *otherdata[]) 6051abf7346Smrg{ 6061abf7346Smrg Byte **sp, **ep; 6071abf7346Smrg Byte **othersp, **otherep; 6081abf7346Smrg int *origorder; 6091abf7346Smrg 6101abf7346Smrg origorder = (int *) calloc (size, sizeof(int)); 6111abf7346Smrg if ( origorder ) 6121abf7346Smrg { 6131abf7346Smrg reg int i; 6141abf7346Smrg 6151abf7346Smrg for ( i=0; i < size; ++i ) 6161abf7346Smrg origorder[i] = i; 6171abf7346Smrg } 6181abf7346Smrg 6191abf7346Smrg sp = data; 6201abf7346Smrg ep = &data[size-1]; 6211abf7346Smrg othersp = otherdata; 6221abf7346Smrg otherep = &otherdata[size-1]; 6231abf7346Smrg if ( origorder ) 6241abf7346Smrg { 6251abf7346Smrg sortstrs_block_oo ( sp, ep, 0, 0x80, origorder, &origorder[size-1], 6261abf7346Smrg othersp, otherep ); 6271abf7346Smrg free (origorder); 6281abf7346Smrg } 6291abf7346Smrg else 6301abf7346Smrg sortstrs_block ( sp, ep, 0, 0x80, othersp, otherep ); 6311abf7346Smrg} 6321abf7346Smrg 6331abf7346Smrg 6341abf7346Smrg 6351abf7346Smrg /*---------------------------------*/ 6361abf7346Smrg /* Sort 1 block of data on 1 bit */ 6371abf7346Smrg /*---------------------------------*/ 6381abf7346Smrg 6391abf7346Smrgstatic void 6401abf7346Smrgsortstrs_block ( 6411abf7346Smrg Byte **start, 6421abf7346Smrg Byte **end, 6431abf7346Smrg int offset, 6441abf7346Smrg Byte mask, 6451abf7346Smrg Byte **otherstart, 6461abf7346Smrg Byte **otherend) 6471abf7346Smrg 6481abf7346Smrg{ 6491abf7346Smrg reg Byte **sp, **ep; 6501abf7346Smrg reg Byte m; 6511abf7346Smrg reg int off; 6521abf7346Smrg reg Byte *t; 6531abf7346Smrg reg int curstrlen; 6541abf7346Smrg int maxstrlen; 6551abf7346Smrg Byte **othersp, **otherep; 6561abf7346Smrg 6571abf7346Smrg 6581abf7346Smrg#define newstring(ptr) \ 6591abf7346Smrg { \ 6601abf7346Smrg t = *ptr; \ 6611abf7346Smrg curstrlen = 0; \ 6621abf7346Smrg while ( *t++ ) ++ curstrlen; \ 6631abf7346Smrg if ( curstrlen > maxstrlen ) maxstrlen = curstrlen; \ 6641abf7346Smrg t = *ptr; \ 6651abf7346Smrg } 6661abf7346Smrg 6671abf7346Smrg 6681abf7346Smrg maxstrlen = 0; 6691abf7346Smrg sp = start; 6701abf7346Smrg ep = end; 6711abf7346Smrg off = offset; 6721abf7346Smrg m = mask; 6731abf7346Smrg othersp = otherstart; 6741abf7346Smrg otherep = otherend; 6751abf7346Smrg 6761abf7346Smrg while (1) 6771abf7346Smrg { 6781abf7346Smrg newstring(sp) 6791abf7346Smrg while (((sp != ep) && ((curstrlen < off) || ((t[off] & m) == 0)))) 6801abf7346Smrg { 6811abf7346Smrg ++ sp; 6821abf7346Smrg ++ othersp; 6831abf7346Smrg newstring(sp) 6841abf7346Smrg } 6851abf7346Smrg if ( sp == ep ) 6861abf7346Smrg break; 6871abf7346Smrg 6881abf7346Smrg newstring(ep); 6891abf7346Smrg while (((sp != ep) && (curstrlen >= off) && ((t[off] & m) != 0))) 6901abf7346Smrg { 6911abf7346Smrg -- ep; 6921abf7346Smrg -- otherep; 6931abf7346Smrg newstring(ep) 6941abf7346Smrg } 6951abf7346Smrg if ( sp == ep ) 6961abf7346Smrg break; 6971abf7346Smrg 6981abf7346Smrg t = *sp; 6991abf7346Smrg *sp = *ep; 7001abf7346Smrg *ep = t; 7011abf7346Smrg 7021abf7346Smrg t = *othersp; 7031abf7346Smrg *othersp = *otherep; 7041abf7346Smrg *otherep = t; 7051abf7346Smrg } 7061abf7346Smrg 7071abf7346Smrg t = *sp; 7081abf7346Smrg if ((curstrlen < off) || ((t[off] & m) == 0)) 7091abf7346Smrg { 7101abf7346Smrg if ( ep != end ) 7111abf7346Smrg { 7121abf7346Smrg ++ ep; 7131abf7346Smrg ++ otherep; 7141abf7346Smrg } 7151abf7346Smrg } 7161abf7346Smrg else 7171abf7346Smrg { 7181abf7346Smrg if ( sp != start ) 7191abf7346Smrg { 7201abf7346Smrg -- sp; 7211abf7346Smrg -- othersp; 7221abf7346Smrg } 7231abf7346Smrg } 7241abf7346Smrg 7251abf7346Smrg m >>= 1; 7261abf7346Smrg if ( m == 0 ) 7271abf7346Smrg { 7281abf7346Smrg m = 0x80; 7291abf7346Smrg if ( ++off >= maxstrlen ) 7301abf7346Smrg return; 7311abf7346Smrg } 7321abf7346Smrg 7331abf7346Smrg 7341abf7346Smrg if ( sp != start ) 7351abf7346Smrg sortstrs_block ( start, sp, off, m, otherstart, othersp ); 7361abf7346Smrg if ( ep != end ) 7371abf7346Smrg sortstrs_block ( ep, end, off, m, otherep, otherend ); 7381abf7346Smrg} 7391abf7346Smrg 7401abf7346Smrg 7411abf7346Smrg 7421abf7346Smrg /*-----------------------------------------------------------------*/ 7431abf7346Smrg /* Sort 1 block of data on 1 bit; check for out-of-order entries */ 7441abf7346Smrg /*-----------------------------------------------------------------*/ 7451abf7346Smrg 7461abf7346Smrgstatic void 7471abf7346Smrg sortstrs_block_oo ( 7481abf7346Smrg Byte **start, 7491abf7346Smrg Byte **end, 7501abf7346Smrg int offset, 7511abf7346Smrg Byte mask, 7521abf7346Smrg int *ostart, 7531abf7346Smrg int *oend, 7541abf7346Smrg Byte **otherstart, 7551abf7346Smrg Byte **otherend) 7561abf7346Smrg 7571abf7346Smrg{ 7581abf7346Smrg reg Byte **sp, **ep; 7591abf7346Smrg reg int *osp, *oep; 7601abf7346Smrg reg Byte m; 7611abf7346Smrg reg int off; 7621abf7346Smrg reg Byte *t; 7631abf7346Smrg reg int u; 7641abf7346Smrg reg int curstrlen; 7651abf7346Smrg int maxstrlen; 7661abf7346Smrg Byte **othersp, **otherep; 7671abf7346Smrg 7681abf7346Smrg 7691abf7346Smrg#define newstring(ptr) \ 7701abf7346Smrg { \ 7711abf7346Smrg t = *ptr; \ 7721abf7346Smrg curstrlen = 0; \ 7731abf7346Smrg while ( *t++ ) ++ curstrlen; \ 7741abf7346Smrg if ( curstrlen > maxstrlen ) maxstrlen = curstrlen; \ 7751abf7346Smrg t = *ptr; \ 7761abf7346Smrg } 7771abf7346Smrg 7781abf7346Smrg 7791abf7346Smrg maxstrlen = 0; 7801abf7346Smrg sp = start; 7811abf7346Smrg ep = end; 7821abf7346Smrg osp = ostart; 7831abf7346Smrg oep = oend; 7841abf7346Smrg off = offset; 7851abf7346Smrg m = mask; 7861abf7346Smrg othersp = otherstart; 7871abf7346Smrg otherep = otherend; 7881abf7346Smrg 7891abf7346Smrg while (1) 7901abf7346Smrg { 7911abf7346Smrg newstring(sp) 7921abf7346Smrg while (((sp != ep) && ((curstrlen < off) || ((t[off] & m) == 0)))) 7931abf7346Smrg { 7941abf7346Smrg ++ sp; 7951abf7346Smrg ++ osp; 7961abf7346Smrg ++ othersp; 7971abf7346Smrg newstring(sp) 7981abf7346Smrg } 7991abf7346Smrg if ( sp == ep ) 8001abf7346Smrg break; 8011abf7346Smrg 8021abf7346Smrg newstring(ep); 8031abf7346Smrg while (((sp != ep) && (curstrlen >= off) && ((t[off] & m) != 0))) 8041abf7346Smrg { 8051abf7346Smrg -- ep; 8061abf7346Smrg -- oep; 8071abf7346Smrg -- otherep; 8081abf7346Smrg newstring(ep) 8091abf7346Smrg } 8101abf7346Smrg if ( sp == ep ) 8111abf7346Smrg break; 8121abf7346Smrg 8131abf7346Smrg t = *sp; 8141abf7346Smrg *sp = *ep; 8151abf7346Smrg *ep = t; 8161abf7346Smrg 8171abf7346Smrg t = *othersp; 8181abf7346Smrg *othersp = *otherep; 8191abf7346Smrg *otherep = t; 8201abf7346Smrg 8211abf7346Smrg u = *osp; 8221abf7346Smrg *osp = *oep; 8231abf7346Smrg *oep = u; 8241abf7346Smrg } 8251abf7346Smrg 8261abf7346Smrg t = *sp; 8271abf7346Smrg if ((curstrlen < off) || ((t[off] & m) == 0)) 8281abf7346Smrg { 8291abf7346Smrg if ( ep != end ) 8301abf7346Smrg { 8311abf7346Smrg ++ ep; 8321abf7346Smrg ++ oep; 8331abf7346Smrg ++ otherep; 8341abf7346Smrg } 8351abf7346Smrg } 8361abf7346Smrg else 8371abf7346Smrg { 8381abf7346Smrg if ( sp != start ) 8391abf7346Smrg { 8401abf7346Smrg -- sp; 8411abf7346Smrg -- osp; 8421abf7346Smrg -- othersp; 8431abf7346Smrg } 8441abf7346Smrg } 8451abf7346Smrg 8461abf7346Smrg m >>= 1; 8471abf7346Smrg if ( m == 0 ) 8481abf7346Smrg { 8491abf7346Smrg m = 0x80; 8501abf7346Smrg if ( ++off >= maxstrlen ) /* Finished sorting block of strings: */ 8511abf7346Smrg { /* Restore duplicates to 8521abf7346Smrgriginal order */ 8531abf7346Smrg reg Byte **cp; 8541abf7346Smrg reg int *ocp; 8551abf7346Smrg Byte **othercp; 8561abf7346Smrg 8571abf7346Smrg 8581abf7346Smrg if ( sp != start ) 8591abf7346Smrg { 8601abf7346Smrg cp = start; 8611abf7346Smrg ocp = ostart; 8621abf7346Smrg othercp = otherstart; 8631abf7346Smrg while ( cp != sp ) 8641abf7346Smrg { 8651abf7346Smrg if ( *ocp > *(ocp+1) ) 8661abf7346Smrg { 8671abf7346Smrg t = *(cp+1); 8681abf7346Smrg *(cp+1) = *cp; 8691abf7346Smrg *cp = t; 8701abf7346Smrg 8711abf7346Smrg t = *(othercp+1); 8721abf7346Smrg *(othercp+1) = *othercp; 8731abf7346Smrg *othercp = t; 8741abf7346Smrg 8751abf7346Smrg u = *(ocp+1); 8761abf7346Smrg *(ocp+1) = *ocp; 8771abf7346Smrg *ocp = u; 8781abf7346Smrg 8791abf7346Smrg if ( cp != start ) 8801abf7346Smrg { 8811abf7346Smrg -- cp; 8821abf7346Smrg -- ocp; 8831abf7346Smrg -- othercp; 8841abf7346Smrg continue; 8851abf7346Smrg } 8861abf7346Smrg } 8871abf7346Smrg ++ cp; 8881abf7346Smrg ++ ocp; 8891abf7346Smrg ++ othercp; 8901abf7346Smrg } 8911abf7346Smrg } 8921abf7346Smrg if ( ep != end ) 8931abf7346Smrg { 8941abf7346Smrg cp = ep; 8951abf7346Smrg ocp = oep; 8961abf7346Smrg othercp = otherep; 8971abf7346Smrg while ( cp != end ) 8981abf7346Smrg { 8991abf7346Smrg if ( *ocp > *(ocp+1) ) 9001abf7346Smrg { 9011abf7346Smrg t = *(cp+1); 9021abf7346Smrg *(cp+1) = *cp; 9031abf7346Smrg *cp = t; 9041abf7346Smrg 9051abf7346Smrg t = *(othercp+1); 9061abf7346Smrg *(othercp+1) = *othercp; 9071abf7346Smrg *othercp = t; 9081abf7346Smrg 9091abf7346Smrg u = *(ocp+1); 9101abf7346Smrg *(ocp+1) = *ocp; 9111abf7346Smrg *ocp = u; 9121abf7346Smrg 9131abf7346Smrg if ( cp != ep ) 9141abf7346Smrg { 9151abf7346Smrg -- cp; 9161abf7346Smrg -- ocp; 9171abf7346Smrg -- othercp; 9181abf7346Smrg continue; 9191abf7346Smrg } 9201abf7346Smrg } 9211abf7346Smrg ++ cp; 9221abf7346Smrg ++ ocp; 9231abf7346Smrg ++ othercp; 9241abf7346Smrg } 9251abf7346Smrg } 9261abf7346Smrg return; 9271abf7346Smrg } 9281abf7346Smrg } 9291abf7346Smrg 9301abf7346Smrg 9311abf7346Smrg if ( sp != start ) 9321abf7346Smrg sortstrs_block_oo ( start, sp, off, m, ostart, osp, otherstart, othersp ); 9331abf7346Smrg if ( ep != end ) 9341abf7346Smrg sortstrs_block_oo ( ep, end, off, m, oep, oend, otherep, otherend ); 9351abf7346Smrg} 9361abf7346Smrg 9371abf7346Smrg 9381abf7346Smrg/* Function Name: InitManual 9391abf7346Smrg * Description: Initializes this manual section. 9401abf7346Smrg * Arguments: l_manual - local copy of the manual structure. 9411abf7346Smrg * label - the button label for this section. 9421abf7346Smrg * Returns: none. 9431abf7346Smrg */ 9441abf7346Smrg 9451abf7346Smrgstatic void 9461abf7346SmrgInitManual(Manual * l_manual, char * label) 9471abf7346Smrg{ 9481abf7346Smrg bzero( l_manual, sizeof(Manual) ); /* clear it. */ 9491abf7346Smrg l_manual->blabel = label; /* set label. */ 9501abf7346Smrg} 9511abf7346Smrg 9521abf7346Smrg#if defined(DEBUG) 9531abf7346Smrg 9541abf7346Smrg/* Function Name: DumpManual 9551abf7346Smrg * Description: Debugging function that dumps the entire manual page 9561abf7346Smrg * structure. 9571abf7346Smrg * Arguments: number - the number of sections. 9581abf7346Smrg * Returns: none. 9591abf7346Smrg */ 9601abf7346Smrg 9611abf7346Smrgvoid 9621abf7346SmrgDumpManual(int number) 9631abf7346Smrg{ 9641abf7346Smrg register int i,j; 9651abf7346Smrg 9661abf7346Smrg for ( i = 0; i < number; i++) { 9671abf7346Smrg printf("label: %s\n", manual[i].blabel); 9681abf7346Smrg for (j = 0; j < manual[i].nentries; j++) 9691abf7346Smrg printf("%s\n", manual[i].entries[j]); 9701abf7346Smrg } 9711abf7346Smrg} 9721abf7346Smrg 9731abf7346Smrg#endif /* DEBUG */ 9741abf7346Smrg 9751abf7346Smrg 9761abf7346Smrg 9771abf7346Smrg#ifdef MANCONF 9781abf7346Smrg 9791abf7346Smrg#if defined(MANCONFIGSTYLE_FreeBSD) 9801abf7346Smrg 9811abf7346Smrg/* Function Name: ReadManConfig 9821abf7346Smrg * Description: Reads man.conf file used by FreeBSD man 9831abf7346Smrg * Argument: manpath - char array to return path in. 9841abf7346Smrg * Returns: TRUE if read was successful. 9851abf7346Smrg */ 9861abf7346Smrg 9871abf7346SmrgBool 9881abf7346SmrgReadManConfig(char manpath[]) 9891abf7346Smrg{ 9901abf7346Smrg FILE *fp; 9911abf7346Smrg char line[BUFSIZ]; 9921abf7346Smrg char *path; 9931abf7346Smrg Bool firstpath = TRUE; 9941abf7346Smrg 9951abf7346Smrg if (!(fp = fopen(MANCONF, "r"))) 9961abf7346Smrg return(FALSE); 9971abf7346Smrg 9981abf7346Smrg while (fgets(line, sizeof(line), fp)) { 9991abf7346Smrg path = strtok(line, " \t\n"); 10001abf7346Smrg if (!path || *path == '#') 10011abf7346Smrg continue; 10021abf7346Smrg if (strcmp(path, "MANPATH_MAP") == 0) 10031abf7346Smrg path = strtok((char *)NULL, " \t\n"); 10041abf7346Smrg else if (strcmp(path, "MANDATORY_MANPATH") != 0 && 10051abf7346Smrg strcmp(path, "OPTIONAL_MANPATH") != 0) 10061abf7346Smrg return(FALSE); 10071abf7346Smrg path = strtok((char *)NULL, " \t\n"); 10081abf7346Smrg if (!path || *path == '#') 10091abf7346Smrg return FALSE; 10101abf7346Smrg if (firstpath) { 10111abf7346Smrg strcpy(manpath, path); 10121abf7346Smrg firstpath = FALSE; 10131abf7346Smrg } 10141abf7346Smrg else if (!strstr(manpath,path)) { 10151abf7346Smrg strcat(manpath, ":"); 10161abf7346Smrg strcat(manpath, path); 10171abf7346Smrg } 10181abf7346Smrg } 10191abf7346Smrg fclose(fp); 10201abf7346Smrg return(!firstpath); 10211abf7346Smrg} 10221abf7346Smrg 10231abf7346Smrg 10241abf7346Smrg#elif defined(MANCONFIGSTYLE_Linux) /* not FreeBSD */ 10251abf7346Smrg 10261abf7346Smrg/* Function Name: ReadManConfig 10271abf7346Smrg * Description: Reads man.conf file used by Linux man 10281abf7346Smrg * Argument: manpath - char array to return path in. 10291abf7346Smrg * Returns: TRUE if read was successful. 10301abf7346Smrg */ 10311abf7346Smrg 10321abf7346Smrg 10331abf7346SmrgBool 10341abf7346SmrgReadManConfig(char manpath[]) 10351abf7346Smrg{ 10361abf7346Smrg FILE *fp; 10371abf7346Smrg char line[BUFSIZ]; 10381abf7346Smrg char *path; 10391abf7346Smrg Bool firstpath = TRUE; 10401abf7346Smrg 10411abf7346Smrg if (!(fp = fopen(MANCONF, "r"))) 10421abf7346Smrg return(FALSE); 10431abf7346Smrg 10441abf7346Smrg while (fgets(line, sizeof(line), fp)) { 10451abf7346Smrg path = strtok(line, " \t\n"); 10461abf7346Smrg if (!path || *path == '#' || (strcmp(path, "MANPATH") != 0)) 10471abf7346Smrg continue; 10481abf7346Smrg path = strtok((char *)NULL, " \t\n"); 10491abf7346Smrg if (!path || *path == '#') 10501abf7346Smrg return FALSE; 10511abf7346Smrg if (firstpath) { 10521abf7346Smrg strcpy(manpath, path); 10531abf7346Smrg firstpath = FALSE; 10541abf7346Smrg } 10551abf7346Smrg else { 10561abf7346Smrg strcat(manpath, ":"); 10571abf7346Smrg strcat(manpath, path); 10581abf7346Smrg } 10591abf7346Smrg } 10601abf7346Smrg fclose(fp); 10611abf7346Smrg return(!firstpath); 10621abf7346Smrg} 10631abf7346Smrg 10641abf7346Smrg#elif defined(MANCONFIGSTYLE_OpenBSD) /* not FreeBSD or Linux */ 10651abf7346Smrg 10661abf7346Smrg/* Function Name: ReadManConfig 10671abf7346Smrg * Description: Reads man.conf file used by Open/NetBSD 10681abf7346Smrg * Argument: manpath - char array to return path in. 10691abf7346Smrg * Returns: TRUE if read was successful. 10701abf7346Smrg * 10711abf7346Smrg * This version expands the glob pattern that can be found 10721abf7346Smrg * in man.conf 10731abf7346Smrg */ 10741abf7346Smrg#include <glob.h> 10751abf7346Smrg 10761abf7346SmrgBool 10771abf7346SmrgReadManConfig(char manpath[]) 10781abf7346Smrg{ 10791abf7346Smrg FILE *fp; 10801abf7346Smrg char line[BUFSIZ]; 10811abf7346Smrg char *path; 10821abf7346Smrg Bool firstpath = TRUE; 10831abf7346Smrg glob_t gs; 10841abf7346Smrg int i; 10851abf7346Smrg 10861abf7346Smrg if (!(fp = fopen(MANCONF, "r"))) 10871abf7346Smrg return(FALSE); 10881abf7346Smrg 10891abf7346Smrg while (fgets(line, sizeof(line), fp)) { 10901abf7346Smrg path = strtok(line, " \t\n"); 10911abf7346Smrg if (!path || *path == '#') 10921abf7346Smrg continue; 10931abf7346Smrg if (strcmp(path, "_default")) { 10941abf7346Smrg /* for now */ 10951abf7346Smrg continue; 10961abf7346Smrg } 10971abf7346Smrg memset(&gs, 0, sizeof(glob_t)); 10981abf7346Smrg while ((path = strtok((char *)NULL, " \t\n"))) { 10991abf7346Smrg if (glob(path, GLOB_BRACE, NULL, &gs) < 0) { 11001abf7346Smrg fclose(fp); 11011abf7346Smrg return FALSE; 11021abf7346Smrg } 11031abf7346Smrg } /* while */ 11041abf7346Smrg for (i = 0; i < gs.gl_pathc; i++) { 11051abf7346Smrg 11061abf7346Smrg if (firstpath) { 11071abf7346Smrg strcpy(manpath, gs.gl_pathv[i]); 11081abf7346Smrg firstpath = FALSE; 11091abf7346Smrg } 11101abf7346Smrg else { 11111abf7346Smrg strcat(manpath, ":"); 11121abf7346Smrg strcat(manpath, gs.gl_pathv[i]); 11131abf7346Smrg } 11141abf7346Smrg } /* for */ 11151abf7346Smrg globfree(&gs); 11161abf7346Smrg } 11171abf7346Smrg fclose(fp); 11181abf7346Smrg return(!firstpath); 11191abf7346Smrg} 11201abf7346Smrg 11211abf7346Smrg#elif defined(MANCONFIGSTYLE_BSD) /* not FreeBSD, Linux, or OpenBSD */ 11221abf7346Smrg 11231abf7346Smrg/* Function Name: ReadManConfig 11241abf7346Smrg * Description: Reads man.conf file used by BSD 4.4 11251abf7346Smrg * Argument: manpath - char array to return path in. 11261abf7346Smrg * Returns: TRUE if read was successful. 11271abf7346Smrg */ 11281abf7346Smrg 11291abf7346SmrgBool 11301abf7346SmrgReadManConfig(manpath) 11311abf7346Smrg 11321abf7346Smrgchar manpath[]; 11331abf7346Smrg 11341abf7346Smrg{ 11351abf7346Smrg FILE *fp; 11361abf7346Smrg char line[BUFSIZ]; 11371abf7346Smrg char *path; 11381abf7346Smrg Bool firstpath = TRUE; 11391abf7346Smrg 11401abf7346Smrg if (!(fp = fopen(MANCONF, "r"))) 11411abf7346Smrg return(FALSE); 11421abf7346Smrg 11431abf7346Smrg while (fgets(line, sizeof(line), fp)) { 11441abf7346Smrg path = strtok(line, " \t\n"); 11451abf7346Smrg if (!path || *path == '#' || strcmp(path, "_default")) 11461abf7346Smrg continue; 11471abf7346Smrg while ((path = strtok((char *)NULL, " \t\n"))) { 11481abf7346Smrg if (firstpath) { 11491abf7346Smrg strcpy(manpath, path); 11501abf7346Smrg firstpath = FALSE; 11511abf7346Smrg } 11521abf7346Smrg else { 11531abf7346Smrg strcat(manpath, ":"); 11541abf7346Smrg strcat(manpath, path); 11551abf7346Smrg } 11561abf7346Smrg } 11571abf7346Smrg } 11581abf7346Smrg fclose(fp); 11591abf7346Smrg return(!firstpath); 11601abf7346Smrg} 11611abf7346Smrg 11621abf7346Smrg#else /* not BSD */ 11631abf7346Smrg 11641abf7346Smrg#error "MANCONF defined (in vendor.h) for unknown operating system." 11651abf7346Smrg 11661abf7346Smrg#endif /* MANCONFIGSTYLE == FreeBSD ... BSD */ 11671abf7346Smrg 11681abf7346Smrg#endif /* MANCONF */ 1169