+ if (api_exch_outcommand(EXCH_CMD_ASSOCIATED) == -1) {
+ return -1;
+ } else {
+ return 1;
+ }
+}
+
+
+void
+freestorage()
+{
+ char buffer[40];
+ struct storage_descriptor sd;
+
+ if (storage_accessed) {
+ fprintf(stderr, "Internal error - attempt to free accessed storage.\n");
+ fprintf(stderr, "(Encountered in file %s at line %d.)\n",
+ __FILE__, __LINE__);
+ quit();
+ }
+ if (storage_must_send == 0) {
+ return;
+ }
+ storage_must_send = 0;
+ if (api_exch_outcommand(EXCH_CMD_HEREIS) == -1) {
+ kill_connection();
+ return;
+ }
+ sd.length = storage_length;
+ sd.location = storage_location;
+ if (api_exch_outtype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) == -1) {
+ kill_connection();
+ return;
+ }
+ if (api_exch_outtype(EXCH_TYPE_BYTES, storage_length, (char *)storage)
+ == -1) {
+ kill_connection();
+ return;
+ }
+}
+
+
+static int
+getstorage(address, length, copyin)
+int
+ address,
+ length,
+ copyin;
+{
+ struct storage_descriptor sd;
+ char buffer[40];
+
+ freestorage();
+ if (storage_accessed) {
+ fprintf(stderr,
+ "Internal error - attempt to get while storage accessed.\n");
+ fprintf(stderr, "(Encountered in file %s at line %d.)\n",
+ __FILE__, __LINE__);
+ quit();
+ }
+ storage_must_send = 0;
+ if (api_exch_outcommand(EXCH_CMD_GIMME) == -1) {
+ kill_connection();
+ return -1;
+ }
+ storage_location = address;
+ storage_length = length;
+ if (copyin) {
+ sd.location = storage_location;
+ sd.length = storage_length;
+ if (api_exch_outtype(EXCH_TYPE_STORE_DESC,
+ sizeof sd, (char *)&sd) == -1) {
+ kill_connection();
+ return -1;
+ }
+ if (api_exch_incommand(EXCH_CMD_HEREIS) == -1) {
+ fprintf(stderr, "Bad data from other side.\n");
+ fprintf(stderr, "(Encountered at %s, %d.)\n", __FILE__, __LINE__);
+ return -1;
+ }
+ if (nextstore() == -1) {
+ kill_connection();
+ return -1;
+ }
+ }
+ return 0;
+}
+
+void
+movetous(local, es, di, length)
+char
+ *local;
+int
+ es,
+ di;
+int
+ length;
+{
+ if (length > sizeof storage) {
+ fprintf(stderr, "Internal API error - movetous() length too long.\n");
+ fprintf(stderr, "(detected in file %s, line %d)\n", __FILE__, __LINE__);
+ quit();
+ } else if (length == 0) {
+ return;
+ }
+ getstorage(di, length, 1);
+ memcpy(local, storage+(di-storage_location), length);
+}
+
+void
+movetothem(es, di, local, length)
+int
+ es,
+ di;
+char
+ *local;
+int
+ length;
+{
+ if (length > sizeof storage) {
+ fprintf(stderr, "Internal API error - movetothem() length too long.\n");
+ fprintf(stderr, "(detected in file %s, line %d)\n", __FILE__, __LINE__);
+ quit();
+ } else if (length == 0) {
+ return;
+ }
+ freestorage();
+ memcpy((char *)storage, local, length);
+ storage_length = length;
+ storage_location = di;
+ storage_must_send = 1;
+}
+
+
+char *
+access_api(location, length, copyin)
+int
+ location,
+ length,
+ copyin; /* Do we need to copy in initially? */
+{
+ if (storage_accessed) {
+ fprintf(stderr, "Internal error - storage accessed twice\n");
+ fprintf(stderr, "(Encountered in file %s, line %d.)\n",
+ __FILE__, __LINE__);
+ quit();
+ } else if (length != 0) {
+ freestorage();
+ getstorage(location, length, copyin);
+ storage_accessed = 1;
+ }
+ return (char *) storage;
+}
+
+unaccess_api(location, local, length, copyout)
+int location;
+char *local;
+int length;
+{
+ if (storage_accessed == 0) {
+ fprintf(stderr, "Internal error - unnecessary unaccess_api call.\n");
+ fprintf(stderr, "(Encountered in file %s, line %d.)\n",
+ __FILE__, __LINE__);
+ quit();
+ }
+ storage_accessed = 0;
+ storage_must_send = copyout; /* if needs to go back */
+}
+
+/*
+ * Accept a connection from an API client, aborting if the child dies.
+ */
+
+static int
+doconnect()
+{
+ fd_set fdset;
+ int i;
+
+ sock = -1;
+ FD_ZERO(&fdset);
+ while (shell_active && (sock == -1)) {
+ FD_SET(serversock, &fdset);
+ if ((i = select(serversock+1, &fdset, 0, 0, 0)) < 0) {
+ if (errno = EINTR) {
+ continue;
+ } else {
+ perror("in select waiting for API connection");
+ return -1;
+ }
+ } else {
+ i = accept(serversock, 0, 0);
+ if (i == -1) {
+ perror("accepting API connection");
+ return -1;
+ }
+ sock = i;
+ }
+ }
+ /* If the process has already exited, we may need to close */
+ if ((shell_active == 0) && (sock != -1)) {
+ (void) close(sock);
+ sock = -1;
+ setcommandmode(); /* In case child_died sneaked in */
+ }