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
24 #include <iostream>
25 #include <fstream>
26
27 memcached_return_t memcat(const client_options &opt, memcached_st *memc, const char *key, std::ostream &ref) {
28 memcached_return_t rc;
29 uint32_t flags;
30 size_t len;
31 auto val = memcached_get(memc, key, strlen(key), &len, &flags, &rc);
32
33 if (MEMCACHED_SUCCESS == rc) {
34 if (opt.isset("verbose")) {
35 ref << "key: " << key << "\n";
36 }
37 if (opt.isset("flags")) {
38 ref << "flags: " << flags << "\n";
39 }
40 if (opt.isset("verbose")) {
41 ref << "value: ";
42 }
43 ref.write(val, len);
44 ref << std::endl;
45 }
46
47 if (val) {
48 free(val);
49 }
50 return rc;
51 }
52
53 int main(int argc, char *argv[]) {
54 char **argp = nullptr;
55 memcached_st memc;
56 client_options opt{PROGRAM_NAME, PROGRAM_VERSION, PROGRAM_DESCRIPTION, "key [ key ... ]"};
57
58 for (const auto &def : opt.defaults) {
59 opt.add(def);
60 }
61 opt.add("flags", 'F', no_argument, "Display key flags, too.");
62 opt.add("file", 'f', required_argument, "Output to file instead of standard output.");
63
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 if (!memcached_create(&memc)) {
74 if (!opt.isset("quiet")) {
75 std::cerr << "Failed to initialize memcached client.\n";
76 }
77 exit(EXIT_FAILURE);
78 }
79
80 if (!opt.apply(&memc)) {
81 memcached_free(&memc);
82 exit(EXIT_FAILURE);
83 }
84
85 if (!*argp) {
86 if (!opt.isset("quiet")) {
87 std::cerr << "No key(s) provided.\n";
88 }
89 memcached_free(&memc);
90 exit(EXIT_FAILURE);
91 }
92
93 auto exit_code = EXIT_SUCCESS;
94 for (auto arg = argp; *arg; ++arg) {
95 auto key = *arg;
96 if (*key) {
97 memcached_return_t rc;
98 auto file = opt.argof("file");
99 if (file && *file) {
100 std::ofstream stream{file, std::ios::binary};
101 rc = memcat(opt, &memc, key, stream);
102 } else {
103 rc = memcat(opt, &memc, key, std::cout);
104 }
105 if (MEMCACHED_SUCCESS != rc) {
106 exit_code = EXIT_FAILURE;
107
108 if (MEMCACHED_NOTFOUND == rc) {
109 if (opt.isset("verbose")) {
110 std::cerr << "not found: " << key << "\n";
111 }
112 // continue;
113 } else {
114 if (!opt.isset("quiet")) {
115 std::cerr << memcached_last_error_message(&memc) << "\n";
116 }
117 break;
118 }
119 }
120 }
121 }
122
123 memcached_free(&memc);
124 exit(exit_code);
125 }