int main (int argc, char **argv) { int s; struct sockaddr_un remote; char *socket_path = NULL; char *hfile; int arglen = argc - 1; int c; static struct option long_options[] = { { "server-socket", required_argument, NULL, 's' }, { "version", no_argument, NULL, 'v' }, { "help", no_argument, NULL, 'h' }, { 0, 0, 0, 0 } }; while ((c = getopt_long (argc, argv, "s:hv", long_options, NULL)) != -1) { switch (c) { case 's': socket_path = optarg; arglen--; break; case 'h': usage (argv[0]); exit (EXIT_SUCCESS); break; case 'v': printf ("bitU v" VERSION " \n"); exit (EXIT_SUCCESS); break; default: fprintf (stderr, "Try `%s --help' for more information\n", argv[0]); exit (EXIT_FAILURE); break; } } if (socket_path == NULL) socket_path = SOCKET_PATH; if ((s = socket (AF_UNIX, SOCK_STREAM, 0)) == -1) { perror ("socket"); exit (EXIT_FAILURE); } remote.sun_family = AF_UNIX; strcpy (remote.sun_path, socket_path); if (connect (s, (struct sockaddr *) &remote, sizeof (struct sockaddr_un)) == -1) { fprintf (stderr, "Error when connecting: %s\n", strerror (errno)); return EXIT_FAILURE; } /* Interactive shell only appears when no param is received */ if (arglen > 0) { /* Collecting the command and its parameters to exec them on the * server and then feed back the user. */ char *cmd = NULL, *cmdline = NULL; char *param = NULL, *tmp = NULL; int cmd_len, full_len; int allocated = 0; int bufsize = 128; int start_pos = argc - arglen; int plen, i; cmd = argv[start_pos]; cmd_len = strlen (cmd); full_len = cmd_len; allocated = bufsize; cmdline = malloc (bufsize); memcpy (cmdline, cmd, cmd_len); cmdline[cmd_len] = ' '; full_len++; /* Yes, we have params to collect. */ for (i = 1; i < arglen; i++) { /* The `_escape_param()' also returns the size of the * string. */ param = _escape_param (argv[start_pos + i], &plen); /* Allocatting more space if it's needed */ if ((full_len + plen) > allocated) { while (allocated < full_len + plen) allocated += bufsize; if ((tmp = realloc (cmdline, allocated)) == NULL) { free (cmdline); close (s); exit (EXIT_FAILURE); } else cmdline = tmp; } /* Copying parameter to the command line string */ memcpy (cmdline + full_len, param, plen); /* Adding the space after param */ full_len += plen; cmdline[full_len] = ' '; full_len++; free (param); } cmdline[--full_len] = '\0'; /* Sending the command to the server */ if (send (s, cmdline, full_len, 0) == -1) { perror ("send"); exit (EXIT_FAILURE); } free (cmdline); /* Receiving the answer from the server. */ bitu_shell_recv (s, -1); goto finalize; } printf ("bitU v" VERSION " interactive shell connected!\n"); printf ("Type `help' for more information\n"); /* Initializing history library and registering a callback to write * back to history file when program finishes. */ hfile = _get_history_file (); using_history (); read_history (hfile); atexit (_save_history_file); free (hfile); while (1) { char *line; size_t llen; /* Main readline call.*/ line = readline (PS1); if (line == NULL) { _close_connection (s); printf ("\n"); break; } llen = strlen (line); /* Handling empty lines */ if (llen == 0) continue; /* Saving readline history */ add_history (line); /* Sending command to the server. */ if (send (s, line, llen, 0) == -1) { fprintf (stderr, "Error in send(): %s\n", strerror (errno)); goto finalize; } /* The only hardcoded command is this. It was actually sent to * the server but we should not wait for an answer in this * case. It is easier to catch it here, to finish the program * then implementing a full local command framework again. */ if (strcmp (line, "exit") == 0) { free (line); goto finalize; } free (line); /* Receiving the answer from the server */ bitu_shell_recv (s, -1); } finalize: close (s); return 0; }
// check if a command needs processing static void _poll_command(protocolState_t *ps) { if (ps->stopped) return; threadIPC_t *ipc = ps->ipc; pthread_mutex_lock(&ipc->lock); switch (ipc->command) { case COMMAND_SHUTDOWN: DBGPRINTF("omamqp1: Protocol thread processing shutdown command\n"); ps->stopped = true; _close_connection(ps); // wait for the shutdown to complete before ack'ing this command break; case COMMAND_IS_READY: DBGPRINTF("omamqp1: Protocol thread processing ready query command\n"); ipc->result = _is_ready(ps->sender) ? RS_RET_OK : RS_RET_SUSPENDED; ipc->command = COMMAND_DONE; pthread_cond_signal(&ipc->condition); break; case COMMAND_SEND: if (ps->delivery) break; // currently processing this command DBGPRINTF("omamqp1: Protocol thread processing send message command\n"); if (!_is_ready(ps->sender)) { ipc->result = RS_RET_SUSPENDED; ipc->command = COMMAND_DONE; pthread_cond_signal(&ipc->condition); break; } // send the message ++ps->tag; ps->delivery = pn_delivery(ps->sender, pn_dtag((const char *)&ps->tag, sizeof(ps->tag))); pn_message_t *message = ipc->message; assert(message); int rc = 0; size_t len = ps->buffer_size; do { rc = pn_message_encode(message, ps->encode_buffer, &len); if (rc == PN_OVERFLOW) { _grow_buffer(ps); len = ps->buffer_size; } } while (rc == PN_OVERFLOW); pn_link_send(ps->sender, ps->encode_buffer, len); pn_link_advance(ps->sender); ++ps->msgs_sent; // command completes when remote updates the delivery (see PN_DELIVERY) break; case COMMAND_DONE: break; } pthread_mutex_unlock(&ipc->lock); }