xref: /openbsd-src/regress/usr.bin/mandoc/db/mlinks/mlinks.c (revision 4e948f3e5028c04ed714e05d210a2f3b7f96cea7)
1*4e948f3eSschwarze /*	$OpenBSD: mlinks.c,v 1.3 2016/11/05 16:43:50 schwarze Exp $ */
2fc61954aSschwarze /*
3fc61954aSschwarze  * Copyright (c) 2016 Ingo Schwarze <schwarze@openbsd.org>
4fc61954aSschwarze  *
5fc61954aSschwarze  * Permission to use, copy, modify, and distribute this software for any
6fc61954aSschwarze  * purpose with or without fee is hereby granted, provided that the above
7fc61954aSschwarze  * copyright notice and this permission notice appear in all copies.
8fc61954aSschwarze  *
9fc61954aSschwarze  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10fc61954aSschwarze  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11fc61954aSschwarze  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12fc61954aSschwarze  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13fc61954aSschwarze  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14fc61954aSschwarze  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15fc61954aSschwarze  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16fc61954aSschwarze  *
17fc61954aSschwarze  * Some operating systems need MLINKS for pages with more than one name.
18fc61954aSschwarze  * Extract these in a format suitable for portable LibreSSL.
19fc61954aSschwarze  */
20fc61954aSschwarze #include <err.h>
21fc61954aSschwarze #include <regex.h>
22fc61954aSschwarze #include <stdint.h>
23fc61954aSschwarze #include <stdio.h>
24fc61954aSschwarze #include <string.h>
25fc61954aSschwarze 
26fc61954aSschwarze #include "dbm_map.h"
27fc61954aSschwarze #include "dbm.h"
28fc61954aSschwarze 
29fc61954aSschwarze int
main(int argc,char * argv[])30fc61954aSschwarze main(int argc, char *argv[])
31fc61954aSschwarze {
32fc61954aSschwarze 	const int32_t	*pp;  /* Page record in the pages table. */
33fc61954aSschwarze 	const char	*np;  /* Names of the page. */
34fc61954aSschwarze 	const char	*fp;  /* Primary filename of the page. */
35fc61954aSschwarze 	const char	*ep;  /* Filname extension including the dot. */
364b884190Sschwarze 	size_t		 flen, nlen;
37fc61954aSschwarze 	int32_t		 i, npages;
38fc61954aSschwarze 
39fc61954aSschwarze 	if (argc != 2)
40fc61954aSschwarze 		errx(1, "usage: mlinks filename");
41fc61954aSschwarze 
42fc61954aSschwarze 	if (dbm_open(argv[1]) == -1)
43fc61954aSschwarze 		err(1, "%s", argv[1]);
44fc61954aSschwarze 
45fc61954aSschwarze 	pp = dbm_getint(4);
46fc61954aSschwarze 	npages = be32toh(*pp++);
47fc61954aSschwarze 	if (npages <= 0)
48fc61954aSschwarze 		errx(1, "database empty or corrupt: %d pages", npages);
49fc61954aSschwarze 
50fc61954aSschwarze 	for (i = 0; i < npages; i++, pp += 5) {
51fc61954aSschwarze 		np = dbm_get(pp[0]);
52fc61954aSschwarze 		if (np == NULL)
53fc61954aSschwarze 			errx(1, "database corrupt: bad name pointer");
54fc61954aSschwarze 
55fc61954aSschwarze 		/* Skip files with just one name. */
56fc61954aSschwarze 		if (strchr(np, '\0')[1] == '\0')
57fc61954aSschwarze 			continue;
58fc61954aSschwarze 
59fc61954aSschwarze 		fp = dbm_get(pp[4]);
60fc61954aSschwarze 		if (fp == NULL)
61fc61954aSschwarze 			errx(1, "database corrupt: bad file pointer");
62fc61954aSschwarze 
63fc61954aSschwarze 		/* Skip the file type byte. */
64fc61954aSschwarze 		fp++;
65fc61954aSschwarze 
66fc61954aSschwarze 		/* Skip directory parts of filenames. */
67fc61954aSschwarze 		ep = strrchr(fp, '/');
68fc61954aSschwarze 		if (ep != NULL)
69fc61954aSschwarze 			fp = ep + 1;
70fc61954aSschwarze 
71fc61954aSschwarze 		ep = strrchr(fp, '.');
72fc61954aSschwarze 		if (ep == NULL)
73fc61954aSschwarze 			errx(1, "no filename extension: %s", fp);
74*4e948f3eSschwarze 		flen = ep - fp;
75fc61954aSschwarze 
76fc61954aSschwarze 		while (*np != '\0') {
77fc61954aSschwarze 
78fc61954aSschwarze 			/* Skip the name type byte. */
79fc61954aSschwarze 			np++;
80fc61954aSschwarze 
81fc61954aSschwarze 			/* Skip the primary filename. */
82fc61954aSschwarze 			nlen = strlen(np);
834b884190Sschwarze 			if (nlen == flen && strncmp(fp, np, nlen) == 0) {
84fc61954aSschwarze 				np = strchr(np, '\0') + 1;
85fc61954aSschwarze 				continue;
86fc61954aSschwarze 			}
87fc61954aSschwarze 
88fc61954aSschwarze 			/* Describe the desired mlink. */
89fc61954aSschwarze 			printf("%s,", fp);
90fc61954aSschwarze 			while (*np != '\0')
91fc61954aSschwarze 				putchar(*np++);
92fc61954aSschwarze 			np++;
93fc61954aSschwarze 			puts(ep);
94fc61954aSschwarze 		}
95fc61954aSschwarze 	}
96fc61954aSschwarze 	dbm_close();
97fc61954aSschwarze 	return 0;
98fc61954aSschwarze }
99