1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License").  You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22/*
23 * Copyright 1997 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 */
26
27/*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
28/*	  All Rights Reserved  	*/
29
30
31#pragma ident	"%Z%%M%	%I%	%E% SMI"	/* SVr4.0 1.8	*/
32/* LINTLIBRARY */
33
34# include	<errno.h>
35# include	<string.h>
36# include	<stropts.h>
37
38# include	"lp.h"
39# include	"msgs.h"
40
41int	Lp_prio_msg = 0;
42
43static int	_mwrite ( MESG * md , char * msgbuf , int );
44
45/*
46 * mflush()
47 *	return 0
48 *		if it successfully writes all the queued message(s), or
49 *		if some of them (errno is EAGAIN in this case).
50 *	return -1 (with errno) when it failed.
51 */
52
53int
54mflush(MESG *md)
55{
56	MQUE	*p;
57
58	errno = 0;
59	if (md == NULL || md->mque == NULL) {
60		errno = ENXIO;
61		return (-1);
62	}
63
64	while ((p = md->mque) != NULL) {
65		if (_mwrite(md, p->dat->buf, p->dat->len) != 0)
66			return (errno == EAGAIN ? 0 : -1);
67
68		/* mwrite successful, get the next and free this entry */
69		md->mque = p->next;
70		Free(p->dat->buf);
71		Free(p->dat);
72		Free(p);
73	}
74
75	return (0);
76}
77
78/*
79 * mwrite()
80 *	return 0
81 *		if it successfully writes the messages, or
82 *		if it has been queued  (errno is EAGAIN in this case)
83 *			and md->mque is updated.
84 *	return -1 (with errno) when it failed.
85 */
86
87int mwrite ( MESG * md, char * msgbuf )
88{
89    short		size;
90    MQUE *		p;
91    MQUE *		q;
92
93    errno = 0;
94    if (md == NULL)
95    {
96	errno = ENXIO;
97	return(-1);
98    }
99    if (msgbuf == NULL)
100    {
101	errno = EINVAL;
102	return(-1);
103    }
104
105    size = stoh(msgbuf);
106
107    if (LAST_MESSAGE < stoh(msgbuf + MESG_TYPE))
108    {
109	errno = EINVAL;
110	return (-1);
111    }
112    if (md->mque)
113	goto queue;	/* if there is a queue already, try to write all */
114
115    if (_mwrite(md, msgbuf, size) == 0)
116	return(0);
117
118    if (errno != EAGAIN)
119	return(-1);
120
121	/*
122	 * fall through to queue the messages that cannot be sent now.
123	 */
124
125queue:
126    if ((p = (MQUE *)Malloc(sizeof(MQUE))) == NULL
127        || (p->dat = (struct strbuf *)Malloc(sizeof(struct strbuf))) == NULL
128    	|| (p->dat->buf = (char *)Malloc(size)) == NULL)
129    {
130	errno = ENOMEM;
131	return(-1);
132    }
133    (void) memcpy(p->dat->buf, msgbuf, size);
134    p->dat->len = size;
135    p->next = 0;
136
137    if ((q = md->mque) != NULL)
138    {
139	/* insert the new one to tail */
140	while (q->next)
141	    q = q->next;
142	q->next = p;
143
144    	while ((p = md->mque) != NULL)
145    	{
146		if (_mwrite(md, p->dat->buf, p->dat->len) != 0) {
147	    		return (errno == EAGAIN ? 0 : -1);
148		}
149
150		/* mwrite successful, get the next and free this entry */
151		md->mque = p->next;
152		Free(p->dat->buf);
153		Free(p->dat);
154		Free(p);
155	}
156    }
157    else
158    	md->mque = p;
159
160    return(0);
161}
162
163int _mwrite ( MESG * md, char * msgbuf , int size )
164{
165    int			flag = 0;
166    struct strbuf	ctl;
167    struct strbuf	dat;
168
169    switch (md->type)
170    {
171        case MD_CHILD:
172	case MD_STREAM:
173	case MD_BOUND:
174	    if (size <= 0 || size > MSGMAX)
175	    {
176		errno = EINVAL;
177		return(-1);
178	    }
179
180	    ctl.buf = "xyzzy";
181	    ctl.maxlen = ctl.len = strlen(ctl.buf)+1;
182	    dat.buf = msgbuf;
183	    dat.maxlen = dat.len = size;
184	    flag = Lp_prio_msg;
185	    Lp_prio_msg = 0;	/* clean this up so there are no surprises */
186
187	    if (Putmsg(md, &ctl, &dat, flag) == 0)
188		return(0);
189	    return(-1);
190
191	case MD_SYS_FIFO:
192	case MD_USR_FIFO:
193	    switch (write3_2(md, msgbuf, size))
194	    {
195		case -1:
196		    return(-1);
197		case 0:
198		    break;
199		default:
200		    return(0);
201	    }
202	    break;
203
204	default:
205	    errno = EINVAL;
206	    return(-1);
207    }
208    return 0;
209}
210