main.c revision 93520
1/*
2 *
3 * FreeBSD install - a package for the installation and maintainance
4 * of non-core utilities.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * Jordan K. Hubbard
16 * 18 July 1993
17 *
18 * This is the info module.
19 *
20 */
21
22#include <sys/cdefs.h>
23__FBSDID("$FreeBSD: head/usr.sbin/pkg_install/info/main.c 93520 2002-04-01 09:39:07Z obrien $");
24
25#include "lib.h"
26#include "info.h"
27#include <err.h>
28
29static char Options[] = "acdDe:fgGhiIkl:LmopqrRst:vVW:x";
30
31int	Flags		= 0;
32match_t	MatchType	= MATCH_GLOB;
33Boolean Quiet		= FALSE;
34char *InfoPrefix	= (char *)(uintptr_t)"";
35char PlayPen[FILENAME_MAX];
36char *CheckPkg		= NULL;
37struct which_head *whead;
38
39static void usage __P((void));
40
41int
42main(int argc, char **argv)
43{
44    int ch;
45    char **pkgs, **start;
46    char *pkgs_split;
47
48    whead = malloc(sizeof(struct which_head));
49    if (whead == NULL)
50	err(2, NULL);
51    TAILQ_INIT(whead);
52
53    pkgs = start = argv;
54    if (argc == 1) {
55	MatchType = MATCH_ALL;
56	Flags = SHOW_INDEX;
57    }
58    else while ((ch = getopt(argc, argv, Options)) != -1) {
59	switch(ch) {
60	case 'a':
61	    MatchType = MATCH_ALL;
62	    break;
63
64	case 'v':
65	    Verbose = TRUE;
66	    /* Reasonable definition of 'everything' */
67	    Flags = SHOW_COMMENT | SHOW_DESC | SHOW_PLIST | SHOW_INSTALL |
68		SHOW_DEINSTALL | SHOW_REQUIRE | SHOW_DISPLAY | SHOW_MTREE;
69	    break;
70
71	case 'I':
72	    Flags |= SHOW_INDEX;
73	    break;
74
75	case 'p':
76	    Flags |= SHOW_PREFIX;
77	    break;
78
79	case 'c':
80	    Flags |= SHOW_COMMENT;
81	    break;
82
83	case 'd':
84	    Flags |= SHOW_DESC;
85	    break;
86
87	case 'D':
88	    Flags |= SHOW_DISPLAY;
89	    break;
90
91	case 'f':
92	    Flags |= SHOW_PLIST;
93	    break;
94
95	case 'g':
96	    Flags |= SHOW_CKSUM;
97	    break;
98
99	case 'G':
100	    MatchType = MATCH_EXACT;
101	    break;
102
103	case 'i':
104	    Flags |= SHOW_INSTALL;
105	    break;
106
107	case 'k':
108	    Flags |= SHOW_DEINSTALL;
109	    break;
110
111	case 'r':
112	    Flags |= SHOW_REQUIRE;
113	    break;
114
115	case 'R':
116	    Flags |= SHOW_REQBY;
117	    break;
118
119	case 'L':
120	    Flags |= SHOW_FILES;
121	    break;
122
123	case 'm':
124	    Flags |= SHOW_MTREE;
125	    break;
126
127	case 's':
128	    Flags |= SHOW_SIZE;
129	    break;
130
131	case 'o':
132	    Flags |= SHOW_ORIGIN;
133	    break;
134
135	case 'V':
136	    Flags |= SHOW_FMTREV;
137	    break;
138
139	case 'l':
140	    InfoPrefix = optarg;
141	    break;
142
143	case 'q':
144	    Quiet = TRUE;
145	    break;
146
147	case 't':
148	    strlcpy(PlayPen, optarg, sizeof(PlayPen));
149	    break;
150
151	case 'x':
152	    MatchType = MATCH_REGEX;
153	    break;
154
155	case 'e':
156	    CheckPkg = optarg;
157	    break;
158
159	case 'W':
160	    {
161		struct which_entry *entp;
162
163		entp = calloc(1, sizeof(struct which_entry));
164		if (entp == NULL)
165		    err(2, NULL);
166
167		strlcpy(entp->file, optarg, PATH_MAX);
168		entp->skip = FALSE;
169		TAILQ_INSERT_TAIL(whead, entp, next);
170		break;
171	    }
172
173	case 'h':
174	case '?':
175	default:
176	    usage();
177	    break;
178	}
179    }
180
181    argc -= optind;
182    argv += optind;
183
184    /* Set some reasonable defaults */
185    if (!Flags)
186	Flags = SHOW_COMMENT | SHOW_DESC | SHOW_REQBY;
187
188    /* Get all the remaining package names, if any */
189    while (*argv) {
190	/* Don't try to apply heuristics if arguments are regexs */
191	if (MatchType != MATCH_REGEX)
192	    while ((pkgs_split = strrchr(*argv, (int)'/')) != NULL) {
193		*pkgs_split++ = '\0';
194		/*
195		 * If character after the '/' is alphanumeric or shell
196		 * metachar, then we've found the package name.  Otherwise
197		 * we've come across a trailing '/' and need to continue our
198		 * quest.
199		 */
200		if (isalpha(*pkgs_split) || ((MatchType == MATCH_GLOB) && \
201		    strpbrk(pkgs_split, "*?[]") != NULL)) {
202		    *argv = pkgs_split;
203		    break;
204		}
205	    }
206	*pkgs++ = *argv++;
207    }
208
209    /* If no packages, yelp */
210    if (pkgs == start && MatchType != MATCH_ALL && !CheckPkg &&
211	TAILQ_EMPTY(whead))
212	warnx("missing package name(s)"), usage();
213    *pkgs = NULL;
214    return pkg_perform(start);
215}
216
217static void
218usage()
219{
220    fprintf(stderr, "%s\n%s\n%s\n",
221	"usage: pkg_info [-cdDfGiIkLmopqrRsvVx] [-e package] [-l prefix]",
222	"                [-t template] [-W filename] [pkg-name ...]",
223	"       pkg_info -a [flags]");
224    exit(1);
225}
226