xref: /illumos-gate/usr/src/cmd/lp/lib/msgs/mwrite.c (revision ef150c2b)
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 /* LINTLIBRARY */
31 
32 # include	<errno.h>
33 # include	<string.h>
34 # include	<stropts.h>
35 
36 # include	"lp.h"
37 # include	"msgs.h"
38 
39 int	Lp_prio_msg = 0;
40 
41 static int	_mwrite ( MESG * md , char * msgbuf , int );
42 
43 /*
44  * mflush()
45  *	return 0
46  *		if it successfully writes all the queued message(s), or
47  *		if some of them (errno is EAGAIN in this case).
48  *	return -1 (with errno) when it failed.
49  */
50 
51 int
52 mflush(MESG *md)
53 {
54 	MQUE	*p;
55 
56 	errno = 0;
57 	if (md == NULL || md->mque == NULL) {
58 		errno = ENXIO;
59 		return (-1);
60 	}
61 
62 	while ((p = md->mque) != NULL) {
63 		if (_mwrite(md, p->dat->buf, p->dat->len) != 0)
64 			return (errno == EAGAIN ? 0 : -1);
65 
66 		/* mwrite successful, get the next and free this entry */
67 		md->mque = p->next;
68 		Free(p->dat->buf);
69 		Free(p->dat);
70 		Free(p);
71 	}
72 
73 	return (0);
74 }
75 
76 /*
77  * mwrite()
78  *	return 0
79  *		if it successfully writes the messages, or
80  *		if it has been queued  (errno is EAGAIN in this case)
81  *			and md->mque is updated.
82  *	return -1 (with errno) when it failed.
83  */
84 
85 int mwrite ( MESG * md, char * msgbuf )
86 {
87     short		size;
88     MQUE *		p;
89     MQUE *		q;
90 
91     errno = 0;
92     if (md == NULL)
93     {
94 	errno = ENXIO;
95 	return(-1);
96     }
97     if (msgbuf == NULL)
98     {
99 	errno = EINVAL;
100 	return(-1);
101     }
102 
103     size = stoh(msgbuf);
104 
105     if (LAST_MESSAGE < stoh(msgbuf + MESG_TYPE))
106     {
107 	errno = EINVAL;
108 	return (-1);
109     }
110     if (md->mque)
111 	goto queue;	/* if there is a queue already, try to write all */
112 
113     if (_mwrite(md, msgbuf, size) == 0)
114 	return(0);
115 
116     if (errno != EAGAIN)
117 	return(-1);
118 
119 	/*
120 	 * fall through to queue the messages that cannot be sent now.
121 	 */
122 
123 queue:
124     if ((p = (MQUE *)Malloc(sizeof(MQUE))) == NULL
125         || (p->dat = (struct strbuf *)Malloc(sizeof(struct strbuf))) == NULL
126     	|| (p->dat->buf = (char *)Malloc(size)) == NULL)
127     {
128 	errno = ENOMEM;
129 	return(-1);
130     }
131     (void) memcpy(p->dat->buf, msgbuf, size);
132     p->dat->len = size;
133     p->next = 0;
134 
135     if ((q = md->mque) != NULL)
136     {
137 	/* insert the new one to tail */
138 	while (q->next)
139 	    q = q->next;
140 	q->next = p;
141 
142     	while ((p = md->mque) != NULL)
143     	{
144 		if (_mwrite(md, p->dat->buf, p->dat->len) != 0) {
145 	    		return (errno == EAGAIN ? 0 : -1);
146 		}
147 
148 		/* mwrite successful, get the next and free this entry */
149 		md->mque = p->next;
150 		Free(p->dat->buf);
151 		Free(p->dat);
152 		Free(p);
153 	}
154     }
155     else
156     	md->mque = p;
157 
158     return(0);
159 }
160 
161 int _mwrite ( MESG * md, char * msgbuf , int size )
162 {
163     int			flag = 0;
164     struct strbuf	ctl;
165     struct strbuf	dat;
166 
167     switch (md->type)
168     {
169         case MD_CHILD:
170 	case MD_STREAM:
171 	case MD_BOUND:
172 	    if (size <= 0 || size > MSGMAX)
173 	    {
174 		errno = EINVAL;
175 		return(-1);
176 	    }
177 
178 	    ctl.buf = "xyzzy";
179 	    ctl.maxlen = ctl.len = strlen(ctl.buf)+1;
180 	    dat.buf = msgbuf;
181 	    dat.maxlen = dat.len = size;
182 	    flag = Lp_prio_msg;
183 	    Lp_prio_msg = 0;	/* clean this up so there are no surprises */
184 
185 	    if (Putmsg(md, &ctl, &dat, flag) == 0)
186 		return(0);
187 	    return(-1);
188 
189 	case MD_SYS_FIFO:
190 	case MD_USR_FIFO:
191 	    switch (write3_2(md, msgbuf, size))
192 	    {
193 		case -1:
194 		    return(-1);
195 		case 0:
196 		    break;
197 		default:
198 		    return(0);
199 	    }
200 	    break;
201 
202 	default:
203 	    errno = EINVAL;
204 	    return(-1);
205     }
206     return 0;
207 }
208