xref: /illumos-gate/usr/src/cmd/lp/lib/msgs/mwrite.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
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
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 
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 
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