├── doc ├── examples │ ├── mysuperlib=1.0 │ └── mylib=1.0 ├── man │ └── librarian.1 └── info │ ├── librarian.texinfo │ └── fdl.texinfo ├── .gitignore ├── src ├── librarian.auto-completion ├── util.h └── librarian.c ├── LICENSE ├── README └── Makefile /doc/examples/mysuperlib=1.0: -------------------------------------------------------------------------------- 1 | deps mylib>=0.1 2 | -------------------------------------------------------------------------------- /doc/examples/mylib=1.0: -------------------------------------------------------------------------------- 1 | CFLAGS 2 | CPPFLAGS -I/usr/share/include/my 3 | LDFLAGS -lmy 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | _/ 2 | /bin/ 3 | /obj/ 4 | \#*\# 5 | .* 6 | !.git* 7 | *~ 8 | *.bak 9 | *.new 10 | *.swo 11 | *.swp 12 | *.out 13 | *.o 14 | *.su 15 | *.gch 16 | 17 | -------------------------------------------------------------------------------- /src/librarian.auto-completion: -------------------------------------------------------------------------------- 1 | (librarian 2 | (unargumented (options -d) (complete -d) 3 | (desc 'Add output for dependencies too') 4 | ) 5 | 6 | (unargumented (options -l) (complete -l) 7 | (desc 'Print the location of files') 8 | ) 9 | 10 | (unargumented (options -o) (complete -o) 11 | (desc 'Prefer older versions of libraries') 12 | ) 13 | ) 14 | 15 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT/X Consortium License 2 | 3 | Copyright © 2015 Mattias Andrée 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a 6 | copy of this software and associated documentation files (the "Software"), 7 | to deal in the Software without restriction, including without limitation 8 | the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | and/or sell copies of the Software, and to permit persons to whom the 10 | Software is furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | DEALINGS IN THE SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /src/util.h: -------------------------------------------------------------------------------- 1 | /** 2 | * MIT/X Consortium License 3 | * 4 | * Copyright © 2015 Mattias Andrée 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a 7 | * copy of this software and associated documentation files (the "Software"), 8 | * to deal in the Software without restriction, including without limitation 9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 | * and/or sell copies of the Software, and to permit persons to whom the 11 | * Software is furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22 | * DEALINGS IN THE SOFTWARE. 23 | */ 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | 30 | #define t(...) do { if (__VA_ARGS__) goto fail; } while (0) 31 | 32 | 33 | #define REALLOC(PTR, SIZE) \ 34 | do { \ 35 | void *new__; \ 36 | new__ = realloc(PTR, (SIZE) * sizeof(*(PTR))); \ 37 | t (new__ == NULL); \ 38 | (PTR) = new__; \ 39 | } while (0) 40 | 41 | 42 | #define GROW(PTR, SIZE, DEFAULT) \ 43 | do { \ 44 | (SIZE) = (SIZE) ? ((SIZE) << 1) : (DEFAULT); \ 45 | REALLOC(PTR, SIZE); \ 46 | } while (0) 47 | 48 | 49 | #define MAYBE_GROW(PTR, USED, SIZE, DEFAULT) \ 50 | do { \ 51 | if ((USED) == (SIZE)) \ 52 | GROW(PTR, SIZE, DEFAULT); \ 53 | } while (0) 54 | 55 | 56 | #define GET_VERSION(VER, PATH) \ 57 | do { \ 58 | (VER) = strrchr((PATH), '='); \ 59 | assert((VER) && !strchr((VER), '/')); \ 60 | } while (0) 61 | 62 | 63 | #define NEVER_REACHED \ 64 | do { \ 65 | assert(0); \ 66 | abort(); \ 67 | } while (0) 68 | 69 | 70 | #define RETURN(R) \ 71 | for (int errno__ = errno, x__ = 0;; errno = errno__, x__++) \ 72 | if (x__) return (R); else 73 | 74 | 75 | #define TEMP_NUL(P, ACTION) \ 76 | do { \ 77 | char P##__c = *(P); \ 78 | *(P) = '\0'; \ 79 | ACTION; \ 80 | *(P) = P##__c; \ 81 | } while (0) 82 | 83 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | This repo has been moved to Codeberg and may be out of date on GitHub. 2 | Canonical repo: https://codeberg.org/maandree/librarian 3 | 4 | 5 | NAME 6 | librarian - Return flags for compiling against libraries 7 | 8 | SYNOPSIS 9 | librarian [OPTION]... [--] [VARIABLE]... [LIBRARY]... 10 | 11 | DESCRIPTION 12 | librarian is used to print flags required when compiling 13 | or linking, and want to use library that requires 14 | non-trival flags. 15 | 16 | librarian shall output the flags, required by the 17 | selected libraries, LIBRARY, that are listed under the 18 | selected variables, VARIABLE. 19 | 20 | LIBRARY can either be the name of the required library, 21 | the name of the required library and a version of said 22 | library, or the name of the required library and an 23 | accepted version range of said library. If the same 24 | library name is used more than once, the versions and 25 | version ranges are unioned. Recognised formats are: 26 | 27 | NAME Any version of the library NAME will do. 28 | 29 | NAME=VERSION Only version VERSION of the library NAME 30 | is acceptable. (Multiple version can be 31 | used by specifying more than once.) 32 | 33 | NAME<=MAX Any versions up to and including MAX 34 | of the library NAME will do. 35 | 36 | NAME=MIN At least version MIN of the library 40 | NAME is required. 41 | 42 | NAME>MIN A greater version than version MIN of 43 | the library NAME is required. 44 | 45 | NAME>=MIN<=MAX Combines NAME>=MIN and NAME<=MAX. 46 | 47 | NAME>=MIN=MIN and NAMEMIN<=MAX Combines NAME>MIN and NAME<=MAX. 50 | 51 | NAME>MINMIN and NAME= MIN 55 | At least version 56 | .I MIN 57 | of the library 58 | .I NAME 59 | is required. 60 | .TP 61 | .IB NAME > MIN 62 | A greater version than version 63 | .I MIN 64 | of the library 65 | .I NAME 66 | is required. 67 | .TP 68 | .IB NAME >= MIN <= MAX 69 | Combines 70 | .IB NAME >= MIN 71 | and 72 | .IR NAME \fB<=\fP MAX . 73 | .TP 74 | .IB NAME >= MIN < MAX 75 | Combines 76 | .IB NAME >= MIN 77 | and 78 | .IR NAME \fB<\fP MAX . 79 | .TP 80 | .IB NAME > MIN <= MAX 81 | Combines 82 | .IB NAME > MIN 83 | and 84 | .IR NAME \fB<=\fP MAX . 85 | .TP 86 | .IB NAME > MIN < MAX 87 | Combines 88 | .IB NAME > MIN 89 | and 90 | .IR NAME \fB<\fP MAX . 91 | .PP 92 | The are not predefined values for 93 | .IR VARIABLE , 94 | but the standardised ones are: 95 | .TP 96 | .B CFLAGS 97 | Flags required by the compiler to compile the if the library 98 | .I LIBRARY 99 | is used. The library is a C library. 100 | .TP 101 | .B CPPFLAGS 102 | Flags required by the C preprocessor to compile the if the 103 | library 104 | .I LIBRARY 105 | is used. 106 | .TP 107 | .B LDFLAGS 108 | Flags required by the linker to link the program when the 109 | library 110 | .I LIBRARY 111 | is used. 112 | .TP 113 | .B CXXFLAGS 114 | Flags required by the compiler to compile 115 | the if the library 116 | .I LIBRARY 117 | is used. The library is a C++ library. 118 | .TP 119 | .B deps 120 | Libraries the library 121 | .I LIBRARY 122 | is dependent on. Flags from these libraries should not 123 | appear in the other variables unless the library 124 | .I LIBRARY 125 | requires them directly. 126 | .PP 127 | All variables should be in upper case unless they are 128 | reserved. In the latter case, the are lower cased. 129 | .PP 130 | If 131 | .I VARIABLE 132 | is omitted, the process will exit with the value 133 | .B 0 134 | if all listed 135 | libraries, 136 | .IR LIBRARY , 137 | are available, and otherwise exit with the value 138 | .BR 2 . 139 | .PP 140 | .B 141 | librarian 142 | files should be stored in 143 | .BR PREFIX/share/librarian/ . 144 | Its filename should be the name of the library, followed 145 | by an 146 | .B = 147 | (equals-sign) and the version number. 148 | .PP 149 | Empty lines and lines starting with a 150 | .B # 151 | (she) in a 152 | .B librarian 153 | files are ignored. Other lines should begin with a variable 154 | name and be followed by the required flags relevant to that 155 | variable. For the variable 156 | .BR deps , 157 | libraries that the library requires should be listed in the 158 | same format the 159 | .I LIBRARY 160 | argument uses. 161 | .SH OPTIONS 162 | .TP 163 | .B \-d 164 | Add output for dependencies too. Should be used for 165 | .B LDFLAGS 166 | when linking statically. 167 | .TP 168 | .B \-l 169 | Print the location of the files specified by 170 | .IR LIBRARY . 171 | .TP 172 | .B \-o 173 | Prefer-older libraries, when multiple versions are available. 174 | .SH ENVIRONMENT 175 | .B LIBRARIAN_PATH 176 | Colon separated list of directories to search for librarian files. 177 | .SH "EXIT STATUS" 178 | .TP 179 | .B 0 180 | Program was successful. 181 | .TP 182 | .B 1 183 | An error occurred. 184 | .TP 185 | .B 2 186 | A library was not found. 187 | .TP 188 | .B 3 189 | Usage error. 190 | .SH RATIONALE 191 | .BR pkg-config (1) 192 | sucks. 193 | .SH "FUTURE DIRECTION" 194 | Will be implemented if needed in the real world: 195 | .TP 196 | * 197 | When is used 198 | .BR \-d , 199 | .B librarian 200 | will try all versions of the libraries until it founds 201 | a combination all selected libraries and their dependencies 202 | are compatible with, rather than simply failing. 203 | .TP 204 | * 205 | Library conflicts. 206 | .SH "SEE ALSO" 207 | .BR pkg-config (1) 208 | .SH AUTHORS 209 | Principal author, Mattias Andrée. See the LICENSE file for the full 210 | list of authors. 211 | .SH LICENSE 212 | MIT/X Consortium License. 213 | .SH BUGS 214 | Please report bugs to https://github.com/maandree/librarian/issues or to 215 | maandree@member.fsf.org 216 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Copying and distribution of this file, with or without modification, 2 | # are permitted in any medium without royalty provided the copyright 3 | # notice and this notice are preserved. This file is offered as-is, 4 | # without any warranty. 5 | 6 | PREFIX = /usr 7 | BIN = /bin 8 | DATA = /share 9 | BINDIR = $(PREFIX)$(BIN) 10 | DATADIR = $(PREFIX)$(DATA) 11 | DOCDIR = $(DATADIR)/doc 12 | INFODIR = $(DATADIR)/info 13 | MANDIR = $(DATADIR)/man 14 | MAN1DIR = $(MANDIR)/man1 15 | LICENSEDIR = $(DATADIR)/licenses 16 | 17 | PKGNAME = librarian 18 | COMMAND = librarian 19 | 20 | # Default value for the environment variable LIBRARIAN_PATH. 21 | LIBRARIAN_PATH = /usr/local/share/librarian:/usr/share/librarian 22 | 23 | 24 | OPTIMISE = -O2 25 | WARN = -Wall -Wextra -pedantic 26 | FLAGS = -std=c99 $(WARN) $(OPTIMISE) -D'DEFAULT_PATH="$(LIBRARIAN_PATH)"' 27 | 28 | 29 | 30 | .PHONY: default 31 | default: base info shell 32 | 33 | .PHONY: all 34 | all: base doc shell 35 | 36 | .PHONY: bas 37 | base: cmd 38 | 39 | .PHONY: command 40 | cmd: bin/librarian 41 | 42 | bin/librarian: obj/librarian.o 43 | @mkdir -p bin 44 | ${CC} ${FLAGS} -o $@ $^ ${LDFLAGS} 45 | 46 | obj/%.o: src/%.c src/*.h 47 | mkdir -p obj 48 | ${CC} ${FLAGS} -c -o $@ ${CPPFLAGS} ${CFLAGS} $< 49 | 50 | .PHONY: doc 51 | doc: info pdf dvi ps 52 | 53 | .PHONY: info 54 | info: bin/librarian.info 55 | bin/%.info: doc/info/%.texinfo 56 | @mkdir -p bin 57 | $(MAKEINFO) $< 58 | mv $*.info $@ 59 | 60 | .PHONY: pdf 61 | pdf: bin/librarian.pdf 62 | bin/%.pdf: doc/info/%.texinfo 63 | @! test -d obj/pdf || rm -rf obj/pdf 64 | @mkdir -p bin obj/pdf 65 | cd obj/pdf && texi2pdf ../../"$<" < /dev/null 66 | mv obj/pdf/$*.pdf $@ 67 | 68 | .PHONY: dvi 69 | dvi: bin/librarian.dvi 70 | bin/%.dvi: doc/info/%.texinfo 71 | @! test -d obj/dvi || rm -rf obj/dvi 72 | @mkdir -p bin obj/dvi 73 | cd obj/dvi && $(TEXI2DVI) ../../"$<" < /dev/null 74 | mv obj/dvi/$*.dvi $@ 75 | 76 | .PHONY: ps 77 | ps: bin/librarian.ps 78 | bin/%.ps: doc/info/%.texinfo 79 | @! test -d obj/ps || rm -rf obj/ps 80 | @mkdir -p bin obj/ps 81 | cd obj/ps && texi2pdf --ps ../../"$<" < /dev/null 82 | mv obj/ps/$*.ps $@ 83 | 84 | .PHONY: shell 85 | shell: bash fish zsh 86 | 87 | .PHONY: bash 88 | bash: bin/librarian.bash-completion 89 | 90 | .PHONY: fish 91 | fish: bin/librarian.fish-completion 92 | 93 | .PHONY: zsh 94 | zsh: bin/librarian.zsh-completion 95 | 96 | obj/librarian.auto-completion: src/librarian.auto-completion 97 | @mkdir -p obj 98 | cp $< $@ 99 | sed -i 's/^(librarian$$/($(COMMAND)/' $@ 100 | 101 | bin/librarian.%sh-completion: obj/librarian.auto-completion 102 | @mkdir -p bin 103 | auto-auto-complete $*sh --output $@ --source $< 104 | 105 | 106 | 107 | .PHONY: install 108 | install: install-base install-info install-man install-shell 109 | 110 | .PHONY: install-all 111 | install-all: install-base install-doc install-shell 112 | 113 | .PHONY: install-base 114 | install-base: install-cmd install-copyright 115 | 116 | .PHONY: install-cmd 117 | install-cmd: bin/librarian 118 | install -dm755 -- "$(DESTDIR)$(BINDIR)" 119 | install -m755 $< -- "$(DESTDIR)$(BINDIR)/$(COMMAND)" 120 | 121 | .PHONY: install-copyright 122 | install-copyright: install-license 123 | 124 | .PHONY: install-license 125 | install-license: 126 | install -dm755 -- "$(DESTDIR)$(LICENSEDIR)/$(PKGNAME)" 127 | install -m644 LICENSE -- "$(DESTDIR)$(LICENSEDIR)/$(PKGNAME)" 128 | 129 | .PHONY: install-doc 130 | install-doc: install-info install-pdf install-dvi install-ps install-man 131 | 132 | .PHONY: install-info 133 | install-info: bin/librarian.info 134 | install -dm755 -- "$(DESTDIR)$(INFODIR)" 135 | install -m644 $< -- "$(DESTDIR)$(INFODIR)/$(PKGNAME).info" 136 | 137 | .PHONY: install-pdf 138 | install-pdf: bin/librarian.pdf 139 | install -dm755 -- "$(DESTDIR)$(DOCDIR)" 140 | install -m644 $< -- "$(DESTDIR)$(DOCDIR)/$(PKGNAME).pdf" 141 | 142 | .PHONY: install-dvi 143 | install-dvi: bin/librarian.dvi 144 | install -dm755 -- "$(DESTDIR)$(DOCDIR)" 145 | install -m644 $< -- "$(DESTDIR)$(DOCDIR)/$(PKGNAME).dvi" 146 | 147 | .PHONY: install-ps 148 | install-ps: bin/librarian.ps 149 | install -dm755 -- "$(DESTDIR)$(DOCDIR)" 150 | install -m644 $< -- "$(DESTDIR)$(DOCDIR)/$(PKGNAME).ps" 151 | 152 | .PHONY: install-man 153 | install-man: doc/man/librarian.1 154 | install -dm755 -- "$(DESTDIR)$(MAN1DIR)" 155 | install -m644 $< -- "$(DESTDIR)$(MAN1DIR)/$(COMMAND).1" 156 | 157 | .PHONY: install-shell 158 | install-shell: install-bash install-fish install-zsh 159 | 160 | .PHONY: install-bash 161 | install-bash: bin/librarian.bash-completion 162 | install -dm755 -- "$(DESTDIR)$(DATADIR)/bash-completion/completions" 163 | install -m644 $< -- "$(DESTDIR)$(DATADIR)/bash-completion/completions/$(COMMAND)" 164 | 165 | .PHONY: install-fish 166 | install-fish: bin/librarian.fish-completion 167 | install -dm755 -- "$(DESTDIR)$(DATADIR)/fish/completions" 168 | install -m644 $< -- "$(DESTDIR)$(DATADIR)/fish/completions/$(COMMAND).fish" 169 | 170 | .PHONY: install-zsh 171 | install-zsh: bin/librarian.zsh-completion 172 | install -dm755 -- "$(DESTDIR)$(DATADIR)/zsh/site-functions" 173 | install -m644 $< -- "$(DESTDIR)$(DATADIR)/zsh/site-functions/_$(COMMAND)" 174 | 175 | 176 | 177 | .PHONY: uninstall 178 | uninstall: 179 | -rm -- "$(DESTDIR)$(BINDIR)/$(COMMAND)" 180 | -rm -- "$(DESTDIR)$(LICENSEDIR)/$(PKGNAME)/LICENSE" 181 | -rmdir -- "$(DESTDIR)$(LICENSEDIR)/$(PKGNAME)" 182 | -rm -- "$(DESTDIR)$(INFODIR)/$(PKGNAME).info" 183 | -rm -- "$(DESTDIR)$(DOCDIR)/$(PKGNAME).pdf" 184 | -rm -- "$(DESTDIR)$(DOCDIR)/$(PKGNAME).dvi" 185 | -rm -- "$(DESTDIR)$(DOCDIR)/$(PKGNAME).ps" 186 | -rm -- "$(DESTDIR)$(MAN1DIR)/$(COMMAND).1" 187 | -rm -- "$(DESTDIR)$(DATADIR)/bash-completion/completions/$(COMMAND)" 188 | -rm -- "$(DESTDIR)$(DATADIR)/fish/completions/$(COMMAND).fish" 189 | -rm -- "$(DESTDIR)$(DATADIR)/zsh/site-functions/_$(COMMAND)" 190 | 191 | 192 | 193 | .PHONY: clean 194 | clean: 195 | -rm -r bin obj 196 | 197 | -------------------------------------------------------------------------------- /doc/info/librarian.texinfo: -------------------------------------------------------------------------------- 1 | \input texinfo @c -*-texinfo-*- 2 | 3 | @c %**start of header 4 | @setfilename librarian.info 5 | @settitle librarian 6 | @afourpaper 7 | @documentencoding UTF-8 8 | @documentlanguage en 9 | @finalout 10 | @c %**end of header 11 | 12 | 13 | @dircategory Development 14 | @direntry 15 | * librarian: (librarian). Library to compiler flags resolver 16 | @end direntry 17 | 18 | 19 | @copying 20 | Copyright @copyright{} 2015 Mattias Andrée 21 | 22 | @quotation 23 | Permission is granted to copy, distribute and/or modify this document 24 | under the terms of the GNU Free Documentation License, Version 1.3 or 25 | any later version published by the Free Software Foundation; with no 26 | Invariant Sections, with no Front-Cover Texts, and with no Back-Cover 27 | Texts. A copy of the license is included in the section entitled 28 | ``GNU Free Documentation License''. 29 | @end quotation 30 | @end copying 31 | 32 | @ifnottex 33 | @node Top 34 | @top librarian -- Library to compiler flags resolver 35 | @insertcopying 36 | @end ifnottex 37 | 38 | @titlepage 39 | @title librarian 40 | @subtitle Library to compiler flags resolver 41 | @author by Mattias Andrée (maandree) 42 | 43 | @page 44 | @vskip 0pt plus 1filll 45 | @insertcopying 46 | @page 47 | @end titlepage 48 | 49 | @contents 50 | 51 | 52 | 53 | @menu 54 | * Overview:: Brief overview of @command{librarian}. 55 | * Invoking:: Invocation of @command{librarian}. 56 | * Files:: @command{librarian} files. 57 | * GNU Free Documentation License:: Copying and sharing this manual. 58 | @end menu 59 | 60 | 61 | 62 | @node Overview 63 | @chapter Overview 64 | 65 | @command{librarian} is used to print flags required 66 | when compiling or linking, and want to use library 67 | that requires non-trival flags@footnote{Just @option{-l} 68 | and the library name sans `lib'}. 69 | 70 | 71 | 72 | @node Invoking 73 | @chapter Invoking 74 | 75 | Synopsis: 76 | @example 77 | librarian [OPTION]... [--] [VARIABLE]... [LIBRARY]... 78 | @end example 79 | 80 | @command{librarian} shall output the flags, required 81 | by the selected libraries, that are listed under the 82 | selected variables. 83 | 84 | @code{LIBRARY} can either be the name of the required 85 | library, the name of the required library and a version 86 | of said library, or the name of the required library 87 | and an accepted version range of said library. If the 88 | same library name is used more than once, the versions 89 | and version ranges are unioned. Recognised formats are: 90 | @table @code 91 | @item NAME 92 | Any version of the library @code{NAME} will do. 93 | @item NAME=VERSION 94 | Only version @code{VERSION} of the library @code{NAME} 95 | is acceptable. (Multiple version can be used by 96 | specifying more than once.) 97 | @item NAME<=MAX 98 | Any versions up to and including @code{MAX} of the 99 | library @code{NAME} will do. 100 | @item NAME=MIN 104 | At least version @code{MIN} of the library @code{NAME} 105 | is required. 106 | @item NAME>MIN 107 | A greater version than version @code{MIN} of the 108 | library @code{NAME} is required. 109 | @item NAME>=MIN<=MAX 110 | Combines, by intersection, @code{NAME>=MIN} and 111 | @code{NAME<=MAX}. 112 | @item NAME>=MIN=MIN} and 114 | @code{NAMEMIN<=MAX 116 | Combines, by intersection, @code{NAME>MIN} and 117 | @code{NAME<=MAX}. 118 | @item NAME>MINMIN} and 120 | @code{NAME 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a 7 | * copy of this software and associated documentation files (the "Software"), 8 | * to deal in the Software without restriction, including without limitation 9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 | * and/or sell copies of the Software, and to permit persons to whom the 11 | * Software is furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22 | * DEALINGS IN THE SOFTWARE. 23 | */ 24 | #define _POSIX_C_SOURCE 200809L 25 | #include "util.h" 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | 36 | /** 37 | * Default value for the environment variable LIBRARIAN_PATH. 38 | */ 39 | #ifndef DEFAULT_PATH 40 | # define DEFAULT_PATH "/usr/local/share/librarian:/usr/share/librarian" 41 | #endif 42 | 43 | 44 | 45 | /** 46 | * A library and version range. 47 | */ 48 | struct library { 49 | /** 50 | * The name of the library. 51 | */ 52 | const char *name; 53 | 54 | /** 55 | * The lowest acceptable version. 56 | * `NULL` if unbounded. 57 | */ 58 | char *lower; 59 | 60 | /** 61 | * The highest acceptable version. 62 | * `NULL` if unbounded. 63 | */ 64 | char *upper; 65 | 66 | /** 67 | * Is the version stored in 68 | * `lower` acceptable. 69 | */ 70 | int lower_closed; 71 | 72 | /** 73 | * Is the version stored in 74 | * `ypper` acceptable. 75 | */ 76 | int upper_closed; 77 | }; 78 | 79 | 80 | /** 81 | * Structure for already located librarian files. 82 | */ 83 | struct found_file { 84 | /** 85 | * The name of the library. 86 | */ 87 | const char *name; 88 | 89 | /** 90 | * The found version of the library. 91 | */ 92 | char *version; 93 | 94 | /** 95 | * The path name of the librarian file. 96 | */ 97 | char *path; 98 | }; 99 | 100 | 101 | 102 | /** 103 | * The name of the process. 104 | */ 105 | static const char *argv0; 106 | 107 | /** 108 | * Sorted list of already located librarian files. 109 | */ 110 | static struct found_file *found_files = NULL; 111 | 112 | /** 113 | * The number of elements in `found_files`. 114 | */ 115 | static size_t found_files_count = 0; 116 | 117 | 118 | 119 | /** 120 | * Compares the name of two libraries. 121 | * 122 | * @param a:const struct library * One of the libraries. 123 | * @param b:const struct library * The other library. 124 | * @return <0: `a` < `b`. 125 | * =0: `a` = `b`. 126 | * >0: `a` > `b`. 127 | */ 128 | static int library_name_cmp(const void *a, const void *b) 129 | { 130 | const struct library *la = a; 131 | const struct library *lb = b; 132 | return strcmp(la->name, lb->name); 133 | } 134 | 135 | 136 | /** 137 | * Compares the name of two `struct found_file`. 138 | * 139 | * @param a:const struct found_file * One of the files. 140 | * @param b:const struct found_file * The other file. 141 | * @return <0: `a` < `b`. 142 | * =0: `a` = `b`. 143 | * >0: `a` > `b`. 144 | */ 145 | static int found_file_name_cmp(const void *a, const void *b) 146 | { 147 | const struct found_file *fa = a; 148 | const struct found_file *fb = b; 149 | return strcmp(fa->name, fb->name); 150 | } 151 | 152 | 153 | /** 154 | * Determine whether a string is the 155 | * name of a non-reserved variable. 156 | * 157 | * @param s The string. 158 | * @return 1: The string is a varible name. 159 | * 0: The string is a library. 160 | */ 161 | static int is_variable(const char *s) 162 | { 163 | for (; *s; s++) 164 | if (!isupper(*s) && !isdigit(*s) && !strchr("_-", *s)) 165 | return 0; 166 | return 1; 167 | } 168 | 169 | 170 | /** 171 | * Parse a library–library-version range 172 | * argument. 173 | * 174 | * @param s The string. 175 | * @param lib Output parameter for the library spec:s. 176 | * @return 0: Successful. 177 | * 1: Syntax error. 178 | */ 179 | static int parse_library(char *s, struct library *lib) 180 | { 181 | char *p; 182 | char c; 183 | 184 | memset(lib, 0, sizeof(*lib)); 185 | 186 | if (strchr(s, '/') || strchr("<>=", *s)) 187 | return 1; 188 | 189 | lib->name = s; 190 | p = strpbrk(s, "<>="); 191 | if (p == NULL) 192 | return 0; 193 | c = *p, *p++ = '\0'; 194 | 195 | switch (c) { 196 | case '=': 197 | lib->lower_closed = lib->upper_closed = 1; 198 | lib->lower = lib->upper = p; 199 | break; 200 | case '>': 201 | p += lib->lower_closed = (*p == '='); 202 | lib->lower = p; 203 | s = strchr(p, '<'); 204 | if (s == NULL) 205 | break; 206 | *s++ = '\0'; 207 | if (!*(p = s)) 208 | return 0; 209 | /* fall through */ 210 | case '<': 211 | p += lib->upper_closed = (*p == '='); 212 | lib->upper = p; 213 | break; 214 | default: 215 | NEVER_REACHED; 216 | break; 217 | } 218 | 219 | return (strpbrk(p, "<>=") || !*p); 220 | } 221 | 222 | 223 | /** 224 | * Compare two version numbers that do not 225 | * compare any does, and does not have an 226 | * epoch. 227 | * 228 | * @param a One of the version numbers. 229 | * @param b The other version number. 230 | * @return <0: `a` < `b`. 231 | * =0: `a` = `b`. 232 | * >1: `a` > `b`. 233 | */ 234 | static int version_subcmp(char *a, char *b) 235 | { 236 | char *ap; 237 | char *bp; 238 | int r; 239 | 240 | while (*a || *b) { 241 | /* Compare digit part. */ 242 | /* (We must support arbitrary lenght.) */ 243 | ap = a + strspn(a, "0123456789"); 244 | bp = b + strspn(b, "0123456789"); 245 | while (*a == '0') a++; 246 | while (*b == '0') b++; 247 | if (ap - a < bp - b) return -1; 248 | if (ap - a > bp - b) return +1; 249 | TEMP_NUL(ap, TEMP_NUL(bp, r = strcmp(a, b))); 250 | a = isdigit(*a) ? (ap + 1) : a; 251 | b = isdigit(*b) ? (bp + 1) : b; 252 | if (r) return r; 253 | 254 | /* Compare letter (non-digit) part. */ 255 | ap = a + strcspn(a, "0123456789"); 256 | bp = b + strcspn(b, "0123456789"); 257 | TEMP_NUL(ap, TEMP_NUL(bp, r = strcmp(a, b))); 258 | a = *a && !isdigit(*a) ? (ap + 1) : a; 259 | b = *b && !isdigit(*b) ? (bp + 1) : b; 260 | if (r) return r; 261 | } 262 | 263 | return 0; 264 | } 265 | 266 | 267 | /** 268 | * Compare two version numbers. 269 | * 270 | * @param a One of the version numbers. 271 | * @param b The other version number. 272 | * @return <0: `a` < `b`. 273 | * =0: `a` = `b`. 274 | * >0: `a` > `b`. 275 | */ 276 | static int version_cmp(char *a, char *b) 277 | { 278 | #define COMPARE \ 279 | if (ap && bp) { \ 280 | TEMP_NUL(ap, TEMP_NUL(bp, r = version_subcmp(a, b))); \ 281 | } else if (ap) { \ 282 | TEMP_NUL(ap, r = version_subcmp(a, nil)); \ 283 | } else if (bp) { \ 284 | TEMP_NUL(bp, r = version_subcmp(nil, b)); \ 285 | } \ 286 | a = ap ? (ap + 1) : a; \ 287 | b = bp ? (bp + 1) : b; \ 288 | if (r) return r 289 | #define END_AT(C) ap = strchr(a, (C)), bp = strchr(b, (C)) 290 | 291 | char *ap; 292 | char *bp; 293 | int r = 0; 294 | static char nil[1] = { '\0' }; 295 | 296 | /* Compare epoch. */ 297 | END_AT(':'); 298 | COMPARE; 299 | 300 | /* Compare non-epoch */ 301 | while (END_AT('.'), (ap || bp)) { 302 | COMPARE; 303 | } 304 | END_AT('\0'); 305 | COMPARE; 306 | return 0; 307 | } 308 | 309 | 310 | /** 311 | * Test whether a version of a library is compatible. 312 | * 313 | * @param version The found version. 314 | * @param required Compatible version range. 315 | * @return 1: Version is accepted. 316 | * 0: Version is incompatible. 317 | */ 318 | static int test_library_version(char *version, struct library *required) 319 | { 320 | int upper = required->upper ? version_cmp(version, required->upper) : -1; 321 | int lower = required->lower ? version_cmp(version, required->lower) : +1; 322 | 323 | upper = required->upper_closed ? (upper <= 0) : (upper < 0); 324 | lower = required->lower_closed ? (lower >= 0) : (lower > 0); 325 | 326 | return upper && lower; 327 | } 328 | 329 | 330 | /** 331 | * Locate a librarian file in a directory. 332 | * 333 | * @param lib Library specification. 334 | * @param path The pathname of the directory. 335 | * @param oldest Are older versions prefered? 336 | * @return The pathname of the library's librarian file. 337 | * `NULL` on error or if not found, if not found, 338 | * `errno` is set to 0. 339 | */ 340 | static char *locate_in_dir(struct library *lib, char *path, int oldest) 341 | { 342 | DIR *d = NULL; 343 | struct dirent *f; 344 | char *p; 345 | void *new; 346 | char *best = NULL; 347 | char *best_ver; 348 | int r; 349 | 350 | d = opendir(path); 351 | t (d == NULL); 352 | 353 | while ((f = (errno = 0, readdir(d)))) { 354 | p = strrchr(f->d_name, '='); 355 | if (p == NULL) 356 | continue; 357 | *p = '\0'; 358 | if (strcmp(f->d_name, lib->name)) 359 | continue; 360 | *p++ = '='; 361 | if (!test_library_version(p, lib)) 362 | continue; 363 | if (best != NULL) { 364 | GET_VERSION(best_ver, best); 365 | r = version_cmp(p, best_ver + 1); 366 | if (!(oldest ? (r < 0) : (r > 0))) 367 | continue; 368 | } 369 | new = strdup(f->d_name); 370 | t (new == NULL); 371 | free(best), best = new; 372 | } 373 | t (errno); 374 | 375 | closedir(d), d = NULL; 376 | 377 | if (best == NULL) 378 | return errno = 0, NULL; 379 | 380 | p = malloc(strlen(path) + strlen(best) + 2); 381 | t (p == NULL); 382 | stpcpy(stpcpy(stpcpy(p, path), "/"), best); 383 | 384 | free(best); 385 | return p; 386 | 387 | fail: 388 | RETURN (NULL) { 389 | free(best); 390 | if (d != NULL) 391 | closedir(d); 392 | } 393 | } 394 | 395 | 396 | /** 397 | * Locate a librarian file on the system. 398 | * 399 | * @param lib Library specification. 400 | * @param path LIBRARIAN_PATH. 401 | * @param oldest Are older versions prefered? 402 | * @return The pathname of the library's librarian file. 403 | * `NULL` on error or if not found, if not found, 404 | * `errno` is set to 0. 405 | */ 406 | static char *locate(struct library *lib, char *path, int oldest) 407 | { 408 | char *p; 409 | char *end = path; 410 | char *e; 411 | char *best = NULL; 412 | char *found; 413 | char *old; 414 | char *best_ver; 415 | char *found_ver; 416 | int r; 417 | 418 | for (p = path; end; *e = (end ? ':' : '\0'), p = end + 1) { 419 | end = strchr(p, ':'); 420 | e = end ? end : strchr(p, '\0'); 421 | *e = '\0'; 422 | if (!*p) 423 | continue; 424 | found = locate_in_dir(lib, p, oldest); 425 | if (found == NULL) { 426 | t (errno); 427 | continue; 428 | } 429 | old = found; 430 | if (best == NULL) { 431 | old = best, best = found; 432 | } else { 433 | GET_VERSION(best_ver, best); 434 | GET_VERSION(found_ver, found); 435 | r = version_cmp(found_ver + 1, best_ver + 1); 436 | if (oldest ? (r < 0) : (r > 0)) 437 | old = best, best = found; 438 | } 439 | free(old); 440 | } 441 | 442 | return errno = 0, best; 443 | 444 | fail: 445 | RETURN (NULL) 446 | free(best); 447 | } 448 | 449 | 450 | /** 451 | * Find librarian files for all libraries. 452 | * 453 | * Found files are appended to `found_files`. 454 | * 455 | * @param libraries The sought libraries. 456 | * @param n The number of elements in `libraries`. 457 | * @param path LIBRARIAN_PATH. 458 | * @param oldest Are older versions prefered? 459 | * @return 0: Successful and found all files. 460 | * -1 and !errno: Did not find all files, but otherwise successful. 461 | * -1 and errno: An error occurred 462 | */ 463 | static int find_librarian_files(struct library *libraries, size_t n, char *path, int oldest) 464 | { 465 | size_t i; 466 | char *best = NULL; 467 | char *found; 468 | char *best_ver; 469 | char *found_ver; 470 | const char *last = NULL; 471 | size_t ffc = found_files_count; 472 | int r; 473 | struct found_file f; 474 | struct found_file *have; 475 | 476 | qsort(libraries, n, sizeof(*libraries), library_name_cmp); 477 | qsort(found_files, ffc, sizeof(*found_files), found_file_name_cmp); 478 | REALLOC(found_files, ffc + n); 479 | 480 | for (i = 0; i < n; i++) { 481 | f.name = libraries[i].name; 482 | have = bsearch(&f, found_files, ffc, sizeof(*found_files), found_file_name_cmp); 483 | if (have) { 484 | if (test_library_version(have->version, libraries + i)) 485 | continue; 486 | goto not_this_range; 487 | } 488 | found = locate(libraries + i, path, oldest); 489 | t (!found && errno); 490 | if (found == NULL) 491 | goto not_this_range; 492 | if (last && !strcmp(f.name, last)) { 493 | GET_VERSION(best_ver, best); 494 | GET_VERSION(found_ver, found); 495 | r = version_cmp(found + 1, best_ver + 1); 496 | if (!(oldest ? (r < 0) : (r > 0))) 497 | continue; 498 | free(best); 499 | } else { 500 | last = f.name, found_files_count++; 501 | } 502 | GET_VERSION(found_ver, found); 503 | found_files[found_files_count - 1].name = f.name; 504 | found_files[found_files_count - 1].version = found_ver + 1; 505 | found_files[found_files_count - 1].path = best = found; 506 | continue; 507 | 508 | not_this_range: 509 | if ((i + 1 == n) || strcmp(f.name, libraries[i + 1].name)) 510 | goto not_found; 511 | continue; 512 | } 513 | 514 | return 0; 515 | 516 | not_found: 517 | if (libraries[i].upper == libraries[i].lower) { 518 | fprintf(stderr, "%s: cannot find library: %s%s%s", argv0, 519 | libraries[i].name, libraries[i].upper ? "=" : "", 520 | libraries[i].upper ? libraries[i].upper : ""); 521 | } else { 522 | fprintf(stderr, "%s: cannot find library: %s%s%s%s%s%s%s", argv0, 523 | libraries[i].name, 524 | libraries[i].lower ? ">" : "", libraries[i].lower_closed ? "=" : "", 525 | libraries[i].lower ? libraries[i].lower : "", 526 | libraries[i].upper ? "<" : "", libraries[i].upper_closed ? "=" : "", 527 | libraries[i].upper ? libraries[i].upper : ""); 528 | } 529 | errno = 0; 530 | fail: 531 | return -1; 532 | } 533 | 534 | 535 | /** 536 | * Read the value of a variable in a file. 537 | * 538 | * @param path The pathname of the file to read. 539 | * @param var The variable to retrieve 540 | * @return The value of variable. `NULL` on error or if 541 | * not found, `errno` is set to 0 if not found. 542 | */ 543 | static char *find_variable(const char *path, const char *var) 544 | { 545 | int fd = -1; 546 | size_t ptr = 0, size = 0, len; 547 | char *buffer = NULL; 548 | char *p; 549 | char *q; 550 | char *sought = NULL; 551 | ssize_t n; 552 | 553 | fd = open(path, O_RDONLY); 554 | t (fd == -1); 555 | 556 | for (;;) { 557 | MAYBE_GROW(buffer, ptr, size, 512); 558 | n = read(fd, buffer + ptr, size - ptr); 559 | t (n < 0); 560 | if (n == 0) 561 | break; 562 | ptr += (size_t)n; 563 | } 564 | 565 | close(fd), fd = -1; 566 | REALLOC(buffer, ptr + 3); 567 | buffer[ptr++] = '\n'; 568 | buffer[ptr++] = '\0'; 569 | memmove(buffer + 1, buffer, ptr); 570 | *buffer = '\n'; 571 | 572 | sought = malloc(strlen(var) + 2); 573 | t (sought == NULL); 574 | sought[0] = '\n'; 575 | strcpy(sought + 1, var); 576 | 577 | len = strlen(sought); 578 | for (p = buffer; p;) { 579 | p = strstr(p, sought); 580 | if (p == NULL) 581 | break; 582 | if (!isspace(p[len])) { 583 | p = strchr(p + 1, '\n'); 584 | continue; 585 | } 586 | p += len + 1; 587 | q = strchr(p, '\n'); 588 | *q = '\0'; 589 | break; 590 | } 591 | 592 | if (p != NULL) { 593 | p = strdup(p); 594 | t (p == NULL); 595 | } 596 | free(sought); 597 | free(buffer); 598 | return p; 599 | 600 | fail: 601 | RETURN (NULL) { 602 | if (fd >= 0) 603 | close(fd); 604 | free(buffer); 605 | free(sought); 606 | } 607 | } 608 | 609 | 610 | /** 611 | * Get variables values stored in librarian files. 612 | * 613 | * @param vars Pointer to the first variable. 614 | * @param vars_end Pointer to just after the last variable. 615 | * @param files_start The index of the first file in `found_files` 616 | * for which variables should be retrieved. 617 | * @return String with all variables, `NULL` on error. 618 | */ 619 | static char *get_variables(const char **vars, const char **vars_end, size_t files_start) 620 | { 621 | char *path; 622 | const char **var; 623 | char **parts = NULL; 624 | char *part; 625 | size_t ptr = 0; 626 | size_t size = 0; 627 | size_t len = 0; 628 | char *rc; 629 | char *p; 630 | 631 | while (files_start < found_files_count) { 632 | path = found_files[files_start++].path; 633 | for (var = vars; var != vars_end; var++) { 634 | part = find_variable(path, *var); 635 | t (!part && errno); 636 | if (!part || !*part) 637 | continue; 638 | MAYBE_GROW(parts, ptr, size, 8); 639 | len += strlen(part) + 1; 640 | parts[ptr++] = part; 641 | } 642 | } 643 | 644 | if (len == 0) 645 | return strdup(""); 646 | 647 | p = rc = malloc(len); 648 | t (rc == NULL); 649 | for (size = ptr, ptr = 0; ptr < size; ptr++) { 650 | p = stpcpy(p, parts[ptr]); 651 | *p++ = ' '; 652 | free(parts[ptr]); 653 | } 654 | free(parts); 655 | p[-1] = 0; 656 | 657 | return rc; 658 | fail: 659 | RETURN (NULL) { 660 | while (ptr--) 661 | free(parts[ptr]); 662 | free(parts); 663 | } 664 | } 665 | 666 | 667 | /** 668 | * @return 0: Program was successful. 669 | * 1: An error occurred. 670 | * 2: A library was not found. 671 | * 3: Usage error. 672 | */ 673 | int main(int argc, char *argv[]) 674 | { 675 | int dashed = 0, f_deps = 0, f_locate = 0, f_oldest = 0; 676 | char *arg; 677 | char **args = argv; 678 | char **args_last = args; 679 | const char **variables = (const char **)argv; 680 | const char **variables_last = variables; 681 | struct library *libraries = NULL; 682 | size_t libraries_ptr = 0; 683 | size_t libraries_size = 0; 684 | const char *path_; 685 | char *path = NULL; 686 | int rc; 687 | size_t start_files; 688 | size_t start_libs, n; 689 | char *data = NULL; 690 | char *s; 691 | char *end; 692 | void** free_this = NULL; 693 | size_t free_this_ptr = 0; 694 | size_t free_this_size = 0; 695 | const char *deps_string = "deps"; 696 | 697 | /* Parse arguments. */ 698 | argv0 = argv ? (argc--, *argv++) : "pp"; 699 | while (argc--) { 700 | if (!dashed && !strcmp(*argv, "--")) { 701 | dashed = 1; 702 | argv++; 703 | } else if (!dashed && (**argv == '-')) { 704 | arg = *argv++; 705 | if (!*arg) 706 | goto usage; 707 | for (arg++; *arg; arg++) { 708 | if (*arg == 'd') f_deps = 1; 709 | else if (*arg == 'l') f_locate = 1; 710 | else if (*arg == 'o') f_oldest = 1; 711 | else goto usage; 712 | } 713 | } else { 714 | *args_last++ = *argv++; 715 | } 716 | } 717 | if (f_deps && f_locate) 718 | goto usage; 719 | 720 | /* Parse VARIABLE and LIBRARY arguments. */ 721 | libraries_size = (size_t)(args_last - args); 722 | libraries = malloc(libraries_size * sizeof(*libraries)); 723 | t (libraries == NULL); 724 | for (; args != args_last; args++) { 725 | if (is_variable(*args)) 726 | *variables_last++ = *args; 727 | else if (parse_library(*args, libraries + libraries_ptr++)) 728 | goto usage; 729 | } 730 | 731 | /* Get LIBRARIAN_PATH. */ 732 | path_ = getenv("LIBRARIAN_PATH"); 733 | if (!path_ || !*path_) 734 | path_ = DEFAULT_PATH; 735 | path = strdup(path_); 736 | t (path == NULL); 737 | 738 | /* Find librarian files. */ 739 | for (start_libs = 0; (n = libraries_ptr - start_libs);) { 740 | start_files = found_files_count; 741 | if (find_librarian_files(libraries + start_libs, n, path, f_oldest)) { 742 | t (errno); 743 | goto not_found; 744 | } 745 | start_libs += n; 746 | if (f_locate || !f_deps) 747 | break; 748 | data = get_variables(&deps_string, 1 + &deps_string, start_files); 749 | t (data == NULL); 750 | for (end = s = data; end; s = end + 1) { 751 | while (isspace(*s)) 752 | s++; 753 | if ((end = strpbrk(s, " \t\r\n\f\v"))) 754 | *end = '\0'; 755 | MAYBE_GROW(libraries, libraries_ptr, libraries_size, 1); 756 | if (*s && parse_library(s, libraries + libraries_ptr++)) 757 | goto not_found; 758 | } 759 | MAYBE_GROW(free_this, free_this_ptr, free_this_size, 4); 760 | free_this[free_this_ptr++] = data, data = NULL; 761 | } 762 | if (f_locate) { 763 | for (n = 0; n < found_files_count; n++) 764 | t (printf("%s\n", found_files[n].path) < 0); 765 | goto done; 766 | } 767 | 768 | /* Print requested data. */ 769 | data = get_variables(variables, variables_last, 0); 770 | t (data == NULL); 771 | t (printf("%s\n", data) < 0); 772 | 773 | done: 774 | rc = 0; 775 | goto cleanup; 776 | fail: 777 | perror(argv0); 778 | rc = 1; 779 | goto cleanup; 780 | not_found: 781 | rc = 2; 782 | goto cleanup; 783 | usage: 784 | fprintf(stderr, "%s: Invalid arguments, see `man 1 librarian'.\n", argv0); 785 | rc = 3; 786 | goto cleanup; 787 | 788 | cleanup: 789 | while (found_files_count--) 790 | free(found_files[found_files_count].path); 791 | free(found_files); 792 | while (free_this_ptr--) 793 | free(free_this[free_this_ptr]); 794 | free(free_this); 795 | free(libraries); 796 | free(path); 797 | free(data); 798 | return rc; 799 | } 800 | 801 | -------------------------------------------------------------------------------- /doc/info/fdl.texinfo: -------------------------------------------------------------------------------- 1 | @c The GNU Free Documentation License. 2 | @center Version 1.3, 3 November 2008 3 | 4 | @c This file is intended to be included within another document, 5 | @c hence no sectioning command or @node. 6 | 7 | @display 8 | Copyright @copyright{} 2000, 2001, 2002, 2007, 2008 Free Software Foundation, Inc. 9 | @uref{http://fsf.org/} 10 | 11 | Everyone is permitted to copy and distribute verbatim copies 12 | of this license document, but changing it is not allowed. 13 | @end display 14 | 15 | @enumerate 0 16 | @item 17 | PREAMBLE 18 | 19 | The purpose of this License is to make a manual, textbook, or other 20 | functional and useful document @dfn{free} in the sense of freedom: to 21 | assure everyone the effective freedom to copy and redistribute it, 22 | with or without modifying it, either commercially or noncommercially. 23 | Secondarily, this License preserves for the author and publisher a way 24 | to get credit for their work, while not being considered responsible 25 | for modifications made by others. 26 | 27 | This License is a kind of ``copyleft'', which means that derivative 28 | works of the document must themselves be free in the same sense. It 29 | complements the GNU General Public License, which is a copyleft 30 | license designed for free software. 31 | 32 | We have designed this License in order to use it for manuals for free 33 | software, because free software needs free documentation: a free 34 | program should come with manuals providing the same freedoms that the 35 | software does. But this License is not limited to software manuals; 36 | it can be used for any textual work, regardless of subject matter or 37 | whether it is published as a printed book. We recommend this License 38 | principally for works whose purpose is instruction or reference. 39 | 40 | @item 41 | APPLICABILITY AND DEFINITIONS 42 | 43 | This License applies to any manual or other work, in any medium, that 44 | contains a notice placed by the copyright holder saying it can be 45 | distributed under the terms of this License. Such a notice grants a 46 | world-wide, royalty-free license, unlimited in duration, to use that 47 | work under the conditions stated herein. The ``Document'', below, 48 | refers to any such manual or work. Any member of the public is a 49 | licensee, and is addressed as ``you''. You accept the license if you 50 | copy, modify or distribute the work in a way requiring permission 51 | under copyright law. 52 | 53 | A ``Modified Version'' of the Document means any work containing the 54 | Document or a portion of it, either copied verbatim, or with 55 | modifications and/or translated into another language. 56 | 57 | A ``Secondary Section'' is a named appendix or a front-matter section 58 | of the Document that deals exclusively with the relationship of the 59 | publishers or authors of the Document to the Document's overall 60 | subject (or to related matters) and contains nothing that could fall 61 | directly within that overall subject. (Thus, if the Document is in 62 | part a textbook of mathematics, a Secondary Section may not explain 63 | any mathematics.) The relationship could be a matter of historical 64 | connection with the subject or with related matters, or of legal, 65 | commercial, philosophical, ethical or political position regarding 66 | them. 67 | 68 | The ``Invariant Sections'' are certain Secondary Sections whose titles 69 | are designated, as being those of Invariant Sections, in the notice 70 | that says that the Document is released under this License. If a 71 | section does not fit the above definition of Secondary then it is not 72 | allowed to be designated as Invariant. The Document may contain zero 73 | Invariant Sections. If the Document does not identify any Invariant 74 | Sections then there are none. 75 | 76 | The ``Cover Texts'' are certain short passages of text that are listed, 77 | as Front-Cover Texts or Back-Cover Texts, in the notice that says that 78 | the Document is released under this License. A Front-Cover Text may 79 | be at most 5 words, and a Back-Cover Text may be at most 25 words. 80 | 81 | A ``Transparent'' copy of the Document means a machine-readable copy, 82 | represented in a format whose specification is available to the 83 | general public, that is suitable for revising the document 84 | straightforwardly with generic text editors or (for images composed of 85 | pixels) generic paint programs or (for drawings) some widely available 86 | drawing editor, and that is suitable for input to text formatters or 87 | for automatic translation to a variety of formats suitable for input 88 | to text formatters. A copy made in an otherwise Transparent file 89 | format whose markup, or absence of markup, has been arranged to thwart 90 | or discourage subsequent modification by readers is not Transparent. 91 | An image format is not Transparent if used for any substantial amount 92 | of text. A copy that is not ``Transparent'' is called ``Opaque''. 93 | 94 | Examples of suitable formats for Transparent copies include plain 95 | ASCII without markup, Texinfo input format, La@TeX{} input 96 | format, SGML or XML using a publicly available 97 | DTD, and standard-conforming simple HTML, 98 | PostScript or PDF designed for human modification. Examples 99 | of transparent image formats include PNG, XCF and 100 | JPG. Opaque formats include proprietary formats that can be 101 | read and edited only by proprietary word processors, SGML or 102 | XML for which the DTD and/or processing tools are 103 | not generally available, and the machine-generated HTML, 104 | PostScript or PDF produced by some word processors for 105 | output purposes only. 106 | 107 | The ``Title Page'' means, for a printed book, the title page itself, 108 | plus such following pages as are needed to hold, legibly, the material 109 | this License requires to appear in the title page. For works in 110 | formats which do not have any title page as such, ``Title Page'' means 111 | the text near the most prominent appearance of the work's title, 112 | preceding the beginning of the body of the text. 113 | 114 | The ``publisher'' means any person or entity that distributes copies 115 | of the Document to the public. 116 | 117 | A section ``Entitled XYZ'' means a named subunit of the Document whose 118 | title either is precisely XYZ or contains XYZ in parentheses following 119 | text that translates XYZ in another language. (Here XYZ stands for a 120 | specific section name mentioned below, such as ``Acknowledgements'', 121 | ``Dedications'', ``Endorsements'', or ``History''.) To ``Preserve the Title'' 122 | of such a section when you modify the Document means that it remains a 123 | section ``Entitled XYZ'' according to this definition. 124 | 125 | The Document may include Warranty Disclaimers next to the notice which 126 | states that this License applies to the Document. These Warranty 127 | Disclaimers are considered to be included by reference in this 128 | License, but only as regards disclaiming warranties: any other 129 | implication that these Warranty Disclaimers may have is void and has 130 | no effect on the meaning of this License. 131 | 132 | @item 133 | VERBATIM COPYING 134 | 135 | You may copy and distribute the Document in any medium, either 136 | commercially or noncommercially, provided that this License, the 137 | copyright notices, and the license notice saying this License applies 138 | to the Document are reproduced in all copies, and that you add no other 139 | conditions whatsoever to those of this License. You may not use 140 | technical measures to obstruct or control the reading or further 141 | copying of the copies you make or distribute. However, you may accept 142 | compensation in exchange for copies. If you distribute a large enough 143 | number of copies you must also follow the conditions in section 3. 144 | 145 | You may also lend copies, under the same conditions stated above, and 146 | you may publicly display copies. 147 | 148 | @item 149 | COPYING IN QUANTITY 150 | 151 | If you publish printed copies (or copies in media that commonly have 152 | printed covers) of the Document, numbering more than 100, and the 153 | Document's license notice requires Cover Texts, you must enclose the 154 | copies in covers that carry, clearly and legibly, all these Cover 155 | Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on 156 | the back cover. Both covers must also clearly and legibly identify 157 | you as the publisher of these copies. The front cover must present 158 | the full title with all words of the title equally prominent and 159 | visible. You may add other material on the covers in addition. 160 | Copying with changes limited to the covers, as long as they preserve 161 | the title of the Document and satisfy these conditions, can be treated 162 | as verbatim copying in other respects. 163 | 164 | If the required texts for either cover are too voluminous to fit 165 | legibly, you should put the first ones listed (as many as fit 166 | reasonably) on the actual cover, and continue the rest onto adjacent 167 | pages. 168 | 169 | If you publish or distribute Opaque copies of the Document numbering 170 | more than 100, you must either include a machine-readable Transparent 171 | copy along with each Opaque copy, or state in or with each Opaque copy 172 | a computer-network location from which the general network-using 173 | public has access to download using public-standard network protocols 174 | a complete Transparent copy of the Document, free of added material. 175 | If you use the latter option, you must take reasonably prudent steps, 176 | when you begin distribution of Opaque copies in quantity, to ensure 177 | that this Transparent copy will remain thus accessible at the stated 178 | location until at least one year after the last time you distribute an 179 | Opaque copy (directly or through your agents or retailers) of that 180 | edition to the public. 181 | 182 | It is requested, but not required, that you contact the authors of the 183 | Document well before redistributing any large number of copies, to give 184 | them a chance to provide you with an updated version of the Document. 185 | 186 | @item 187 | MODIFICATIONS 188 | 189 | You may copy and distribute a Modified Version of the Document under 190 | the conditions of sections 2 and 3 above, provided that you release 191 | the Modified Version under precisely this License, with the Modified 192 | Version filling the role of the Document, thus licensing distribution 193 | and modification of the Modified Version to whoever possesses a copy 194 | of it. In addition, you must do these things in the Modified Version: 195 | 196 | @enumerate A 197 | @item 198 | Use in the Title Page (and on the covers, if any) a title distinct 199 | from that of the Document, and from those of previous versions 200 | (which should, if there were any, be listed in the History section 201 | of the Document). You may use the same title as a previous version 202 | if the original publisher of that version gives permission. 203 | 204 | @item 205 | List on the Title Page, as authors, one or more persons or entities 206 | responsible for authorship of the modifications in the Modified 207 | Version, together with at least five of the principal authors of the 208 | Document (all of its principal authors, if it has fewer than five), 209 | unless they release you from this requirement. 210 | 211 | @item 212 | State on the Title page the name of the publisher of the 213 | Modified Version, as the publisher. 214 | 215 | @item 216 | Preserve all the copyright notices of the Document. 217 | 218 | @item 219 | Add an appropriate copyright notice for your modifications 220 | adjacent to the other copyright notices. 221 | 222 | @item 223 | Include, immediately after the copyright notices, a license notice 224 | giving the public permission to use the Modified Version under the 225 | terms of this License, in the form shown in the Addendum below. 226 | 227 | @item 228 | Preserve in that license notice the full lists of Invariant Sections 229 | and required Cover Texts given in the Document's license notice. 230 | 231 | @item 232 | Include an unaltered copy of this License. 233 | 234 | @item 235 | Preserve the section Entitled ``History'', Preserve its Title, and add 236 | to it an item stating at least the title, year, new authors, and 237 | publisher of the Modified Version as given on the Title Page. If 238 | there is no section Entitled ``History'' in the Document, create one 239 | stating the title, year, authors, and publisher of the Document as 240 | given on its Title Page, then add an item describing the Modified 241 | Version as stated in the previous sentence. 242 | 243 | @item 244 | Preserve the network location, if any, given in the Document for 245 | public access to a Transparent copy of the Document, and likewise 246 | the network locations given in the Document for previous versions 247 | it was based on. These may be placed in the ``History'' section. 248 | You may omit a network location for a work that was published at 249 | least four years before the Document itself, or if the original 250 | publisher of the version it refers to gives permission. 251 | 252 | @item 253 | For any section Entitled ``Acknowledgements'' or ``Dedications'', Preserve 254 | the Title of the section, and preserve in the section all the 255 | substance and tone of each of the contributor acknowledgements and/or 256 | dedications given therein. 257 | 258 | @item 259 | Preserve all the Invariant Sections of the Document, 260 | unaltered in their text and in their titles. Section numbers 261 | or the equivalent are not considered part of the section titles. 262 | 263 | @item 264 | Delete any section Entitled ``Endorsements''. Such a section 265 | may not be included in the Modified Version. 266 | 267 | @item 268 | Do not retitle any existing section to be Entitled ``Endorsements'' or 269 | to conflict in title with any Invariant Section. 270 | 271 | @item 272 | Preserve any Warranty Disclaimers. 273 | @end enumerate 274 | 275 | If the Modified Version includes new front-matter sections or 276 | appendices that qualify as Secondary Sections and contain no material 277 | copied from the Document, you may at your option designate some or all 278 | of these sections as invariant. To do this, add their titles to the 279 | list of Invariant Sections in the Modified Version's license notice. 280 | These titles must be distinct from any other section titles. 281 | 282 | You may add a section Entitled ``Endorsements'', provided it contains 283 | nothing but endorsements of your Modified Version by various 284 | parties---for example, statements of peer review or that the text has 285 | been approved by an organization as the authoritative definition of a 286 | standard. 287 | 288 | You may add a passage of up to five words as a Front-Cover Text, and a 289 | passage of up to 25 words as a Back-Cover Text, to the end of the list 290 | of Cover Texts in the Modified Version. Only one passage of 291 | Front-Cover Text and one of Back-Cover Text may be added by (or 292 | through arrangements made by) any one entity. If the Document already 293 | includes a cover text for the same cover, previously added by you or 294 | by arrangement made by the same entity you are acting on behalf of, 295 | you may not add another; but you may replace the old one, on explicit 296 | permission from the previous publisher that added the old one. 297 | 298 | The author(s) and publisher(s) of the Document do not by this License 299 | give permission to use their names for publicity for or to assert or 300 | imply endorsement of any Modified Version. 301 | 302 | @item 303 | COMBINING DOCUMENTS 304 | 305 | You may combine the Document with other documents released under this 306 | License, under the terms defined in section 4 above for modified 307 | versions, provided that you include in the combination all of the 308 | Invariant Sections of all of the original documents, unmodified, and 309 | list them all as Invariant Sections of your combined work in its 310 | license notice, and that you preserve all their Warranty Disclaimers. 311 | 312 | The combined work need only contain one copy of this License, and 313 | multiple identical Invariant Sections may be replaced with a single 314 | copy. If there are multiple Invariant Sections with the same name but 315 | different contents, make the title of each such section unique by 316 | adding at the end of it, in parentheses, the name of the original 317 | author or publisher of that section if known, or else a unique number. 318 | Make the same adjustment to the section titles in the list of 319 | Invariant Sections in the license notice of the combined work. 320 | 321 | In the combination, you must combine any sections Entitled ``History'' 322 | in the various original documents, forming one section Entitled 323 | ``History''; likewise combine any sections Entitled ``Acknowledgements'', 324 | and any sections Entitled ``Dedications''. You must delete all 325 | sections Entitled ``Endorsements.'' 326 | 327 | @item 328 | COLLECTIONS OF DOCUMENTS 329 | 330 | You may make a collection consisting of the Document and other documents 331 | released under this License, and replace the individual copies of this 332 | License in the various documents with a single copy that is included in 333 | the collection, provided that you follow the rules of this License for 334 | verbatim copying of each of the documents in all other respects. 335 | 336 | You may extract a single document from such a collection, and distribute 337 | it individually under this License, provided you insert a copy of this 338 | License into the extracted document, and follow this License in all 339 | other respects regarding verbatim copying of that document. 340 | 341 | @item 342 | AGGREGATION WITH INDEPENDENT WORKS 343 | 344 | A compilation of the Document or its derivatives with other separate 345 | and independent documents or works, in or on a volume of a storage or 346 | distribution medium, is called an ``aggregate'' if the copyright 347 | resulting from the compilation is not used to limit the legal rights 348 | of the compilation's users beyond what the individual works permit. 349 | When the Document is included in an aggregate, this License does not 350 | apply to the other works in the aggregate which are not themselves 351 | derivative works of the Document. 352 | 353 | If the Cover Text requirement of section 3 is applicable to these 354 | copies of the Document, then if the Document is less than one half of 355 | the entire aggregate, the Document's Cover Texts may be placed on 356 | covers that bracket the Document within the aggregate, or the 357 | electronic equivalent of covers if the Document is in electronic form. 358 | Otherwise they must appear on printed covers that bracket the whole 359 | aggregate. 360 | 361 | @item 362 | TRANSLATION 363 | 364 | Translation is considered a kind of modification, so you may 365 | distribute translations of the Document under the terms of section 4. 366 | Replacing Invariant Sections with translations requires special 367 | permission from their copyright holders, but you may include 368 | translations of some or all Invariant Sections in addition to the 369 | original versions of these Invariant Sections. You may include a 370 | translation of this License, and all the license notices in the 371 | Document, and any Warranty Disclaimers, provided that you also include 372 | the original English version of this License and the original versions 373 | of those notices and disclaimers. In case of a disagreement between 374 | the translation and the original version of this License or a notice 375 | or disclaimer, the original version will prevail. 376 | 377 | If a section in the Document is Entitled ``Acknowledgements'', 378 | ``Dedications'', or ``History'', the requirement (section 4) to Preserve 379 | its Title (section 1) will typically require changing the actual 380 | title. 381 | 382 | @item 383 | TERMINATION 384 | 385 | You may not copy, modify, sublicense, or distribute the Document 386 | except as expressly provided under this License. Any attempt 387 | otherwise to copy, modify, sublicense, or distribute it is void, and 388 | will automatically terminate your rights under this License. 389 | 390 | However, if you cease all violation of this License, then your license 391 | from a particular copyright holder is reinstated (a) provisionally, 392 | unless and until the copyright holder explicitly and finally 393 | terminates your license, and (b) permanently, if the copyright holder 394 | fails to notify you of the violation by some reasonable means prior to 395 | 60 days after the cessation. 396 | 397 | Moreover, your license from a particular copyright holder is 398 | reinstated permanently if the copyright holder notifies you of the 399 | violation by some reasonable means, this is the first time you have 400 | received notice of violation of this License (for any work) from that 401 | copyright holder, and you cure the violation prior to 30 days after 402 | your receipt of the notice. 403 | 404 | Termination of your rights under this section does not terminate the 405 | licenses of parties who have received copies or rights from you under 406 | this License. If your rights have been terminated and not permanently 407 | reinstated, receipt of a copy of some or all of the same material does 408 | not give you any rights to use it. 409 | 410 | @item 411 | FUTURE REVISIONS OF THIS LICENSE 412 | 413 | The Free Software Foundation may publish new, revised versions 414 | of the GNU Free Documentation License from time to time. Such new 415 | versions will be similar in spirit to the present version, but may 416 | differ in detail to address new problems or concerns. See 417 | @uref{http://www.gnu.org/copyleft/}. 418 | 419 | Each version of the License is given a distinguishing version number. 420 | If the Document specifies that a particular numbered version of this 421 | License ``or any later version'' applies to it, you have the option of 422 | following the terms and conditions either of that specified version or 423 | of any later version that has been published (not as a draft) by the 424 | Free Software Foundation. If the Document does not specify a version 425 | number of this License, you may choose any version ever published (not 426 | as a draft) by the Free Software Foundation. If the Document 427 | specifies that a proxy can decide which future versions of this 428 | License can be used, that proxy's public statement of acceptance of a 429 | version permanently authorizes you to choose that version for the 430 | Document. 431 | 432 | @item 433 | RELICENSING 434 | 435 | ``Massive Multiauthor Collaboration Site'' (or ``MMC Site'') means any 436 | World Wide Web server that publishes copyrightable works and also 437 | provides prominent facilities for anybody to edit those works. A 438 | public wiki that anybody can edit is an example of such a server. A 439 | ``Massive Multiauthor Collaboration'' (or ``MMC'') contained in the 440 | site means any set of copyrightable works thus published on the MMC 441 | site. 442 | 443 | ``CC-BY-SA'' means the Creative Commons Attribution-Share Alike 3.0 444 | license published by Creative Commons Corporation, a not-for-profit 445 | corporation with a principal place of business in San Francisco, 446 | California, as well as future copyleft versions of that license 447 | published by that same organization. 448 | 449 | ``Incorporate'' means to publish or republish a Document, in whole or 450 | in part, as part of another Document. 451 | 452 | An MMC is ``eligible for relicensing'' if it is licensed under this 453 | License, and if all works that were first published under this License 454 | somewhere other than this MMC, and subsequently incorporated in whole 455 | or in part into the MMC, (1) had no cover texts or invariant sections, 456 | and (2) were thus incorporated prior to November 1, 2008. 457 | 458 | The operator of an MMC Site may republish an MMC contained in the site 459 | under CC-BY-SA on the same site at any time before August 1, 2009, 460 | provided the MMC is eligible for relicensing. 461 | 462 | @end enumerate 463 | 464 | @page 465 | @heading ADDENDUM: How to use this License for your documents 466 | 467 | To use this License in a document you have written, include a copy of 468 | the License in the document and put the following copyright and 469 | license notices just after the title page: 470 | 471 | @smallexample 472 | @group 473 | Copyright (C) @var{year} @var{your name}. 474 | Permission is granted to copy, distribute and/or modify this document 475 | under the terms of the GNU Free Documentation License, Version 1.3 476 | or any later version published by the Free Software Foundation; 477 | with no Invariant Sections, no Front-Cover Texts, and no Back-Cover 478 | Texts. A copy of the license is included in the section entitled ``GNU 479 | Free Documentation License''. 480 | @end group 481 | @end smallexample 482 | 483 | If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts, 484 | replace the ``with@dots{}Texts.''@: line with this: 485 | 486 | @smallexample 487 | @group 488 | with the Invariant Sections being @var{list their titles}, with 489 | the Front-Cover Texts being @var{list}, and with the Back-Cover Texts 490 | being @var{list}. 491 | @end group 492 | @end smallexample 493 | 494 | If you have Invariant Sections without Cover Texts, or some other 495 | combination of the three, merge those two alternatives to suit the 496 | situation. 497 | 498 | If your document contains nontrivial examples of program code, we 499 | recommend releasing these examples in parallel under your choice of 500 | free software license, such as the GNU General Public License, 501 | to permit their use in free software. 502 | 503 | @c Local Variables: 504 | @c ispell-local-pdict: "ispell-dict" 505 | @c End: 506 | --------------------------------------------------------------------------------