1212#include < libHX/io.h>
1313#include < libHX/option.h>
1414#include < libHX/scope.hpp>
15+ #include < libHX/socket.h>
1516#include < libHX/string.h>
1617#include < gromox/exmdb_client.hpp>
1718#include < gromox/exmdb_rpc.hpp>
19+ #include < gromox/fileio.h>
1820#include < gromox/freebusy.hpp>
1921#include < gromox/mapidefs.h>
2022#include < gromox/mysql_adaptor.hpp>
@@ -211,6 +213,75 @@ static int freeze_main(int argc, char **argv)
211213
212214}
213215
216+ namespace sync_midb {
217+
218+ static const char *g_folder_spec;
219+ static constexpr HXoption g_options_table[] = {
220+ {{}, ' f' , HXTYPE_STRP, &g_folder_spec, {}, {}, {}, " Forcibly rescan this folder" , " SPEC" },
221+ MBOP_AUTOHELP,
222+ HXOPT_TABLEEND,
223+ };
224+
225+ static int send_cmd (const char *host, uint16_t port, const std::string &cmd)
226+ {
227+ int fd = HX_inet_connect (host, port, 0 );
228+ if (fd < 0 ) {
229+ fprintf (stderr, " connect [%s]:%hu: %s" , host, port, strerror (errno));
230+ return -1 ;
231+ }
232+ std::unique_ptr<FILE, file_deleter> fp (fdopen (fd, " r+" ));
233+ if (fp == nullptr ) {
234+ perror (" fdopen" );
235+ return -1 ;
236+ }
237+ setvbuf (fp.get (), nullptr , _IOLBF, 0 );
238+ hxmc_t *line = nullptr ;
239+ auto cl_0 = HX::make_scope_exit ([&]() { HXmc_free (line); });
240+ if (HX_getl (&line, fp.get ()) == nullptr )
241+ return -1 ;
242+ if (strcmp (line, " OK\r\n " ) != 0 ) {
243+ fprintf (stderr, " No MIDB intro line received\n " );
244+ return -1 ;
245+ }
246+ fprintf (fp.get (), " %s" , cmd.c_str ());
247+ if (HX_getl (&line, fp.get ()) == nullptr ) {
248+ fprintf (stderr, " MIDB connection aborted?!\n " );
249+ return -1 ;
250+ }
251+ if (strncasecmp (line, " true" , 4 ) == 0 && HX_isspace (line[4 ]))
252+ return 0 ;
253+ mbop_fprintf (stderr, " MIDB command unsuccessful\n " );
254+ return 1 ;
255+ }
256+
257+ int main (int argc, char **argv)
258+ {
259+ HXopt6_auto_result argp;
260+ const char *host = " localhost" ;
261+ uint16_t port = 5555 ;
262+
263+ if (HX_getopt6 (g_options_table, argc, argv, nullptr ,
264+ HXOPT_USAGEONERR) != HXOPT_ERR_SUCCESS || g_exit_after_optparse)
265+ return EXIT_PARAM;
266+
267+ int ret;
268+ if (g_folder_spec == nullptr ) {
269+ ret = send_cmd (host, port, " M-PING " + g_storedir_s + " \r\n " );
270+ } else if (strcasecmp (g_folder_spec, " all" ) == 0 ) {
271+ ret = send_cmd (host, port, " X-RSYM " + g_storedir_s + " \r\n " );
272+ } else {
273+ eid_t eid = gi_lookup_eid_by_name (g_storedir, g_folder_spec);
274+ if (eid == 0 ) {
275+ mbop_fprintf (stderr, " Not recognized/found: \" %s\"\n " , g_folder_spec);
276+ return EXIT_FAILURE;
277+ }
278+ ret = send_cmd (host, port, " X-RSYF " + g_storedir_s + " " + std::to_string (eid.gcv ()) + " \r\n " );
279+ }
280+ return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
281+ }
282+
283+ }
284+
214285static errno_t resolvename (const GUID &guid, const char *name, bool create,
215286 uint16_t *out)
216287{
@@ -426,8 +497,9 @@ static int single_user_wrap(int argc, char **argv)
426497 return ret;
427498}
428499
429- static constexpr generic_module g_dfl_svc_plugins[] =
430- {{" libgxs_mysql_adaptor.so" , SVC_mysql_adaptor}};
500+ static constexpr generic_module g_dfl_svc_plugins[] = {
501+ {" libgxs_mysql_adaptor.so" , SVC_mysql_adaptor},
502+ };
431503
432504int main (int argc, char **argv)
433505{
@@ -447,7 +519,7 @@ int main(int argc, char **argv)
447519 argv = result.uarg ;
448520 if (argc == 0 )
449521 return global::help ();
450- service_init ({nullptr , g_dfl_svc_plugins, 1 });
522+ service_init ({nullptr , g_dfl_svc_plugins, 2 });
451523 auto cl_1 = HX::make_scope_exit (service_stop);
452524 if (service_run_early () != 0 || service_run () != 0 ) {
453525 fprintf (stderr, " service_run: failed\n " );
@@ -535,6 +607,8 @@ int cmd_parser(int argc, char **argv)
535607 return set_locale::main (argc, argv);
536608 else if (strcmp (argv[0 ], " get-freebusy" ) == 0 || strcmp (argv[0 ], " gfb" ) == 0 )
537609 return getfreebusy::main (argc, argv);
610+ else if (strcmp (argv[0 ], " sync-midb" ) == 0 )
611+ return sync_midb::main (argc, argv);
538612
539613 if (strcmp (argv[0 ], " clear-profile" ) == 0 ) {
540614 auto ret = delstoreprop (argc, argv, PSETID_Gromox, " zcore_profsect" , PT_BINARY);
0 commit comments