bin: consolidate clients
[awesomized/libmemcached] / src / bin / memcat.cc
1 /*
2 +--------------------------------------------------------------------+
3 | libmemcached - C/C++ Client Library for memcached |
4 +--------------------------------------------------------------------+
5 | Redistribution and use in source and binary forms, with or without |
6 | modification, are permitted under the terms of the BSD license. |
7 | You should have received a copy of the license in a bundled file |
8 | named LICENSE; in case you did not receive a copy you can review |
9 | the terms online at: https://opensource.org/licenses/BSD-3-Clause |
10 +--------------------------------------------------------------------+
11 | Copyright (c) 2006-2014 Brian Aker https://datadifferential.com/ |
12 | Copyright (c) 2020 Michael Wallner <mike@php.net> |
13 +--------------------------------------------------------------------+
14 */
15
16 #include "mem_config.h"
17
18 #define PROGRAM_NAME "memcat"
19 #define PROGRAM_DESCRIPTION "Cat a set of key values to stdout."
20 #define PROGRAM_VERSION "1.1"
21
22 #include "common/options.hpp"
23 #include "common/checks.hpp"
24
25 #include <iostream>
26 #include <fstream>
27
28 memcached_return_t memcat(const client_options &opt, memcached_st *memc, const char *key, std::ostream *ref) {
29 memcached_return_t rc;
30 uint32_t flags;
31 size_t len;
32 auto val = memcached_get(memc, key, strlen(key), &len, &flags, &rc);
33 auto verbose = opt.isset("verbose");
34
35 if (MEMCACHED_SUCCESS == rc) {
36 if (verbose) {
37 *ref << "key: " << key << "\n";
38 }
39 if (opt.isset("flags")) {
40 *ref << "flags: " << flags << "\n";
41 }
42 if (verbose) {
43 *ref << "value: ";
44 }
45 ref->write(val, len) << std::endl;
46 }
47
48 if (val) {
49 free(val);
50 }
51 return rc;
52 }
53
54 int main(int argc, char *argv[]) {
55 client_options opt{PROGRAM_NAME, PROGRAM_VERSION, PROGRAM_DESCRIPTION, "key [ key ... ]"};
56
57 for (const auto &def : opt.defaults) {
58 opt.add(def);
59 }
60 opt.add("flags", 'F', no_argument, "Display key flags, too.");
61 opt.add("file", 'f', required_argument, "Output to file instead of standard output.");
62
63 char **argp = nullptr;
64 if (!opt.parse(argc, argv, &argp)) {
65 exit(EXIT_FAILURE);
66 }
67
68 if (opt.isset("quiet") && !opt.isset("file")) {
69 std::cerr << "--quiet operation was requested, but --file was not set.\n";
70 exit(EXIT_FAILURE);
71 }
72
73 memcached_st memc;
74 if (!check_memcached(opt, memc)) {
75 exit(EXIT_FAILURE);
76 }
77
78 if (!opt.apply(&memc)) {
79 memcached_free(&memc);
80 exit(EXIT_FAILURE);
81 }
82
83 if (!check_argp(opt, argp, "No key(s) provided.")) {
84 memcached_free(&memc);
85 exit(EXIT_FAILURE);
86 }
87
88 auto exit_code = EXIT_SUCCESS;
89 for (auto arg = argp; *arg; ++arg) {
90 auto key = *arg;
91 if (*key) {
92
93 std::ofstream fstream{};
94 std::ostream *ostream = check_ostream(opt, opt.argof("file"), fstream);
95
96 auto file = opt.argof("file");
97 if (file && *file) {
98 fstream.open(file, std::ios::binary | std::ios::out);
99 if (!fstream.is_open()) {
100 exit_code = EXIT_FAILURE;
101 if (!opt.isset("quiet")) {
102 std::cerr << "Failed to open " << file << " for writing.\n";
103 }
104 continue;
105 }
106 ostream = &fstream;
107 }
108
109 if (!check_return(opt, memc, key, memcat(opt, &memc, key, ostream))) {
110 exit_code = EXIT_FAILURE;
111 }
112 }
113 }
114
115 memcached_free(&memc);
116 exit(exit_code);
117 }