1327Sjkh/*
2327Sjkh *
3228990Suqs * FreeBSD install - a package for the installation and maintenance
4327Sjkh * of non-core utilities.
5327Sjkh *
6327Sjkh * Redistribution and use in source and binary forms, with or without
7327Sjkh * modification, are permitted provided that the following conditions
8327Sjkh * are met:
9327Sjkh * 1. Redistributions of source code must retain the above copyright
10327Sjkh *    notice, this list of conditions and the following disclaimer.
11327Sjkh * 2. Redistributions in binary form must reproduce the above copyright
12327Sjkh *    notice, this list of conditions and the following disclaimer in the
13327Sjkh *    documentation and/or other materials provided with the distribution.
14327Sjkh *
15327Sjkh * Jordan K. Hubbard
16327Sjkh * 18 July 1993
17327Sjkh *
1831997Shoek * This is the info module.
19327Sjkh *
20327Sjkh */
21327Sjkh
2293520Sobrien#include <sys/cdefs.h>
2393520Sobrien__FBSDID("$FreeBSD: releng/10.3/usr.sbin/pkg_install/info/main.c 241830 2012-10-22 02:12:20Z eadler $");
2493520Sobrien
25179433Sflz#include <getopt.h>
26179433Sflz#include <err.h>
27179433Sflz
28222035Sflz#include "lib.h"
29327Sjkh#include "info.h"
30327Sjkh
31327Sjkhint	Flags		= 0;
3272174Ssobomaxmatch_t	MatchType	= MATCH_GLOB;
33112572SmdoddBoolean QUIET		= FALSE;
34112579SmdoddBoolean UseBlkSz	= FALSE;
3584745Ssobomaxchar *InfoPrefix	= (char *)(uintptr_t)"";
3611780Sjkhchar PlayPen[FILENAME_MAX];
37392Sjkhchar *CheckPkg		= NULL;
3896030Ssobomaxchar *LookUpOrigin	= NULL;
39154145SflzBoolean KeepPackage	= FALSE;
4074699Ssobomaxstruct which_head *whead;
41327Sjkh
42173412Skevlostatic void usage(void);
4330221Scharnier
44179433Sflzstatic char opts[] = "abcdDe:EfgGhiIjkKl:LmoO:pPqQrRst:vVW:xX";
45179433Sflzstatic struct option longopts[] = {
46179433Sflz	{ "all",	no_argument,		NULL,		'a' },
47179433Sflz	{ "blocksize",	no_argument,		NULL,		'b' },
48179433Sflz	{ "exist",	required_argument,	NULL,		'X' },
49179433Sflz	{ "exists",	required_argument,	NULL,		'X' },
50179433Sflz	{ "extended",	no_argument,		NULL,		'e' },
51179433Sflz	{ "help",	no_argument,		NULL,		'h' },
52179433Sflz	{ "keep",	no_argument,		NULL,		'K' },
53179433Sflz	{ "no-glob",	no_argument,		NULL,		'G' },
54179433Sflz	{ "origin",	required_argument,	NULL,		'O' },
55179433Sflz	{ "quiet",	no_argument,		NULL,		'q' },
56179433Sflz	{ "regex",	no_argument,		NULL,		'x' },
57179433Sflz	{ "template",	required_argument,	NULL,		't' },
58179433Sflz	{ "verbose",	no_argument,		NULL,		'v' },
59179433Sflz	{ "version",	no_argument,		NULL,		'P' },
60179433Sflz	{ "which",	required_argument,	NULL,		'W' },
61193273Sjilles	{ NULL,		0,			NULL,		0 }
62179433Sflz};
63179433Sflz
64327Sjkhint
65327Sjkhmain(int argc, char **argv)
66327Sjkh{
67327Sjkh    int ch;
68327Sjkh    char **pkgs, **start;
6956001Sdan    char *pkgs_split;
70327Sjkh
71241830Seadler    warnpkgng();
7274699Ssobomax    whead = malloc(sizeof(struct which_head));
7374699Ssobomax    if (whead == NULL)
7474699Ssobomax	err(2, NULL);
7574699Ssobomax    TAILQ_INIT(whead);
7674699Ssobomax
77327Sjkh    pkgs = start = argv;
7846105Sjkh    if (argc == 1) {
7972174Ssobomax	MatchType = MATCH_ALL;
8046105Sjkh	Flags = SHOW_INDEX;
8146105Sjkh    }
82179433Sflz    else while ((ch = getopt_long(argc, argv, opts, longopts, NULL)) != -1) {
83327Sjkh	switch(ch) {
84327Sjkh	case 'a':
8572174Ssobomax	    MatchType = MATCH_ALL;
86327Sjkh	    break;
87327Sjkh
88112579Smdodd	case 'b':
89112579Smdodd	    UseBlkSz = TRUE;
90112579Smdodd	    break;
91112579Smdodd
92327Sjkh	case 'v':
93159554Sobrien	    Verbose++;
94327Sjkh	    /* Reasonable definition of 'everything' */
95327Sjkh	    Flags = SHOW_COMMENT | SHOW_DESC | SHOW_PLIST | SHOW_INSTALL |
964996Sjkh		SHOW_DEINSTALL | SHOW_REQUIRE | SHOW_DISPLAY | SHOW_MTREE;
97327Sjkh	    break;
98327Sjkh
99131275Seik	case 'E':
100131275Seik	    Flags |= SHOW_PKGNAME;
101131275Seik	    break;
102131275Seik
103327Sjkh	case 'I':
104327Sjkh	    Flags |= SHOW_INDEX;
105327Sjkh	    break;
106327Sjkh
107327Sjkh	case 'p':
108327Sjkh	    Flags |= SHOW_PREFIX;
109327Sjkh	    break;
110327Sjkh
111327Sjkh	case 'c':
112327Sjkh	    Flags |= SHOW_COMMENT;
113327Sjkh	    break;
114327Sjkh
115327Sjkh	case 'd':
116327Sjkh	    Flags |= SHOW_DESC;
117327Sjkh	    break;
118327Sjkh
1194996Sjkh	case 'D':
1204996Sjkh	    Flags |= SHOW_DISPLAY;
1214996Sjkh	    break;
1224996Sjkh
123327Sjkh	case 'f':
124327Sjkh	    Flags |= SHOW_PLIST;
125327Sjkh	    break;
126327Sjkh
12771965Sjkh	case 'g':
12871965Sjkh	    Flags |= SHOW_CKSUM;
12971965Sjkh	    break;
13071965Sjkh
13172174Ssobomax	case 'G':
13272174Ssobomax	    MatchType = MATCH_EXACT;
13372174Ssobomax	    break;
13472174Ssobomax
135327Sjkh	case 'i':
136327Sjkh	    Flags |= SHOW_INSTALL;
137327Sjkh	    break;
138327Sjkh
139131280Seik	case 'j':
140131280Seik	    Flags |= SHOW_REQUIRE;
141131280Seik	    break;
142131280Seik
143327Sjkh	case 'k':
144327Sjkh	    Flags |= SHOW_DEINSTALL;
145327Sjkh	    break;
146327Sjkh
147154145Sflz	case 'K':
148154145Sflz	    KeepPackage = TRUE;
149154145Sflz	    break;
150154145Sflz
151327Sjkh	case 'r':
152131280Seik	    Flags |= SHOW_DEPEND;
153327Sjkh	    break;
154327Sjkh
1554996Sjkh	case 'R':
1564996Sjkh	    Flags |= SHOW_REQBY;
1574996Sjkh	    break;
1584996Sjkh
159411Sjkh	case 'L':
160411Sjkh	    Flags |= SHOW_FILES;
161411Sjkh	    break;
162411Sjkh
1634996Sjkh	case 'm':
1644996Sjkh	    Flags |= SHOW_MTREE;
1654996Sjkh	    break;
1664996Sjkh
16772174Ssobomax	case 's':
16872174Ssobomax	    Flags |= SHOW_SIZE;
16972174Ssobomax	    break;
17062775Ssobomax
17167454Ssobomax	case 'o':
17267454Ssobomax	    Flags |= SHOW_ORIGIN;
17367454Ssobomax	    break;
17467454Ssobomax
17596030Ssobomax	case 'O':
17696030Ssobomax	    LookUpOrigin = strdup(optarg);
17796030Ssobomax	    if (LookUpOrigin == NULL)
17896030Ssobomax		err(2, NULL);
17996030Ssobomax	    break;
18096030Ssobomax
18184750Ssobomax	case 'V':
18284750Ssobomax	    Flags |= SHOW_FMTREV;
18384750Ssobomax	    break;
18484750Ssobomax
185379Sjkh	case 'l':
186379Sjkh	    InfoPrefix = optarg;
187379Sjkh	    break;
188379Sjkh
189411Sjkh	case 'q':
190411Sjkh	    Quiet = TRUE;
191411Sjkh	    break;
192411Sjkh
193112572Smdodd	case 'Q':
194112572Smdodd	    Quiet = TRUE;
195112572Smdodd	    QUIET = TRUE;
196112572Smdodd	    break;
197112572Smdodd
198383Sjkh	case 't':
19985019Ssobomax	    strlcpy(PlayPen, optarg, sizeof(PlayPen));
200383Sjkh	    break;
201383Sjkh
20272174Ssobomax	case 'x':
20372174Ssobomax	    MatchType = MATCH_REGEX;
20472174Ssobomax	    break;
20572174Ssobomax
206131275Seik	case 'X':
207131275Seik	    MatchType = MATCH_EREGEX;
208131275Seik	    break;
209131275Seik
210392Sjkh	case 'e':
211392Sjkh	    CheckPkg = optarg;
212392Sjkh	    break;
213392Sjkh
21474699Ssobomax	case 'W':
21574699Ssobomax	    {
21674699Ssobomax		struct which_entry *entp;
21774699Ssobomax
21874699Ssobomax		entp = calloc(1, sizeof(struct which_entry));
21974699Ssobomax		if (entp == NULL)
22074699Ssobomax		    err(2, NULL);
22174699Ssobomax
22274699Ssobomax		strlcpy(entp->file, optarg, PATH_MAX);
22374699Ssobomax		entp->skip = FALSE;
22474699Ssobomax		TAILQ_INSERT_TAIL(whead, entp, next);
22574699Ssobomax		break;
22674699Ssobomax	    }
22774699Ssobomax
228103149Ssobomax	case 'P':
229222035Sflz	    Flags = SHOW_PTREV;
230103149Ssobomax	    break;
231103149Ssobomax
232327Sjkh	case 'h':
233327Sjkh	default:
23430221Scharnier	    usage();
235327Sjkh	    break;
236327Sjkh	}
23746105Sjkh    }
238327Sjkh
2398857Srgrimes    argc -= optind;
240327Sjkh    argv += optind;
241327Sjkh
242103149Ssobomax    if (Flags & SHOW_PTREV) {
243103149Ssobomax	if (!Quiet)
244103149Ssobomax	    printf("Package tools revision: ");
245103149Ssobomax	printf("%d\n", PKG_INSTALL_VERSION);
246103149Ssobomax	exit(0);
247103149Ssobomax    }
248103149Ssobomax
249327Sjkh    /* Set some reasonable defaults */
250327Sjkh    if (!Flags)
2514996Sjkh	Flags = SHOW_COMMENT | SHOW_DESC | SHOW_REQBY;
252327Sjkh
253327Sjkh    /* Get all the remaining package names, if any */
25460563Ssteve    while (*argv) {
25595934Ssobomax	/*
25695934Ssobomax	 * Don't try to apply heuristics if arguments are regexs or if
25795934Ssobomax	 * the argument refers to an existing file.
25895934Ssobomax	 */
259178246Sflz	if (MatchType != MATCH_REGEX && MatchType != MATCH_EREGEX && !isfile(*argv) && !isURL(*argv))
26072174Ssobomax	    while ((pkgs_split = strrchr(*argv, (int)'/')) != NULL) {
26172174Ssobomax		*pkgs_split++ = '\0';
26272174Ssobomax		/*
26372174Ssobomax		 * If character after the '/' is alphanumeric or shell
26472174Ssobomax		 * metachar, then we've found the package name.  Otherwise
26572174Ssobomax		 * we've come across a trailing '/' and need to continue our
26672174Ssobomax		 * quest.
26772174Ssobomax		 */
268151188Skrion		if (isalnum(*pkgs_split) || ((MatchType == MATCH_GLOB) && \
26972174Ssobomax		    strpbrk(pkgs_split, "*?[]") != NULL)) {
27072174Ssobomax		    *argv = pkgs_split;
27172174Ssobomax		    break;
27272174Ssobomax		}
27360563Ssteve	    }
27460563Ssteve	*pkgs++ = *argv++;
27556001Sdan    }
276327Sjkh
277327Sjkh    /* If no packages, yelp */
27874699Ssobomax    if (pkgs == start && MatchType != MATCH_ALL && !CheckPkg &&
27996030Ssobomax	TAILQ_EMPTY(whead) && LookUpOrigin == NULL)
28030221Scharnier	warnx("missing package name(s)"), usage();
281327Sjkh    *pkgs = NULL;
282327Sjkh    return pkg_perform(start);
283327Sjkh}
284327Sjkh
28530221Scharnierstatic void
286201226Sedusage(void)
287327Sjkh{
28896067Ssobomax    fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n",
289154145Sflz	"usage: pkg_info [-bcdDEfgGiIjkKLmopPqQrRsvVxX] [-e package] [-l prefix]",
290127641Scperciva	"                [-t template] -a | pkg-name ...",
291127641Scperciva	"       pkg_info [-qQ] -W filename",
292127641Scperciva	"       pkg_info [-qQ] -O origin",
293127641Scperciva	"       pkg_info");
294327Sjkh    exit(1);
295327Sjkh}
296