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
41 int Lp_prio_msg = 0;
42
43 static 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
53 int
mflush(MESG * md)54 mflush(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
mwrite(MESG * md,char * msgbuf)87 int 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
125 queue:
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
_mwrite(MESG * md,char * msgbuf,int size)163 int _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