Initial import from FreeBSD RELENG_4:
[dragonfly.git] / usr.sbin / pkg_install / info / main.c
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: src/usr.sbin/pkg_install/info/main.c,v 1.22.2.14 2002/08/20 06:35:08 obrien Exp $");
24
25 #include "lib.h"
26 #include "info.h"
27 #include <err.h>
28
29 static char Options[] = "acdDe:fgGhiIkl:LmoO:pqrRst:vVW:x";
30
31 int     Flags           = 0;
32 match_t MatchType       = MATCH_GLOB;
33 Boolean Quiet           = FALSE;
34 char *InfoPrefix        = (char *)(uintptr_t)"";
35 char PlayPen[FILENAME_MAX];
36 char *CheckPkg          = NULL;
37 char *LookUpOrigin      = NULL;
38 struct which_head *whead;
39
40 static void usage __P((void));
41
42 int
43 main(int argc, char **argv)
44 {
45     int ch;
46     char **pkgs, **start;
47     char *pkgs_split;
48
49     whead = malloc(sizeof(struct which_head));
50     if (whead == NULL)
51         err(2, NULL);
52     TAILQ_INIT(whead);
53
54     pkgs = start = argv;
55     if (argc == 1) {
56         MatchType = MATCH_ALL;
57         Flags = SHOW_INDEX;
58     }
59     else while ((ch = getopt(argc, argv, Options)) != -1) {
60         switch(ch) {
61         case 'a':
62             MatchType = MATCH_ALL;
63             break;
64
65         case 'v':
66             Verbose = TRUE;
67             /* Reasonable definition of 'everything' */
68             Flags = SHOW_COMMENT | SHOW_DESC | SHOW_PLIST | SHOW_INSTALL |
69                 SHOW_DEINSTALL | SHOW_REQUIRE | SHOW_DISPLAY | SHOW_MTREE;
70             break;
71
72         case 'I':
73             Flags |= SHOW_INDEX;
74             break;
75
76         case 'p':
77             Flags |= SHOW_PREFIX;
78             break;
79
80         case 'c':
81             Flags |= SHOW_COMMENT;
82             break;
83
84         case 'd':
85             Flags |= SHOW_DESC;
86             break;
87
88         case 'D':
89             Flags |= SHOW_DISPLAY;
90             break;
91
92         case 'f':
93             Flags |= SHOW_PLIST;
94             break;
95
96         case 'g':
97             Flags |= SHOW_CKSUM;
98             break;
99
100         case 'G':
101             MatchType = MATCH_EXACT;
102             break;
103
104         case 'i':
105             Flags |= SHOW_INSTALL;
106             break;
107
108         case 'k':
109             Flags |= SHOW_DEINSTALL;
110             break;
111
112         case 'r':
113             Flags |= SHOW_REQUIRE;
114             break;
115
116         case 'R':
117             Flags |= SHOW_REQBY;
118             break;
119
120         case 'L':
121             Flags |= SHOW_FILES;
122             break;
123
124         case 'm':
125             Flags |= SHOW_MTREE;
126             break;
127
128         case 's':
129             Flags |= SHOW_SIZE;
130             break;
131
132         case 'o':
133             Flags |= SHOW_ORIGIN;
134             break;
135
136         case 'O':
137             LookUpOrigin = strdup(optarg);
138             if (LookUpOrigin == NULL)
139                 err(2, NULL);
140             break;
141
142         case 'V':
143             Flags |= SHOW_FMTREV;
144             break;
145
146         case 'l':
147             InfoPrefix = optarg;
148             break;
149
150         case 'q':
151             Quiet = TRUE;
152             break;
153
154         case 't':
155             strlcpy(PlayPen, optarg, sizeof(PlayPen));
156             break;
157
158         case 'x':
159             MatchType = MATCH_REGEX;
160             break;
161
162         case 'e':
163             CheckPkg = optarg;
164             break;
165
166         case 'W':
167             {
168                 struct which_entry *entp;
169
170                 entp = calloc(1, sizeof(struct which_entry));
171                 if (entp == NULL)
172                     err(2, NULL);
173                 
174                 strlcpy(entp->file, optarg, PATH_MAX);
175                 entp->skip = FALSE;
176                 TAILQ_INSERT_TAIL(whead, entp, next);
177                 break;
178             }
179
180         case 'h':
181         case '?':
182         default:
183             usage();
184             break;
185         }
186     }
187
188     argc -= optind;
189     argv += optind;
190
191     /* Set some reasonable defaults */
192     if (!Flags)
193         Flags = SHOW_COMMENT | SHOW_DESC | SHOW_REQBY;
194
195     /* Get all the remaining package names, if any */
196     while (*argv) {
197         /* 
198          * Don't try to apply heuristics if arguments are regexs or if
199          * the argument refers to an existing file.
200          */
201         if (MatchType != MATCH_REGEX && !isfile(*argv))
202             while ((pkgs_split = strrchr(*argv, (int)'/')) != NULL) {
203                 *pkgs_split++ = '\0';
204                 /*
205                  * If character after the '/' is alphanumeric or shell
206                  * metachar, then we've found the package name.  Otherwise
207                  * we've come across a trailing '/' and need to continue our
208                  * quest.
209                  */
210                 if (isalpha(*pkgs_split) || ((MatchType == MATCH_GLOB) && \
211                     strpbrk(pkgs_split, "*?[]") != NULL)) {
212                     *argv = pkgs_split;
213                     break;
214                 }
215             }
216         *pkgs++ = *argv++;
217     }
218
219     /* If no packages, yelp */
220     if (pkgs == start && MatchType != MATCH_ALL && !CheckPkg && 
221         TAILQ_EMPTY(whead) && LookUpOrigin == NULL)
222         warnx("missing package name(s)"), usage();
223     *pkgs = NULL;
224     return pkg_perform(start);
225 }
226
227 static void
228 usage()
229 {
230     fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n",
231         "usage: pkg_info [-cdDfGiIkLmopqrRsvVx] [-e package] [-l prefix]",
232         "                [-t template] [pkg-name ...]",
233         "       pkg_info [-q] -W filename",
234         "       pkg_info [-q] -O origin",
235         "       pkg_info -a [flags]");
236     exit(1);
237 }