static struct proxy_context * cmd_proxy_init(int argc, char *argv[], const char *getopt_args, doveadm_command_t *cmd) { struct proxy_context *ctx; const char *socket_path; int c; ctx = t_new(struct proxy_context, 1); socket_path = t_strconcat(doveadm_settings->base_dir, "/ipc", NULL); while ((c = getopt(argc, argv, getopt_args)) > 0) { switch (c) { case 'a': socket_path = optarg; break; case 'f': ctx->username_field = optarg; break; default: proxy_cmd_help(cmd); } } ctx->ipc = ipc_client_init(socket_path); return ctx; }
/** * main - Main program * * Parses command line options and enters either daemon or client mode. * * In daemon mode, acquires multicast routing sockets, opens IPC socket * and goes in receive-execute command loop. * * In client mode, creates commands from command line and sends them to * the daemon. */ int main(int argc, const char *argv[]) { int i, num_opts, result = 0; int start_daemon = 0; int background = 1; uint8 buf[MX_CMDPKT_SZ]; const char *arg; unsigned int cmdnum = 0; struct cmd *cmdv[16]; /* init syslog */ openlog(__progname, LOG_PID, LOG_DAEMON); if (argc <= 1) return usage(); /* Parse command line options */ for (num_opts = 1; (num_opts = num_option_arguments(argv += num_opts));) { if (num_opts < 0) /* error */ return usage(); /* handle option */ arg = argv[0]; switch (arg[1]) { case 'a': /* add route */ if (num_opts < 5) return usage(); break; case 'r': /* remove route */ if (num_opts < 4) return usage(); break; case 'j': /* join */ case 'l': /* leave */ if (num_opts != 3) return usage(); break; case 'k': /* kill daemon */ if (num_opts != 1) return usage(); break; case 'h': /* help */ return usage(); case 'v': /* verbose */ fputs(version_info, stderr); log_stderr = LOG_DEBUG; continue; case 'd': /* daemon */ start_daemon = 1; continue; case 'n': /* run daemon in foreground, i.e., do not fork */ background = 0; continue; case 'f': if (num_opts != 2) return usage(); conf_file = argv[1]; continue; case 'D': do_debug_logging = 1; continue; default: /* unknown option */ return usage(); } /* Check and build command argument list. */ if (cmdnum >= ARRAY_ELEMENTS(cmdv)) { fprintf(stderr, "Too many command options\n"); return usage(); } cmdv[cmdnum] = cmd_build(arg[1], argv + 1, num_opts - 1); if (!cmdv[cmdnum]) { perror("Failed parsing command"); for (i = 0; i < cmdnum; i++) free(cmdv[i]); return 1; } cmdnum++; } if (start_daemon) { /* only daemon parent enters */ if (geteuid() != 0) { smclog(LOG_ERR, 0, "Need root privileges to start %s", __progname); return 1; } start_server(background); if (!background) return 0; } /* Client or daemon parent only, the daemon never reaches this point */ /* send commands */ if (cmdnum) { int retry_count = 30; openlog(argv[0], LOG_PID, LOG_USER); /* connect to daemon */ while (ipc_client_init()) { switch (errno) { case EACCES: smclog(LOG_ERR, EACCES, "Need root privileges to connect to daemon"); break; case ENOENT: case ECONNREFUSED: /* When starting daemon, give it 30 times a 1/10 second to get ready */ if (start_daemon && --retry_count) { usleep(100000); continue; } smclog(LOG_WARNING, errno, "Daemon not running"); result = 1; break; default: smclog(LOG_WARNING, errno, "Failed connecting to daemon"); result = 1; break; } } for (i = 0; !result && i < cmdnum; i++) { int slen, rlen; struct cmd *command = cmdv[i]; /* Send command */ slen = ipc_send(command, command->len); /* Wait here for reply */ rlen = ipc_receive(buf, sizeof(buf)); if (slen < 0 || rlen < 0) { smclog(LOG_WARNING, errno, "Communication with daemon failed"); result = 1; } if (rlen != 1 || *buf != '\0') { fprintf(stderr, "Daemon error: %s\n", buf); result = 1; } } for (i = 0; i < cmdnum; i++) free(cmdv[i]); } return result; }