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
mflush(MESG * md)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
mwrite(MESG * md,char * msgbuf)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
_mwrite(MESG * md,char * msgbuf,int size)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