xref: /haiku/src/bin/package/command_info.cpp (revision e81a954787e50e56a7f06f72705b7859b6ab06d1)
1 /*
2  * Copyright 2013, Ingo Weinhold, ingo_weinhold@gmx.de.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 
7 #include <getopt.h>
8 #include <stdio.h>
9 #include <string.h>
10 
11 #include <Entry.h>
12 #include <package/PackageInfo.h>
13 
14 #include "package.h"
15 
16 
17 using namespace BPackageKit;
18 
19 
20 int
21 command_info(int argc, const char* const* argv)
22 {
23 	const char* format = "name: %name%  version: %version%\n";
24 
25 	while (true) {
26 		static struct option sLongOptions[] = {
27 			{ "format", required_argument, 0, 'f' },
28 			{ "help", no_argument, 0, 'h' },
29 			{ 0, 0, 0, 0 }
30 		};
31 
32 		opterr = 0; // don't print errors
33 		int c = getopt_long(argc, (char**)argv, "f:h", sLongOptions, NULL);
34 		if (c == -1)
35 			break;
36 
37 		switch (c) {
38 			case 'f':
39 				format = optarg;
40 				break;
41 
42 			default:
43 				print_usage_and_exit(true);
44 				break;
45 		}
46 	}
47 
48 	// One argument should remain -- the package file name.
49 	if (optind + 1 != argc)
50 		print_usage_and_exit(true);
51 
52 	const char* fileName = argv[optind++];
53 
54 	// Read the package info from the package file. If it doesn't look like a
55 	// package file, assume it is a package info file.
56 	BPackageInfo info;
57 	if (BString(fileName).EndsWith(".hpkg")) {
58 		status_t error = info.ReadFromPackageFile(fileName);
59 		if (error != B_OK) {
60 			fprintf(stderr, "Error: Failed to read package file \"%s\": %s\n",
61 				fileName, strerror(error));
62 			return 1;
63 		}
64 	} else {
65 		status_t error = info.ReadFromConfigFile(BEntry(fileName));
66 		if (error != B_OK) {
67 			fprintf(stderr, "Error: Failed to read package info file \"%s\": "
68 				"%s\n", fileName, strerror(error));
69 			return 1;
70 		}
71 	}
72 
73 	// parse format string and produce output
74 	BString output;
75 	while (*format != '\0') {
76 		char c = *format++;
77 		switch (c) {
78 			case '%':
79 			{
80 				const char* start = format;
81 				while (*format != '\0' && *format != '%')
82 					format++;
83 				if (*format != '%') {
84 					fprintf(stderr, "Error: Unexpected at end of the format "
85 						"string. Expected \"%%\".\n");
86 					return 1;
87 				}
88 
89 				if (format == start) {
90 					output << '%';
91 				} else {
92 					BString variable(start, format - start);
93 					if (variable == "fileName") {
94 						output << info.CanonicalFileName();
95 					} else if (variable == "name") {
96 						output << info.Name();
97 					} else if (variable == "version") {
98 						output << info.Version().ToString();
99 					} else {
100 						fprintf(stderr, "Error: Unsupported placeholder \"%s\" "
101 							"in format string.\n", variable.String());
102 						return 1;
103 					}
104 				}
105 
106 				format++;
107 				break;
108 			}
109 
110 			case '\\':
111 				c = *format++;
112 				if (c == '\0') {
113 					fprintf(stderr, "Error: \"\\\" at the end of the format "
114 						"string.\n");
115 					return 1;
116 				}
117 				switch (c) {
118 					case 'n':
119 						c = '\n';
120 						break;
121 					case 't':
122 						c = '\t';
123 						break;
124 				}
125 				// fall through
126 
127 			default:
128 				output << c;
129 				break;
130 		}
131 	}
132 
133 	fputs(output.String(), stdout);
134 
135 	return 0;
136 }
137