3 // Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; version 2 of the License.
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // You should have received a copy of the GNU General Public License
15 // along with this program; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 // version 0.0.7, 2003-11-21
19 // * made it compilable with non-C99 compilers
21 // version 0.0.6, 2003-11-21
22 // * added rpm-4.0.4 compatibility (define RPM404 macro)
24 // version 0.0.5, 2003-11-21
25 // * added '--uid' and '--gid' options
26 // * use macros for option-ids
28 // version 0.0.4, 2003-11-19
29 // * set 'force' flag on parseSpec() to ignore missing sources & patches
31 // version 0.0.3, 2003-11-19
32 // * fixed buffer-overflow in '--with[out]' statements
34 // version 0.0.2, 2003-11-19
35 // * big rewrite; implemented nearly the full functionality
37 // version 0.0.1, 2003-11-19
53 #include <sys/types.h>
64 #define ARG_WITHOUT 1025
65 #define ARG_DEFINE 1026
66 #define ARG_TARGET 1027
67 #define ARG_RCFILE 1028
68 #define ARG_CHROOT 1029
72 static struct option const
74 { "help", no_argument, 0, 'h' },
75 { "version", no_argument, 0, 'v' },
76 { "with", required_argument, 0, ARG_WITH },
77 { "without", required_argument, 0, ARG_WITHOUT },
78 { "define", required_argument, 0, ARG_DEFINE },
79 { "target", required_argument, 0, ARG_TARGET },
80 { "rcfile", required_argument, 0, ARG_RCFILE },
81 { "chroot", required_argument, 0, ARG_CHROOT },
82 { "uid", required_argument, 0, ARG_UID },
83 { "gid", required_argument, 0, ARG_GID },
101 char const * specfile;
105 int32_t const * flags;
107 char const ** version;
112 writeStr(int fd, char const *cmd)
114 (void)write(fd, cmd, strlen(cmd));
117 #define WRITE_MSG(FD,X) (void)(write(FD,X,sizeof(X)-1))
118 #define WRITE_STR(FD,X) writeStr(FD,X)
121 showHelp(int fd, char const *cmd, int res)
123 char tmp[strlen(cmd)+1];
126 WRITE_MSG(fd, "Usage: ");
127 WRITE_STR(fd, basename(tmp));
129 " [--define '<macro> <value>']* [--with[out] <key>]* [--chroot <dir>]\n"
130 " [--target <target>] [--rcfile <rcfile>] [--] <specfile>\n");
135 addDefine(struct Arguments *args, char const *val)
137 register size_t c = args->macros.cnt;
138 if (args->macros.reserved <= c) {
139 args->macros.reserved *= 2;
140 args->macros.reserved += 1;
142 args->macros.values = realloc(args->macros.values,
143 args->macros.reserved * sizeof(char const *));
144 if (args->macros.values==0) {
150 args->macros.values[c] = strdup(val);
155 setWithMacro(struct Arguments *args,
156 char const *name, char const *prefix, size_t prefix_len)
158 size_t len = strlen(name);
159 char tmp[2*len + 2*prefix_len + sizeof("__ ---")];
162 // set '_<prefix>_<name>'
164 memcpy(ptr, prefix, prefix_len); ptr += prefix_len;
166 memcpy(ptr, name, len); ptr += len;
169 // append ' --<prefix>-<name>'
172 memcpy(ptr, prefix, prefix_len); ptr += prefix_len;
174 memcpy(ptr, name, len); ptr += len;
177 addDefine(args, tmp);
182 parseArgs(struct Arguments *args, int argc, char *argv[])
185 int c = getopt_long(argc, argv, "", CMDLINE_OPTIONS, 0);
188 case 'h' : showHelp(1, argv[0], 0);
189 case ARG_TARGET : args->target = optarg; break;
190 case ARG_RCFILE : args->rcfile = optarg; break;
191 case ARG_CHROOT : args->chroot = optarg; break;
192 case ARG_UID : args->uid = atoi(optarg); break;
193 case ARG_GID : args->gid = atoi(optarg); break;
194 case ARG_DEFINE : addDefine(args, optarg); break;
195 case ARG_WITH : setWithMacro(args, optarg, "with", 4); break;
196 case ARG_WITHOUT : setWithMacro(args, optarg, "without", 7); break;
198 WRITE_MSG(2, "Try '");
199 WRITE_STR(2, argv[0]);
200 WRITE_MSG(2, " --help\" for more information.\n");
205 if (optind+1!=argc) {
206 write(2, "No/too much specfile(s) given; aborting\n", 40);
210 if (args->gid==(gid_t)(-1))
211 args->gid = args->uid;
213 args->specfile = argv[optind];
217 setMacros(char const * const *macros, size_t cnt)
220 for (i=0; i<cnt; ++i)
221 rpmDefineMacro(rpmGlobalMacroContext, macros[i], 0);
225 printDepSet(struct DepSet const *set, char const *prefix)
228 for (i=0; i<set->cnt; ++i)
229 printf("%s%08x %s %s\n", prefix, set->flags[i], set->name[i], set->version[i]);
233 evaluateHeader(Header h)
236 struct DepSet buildreqs = { 0,0,0,0 };
237 struct DepSet conflicts = { 0,0,0,0 };
239 if (headerGetEntry(h, RPMTAG_REQUIREFLAGS, 0, (void**)&buildreqs.flags, cnt+0) &&
240 headerGetEntry(h, RPMTAG_REQUIRENAME, 0, (void**)&buildreqs.name, cnt+1) &&
241 headerGetEntry(h, RPMTAG_REQUIREVERSION, 0, (void**)&buildreqs.version, cnt+2)) {
242 assert(cnt[0]==cnt[1] && cnt[1]==cnt[2]);
243 buildreqs.cnt = cnt[0];
246 if (headerGetEntry(h, RPMTAG_CONFLICTFLAGS, 0, (void**)&conflicts.flags, cnt+0) &&
247 headerGetEntry(h, RPMTAG_CONFLICTNAME, 0, (void**)&conflicts.name, cnt+1) &&
248 headerGetEntry(h, RPMTAG_CONFLICTVERSION, 0, (void**)&conflicts.version, cnt+2)) {
249 assert(cnt[0]==cnt[1] && cnt[1]==cnt[2]);
250 conflicts.cnt = cnt[0];
253 printDepSet(&buildreqs, "+ ");
254 printDepSet(&conflicts, "- ");
257 int main(int argc, char *argv[])
259 struct Arguments args = { 0,0,0,-1,-1, {0,0,0}, 0 };
262 parseArgs(&args, argc, argv);
264 if ((args.chroot && chroot(args.chroot)==-1) ||
265 (args.uid!=(uid_t)(-1) && (setgroups(0,0) ==-1 || getgroups(0,0)!=0)) ||
266 (args.gid!=(gid_t)(-1) && (setgid(args.gid)==-1 || getgid()!=args.gid)) ||
267 (args.uid!=(uid_t)(-1) && (setuid(args.uid)==-1 || getuid()!=args.uid))) {
268 perror("chroot/setuid/setgid()");
272 rpmReadConfigFiles(args.rcfile, args.target);
273 setMacros(args.macros.values, args.macros.cnt);
277 rpmts ts = rpmtsCreate();
278 if (parseSpec(ts, args.specfile, 0,0, 1, 0,0, 1,1)!=0) {
284 if (parseSpec(&s, args.specfile, 0,0, 1, 0,0, 1,1)!=0) {
289 evaluateHeader(s->buildRestrictions);
293 /// compile-command: "make getdeps LDFLAGS='-lrpm -lrpmbuild' CFLAGS='-I/usr/include/rpm -Wall -W -pedantic --std=c99 -g3 -O0'"
294 /// compile-commandX: "make getdeps LDFLAGS='-lrpm-4.0.4 -lrpmbuild-4.0.4 -lrpmio-4.0.4 -lrpmdb-4.0.4 -lpopt' CFLAGS='-I/usr/include/rpm-4.0.4 -Wall -W -pedantic --std=c99 -g3 -O0 -DRPM404'"