+ /*
+ * When we come here, we're terminating, and should clean up our
+ * Unix socket file if possible.
+ */
+ if (unlink(socketname) < 0) {
+ fprintf(stderr, "pageant: %s: %s\n", socketname, strerror(errno));
+ exit(1);
+ }
+}
+
+int main(int argc, char **argv)
+{
+ int doing_opts = TRUE;
+ keyact curr_keyact = KEYACT_AGENT_LOAD;
+
+ /*
+ * Process the command line.
+ */
+ while (--argc > 0) {
+ char *p = *++argv;
+ if (*p == '-' && doing_opts) {
+ if (!strcmp(p, "-V") || !strcmp(p, "--version")) {
+ version();
+ } else if (!strcmp(p, "--help")) {
+ usage();
+ exit(0);
+ } else if (!strcmp(p, "-v")) {
+ pageant_logfp = stderr;
+ } else if (!strcmp(p, "-a")) {
+ curr_keyact = KEYACT_CLIENT_ADD;
+ } else if (!strcmp(p, "-d")) {
+ curr_keyact = KEYACT_CLIENT_DEL;
+ } else if (!strcmp(p, "-s")) {
+ shell_type = SHELL_SH;
+ } else if (!strcmp(p, "-c")) {
+ shell_type = SHELL_CSH;
+ } else if (!strcmp(p, "-D")) {
+ add_keyact(KEYACT_CLIENT_DEL_ALL, NULL);
+ } else if (!strcmp(p, "-l")) {
+ add_keyact(KEYACT_CLIENT_LIST, NULL);
+ } else if (!strcmp(p, "--public")) {
+ curr_keyact = KEYACT_CLIENT_PUBLIC;
+ } else if (!strcmp(p, "--public-openssh")) {
+ curr_keyact = KEYACT_CLIENT_PUBLIC_OPENSSH;
+ } else if (!strcmp(p, "-X")) {
+ life = LIFE_X11;
+ } else if (!strcmp(p, "-T")) {
+ life = LIFE_TTY;
+ } else if (!strcmp(p, "--debug")) {
+ life = LIFE_DEBUG;
+ } else if (!strcmp(p, "--permanent")) {
+ life = LIFE_PERM;
+ } else if (!strcmp(p, "--exec")) {
+ life = LIFE_EXEC;
+ /* Now all subsequent arguments go to the exec command. */
+ if (--argc > 0) {
+ exec_args = ++argv;
+ argc = 0; /* force end of option processing */
+ } else {
+ fprintf(stderr, "pageant: expected a command "
+ "after --exec\n");
+ exit(1);
+ }
+ } else if (!strcmp(p, "--")) {
+ doing_opts = FALSE;
+ }
+ } else {
+ /*
+ * Non-option arguments (apart from those after --exec,
+ * which are treated specially above) are interpreted as
+ * the names of private key files to either add or delete
+ * from an agent.
+ */
+ add_keyact(curr_keyact, p);
+ }
+ }
+
+ if (life == LIFE_EXEC && !exec_args) {
+ fprintf(stderr, "pageant: expected a command with --exec\n");
+ exit(1);
+ }
+
+ /*
+ * Block SIGPIPE, so that we'll get EPIPE individually on
+ * particular network connections that go wrong.
+ */
+ putty_signal(SIGPIPE, SIG_IGN);
+
+ sk_init();
+ uxsel_init();
+
+ if (!display) {
+ display = getenv("DISPLAY");
+ if (display && !*display)
+ display = NULL;
+ }
+
+ /*
+ * Now distinguish our two main running modes. Either we're
+ * actually starting up an agent, in which case we should have a
+ * lifetime mode, and no key actions of KEYACT_CLIENT_* type; or
+ * else we're contacting an existing agent to add or remove keys,
+ * in which case we should have no lifetime mode, and no key
+ * actions of KEYACT_AGENT_* type.
+ */
+ {
+ int has_agent_actions = FALSE;
+ int has_client_actions = FALSE;
+ int has_lifetime = FALSE;
+ const struct cmdline_key_action *act;
+
+ for (act = keyact_head; act; act = act->next) {
+ if (is_agent_action(act->action))
+ has_agent_actions = TRUE;
+ else
+ has_client_actions = TRUE;
+ }
+ if (life != LIFE_UNSPEC)
+ has_lifetime = TRUE;
+
+ if (has_lifetime && has_client_actions) {
+ fprintf(stderr, "pageant: client key actions (-a, -d, -D, -l, -L)"
+ " do not go with an agent lifetime option\n");
+ exit(1);
+ }
+ if (!has_lifetime && has_agent_actions) {
+ fprintf(stderr, "pageant: expected an agent lifetime option with"
+ " bare key file arguments\n");
+ exit(1);
+ }
+ if (!has_lifetime && !has_client_actions) {
+ fprintf(stderr, "pageant: expected an agent lifetime option"
+ " or a client key action\n");
+ exit(1);
+ }
+
+ if (has_lifetime) {
+ run_agent();
+ } else if (has_client_actions) {
+ run_client();
+ }
+ }
+