aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcello Stanisci <marcello.stanisci@inria.fr>2015-07-31 18:41:56 +0200
committerMarcello Stanisci <marcello.stanisci@inria.fr>2015-07-31 18:41:56 +0200
commit4e8112a444a4b93efe8f439a40d1f78faea49d2f (patch)
tree1d2cf7f6b99b2f6fd1a942927ccfcd7c381b5db5
parent403e50afd96f2f3caf84c6d2c55ce4adcf026313 (diff)
downloadmerchant-4e8112a444a4b93efe8f439a40d1f78faea49d2f.tar.gz
merchant-4e8112a444a4b93efe8f439a40d1f78faea49d2f.zip
merchant DB initializable
-rw-r--r--src/backend/Makefile.am14
-rw-r--r--src/backend/merchant_db.c348
-rw-r--r--src/backend/merchant_db.h98
-rwxr-xr-xsrc/backend/taler-merchant-dbinitbin0 -> 35040 bytes
-rw-r--r--src/backend/taler-merchant-dbinit.c79
-rw-r--r--src/backend/taler-merchant-httpd.c83
6 files changed, 611 insertions, 11 deletions
diff --git a/src/backend/Makefile.am b/src/backend/Makefile.am
index d16859a7..f7afde8e 100644
--- a/src/backend/Makefile.am
+++ b/src/backend/Makefile.am
@@ -2,11 +2,23 @@ AM_CPPFLAGS = -I$(top_srcdir)/src/include $(POSTGRESQL_CPPFLAGS)
2 2
3MERCHANT_DB = merchant_db.c merchant_db.h 3MERCHANT_DB = merchant_db.c merchant_db.h
4bin_PROGRAMS = \ 4bin_PROGRAMS = \
5 taler-merchant-httpd 5 taler-merchant-httpd \
6 taler-merchant-dbinit
6 7
7taler_merchant_httpd_SOURCES = \ 8taler_merchant_httpd_SOURCES = \
8 taler-merchant-httpd.c 9 taler-merchant-httpd.c
9 10
11taler_merchant_dbinit_SOURCES = \
12 taler-merchant-dbinit.c \
13 $(MERCHANT_DB)
14
10taler_merchant_httpd_LDADD = \ 15taler_merchant_httpd_LDADD = \
11 -lmicrohttpd \ 16 -lmicrohttpd \
12 -lgnunetutil 17 -lgnunetutil
18
19
20taler_merchant_dbinit_LDADD = \
21 -ltalerpq \
22 -lgnunetutil \
23 -lgnunetpostgres \
24 -lpq
diff --git a/src/backend/merchant_db.c b/src/backend/merchant_db.c
new file mode 100644
index 00000000..66ab5bcf
--- /dev/null
+++ b/src/backend/merchant_db.c
@@ -0,0 +1,348 @@
1/*
2 This file is part of TALER
3 (C) 2014 Christian Grothoff (and other contributing authors)
4
5 TALER is free software; you can redistribute it and/or modify it under the
6 terms of the GNU General Public License as published by the Free Software
7 Foundation; either version 3, or (at your option) any later version.
8
9 TALER is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License along with
14 TALER; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/>
15*/
16
17/**
18 * @file merchant/merchant_db.c
19 * @brief database helper functions used by the merchant
20 * @author Sree Harsha Totakura <sreeharsha@totakura.in>
21 */
22
23#include "platform.h"
24#include <gnunet/gnunet_util_lib.h>
25#include <taler/taler_util.h>
26#include <taler/taler_pq_lib.h>
27#include "merchant_db.h"
28
29
30#define PQSQL_strerror(kind, cmd, res) \
31 GNUNET_log_from (kind, "merchant-db", \
32 "SQL %s failed at %s:%u with error: %s", \
33 cmd, __FILE__, __LINE__, PQresultErrorMessage (res));
34
35/**
36 * Shorthand for exit jumps.
37 */
38#define EXITIF(cond) \
39 do { \
40 if (cond) { GNUNET_break (0); goto EXITIF_exit; } \
41 } while (0)
42
43
44/**
45 * Connect to postgresql database
46 *
47 * @param cfg the configuration handle
48 * @return connection to the postgresql database; NULL upon error
49 */
50PGconn *
51MERCHANT_DB_connect (const struct GNUNET_CONFIGURATION_Handle *cfg)
52{
53 return GNUNET_POSTGRES_connect (cfg, "merchant-db");
54}
55
56
57/**
58 * Disconnect from the database
59 *
60 * @param conn database handle to close
61 */
62void
63MERCHANT_DB_disconnect (PGconn *conn)
64{
65 PQfinish (conn);
66}
67
68
69/**
70 * Initialize merchant tables
71 *
72 * @param conn the connection handle to postgres db.
73 * @param tmp GNUNET_YES if the tables are to be made temporary i.e. their
74 * contents are dropped when the @a conn is closed
75 * @return GNUNET_OK upon success; GNUNET_SYSERR upon failure
76 */
77int
78MERCHANT_DB_initialize (PGconn *conn, int tmp)
79{
80 const char *tmp_str = (1 == tmp) ? "TEMPORARY" : "";
81 char *sql;
82 PGresult *res;
83 ExecStatusType status;
84 int ret;
85
86 res = NULL;
87 (void) GNUNET_asprintf (&sql,
88 "BEGIN TRANSACTION;"
89 "CREATE %1$s TABLE IF NOT EXISTS contracts ("
90 "transaction_id SERIAL8 PRIMARY KEY,"
91 "amount INT4 NOT NULL,"
92 "amount_fraction INT4 NOT NULL,"
93 "description TEXT NOT NULL,"
94 "nounce BYTEA NOT NULL,"
95 "expiry INT8 NOT NULL,"
96 "product INT8 NOT NULL);"
97 "CREATE %1$s TABLE IF NOT EXISTS checkouts ("
98 "coin_pub BYTEA PRIMARY KEY,"
99 "transaction_id INT8 REFERENCES contracts(transaction_id),"
100 "amount INT4 NOT NULL,"
101 "amount_fraction INT4 NOT NULL,"
102 "coin_sig BYTEA NOT NULL);",
103 tmp_str);
104 ret = GNUNET_POSTGRES_exec (conn, sql);
105 (void) GNUNET_POSTGRES_exec (conn,
106 (GNUNET_OK == ret) ? "COMMIT;" : "ROLLBACK");
107 GNUNET_free (sql);
108 if (GNUNET_OK != ret)
109 return ret;
110
111 while (NULL != (res = PQgetResult (conn)))
112 {
113 status = PQresultStatus (res);
114 PQclear (res);
115 }
116
117 EXITIF (NULL == (res = PQprepare
118 (conn,
119 "contract_create",
120 "INSERT INTO contracts"
121 "(amount, amount_fraction, description,"
122 "nounce, expiry, product) VALUES"
123 "($1, $2, $3, $4, $5, $6)"
124 "RETURNING transaction_id",
125 6, NULL)));
126 EXITIF (PGRES_COMMAND_OK != (status = PQresultStatus(res)));
127 PQclear (res);
128
129 EXITIF (NULL == (res = PQprepare
130 (conn,
131 "get_contract_product",
132 "SELECT ("
133 "product"
134 ") FROM contracts "
135 "WHERE ("
136 "transaction_id=$1"
137 ")",
138 1, NULL)));
139 EXITIF (PGRES_COMMAND_OK != (status = PQresultStatus(res)));
140 PQclear (res);
141
142 EXITIF (NULL == (res = PQprepare
143 (conn,
144 "checkout_create",
145 "INSERT INTO checkouts ("
146 "coin_pub,"
147 "transaction_id,"
148 "amount,"
149 "amount_fraction,"
150 "coin_sig"
151 ") VALUES ("
152 "$1, $2, $3, $4, $5"
153 ")",
154 5, NULL)));
155 EXITIF (PGRES_COMMAND_OK != (status = PQresultStatus (res)));
156 PQclear (res);
157
158 EXITIF (NULL == (res = PQprepare
159 (conn,
160 "get_checkout_product",
161 "SELECT ("
162 "product"
163 ") FROM contracts "
164 "WHERE "
165 "transaction_id IN ("
166 "SELECT (transaction_id) FROM checkouts "
167 "WHERE coin_pub=$1"
168 ")",
169 1, NULL)));
170 EXITIF (PGRES_COMMAND_OK != (status = PQresultStatus (res)));
171 PQclear (res);
172
173 return GNUNET_OK;
174
175 EXITIF_exit:
176 if (NULL != res)
177 {
178 PQSQL_strerror (GNUNET_ERROR_TYPE_ERROR, "PQprepare", res);
179 PQclear (res);
180 }
181 return GNUNET_SYSERR;
182}
183
184
185/**
186 * Inserts a contract record into the database and if successfull returns the
187 * serial number of the inserted row.
188 *
189 * @param conn the database connection
190 * @param expiry the time when the contract will expire
191 * @param amount the taler amount corresponding to the contract
192 * @param desc descripition of the contract
193 * @param nounce a random 64-bit nounce
194 * @param product description to identify a product
195 * @return -1 upon error; the serial id of the inserted contract upon success
196 */
197long long
198MERCHANT_DB_contract_create (PGconn *conn,
199 struct GNUNET_TIME_Absolute expiry,
200 struct TALER_Amount *amount,
201 const char *desc,
202 uint64_t nounce,
203 uint64_t product)
204{
205 PGresult *res;
206 uint64_t expiry_ms_nbo;
207 uint32_t value_nbo;
208 uint32_t fraction_nbo;
209 uint64_t nounce_nbo;
210 ExecStatusType status;
211 uint64_t id;
212 /* ported. To be tested/compiled */
213 struct TALER_PQ_QueryParam params[] = {
214 TALER_PQ_query_param_uint32 (&value_nbo),
215 TALER_PQ_query_param_uint32 (&fraction_nbo),
216 /* a *string* is being put in the following statement,
217 though the API talks about a *blob*. Will this be liked by
218 the DB ? */
219 TALER_PQ_query_param_fixed_size (desc, strlen(desc)),
220 TALER_PQ_query_param_uint64 (&nounce_nbo),
221 TALER_PQ_query_param_uint64 (&expiry_ms_nbo),
222 TALER_PQ_query_param_uint64 (&product),
223 TALER_PQ_query_param_end
224 };
225 struct TALER_PQ_ResultSpec rs[] = {
226 TALER_PQ_result_spec_uint64 ("transaction_id", &id),
227 TALER_PQ_result_spec_end
228 };
229
230 expiry_ms_nbo = GNUNET_htonll (expiry.abs_value_us);
231 value_nbo = htonl (amount->value);
232 fraction_nbo = htonl (amount->fraction);
233 nounce_nbo = GNUNET_htonll (nounce);
234 product = GNUNET_htonll (product);
235 /* NOTE: the statement is prepared by MERCHANT_DB_initialize function */
236 res = TALER_PQ_exec_prepared (conn, "contract_create", params);
237 status = PQresultStatus (res);
238 EXITIF (PGRES_TUPLES_OK != status);
239 EXITIF (1 != PQntuples (res));
240 EXITIF (GNUNET_YES != TALER_PQ_extract_result (res, rs, 0));
241 PQclear (res);
242 return GNUNET_ntohll ((uint64_t) id);
243
244 EXITIF_exit:
245 PQclear (res);
246 return -1;
247}
248
249long long
250MERCHANT_DB_get_contract_product (PGconn *conn,
251 uint64_t contract_id)
252{
253 PGresult *res;
254 uint64_t product;
255 ExecStatusType status;
256 struct TALER_PQ_QueryParam params[] = {
257 TALER_PQ_query_param_uint64 (&contract_id),
258 TALER_PQ_query_param_end
259 };
260 struct TALER_PQ_ResultSpec rs[] = {
261 TALER_PQ_result_spec_uint64 ("product", &product),
262 TALER_PQ_result_spec_end
263 };
264
265 contract_id = GNUNET_htonll (contract_id);
266 res = TALER_PQ_exec_prepared (conn, "get_contract_product", params);
267 status = PQresultStatus (res);
268 EXITIF (PGRES_TUPLES_OK != status);
269 EXITIF (1 != PQntuples (res));
270 EXITIF (GNUNET_YES != TALER_PQ_extract_result (res, rs, 0));
271 PQclear (res);
272 return GNUNET_ntohll ((uint64_t) product);
273
274 EXITIF_exit:
275 PQclear (res);
276 return -1;
277}
278
279unsigned int
280MERCHANT_DB_checkout_create (PGconn *conn,
281 struct GNUNET_CRYPTO_rsa_PublicKey *coin_pub,
282 uint64_t transaction_id,
283 struct TALER_Amount *amount,
284 struct GNUNET_CRYPTO_rsa_Signature *coin_sig)
285{
286 PGresult *res;
287 ExecStatusType status;
288 uint32_t value_nbo;
289 uint32_t fraction_nbo;
290 struct TALER_PQ_QueryParam params[] = {
291 TALER_PQ_query_param_rsa_public_key (coin_pub),
292 TALER_PQ_query_param_uint64 (&transaction_id),
293 TALER_PQ_query_param_uint32 (&value_nbo),
294 TALER_PQ_query_param_uint32 (&fraction_nbo),
295 TALER_PQ_query_param_rsa_signature (coin_sig),
296 TALER_PQ_query_param_end
297 };
298
299 transaction_id = GNUNET_htonll (transaction_id);
300 value_nbo = htonl (amount->value);
301 fraction_nbo = htonl (amount->fraction);
302 res = TALER_PQ_exec_prepared (conn, "checkout_create", params);
303 status = PQresultStatus (res);
304 EXITIF (PGRES_COMMAND_OK != status);
305 PQclear (res);
306 return GNUNET_OK;
307
308 EXITIF_exit:
309 PQclear (res);
310 return GNUNET_SYSERR;
311}
312
313
314long long
315MERCHANT_DB_get_checkout_product (PGconn *conn,
316 struct GNUNET_CRYPTO_rsa_PublicKey *coin_pub)
317{
318 PGresult *res;
319 ExecStatusType status;
320 uint64_t product;
321 struct TALER_PQ_QueryParam params[] = {
322 TALER_PQ_query_param_rsa_public_key (coin_pub),
323 TALER_PQ_query_param_end
324 };
325 struct TALER_PQ_ResultSpec rs[] = {
326 TALER_PQ_result_spec_uint64 ("product", &product),
327 TALER_PQ_result_spec_end
328 };
329
330 product = -1;
331 res = TALER_PQ_exec_prepared (conn, "get_checkout_product", params);
332 status = PQresultStatus (res);
333 EXITIF (PGRES_TUPLES_OK != status);
334 if (0 == PQntuples (res))
335 {
336 TALER_LOG_DEBUG ("Checkout not found for given coin");
337 goto EXITIF_exit;
338 }
339 EXITIF (1 != PQntuples (res));
340 EXITIF (GNUNET_YES != TALER_PQ_extract_result (res, rs, 0));
341 PQclear (res);
342 return GNUNET_ntohll ((uint64_t) product);
343
344 EXITIF_exit:
345 PQclear (res);
346 return -1;
347}
348/* end of merchant-db.c */
diff --git a/src/backend/merchant_db.h b/src/backend/merchant_db.h
new file mode 100644
index 00000000..bf334989
--- /dev/null
+++ b/src/backend/merchant_db.h
@@ -0,0 +1,98 @@
1/*
2 This file is part of TALER
3 (C) 2014 Christian Grothoff (and other contributing authors)
4
5 TALER is free software; you can redistribute it and/or modify it under the
6 terms of the GNU General Public License as published by the Free Software
7 Foundation; either version 3, or (at your option) any later version.
8
9 TALER is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License along with
14 TALER; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/>
15*/
16
17/**
18 * @file merchant/merchant_db.h
19 * @brief database helper functions used by the merchant
20 * @author Sree Harsha Totakura <sreeharsha@totakura.in>
21 */
22
23#ifndef MERCHANT_DB_H
24#define MERCHANT_DB_H
25
26#include <gnunet/gnunet_postgres_lib.h>
27#include <taler/taler_util.h>
28
29/**
30 * Connect to postgresql database
31 *
32 * @param cfg the configuration handle
33 * @return connection to the postgresql database; NULL upon error
34 */
35PGconn *
36MERCHANT_DB_connect (const struct GNUNET_CONFIGURATION_Handle *cfg);
37
38
39/**
40 * Disconnect from the database
41 *
42 * @param conn database handle to close
43 */
44void
45MERCHANT_DB_disconnect (PGconn *conn);
46
47
48/**
49 * Initialize merchant tables
50 *
51 * @param conn the connection handle to postgres db.
52 * @param tmp GNUNET_YES if the tables are to be made temporary i.e. their
53 * contents are dropped when the @a conn is closed
54 * @return GNUNET_OK upon success; GNUNET_SYSERR upon failure
55 */
56int
57MERCHANT_DB_initialize (PGconn *conn, int tmp);
58
59
60/**
61 * Inserts a contract record into the database and if successfull returns the
62 * serial number of the inserted row.
63 *
64 * @param conn the database connection
65 * @param expiry the time when the contract will expire
66 * @param amount the taler amount corresponding to the contract
67 * @param desc descripition of the contract
68 * @param nounce a random 64-bit nounce
69 * @param product description to identify a product
70 * @return -1 upon error; the serial id of the inserted contract upon success
71 */
72long long
73MERCHANT_DB_contract_create (PGconn *conn,
74 struct GNUNET_TIME_Absolute expiry,
75 struct TALER_Amount *amount,
76 const char *desc,
77 uint64_t nounce,
78 uint64_t product);
79
80long long
81MERCHANT_DB_get_contract_product (PGconn *conn,
82 uint64_t contract_id);
83
84unsigned int
85MERCHANT_DB_checkout_create (PGconn *conn,
86 struct GNUNET_CRYPTO_rsa_PublicKey *coin_pub,
87 uint64_t transaction_id,
88 struct TALER_Amount *amount,
89 struct GNUNET_CRYPTO_rsa_Signature *coin_sig);
90
91
92long long
93MERCHANT_DB_get_checkout_product (PGconn *conn,
94 struct GNUNET_CRYPTO_rsa_PublicKey *coin_pub);
95
96#endif /* MERCHANT_DB_H */
97
98/* end of merchant-db.h */
diff --git a/src/backend/taler-merchant-dbinit b/src/backend/taler-merchant-dbinit
new file mode 100755
index 00000000..850b77d0
--- /dev/null
+++ b/src/backend/taler-merchant-dbinit
Binary files differ
diff --git a/src/backend/taler-merchant-dbinit.c b/src/backend/taler-merchant-dbinit.c
new file mode 100644
index 00000000..07731b47
--- /dev/null
+++ b/src/backend/taler-merchant-dbinit.c
@@ -0,0 +1,79 @@
1/*
2 This file is part of TALER
3 (C) 2014 Christian Grothoff (and other contributing authors)
4
5 TALER is free software; you can redistribute it and/or modify it under the
6 terms of the GNU General Public License as published by the Free Software
7 Foundation; either version 3, or (at your option) any later version.
8
9 TALER is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License along with
14 TALER; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/>
15*/
16
17/**
18 * @file merchant/taler_merchant_dbinit.c
19 * @brief Program to initialise merchant database
20 * @author Sree Harsha Totakura <sreeharsha@totakura.in>
21 */
22
23#include "platform.h"
24#include <gnunet/gnunet_util_lib.h>
25#include "merchant_db.h"
26
27
28/**
29 * Global execution result
30 */
31static int result;
32
33
34/**
35 * Main function that will be run by the scheduler.
36 *
37 * @param cls closure
38 * @param args remaining command-line arguments
39 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
40 * @param config configuration
41 */
42static void
43run (void *cls, char *const *args, const char *cfgfile,
44 const struct GNUNET_CONFIGURATION_Handle *config)
45{
46 PGconn *conn;
47
48 conn = MERCHANT_DB_connect (config);
49 if (NULL == conn)
50 return;
51 if (GNUNET_OK == MERCHANT_DB_initialize (conn, GNUNET_NO))
52 result = GNUNET_OK;
53 MERCHANT_DB_disconnect (conn);
54}
55
56
57/**
58 * The main function
59 *
60 * @param argc number of arguments from the command line
61 * @param argv command line arguments
62 * @return 0 ok, 1 on error
63 */
64int
65main (int argc, char *const *argv)
66{
67 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
68 GNUNET_GETOPT_OPTION_END
69 };
70
71 result = GNUNET_SYSERR;
72 if (GNUNET_OK !=
73 GNUNET_PROGRAM_run (argc, argv, "taler-merchant-dbinit",
74 gettext_noop
75 ("Initialise Taler Merchant's database"),
76 options, &run, NULL))
77 return 3;
78 return (GNUNET_OK == result) ? 0 : 1;
79}
diff --git a/src/backend/taler-merchant-httpd.c b/src/backend/taler-merchant-httpd.c
index eafef40b..515cefc2 100644
--- a/src/backend/taler-merchant-httpd.c
+++ b/src/backend/taler-merchant-httpd.c
@@ -45,6 +45,16 @@ unsigned short port;
45static struct MHD_Daemon *mhd; 45static struct MHD_Daemon *mhd;
46 46
47/** 47/**
48 * Shutdown task identifier
49 */
50static struct GNUNET_SCHEDULER_Task *shutdown_task;
51
52/**
53 * Should we do a dry run where temporary tables are used for storing the data.
54 */
55static int dry;
56
57/**
48 * Global return code 58 * Global return code
49 */ 59 */
50static int result; 60static int result;
@@ -216,32 +226,85 @@ url_handler (void *cls,
216 226
217} 227}
218 228
229/**
230 * Shutdown task (magically invoked when the application is being
231 * quit)
232 *
233 * @param cls NULL
234 * @param tc scheduler task context
235 */
236static void
237do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
238{
239
240 if (NULL != mhd)
241 {
242 MHD_stop_daemon (mhd);
243 mhd = NULL;
244 }
245
246}
219 247
220 248
221/** 249/**
222 * The main function of the serve tool 250 * Main function that will be run by the scheduler.
223 * 251 *
224 * @param argc number of arguments from the command line 252 * @param cls closure
225 * @param argv command line arguments 253 * @param args remaining command-line arguments
226 * @return 0 ok, 1 on error 254 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
255 * @param config configuration
227 */ 256 */
228int 257static void
229main (int argc, char *const *argv) 258run (void *cls, char *const *args, const char *cfgfile,
259 const struct GNUNET_CONFIGURATION_Handle *config)
230{ 260{
231 261
232 port = 9966; 262 port = 9966;
263
264 shutdown_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
265 &do_shutdown, NULL);
266
233 mhd = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY, 267 mhd = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY,
234 port, 268 port,
235 NULL, NULL, 269 NULL, NULL,
236 &url_handler, NULL, 270 &url_handler, NULL,
237 MHD_OPTION_END); 271 MHD_OPTION_END);
238 272
239 getchar ();
240 MHD_stop_daemon (mhd);
241 return 0;
242 273
274 EXITIF (NULL == mhd);
275 result = GNUNET_OK;
243 276
277 EXITIF_exit:
278 if (GNUNET_OK != result)
279 GNUNET_SCHEDULER_shutdown ();
244 280
245 281
282}
246 283
284/**
285 * The main function of the serve tool
286 *
287 * @param argc number of arguments from the command line
288 * @param argv command line arguments
289 * @return 0 ok, 1 on error
290 */
291int
292main (int argc, char *const *argv)
293{
294
295 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
296 GNUNET_GETOPT_OPTION_END
297 };
298
299
300 if (GNUNET_OK !=
301 GNUNET_PROGRAM_run (argc, argv,
302 "taler-merchant-serve",
303 "Serve merchant's HTTP interface",
304 options, &run, NULL))
305 return 3;
306 return (GNUNET_OK == result) ? 0 : 1;
307
308
309
247} 310}