+static int
+nextchar()
+{
+ unsigned char c;
+
+ if (read(sock, &c, 1) != 1) {
+ return -1;
+ } else {
+ return c;
+ }
+}
+
+static int
+checktype(type)
+int type;
+{
+ int was;
+
+ if ((was = nextchar()) != type) {
+ fprintf(stderr, "Wrong type of data. Should be 0x%02x, was 0x%02x.\n",
+ type, was);
+ return -1;
+ } else {
+ return 0;
+ }
+}
+
+
+static int
+fill(where, length)
+char *where;
+int length;
+{
+ while (length) {
+ int i;
+
+ if ((i = read(sock, where, length)) < 0) {
+ perror("read");
+ return -1;
+ } else {
+ length -= i;
+ where += i;
+ }
+ }
+}
+
+
+static int
+nextlength()
+{
+ short length;
+
+ if (fill(&length, sizeof length) == -1) {
+ return -1;
+ } else {
+ return ntohs(length);
+ }
+}
+
+
+static int
+nextaddress()
+{
+ long address;
+
+ return fill(&address, sizeof address);
+}
+
+
+
+static int
+nextbytes(type, where, length)
+int type;
+char *where;
+int length;
+{
+ int was;
+
+ if (checktype(type) == -1) {
+ return -1;
+ }
+ if ((was = nextlength()) != length) {
+ fprintf(stderr, "Type 0x%02x had bad length. Should be %d, was %d.\n",
+ type, length, was);
+ return -1;
+ } else {
+ return fill(where, length);
+ }
+}
+
+static int
+nextstore()
+{
+ if (nextchar() != EXCH_HEREIS) {
+ fprintf(stderr, "Bad data from other side.\n");
+ fprintf(stderr, "(Encountered at %s, %s.)\n", __FILE__, __LINE__);
+ return -1;
+ }
+ if ((storage_address = nextaddress()) == -1) {
+ storage_length = 0;
+ return -1;
+ }
+ if ((storage_length = nextlength()) > sizeof storage) {
+ fprintf(stderr, "API client tried to send too much storage (%d).\n",
+ storage_length);
+ return -1;
+ }
+ return fill((char *)storage, storage_length);
+}
+
+
+static int
+doreject(message)
+char *message;
+{
+ int length = strlen(message);
+ char buffer[100];
+
+ length = htons(length);
+ sprintf(buffer, "%c%c%c%s", EXCH_REJECTED, length>>8, length&0xff, buffer);
+ if (write(sock, buffer, length+3) != length+3) {
+ perror("writing API socket");
+ return -1;
+ }
+ return 0;
+}
+
+
+/*
+ * doconnect()
+ *
+ * Negotiate with the other side and try to do something.
+ */
+
+static int
+doconnect()
+{
+ struct passwd *pwent;
+ char
+ promptbuf[100],
+ buffer[200];
+ int promptlen, passwdlen;
+ int length;
+ int was;
+
+ if ((pwent = getpwuid(geteuid())) == 0) {
+ return -1;
+ }
+ sprintf(promptbuf, "Enter password for user %s:", pwent->pw_name);
+ promptlen = strlen(promptbuf);
+ passwdlen = strlen(pwent->pw_name);
+ sprintf(buffer, "%c%c%c%s%c%c%s", EXCH_SEND_AUTH,
+ promptlen>>8, promptlen&0xff, promptbuf,
+ passwdlen>>8, passwdlen&0xff, pwent->pw_name);
+ length = strlen(buffer);
+ if (write(sock, buffer, length) != length) {
+ perror("write to API socket");
+ return -1;
+ }
+ if ((was = nextchar()) != EXCH_AUTH) {
+ fprintf(stderr,
+ "API client sent command 0x%02x when EXCH_AUTH expected.\n", was);
+ }
+ if ((length = nextlength()) > sizeof buffer) {
+ doreject("Password entered was too long");
+ return 0;
+ }
+ if (fill(buffer, length) == -1) {
+ return -1;
+ }
+ buffer[length] = 0;
+
+ /* Is this the correct password? */
+ if (strcmp(crypt(buffer, pwent->pw_passwd), pwent->pw_passwd) == 0) {
+ char code = EXCH_CONNECTED;
+ if (write(sock, &code, 1) != 1) {
+ perror("writing to API socket");
+ return -1;
+ }
+ } else {
+ doreject("Invalid password");
+ sleep(10); /* Don't let us do too many of these */
+ }
+ return 0;
+}
+
+
+void
+freestorage()
+{
+ int i, j;
+ char buffer[40];
+
+ if (storage_accessed) {
+ fprintf(stderr, "Internal error - attempt to free accessed storage.\n");
+ fprintf(stderr, "(Enountered in file %s at line %s.)\n",
+ __FILE__, __LINE__);
+ quit();
+ }
+ if (storage_must_send == 0) {
+ return;
+ }
+ storage_must_send = 0;
+ i = htonl(storage_address);
+ j = htonl(storage_length);
+ sprintf(buffer, "%c%c%c%c%c%c%c",
+ EXCH_HEREIS, i>>24, i>>16, i>>8, i, j>>8, j);
+ if (write(sock, buffer, 5) != 5) {
+ perror("writing to API socket");
+ kill_connection();
+ return;
+ }
+ if (write(sock, (char *)storage, storage_length) != storage_length) {
+ perror("writing to API socket");
+ kill_connection();
+ return;
+ }
+}
+
+
+void
+getstorage(address, length)
+{
+ int i, j;
+ char buffer[40];
+
+ freestorage();
+ if (storage_accessed) {
+ fprintf(stderr,
+ "Internal error - attempt to get while storage accessed.\n");
+ fprintf(stderr, "(Enountered in file %s at line %s.)\n",
+ __FILE__, __LINE__);
+ quit();
+ }
+ if (storage_must_send == 0) {
+ return;
+ }
+ storage_must_send = 0;
+ i = htonl(storage_address);
+ j = htonl(storage_length);
+ sprintf(buffer, "%c%c%c%c%c%c%c",
+ EXCH_GIMME, i>>24, i>>16, i>>8, i, j>>8, j);
+ if (write(sock, buffer, 5) != 5) {
+ perror("writing to API socket");
+ kill_connection();
+ return;
+ }
+ if (nextstore() == -1) {
+ kill_connection();
+ return;
+ }
+}
+
+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);
+ memcpy(local, storage+(di-storage_address), 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_address = di;
+ storage_must_send = 1;
+}
+
+
+char *
+access_api(location, length)
+int
+ location,
+ length;
+{
+ if (storage_accessed) {
+ fprintf(stderr, "Internal error - storage accessed twice\n");
+ fprintf(stderr, "(Encountered in file %s, line %s.)\n",
+ __FILE__, __LINE__);
+ quit();
+ } else if (length != 0) {
+ storage_accessed = 1;
+ freestorage();
+ getstorage(location, length);
+ }
+ return (char *) storage;
+}
+
+unaccess_api(location, local, length)
+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 %s.)\n",
+ __FILE__, __LINE__);
+ quit();
+ }
+ storage_accessed = 0;
+ storage_must_send = 1; /* Needs to go back */
+}
+
+