xref: /dflybsd-src/usr.sbin/installer/libdfui/conn_npipe.c (revision d056b4791691895675342b2abe77a65087658bb1)
121c1c48aSSascha Wildner /*
221c1c48aSSascha Wildner  * Copyright (c)2004 Cat's Eye Technologies.  All rights reserved.
321c1c48aSSascha Wildner  *
421c1c48aSSascha Wildner  * Redistribution and use in source and binary forms, with or without
521c1c48aSSascha Wildner  * modification, are permitted provided that the following conditions
621c1c48aSSascha Wildner  * are met:
721c1c48aSSascha Wildner  *
821c1c48aSSascha Wildner  *   Redistributions of source code must retain the above copyright
921c1c48aSSascha Wildner  *   notice, this list of conditions and the following disclaimer.
1021c1c48aSSascha Wildner  *
1121c1c48aSSascha Wildner  *   Redistributions in binary form must reproduce the above copyright
1221c1c48aSSascha Wildner  *   notice, this list of conditions and the following disclaimer in
1321c1c48aSSascha Wildner  *   the documentation and/or other materials provided with the
1421c1c48aSSascha Wildner  *   distribution.
1521c1c48aSSascha Wildner  *
1621c1c48aSSascha Wildner  *   Neither the name of Cat's Eye Technologies nor the names of its
1721c1c48aSSascha Wildner  *   contributors may be used to endorse or promote products derived
1821c1c48aSSascha Wildner  *   from this software without specific prior written permission.
1921c1c48aSSascha Wildner  *
2021c1c48aSSascha Wildner  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2121c1c48aSSascha Wildner  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2221c1c48aSSascha Wildner  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
2321c1c48aSSascha Wildner  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
2421c1c48aSSascha Wildner  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
2521c1c48aSSascha Wildner  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
2621c1c48aSSascha Wildner  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
2721c1c48aSSascha Wildner  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2821c1c48aSSascha Wildner  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
2921c1c48aSSascha Wildner  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
3021c1c48aSSascha Wildner  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
3121c1c48aSSascha Wildner  * OF THE POSSIBILITY OF SUCH DAMAGE.
3221c1c48aSSascha Wildner  */
3321c1c48aSSascha Wildner 
3421c1c48aSSascha Wildner /*
3521c1c48aSSascha Wildner  * conn_npipe.c
3621c1c48aSSascha Wildner  * $Id: conn_npipe.c,v 1.13 2005/02/06 19:53:19 cpressey Exp $
3721c1c48aSSascha Wildner  */
3821c1c48aSSascha Wildner 
3921c1c48aSSascha Wildner #include "system.h"
4021c1c48aSSascha Wildner #ifdef HAS_NPIPE
4121c1c48aSSascha Wildner 
4221c1c48aSSascha Wildner #include <sys/types.h>
4321c1c48aSSascha Wildner #include <sys/stat.h>
4421c1c48aSSascha Wildner #include <sys/time.h>
4521c1c48aSSascha Wildner #include <sys/errno.h>
4621c1c48aSSascha Wildner 
4721c1c48aSSascha Wildner #include <err.h>
4821c1c48aSSascha Wildner #include <stdarg.h>
4921c1c48aSSascha Wildner #include <stdio.h>
5021c1c48aSSascha Wildner #include <stdlib.h>
5121c1c48aSSascha Wildner #include <string.h>
5221c1c48aSSascha Wildner #include <unistd.h>
5321c1c48aSSascha Wildner 
5421c1c48aSSascha Wildner #include <libaura/buffer.h>
5521c1c48aSSascha Wildner #include <libaura/fspred.h>
5621c1c48aSSascha Wildner 
5721c1c48aSSascha Wildner #define	NEEDS_DFUI_STRUCTURE_DEFINITIONS
5821c1c48aSSascha Wildner #include "dfui.h"
5921c1c48aSSascha Wildner #undef	NEEDS_DFUI_STRUCTURE_DEFINITIONS
6021c1c48aSSascha Wildner #include "encoding.h"
6121c1c48aSSascha Wildner #include "dump.h"
6221c1c48aSSascha Wildner #include "conn_npipe.h"
6321c1c48aSSascha Wildner 
6421c1c48aSSascha Wildner /***** BACKEND ******/
6521c1c48aSSascha Wildner 
6621c1c48aSSascha Wildner /** High Level **/
6721c1c48aSSascha Wildner 
6821c1c48aSSascha Wildner /*
6921c1c48aSSascha Wildner  * Connect to the frontend.
7021c1c48aSSascha Wildner  */
7121c1c48aSSascha Wildner dfui_err_t
dfui_npipe_be_start(struct dfui_connection * c)7221c1c48aSSascha Wildner dfui_npipe_be_start(struct dfui_connection *c)
7321c1c48aSSascha Wildner {
7421c1c48aSSascha Wildner 	asprintf(&T_NPIPE(c)->out_pipename, "/tmp/dfui.%s.to_fe", c->rendezvous);
7521c1c48aSSascha Wildner 	asprintf(&T_NPIPE(c)->in_pipename, "/tmp/dfui.%s.from_fe", c->rendezvous);
7621c1c48aSSascha Wildner 
7721c1c48aSSascha Wildner 	/*
7821c1c48aSSascha Wildner 	 * Create the named pipes.
7921c1c48aSSascha Wildner 	 */
8021c1c48aSSascha Wildner 	errno = 0;
8121c1c48aSSascha Wildner 	if (mkfifo(T_NPIPE(c)->in_pipename, 0600) < 0) {
8221c1c48aSSascha Wildner 		if (errno != EEXIST) {
8321c1c48aSSascha Wildner 			warn("mkfifo (to_be)");
8421c1c48aSSascha Wildner 			return(DFUI_FAILURE);
8521c1c48aSSascha Wildner 		}
8621c1c48aSSascha Wildner 	}
8721c1c48aSSascha Wildner 	errno = 0;
8821c1c48aSSascha Wildner 	if (mkfifo(T_NPIPE(c)->out_pipename, 0600) < 0) {
8921c1c48aSSascha Wildner 		if (errno != EEXIST) {
9021c1c48aSSascha Wildner 			warn("mkfifo (to_fe)");
9121c1c48aSSascha Wildner 			return(DFUI_FAILURE);
9221c1c48aSSascha Wildner 		}
9321c1c48aSSascha Wildner 	}
9421c1c48aSSascha Wildner 	dfui_debug("opening pipes...\n");
9521c1c48aSSascha Wildner 	if ((T_NPIPE(c)->out = fopen(T_NPIPE(c)->out_pipename, "w")) == NULL) {
9621c1c48aSSascha Wildner 		return(DFUI_FAILURE);
9721c1c48aSSascha Wildner 	}
9821c1c48aSSascha Wildner 	dfui_debug("opened to_fe pipe\n");
9921c1c48aSSascha Wildner 	setvbuf(T_NPIPE(c)->out, NULL, _IONBF, 0);
10021c1c48aSSascha Wildner 	if ((T_NPIPE(c)->in = fopen(T_NPIPE(c)->in_pipename, "r")) == NULL) {
10121c1c48aSSascha Wildner 		fclose(T_NPIPE(c)->out);
10221c1c48aSSascha Wildner 		return(DFUI_FAILURE);
10321c1c48aSSascha Wildner 	}
10421c1c48aSSascha Wildner 	dfui_debug("opened to_be pipe\n");
10521c1c48aSSascha Wildner 	return(DFUI_SUCCESS);
10621c1c48aSSascha Wildner }
10721c1c48aSSascha Wildner 
10821c1c48aSSascha Wildner /*
10921c1c48aSSascha Wildner  * Tell the frontend that we're done and disconnect from it.
11021c1c48aSSascha Wildner  */
11121c1c48aSSascha Wildner dfui_err_t
dfui_npipe_be_stop(struct dfui_connection * c)11221c1c48aSSascha Wildner dfui_npipe_be_stop(struct dfui_connection *c)
11321c1c48aSSascha Wildner {
11421c1c48aSSascha Wildner 	if (dfui_npipe_be_ll_exchange(c, DFUI_BE_MSG_STOP, "")) {
11521c1c48aSSascha Wildner 		fclose(T_NPIPE(c)->in);
11621c1c48aSSascha Wildner 		fclose(T_NPIPE(c)->out);
11721c1c48aSSascha Wildner 		return(DFUI_SUCCESS);
11821c1c48aSSascha Wildner 	} else
11921c1c48aSSascha Wildner 		return(DFUI_FAILURE);
12021c1c48aSSascha Wildner }
12121c1c48aSSascha Wildner 
12221c1c48aSSascha Wildner /** Low Level **/
12321c1c48aSSascha Wildner 
12421c1c48aSSascha Wildner /*
12521c1c48aSSascha Wildner  * Exchange a message with the frontend.  This involves two receive()/reply()
12621c1c48aSSascha Wildner  * cycles: one to provide our message, one to get a reply from the frontend.
12721c1c48aSSascha Wildner  *
12821c1c48aSSascha Wildner  * Note that this does not immediately send the message to the frontend -
12921c1c48aSSascha Wildner  * it can't, because we're a service and it's a client.  What it does is
13021c1c48aSSascha Wildner  * keep the message handy and wait for a frontend request to come in.  It
13121c1c48aSSascha Wildner  * then replies to that request with our message.
13221c1c48aSSascha Wildner  *
13321c1c48aSSascha Wildner  * The protocol looks something like the following, using the PRESENT and
13421c1c48aSSascha Wildner  * SUBMIT exchange as an example:
13521c1c48aSSascha Wildner  *
13621c1c48aSSascha Wildner  * frontend (client) | backend (service)
13721c1c48aSSascha Wildner  * ------------------+------------------
13821c1c48aSSascha Wildner  *
13921c1c48aSSascha Wildner  *                                     [stage 1]
14021c1c48aSSascha Wildner  * READY            -->                ll_receive()
14121c1c48aSSascha Wildner  *                 <--  PRESENT(form)  ll_reply()
14221c1c48aSSascha Wildner  *
14321c1c48aSSascha Wildner  *                                     [stage 2]
14421c1c48aSSascha Wildner  * SUBMIT(form)     -->                ll_receive()
14521c1c48aSSascha Wildner  *                 <--  READY          ll_reply()
14621c1c48aSSascha Wildner  *
14721c1c48aSSascha Wildner  * Each of those exchanges is a pair of calls, on our end, to
14821c1c48aSSascha Wildner  * dfui_npipe_be_ll_receive() and dfui_npipe_be_ll_reply().
14921c1c48aSSascha Wildner  *
15021c1c48aSSascha Wildner  * The set of messages that the client can pass us is determined by
15121c1c48aSSascha Wildner  * the conversation state:
15221c1c48aSSascha Wildner  *
15321c1c48aSSascha Wildner  *   o  In stage 1, only READY and ABORT are meaningful.
15421c1c48aSSascha Wildner  *   o  After a PRESENT, the messages SUBMIT and ABORT are meaningul
15521c1c48aSSascha Wildner  *      in stage 2.
15621c1c48aSSascha Wildner  *   o  During a PROG_*, the messages CONTINUE, CANCEL, and ABORT
15721c1c48aSSascha Wildner  *      are meaningful in stage 2.
15821c1c48aSSascha Wildner  *
15921c1c48aSSascha Wildner  * If the frontend sends us with READY in stage 2, we assume it has
16021c1c48aSSascha Wildner  * fallen out of sync, so we send the same initial reply again, going
16121c1c48aSSascha Wildner  * back to stage 1 as it were.
16221c1c48aSSascha Wildner  *
16321c1c48aSSascha Wildner  * After this call, the message is available in c->ebuf.
16421c1c48aSSascha Wildner  */
16521c1c48aSSascha Wildner dfui_err_t
dfui_npipe_be_ll_exchange(struct dfui_connection * c,char msgtype,const char * msg)16621c1c48aSSascha Wildner dfui_npipe_be_ll_exchange(struct dfui_connection *c, char msgtype, const char *msg)
16721c1c48aSSascha Wildner {
16821c1c48aSSascha Wildner 	char *fmsg;
16921c1c48aSSascha Wildner 
17021c1c48aSSascha Wildner 	/*
17121c1c48aSSascha Wildner 	 * Construct our message to send.
17221c1c48aSSascha Wildner 	 */
17321c1c48aSSascha Wildner 
17421c1c48aSSascha Wildner 	fmsg = malloc(strlen(msg) + 2);
17521c1c48aSSascha Wildner 	fmsg[0] = msgtype;
17621c1c48aSSascha Wildner 	strcpy(fmsg + 1, msg);
17721c1c48aSSascha Wildner 
17821c1c48aSSascha Wildner 	/*
17921c1c48aSSascha Wildner 	 * Get the frontend's message.
18021c1c48aSSascha Wildner 	 */
18121c1c48aSSascha Wildner 
18221c1c48aSSascha Wildner 	dfui_npipe_be_ll_receive(c);
18321c1c48aSSascha Wildner 
18421c1c48aSSascha Wildner 	/*
18521c1c48aSSascha Wildner 	 * Frontend message should have been either READY or ABORT.
18621c1c48aSSascha Wildner 	 * If ABORT, we get out of here pronto.
18721c1c48aSSascha Wildner 	 */
18821c1c48aSSascha Wildner 
18921c1c48aSSascha Wildner 	if (aura_buffer_buf(c->ebuf)[0] == DFUI_FE_MSG_ABORT) {
19021c1c48aSSascha Wildner 		free(fmsg);
19121c1c48aSSascha Wildner 		return(DFUI_FAILURE);
19221c1c48aSSascha Wildner 	}
19321c1c48aSSascha Wildner 
19421c1c48aSSascha Wildner 	/* XXX if (!READY) ??? */
19521c1c48aSSascha Wildner 
19621c1c48aSSascha Wildner 	do {
19721c1c48aSSascha Wildner 		dfui_npipe_be_ll_reply(c, fmsg);
19821c1c48aSSascha Wildner 
19921c1c48aSSascha Wildner 		/*
20021c1c48aSSascha Wildner 		 * Here, the frontend has picked up our request and is
20121c1c48aSSascha Wildner 		 * processing it.  We have to wait for the response.
20221c1c48aSSascha Wildner 		 */
20321c1c48aSSascha Wildner 
20421c1c48aSSascha Wildner 		dfui_npipe_be_ll_receive(c);
20521c1c48aSSascha Wildner 
20621c1c48aSSascha Wildner 		/*
20721c1c48aSSascha Wildner 		 * Did we get READY from this?
20821c1c48aSSascha Wildner 		 * If so, loop!
20921c1c48aSSascha Wildner 		 */
21021c1c48aSSascha Wildner 
21121c1c48aSSascha Wildner 	} while (aura_buffer_buf(c->ebuf)[0] == DFUI_FE_MSG_READY);
21221c1c48aSSascha Wildner 
21321c1c48aSSascha Wildner 	fmsg[0] = DFUI_BE_MSG_READY;
21421c1c48aSSascha Wildner 	fmsg[1] = '\0';
21521c1c48aSSascha Wildner 	dfui_npipe_be_ll_reply(c, fmsg);
21621c1c48aSSascha Wildner 
21721c1c48aSSascha Wildner 	free(fmsg);
21821c1c48aSSascha Wildner 	return(DFUI_SUCCESS);
21921c1c48aSSascha Wildner }
22021c1c48aSSascha Wildner 
22121c1c48aSSascha Wildner /*
22221c1c48aSSascha Wildner  * Receive a message from the frontend.
22321c1c48aSSascha Wildner  * This call is synchronous.
22421c1c48aSSascha Wildner  * After this call, the NUL-terminated message is available in
22521c1c48aSSascha Wildner  * c->ebuf.
22621c1c48aSSascha Wildner  */
22721c1c48aSSascha Wildner dfui_err_t
dfui_npipe_be_ll_receive(struct dfui_connection * c)22821c1c48aSSascha Wildner dfui_npipe_be_ll_receive(struct dfui_connection *c)
22921c1c48aSSascha Wildner {
23021c1c48aSSascha Wildner 	int length;
23121c1c48aSSascha Wildner 	char *buf;
23221c1c48aSSascha Wildner 
23321c1c48aSSascha Wildner 	dfui_debug("WAITING<<>>\n");
23421c1c48aSSascha Wildner 
23521c1c48aSSascha Wildner 	fread(&length, 4, 1, T_NPIPE(c)->in);
23621c1c48aSSascha Wildner 
23721c1c48aSSascha Wildner 	dfui_debug("LENGTH<<%d>>\n", length);
23821c1c48aSSascha Wildner 
23921c1c48aSSascha Wildner 	buf = malloc(length + 1);
24021c1c48aSSascha Wildner 	fread(buf, length, 1, T_NPIPE(c)->in);
24121c1c48aSSascha Wildner 	aura_buffer_set(c->ebuf, buf, length);
24221c1c48aSSascha Wildner 	free(buf);
24321c1c48aSSascha Wildner 
24421c1c48aSSascha Wildner 	dfui_debug("RECEIVED<<%s>>\n", aura_buffer_buf(c->ebuf));
24521c1c48aSSascha Wildner 
24621c1c48aSSascha Wildner 	return(DFUI_SUCCESS);
24721c1c48aSSascha Wildner }
24821c1c48aSSascha Wildner 
24921c1c48aSSascha Wildner /*
25021c1c48aSSascha Wildner  * Send a NUL-terminated reply to the frontend.
25121c1c48aSSascha Wildner  */
25221c1c48aSSascha Wildner dfui_err_t
dfui_npipe_be_ll_reply(struct dfui_connection * c,const char * fmsg)25321c1c48aSSascha Wildner dfui_npipe_be_ll_reply(struct dfui_connection *c, const char *fmsg)
25421c1c48aSSascha Wildner {
25521c1c48aSSascha Wildner 	int length;
25621c1c48aSSascha Wildner 
25721c1c48aSSascha Wildner 	dfui_debug("SEND<<%s>>\n", fmsg);
25821c1c48aSSascha Wildner 
25921c1c48aSSascha Wildner 	length = strlen(fmsg);
26021c1c48aSSascha Wildner 
26121c1c48aSSascha Wildner 	fwrite(&length, 4, 1, T_NPIPE(c)->out);
26221c1c48aSSascha Wildner 	fwrite(fmsg, length, 1, T_NPIPE(c)->out);
26321c1c48aSSascha Wildner 
26421c1c48aSSascha Wildner 	return(DFUI_SUCCESS);
26521c1c48aSSascha Wildner }
26621c1c48aSSascha Wildner 
26721c1c48aSSascha Wildner /******** FRONTEND ********/
26821c1c48aSSascha Wildner 
26921c1c48aSSascha Wildner /** High Level **/
27021c1c48aSSascha Wildner 
27121c1c48aSSascha Wildner dfui_err_t
dfui_npipe_fe_connect(struct dfui_connection * c)27221c1c48aSSascha Wildner dfui_npipe_fe_connect(struct dfui_connection *c)
27321c1c48aSSascha Wildner {
27421c1c48aSSascha Wildner 	asprintf(&T_NPIPE(c)->in_pipename, "/tmp/dfui.%s.to_fe", c->rendezvous);
27521c1c48aSSascha Wildner 	asprintf(&T_NPIPE(c)->out_pipename, "/tmp/dfui.%s.from_fe", c->rendezvous);
27621c1c48aSSascha Wildner 
27721c1c48aSSascha Wildner 	dfui_debug("waiting for named pipes...\n");
27821c1c48aSSascha Wildner 
27921c1c48aSSascha Wildner 	/*
28021c1c48aSSascha Wildner 	 * Wait for named pipes to be created.
28121c1c48aSSascha Wildner 	 */
282*9462167aSSascha Wildner 	if (!is_named_pipe("%s", T_NPIPE(c)->in_pipename)) {
283*9462167aSSascha Wildner 		while (!is_named_pipe("%s", T_NPIPE(c)->in_pipename)) {
28421c1c48aSSascha Wildner 			sleep(1);
28521c1c48aSSascha Wildner 		}
28621c1c48aSSascha Wildner 		sleep(1);
28721c1c48aSSascha Wildner 	}
28821c1c48aSSascha Wildner 
28921c1c48aSSascha Wildner 	dfui_debug("opening inflow pipe...\n");
29021c1c48aSSascha Wildner 
29121c1c48aSSascha Wildner 	if ((T_NPIPE(c)->in = fopen(T_NPIPE(c)->in_pipename, "r")) == NULL) {
29221c1c48aSSascha Wildner 		return(DFUI_FAILURE);
29321c1c48aSSascha Wildner 	}
29421c1c48aSSascha Wildner 
29521c1c48aSSascha Wildner 	dfui_debug("opening outflow pipe...\n");
29621c1c48aSSascha Wildner 
29721c1c48aSSascha Wildner 	if ((T_NPIPE(c)->out = fopen(T_NPIPE(c)->out_pipename, "w")) == NULL) {
29821c1c48aSSascha Wildner 		fclose(T_NPIPE(c)->in);
29921c1c48aSSascha Wildner 		return(DFUI_FAILURE);
30021c1c48aSSascha Wildner 	}
30121c1c48aSSascha Wildner 
30221c1c48aSSascha Wildner 	dfui_debug("making outflow pipe raw...\n");
30321c1c48aSSascha Wildner 
30421c1c48aSSascha Wildner 	setvbuf(T_NPIPE(c)->out, NULL, _IONBF, 0);
30521c1c48aSSascha Wildner 	return(DFUI_SUCCESS);
30621c1c48aSSascha Wildner }
30721c1c48aSSascha Wildner 
30821c1c48aSSascha Wildner dfui_err_t
dfui_npipe_fe_disconnect(struct dfui_connection * c)30921c1c48aSSascha Wildner dfui_npipe_fe_disconnect(struct dfui_connection *c)
31021c1c48aSSascha Wildner {
31121c1c48aSSascha Wildner 	fclose(T_NPIPE(c)->in);
31221c1c48aSSascha Wildner 	fclose(T_NPIPE(c)->out);
31321c1c48aSSascha Wildner 	return(DFUI_SUCCESS);
31421c1c48aSSascha Wildner }
31521c1c48aSSascha Wildner 
31621c1c48aSSascha Wildner /** Low Level **/
31721c1c48aSSascha Wildner 
31821c1c48aSSascha Wildner /*
31921c1c48aSSascha Wildner  * Ask for, and subsequently receieve, a message from the backend.
32021c1c48aSSascha Wildner  * msgtype should be one of the DFUI_FE_MSG_* constants.
32121c1c48aSSascha Wildner  * This call is synchronous.
32221c1c48aSSascha Wildner  * After this call, the null-terminated, encoded message is
32321c1c48aSSascha Wildner  * available in T_NPIPE(c)->buf.
32421c1c48aSSascha Wildner  */
32521c1c48aSSascha Wildner dfui_err_t
dfui_npipe_fe_ll_request(struct dfui_connection * c,char msgtype,const char * msg)32621c1c48aSSascha Wildner dfui_npipe_fe_ll_request(struct dfui_connection *c, char msgtype, const char *msg)
32721c1c48aSSascha Wildner {
32821c1c48aSSascha Wildner 	char *fmsg, *buf;
32921c1c48aSSascha Wildner 	int length;
33021c1c48aSSascha Wildner 
33121c1c48aSSascha Wildner 	/*
33221c1c48aSSascha Wildner 	 * First, assert that the connection is open.
33321c1c48aSSascha Wildner 	 */
33421c1c48aSSascha Wildner 
33521c1c48aSSascha Wildner 	if (c == NULL || T_NPIPE(c)->in == NULL || T_NPIPE(c)->out == NULL)
33621c1c48aSSascha Wildner 		return(DFUI_FAILURE);
33721c1c48aSSascha Wildner 
33821c1c48aSSascha Wildner 	/*
33921c1c48aSSascha Wildner 	 * Construct a message.
34021c1c48aSSascha Wildner 	 */
34121c1c48aSSascha Wildner 
34221c1c48aSSascha Wildner 	fmsg = malloc(strlen(msg) + 2);
34321c1c48aSSascha Wildner 	fmsg[0] = msgtype;
34421c1c48aSSascha Wildner 	strcpy(fmsg + 1, msg);
34521c1c48aSSascha Wildner 
34621c1c48aSSascha Wildner 	dfui_debug("SEND<<%s>>\n", fmsg);
34721c1c48aSSascha Wildner 
34821c1c48aSSascha Wildner 	/*
34921c1c48aSSascha Wildner 	 * Send a NUL-terminated message to the backend.
35021c1c48aSSascha Wildner 	 */
35121c1c48aSSascha Wildner 
35221c1c48aSSascha Wildner 	length = strlen(fmsg);
35321c1c48aSSascha Wildner 	fwrite(&length, 4, 1, T_NPIPE(c)->out);
35421c1c48aSSascha Wildner 	fwrite(fmsg, length, 1, T_NPIPE(c)->out);
35521c1c48aSSascha Wildner 
35621c1c48aSSascha Wildner 	/*
35721c1c48aSSascha Wildner 	 * Receive a reply from the backend.
35821c1c48aSSascha Wildner 	 * If our message was a READY, this should be a message like PRESENT.
35921c1c48aSSascha Wildner 	 * Otherwise it should simply be a READY.
36021c1c48aSSascha Wildner 	 */
36121c1c48aSSascha Wildner 
36221c1c48aSSascha Wildner 	dfui_debug("WAITING<<>>\n");
36321c1c48aSSascha Wildner 
36421c1c48aSSascha Wildner 	fread(&length, 4, 1, T_NPIPE(c)->in);
36521c1c48aSSascha Wildner 	buf = malloc(length + 1);
36621c1c48aSSascha Wildner 	fread(buf, length, 1, T_NPIPE(c)->in);
36721c1c48aSSascha Wildner 	aura_buffer_set(c->ebuf, buf, length);
36821c1c48aSSascha Wildner 	free(buf);
36921c1c48aSSascha Wildner 
37021c1c48aSSascha Wildner 	dfui_debug("RECV<<%s>>\n", aura_buffer_buf(c->ebuf));
37121c1c48aSSascha Wildner 
37221c1c48aSSascha Wildner 	free(fmsg);
37321c1c48aSSascha Wildner 
37421c1c48aSSascha Wildner 	return(DFUI_SUCCESS);
37521c1c48aSSascha Wildner }
37621c1c48aSSascha Wildner 
37721c1c48aSSascha Wildner #endif /* HAS_NPIPE */
378