xref: /titanic_50/usr/src/lib/libbc/libc/stdio/common/fputs.c (revision 1cb6af97c6f66f456d4f726ef056e1ebc0f73305)
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 (c) 1995, by Sun Microsystems, Inc.
24  * All rights reserved.
25  */
26 
27 /*      Copyright (c) 1984 AT&T */
28 /*        All Rights Reserved   */
29 
30 #pragma ident	"%Z%%M%	%I%	%E% SMI"
31 
32 
33 /*LINTLIBRARY*/
34 /*
35  * This version writes directly to the buffer rather than looping on putc.
36  * Ptr args aren't checked for NULL because the program would be a
37  * catastrophic mess anyway.  Better to abort than just to return NULL.
38  */
39 #include <stdio.h>
40 #include "stdiom.h"
41 #include <errno.h>
42 
43 extern char *memccpy();
44 static char *memnulccpy();
45 
46 int
47 fputs(ptr, iop)
48 char *ptr;
49 register FILE *iop;
50 {
51 	register int ndone = 0, n;
52 	register unsigned char *cptr, *bufend;
53 	register char *p;
54 	register char c;
55 
56 	if (_WRTCHK(iop)) {
57 		iop->_flag |= _IOERR;
58 #ifdef POSIX
59 		errno = EBADF;
60 #endif POSIX
61 		return (EOF);
62 	}
63 	bufend = iop->_base + iop->_bufsiz;
64 
65 	if ((iop->_flag & _IONBF) == 0)  {
66 		if (iop->_flag & _IOLBF) {
67 			for ( ; ; ptr += n) {
68 				while ((n = bufend - (cptr = iop->_ptr)) <= 0)
69 					/* full buf */
70 					if (_xflsbuf(iop) == EOF)
71 						return(EOF);
72 				if ((p = memnulccpy((char *) cptr, ptr, '\n', n)) != NULL) {
73 					/*
74 					 * Copy terminated either because we
75 					 * saw a newline or we saw a NUL (end
76 					 * of string).
77 					 */
78 					c = *(p - 1);	/* last character moved */
79 					if (c == '\0')
80 						p--;	/* didn't write '\0' */
81 					n = p - (char *) cptr;
82 				}
83 				iop->_cnt -= n;
84 				iop->_ptr += n;
85 				_BUFSYNC(iop);
86 				ndone += n;
87 				if (p != NULL) {
88 					/*
89 					 * We found either a newline or a NUL.
90 					 * If we found a newline, flush the
91 					 * buffer.
92 					 * If we found a NUL, we're done.
93 					 */
94 					if (c == '\n') {
95 						if (_xflsbuf(iop) == EOF)
96 							return(EOF);
97 					} else {
98 						/* done */
99 						return(ndone);
100 					}
101 		       		}
102 			}
103 		} else {
104 			for ( ; ; ptr += n) {
105 				while ((n = bufend - (cptr = iop->_ptr)) <= 0)
106 					/* full buf */
107 					if (_xflsbuf(iop) == EOF)
108 						return(EOF);
109 				if ((p = memccpy((char *) cptr, ptr, '\0', n)) != NULL)
110 					n = (p - (char *) cptr) - 1;
111 				iop->_cnt -= n;
112 				iop->_ptr += n;
113 				_BUFSYNC(iop);
114 				ndone += n;
115 				if (p != NULL)  {
116 					/* done */
117 		       			return(ndone);
118 		       		}
119 			}
120 		}
121 	}  else  {
122 		/* write out to an unbuffered file */
123 		return (write(iop->_file, ptr, strlen(ptr)));
124 	}
125 }
126 
127 /*
128  * Copy s2 to s1, stopping if character c or a NUL is copied.
129  * Copy no more than n bytes.
130  * Return a pointer to the byte after character c or NUL in the copy,
131  * or NULL if c or NUL is not found in the first n bytes.
132  */
133 static char *
134 memnulccpy(s1, s2, c, n)
135 register char *s1, *s2;
136 register int c, n;
137 {
138 	register int cmoved;
139 
140 	while (--n >= 0) {
141 		cmoved = *s2++;
142 		if ((*s1++ = cmoved) == '\0' || cmoved == c)
143 			return (s1);
144 	}
145 	return (0);
146 }
147