diff --git a/assuan/ChangeLog b/assuan/ChangeLog index 28f1b2f4f..9b08c2b4c 100644 --- a/assuan/ChangeLog +++ b/assuan/ChangeLog @@ -1,3 +1,18 @@ +2001-12-12 Werner Koch + + * assuan-connect.c (assuan_pipe_connect): Implemented the inital + handshake. + * assuan-client.c (read_from_server): Renamed to + (_assuan_read_from_server): this and made external. + + * assuan-listen.c (assuan_set_hello_line): New. + (assuan_accept): Use a custom hello line is available. + + * assuan-buffer.c (assuan_read_line): New. + (assuan_pending_line): New. + (_assuan_write_line): Renamed to .. + (assuan_write_line): this, made public and changed all callers. + 2001-12-04 Werner Koch * assuan-connect.c (assuan_pipe_connect): Add more error reporting. diff --git a/assuan/assuan-buffer.c b/assuan/assuan-buffer.c index eec4876f8..50900c425 100644 --- a/assuan/assuan-buffer.c +++ b/assuan/assuan-buffer.c @@ -123,16 +123,25 @@ _assuan_read_line (ASSUAN_CONTEXT ctx) return -1; } + ctx->inbound.attic.pending = 0; for (n=0; n < nread; n++) { if (line[n] == '\n') { if (n+1 < nread) { + char *s, *d; + int i; + n++; /* we have to copy the rest because the handlers are allowed to modify the passed buffer */ - memcpy (ctx->inbound.attic.line, line+n, nread-n); + for (d=ctx->inbound.attic.line, s=line+n, i=nread-n; i; i--) + { + if (*s=='\n') + ctx->inbound.attic.pending = 1; + *d++ = *s++; + } ctx->inbound.attic.linelen = nread-n; n--; } @@ -150,12 +159,43 @@ _assuan_read_line (ASSUAN_CONTEXT ctx) } +/* Read the next line from the client or server and return a pointer + to a buffer with holding that line. linelen returns the length of + the line. This buffer is valid until another read operation is + done on this buffer. The caller is allowed to modify this buffer. + He should only use the buffer if the function returns without an + error. + + Returns: 0 on success or an assuan error code + See also: assuan_pending_line(). +*/ +AssuanError +assuan_read_line (ASSUAN_CONTEXT ctx, char **line, size_t *linelen) +{ + if (!ctx) + return ASSUAN_Invalid_Value; + *line = ctx->inbound.line; + *linelen = ctx->inbound.linelen; + return _assuan_read_line (ctx); +} -int -_assuan_write_line (ASSUAN_CONTEXT ctx, const char *line ) +/* Return true when a full line is pending for a read, without the need + for actual IO */ +int +assuan_pending_line (ASSUAN_CONTEXT ctx) +{ + return ctx && ctx->inbound.attic.pending; +} + + +AssuanError +assuan_write_line (ASSUAN_CONTEXT ctx, const char *line ) { int rc; + + if (!ctx) + return ASSUAN_Invalid_Value; /* fixme: we should do some kind of line buffering */ rc = writen (ctx->outbound.fd, line, strlen(line)); @@ -297,7 +337,7 @@ assuan_send_data (ASSUAN_CONTEXT ctx, const void *buffer, size_t length) if (ctx->outbound.data.error) return ctx->outbound.data.error; if (!ctx->is_server) - return _assuan_write_line (ctx, "END"); + return assuan_write_line (ctx, "END"); } else { diff --git a/assuan/assuan-client.c b/assuan/assuan-client.c index 03c7c099a..a555cf339 100644 --- a/assuan/assuan-client.c +++ b/assuan/assuan-client.c @@ -32,8 +32,8 @@ #define xtoi_2(p) ((xtoi_1(p) * 16) + xtoi_1((p)+1)) -static AssuanError -read_from_server (ASSUAN_CONTEXT ctx, int *okay, int *off) +AssuanError +_assuan_read_from_server (ASSUAN_CONTEXT ctx, int *okay, int *off) { char *line; int linelen; @@ -114,12 +114,12 @@ assuan_transact (ASSUAN_CONTEXT ctx, unsigned char *line; int linelen; - rc = _assuan_write_line (ctx, command); + rc = assuan_write_line (ctx, command); if (rc) return rc; again: - rc = read_from_server (ctx, &okay, &off); + rc = _assuan_read_from_server (ctx, &okay, &off); if (rc) return rc; /* error reading from server */ @@ -162,8 +162,8 @@ assuan_transact (ASSUAN_CONTEXT ctx, { if (!inquire_cb) { - _assuan_write_line (ctx, "END"); /* get out of inquire mode */ - read_from_server (ctx, &okay, &off); /* dummy read the response */ + assuan_write_line (ctx, "END"); /* get out of inquire mode */ + _assuan_read_from_server (ctx, &okay, &off); /* dummy read */ rc = ASSUAN_No_Inquire_Callback; } else diff --git a/assuan/assuan-connect.c b/assuan/assuan-connect.c index abc5d74e2..683c7f060 100644 --- a/assuan/assuan-connect.c +++ b/assuan/assuan-connect.c @@ -40,6 +40,7 @@ #endif #ifdef HAVE_JNLIB_LOGGING +#include "../jnlib/logging.h" #define LOGERROR1(a,b) log_error ((a), (b)) #else #define LOGERROR1(a,b) fprintf (stderr, (a), (b)) @@ -188,35 +189,37 @@ assuan_pipe_connect (ASSUAN_CONTEXT *ctx, const char *name, char *const argv[]) close (rp[1]); close (wp[0]); - _assuan_read_line (*ctx); /* FIXME: Handshake. */ -#if 0 /* old stuff */ - inbound.eof = 0; - inbound.linelen = 0; - inbound.attic.linelen = 0; + /* initial handshake */ + { + int okay, off; - /* The server is available - read the greeting */ - rc = read_from_agent (&okay); - if (rc) + err = _assuan_read_from_server (*ctx, &okay, &off); + if (err) + { + LOGERROR1 ("can't connect server: %s\n", assuan_strerror (err)); + } + else if (okay != 1) + { + LOGERROR1 ("can't connect server: `%s'\n", (*ctx)->inbound.line); + err = ASSUAN_Connect_Failed; + } + } + + if (err) { - log_error ("can't connect to the agent: %s\n", gnupg_strerror (rc)); + if ((*ctx)->pid != -1) + waitpid ((*ctx)->pid, NULL, 0); /* FIXME Check return value. */ + assuan_deinit_pipe_server (*ctx); /* FIXME: Common code should be factored out. */ } - else if (!okay) - { - log_error ("can't connect to the agent: %s\n", inbound.line); - rc = seterr (No_Agent); - } - else -#endif - - return 0; + return err; } void assuan_pipe_disconnect (ASSUAN_CONTEXT ctx) { - _assuan_write_line (ctx, "BYE"); + assuan_write_line (ctx, "BYE"); close (ctx->inbound.fd); close (ctx->outbound.fd); waitpid (ctx->pid, NULL, 0); /* FIXME Check return value. */ diff --git a/assuan/assuan-defs.h b/assuan/assuan-defs.h index 5d61707a5..e0a38a8f0 100644 --- a/assuan/assuan-defs.h +++ b/assuan/assuan-defs.h @@ -38,6 +38,7 @@ struct assuan_context_s { int is_server; /* set if this is context belongs to a server */ int in_inquire; + char *hello_line; void *user_pointer; /* for assuan_[gs]et_pointer () */ @@ -51,6 +52,7 @@ struct assuan_context_s { struct { char line[LINELENGTH]; int linelen ; + int pending; /* i.e. at least one line is available in the attic */ } attic; } inbound; @@ -91,12 +93,12 @@ struct assuan_context_s { int _assuan_register_std_commands (ASSUAN_CONTEXT ctx); /*-- assuan-buffer.c --*/ -int _assuan_write_line (ASSUAN_CONTEXT ctx, const char *line); int _assuan_read_line (ASSUAN_CONTEXT ctx); int _assuan_cookie_write_data (void *cookie, const char *buffer, size_t size); int _assuan_cookie_write_flush (void *cookie); - +/*-- assuan-client.c --*/ +AssuanError _assuan_read_from_server (ASSUAN_CONTEXT ctx, int *okay, int *off); /*-- assuan-util.c --*/ diff --git a/assuan/assuan-handler.c b/assuan/assuan-handler.c index aee2407b2..c8be909d2 100644 --- a/assuan/assuan-handler.c +++ b/assuan/assuan-handler.c @@ -377,11 +377,11 @@ process_request (ASSUAN_CONTEXT ctx) /* Error handling */ if (!rc) { - rc = _assuan_write_line (ctx, "OK"); + rc = assuan_write_line (ctx, "OK"); } else if (rc == -1) { /* No error checking because the peer may have already disconnect */ - _assuan_write_line (ctx, "OK Bye, bye - hope to meet you again"); + assuan_write_line (ctx, "OK Hope to meet you again"); } else { @@ -397,7 +397,7 @@ process_request (ASSUAN_CONTEXT ctx) sprintf (errline, "ERR %d %.50s%s%.100s", rc, assuan_strerror (rc), text? " - ":"", text?text:""); } - rc = _assuan_write_line (ctx, errline); + rc = assuan_write_line (ctx, errline); } return rc; @@ -538,7 +538,7 @@ assuan_write_status (ASSUAN_CONTEXT ctx, const char *keyword, const char *text) strcat (buffer, " "); strcat (buffer, text); } - _assuan_write_line (ctx, buffer); + assuan_write_line (ctx, buffer); } else if ( (helpbuf = xtrymalloc (n)) ) { @@ -549,7 +549,7 @@ assuan_write_status (ASSUAN_CONTEXT ctx, const char *keyword, const char *text) strcat (helpbuf, " "); strcat (helpbuf, text); } - _assuan_write_line (ctx, helpbuf); + assuan_write_line (ctx, helpbuf); xfree (helpbuf); } } diff --git a/assuan/assuan-inquire.c b/assuan/assuan-inquire.c index c4514dfcc..8fec77ef8 100644 --- a/assuan/assuan-inquire.c +++ b/assuan/assuan-inquire.c @@ -151,7 +151,7 @@ assuan_inquire (ASSUAN_CONTEXT ctx, const char *keyword, init_membuf (&mb, maxlen? maxlen:1024, maxlen); strcpy (stpcpy (cmdbuf, "INQUIRE "), keyword); - rc = _assuan_write_line (ctx, cmdbuf); + rc = assuan_write_line (ctx, cmdbuf); if (rc) goto leave; diff --git a/assuan/assuan-listen.c b/assuan/assuan-listen.c index f8ccb2708..822ef32cd 100644 --- a/assuan/assuan-listen.c +++ b/assuan/assuan-listen.c @@ -25,6 +25,28 @@ #include "assuan-defs.h" +AssuanError +assuan_set_hello_line (ASSUAN_CONTEXT ctx, const char *line) +{ + if (!ctx) + return ASSUAN_Invalid_Value; + if (!line) + { + xfree (ctx->hello_line); + ctx->hello_line = NULL; + } + else + { + char *buf = xtrymalloc (3+strlen(line)+1); + if (!buf) + return ASSUAN_Out_Of_Core; + strcpy (buf, "OK "); + strcpy (buf+3, line); + xfree (ctx->hello_line); + ctx->hello_line = buf; + } + return 0; +} /** @@ -38,7 +60,7 @@ * Return value: 0 on success or an error if the connection could for * some reason not be established. **/ -int +AssuanError assuan_accept (ASSUAN_CONTEXT ctx) { int rc; @@ -57,9 +79,8 @@ assuan_accept (ASSUAN_CONTEXT ctx) } /* send the hello */ - - rc = _assuan_write_line (ctx, - "OK Hello dear client - what can I do for you?"); + rc = assuan_write_line (ctx, ctx->hello_line? ctx->hello_line + : "OK Your orders please"); if (rc) return rc; @@ -70,6 +91,7 @@ assuan_accept (ASSUAN_CONTEXT ctx) } + int assuan_get_input_fd (ASSUAN_CONTEXT ctx) { diff --git a/assuan/assuan-pipe-server.c b/assuan/assuan-pipe-server.c index 58d9aa142..2a9b829aa 100644 --- a/assuan/assuan-pipe-server.c +++ b/assuan/assuan-pipe-server.c @@ -55,7 +55,11 @@ assuan_init_pipe_server (ASSUAN_CONTEXT *r_ctx, int filedes[2]) void assuan_deinit_pipe_server (ASSUAN_CONTEXT ctx) { - xfree (ctx); + if (ctx) + { + xfree (ctx->hello_line); + xfree (ctx); + } } @@ -67,4 +71,3 @@ assuan_deinit_pipe_server (ASSUAN_CONTEXT ctx) - diff --git a/assuan/assuan.h b/assuan/assuan.h index 8b805dd10..f97493dc0 100644 --- a/assuan/assuan.h +++ b/assuan/assuan.h @@ -46,6 +46,7 @@ typedef enum { ASSUAN_Invalid_Response = 11, ASSUAN_No_Data_Callback = 12, ASSUAN_No_Inquire_Callback = 13, + ASSUAN_Connect_Failed = 14, /* error codes above 99 are meant as status codes */ ASSUAN_Not_Implemented = 100, @@ -130,7 +131,8 @@ void assuan_write_status (ASSUAN_CONTEXT ctx, /*-- assuan-listen.c --*/ -int assuan_accept (ASSUAN_CONTEXT ctx); +AssuanError assuan_set_hello_line (ASSUAN_CONTEXT ctx, const char *line); +AssuanError assuan_accept (ASSUAN_CONTEXT ctx); int assuan_get_input_fd (ASSUAN_CONTEXT ctx); int assuan_get_output_fd (ASSUAN_CONTEXT ctx); @@ -161,6 +163,10 @@ AssuanError assuan_inquire (ASSUAN_CONTEXT ctx, const char *keyword, char **r_buffer, size_t *r_length, size_t maxlen); /*-- assuan-buffer.c --*/ +AssuanError assuan_read_line (ASSUAN_CONTEXT ctx, + char **line, size_t *linelen); +int assuan_pending_line (ASSUAN_CONTEXT ctx); +AssuanError assuan_write_line (ASSUAN_CONTEXT ctx, const char *line ); AssuanError assuan_send_data (ASSUAN_CONTEXT ctx, const void *buffer, size_t length);