Detabbed
[AROS.git] / rom / dos / setvbuf.c
bloba6cd7b0ecd3cda3a44b1ccc06f8b61f63479fb00
1 /*
2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #include <aros/debug.h>
8 #include <proto/exec.h>
10 #include "dos_intern.h"
12 /*****************************************************************************
14 NAME */
15 #include <dos/stdio.h>
16 #include <proto/dos.h>
18 AROS_LH4(LONG, SetVBuf,
20 /* SetVBuf -- set buffering modes and size */
22 /* SYNOPSIS */
23 AROS_LHA(BPTR , file, D1),
24 AROS_LHA(STRPTR, buff, D2),
25 AROS_LHA(LONG , type, D3),
26 AROS_LHA(LONG , size, D4),
28 /* LOCATION */
29 struct DosLibrary *, DOSBase, 61, Dos)
31 /* FUNCTION
32 Changes the buffering modes and buffer size for a filehandle.
33 With buff == NULL, the current buffer will be deallocated (if it
34 was not a user-supplied one) and a new one of (approximately) size
35 will be allocated. If buffer is non-NULL, it will be used for
36 buffering and must be at least max(size,208) bytes long, and MUST
37 be longword aligned. If size is -1, then only the buffering mode
38 will be changed.
40 INPUTS
41 file - Filehandle
42 buff - buffer pointer for buffered I/O or NULL.
43 type - buffering mode (see <dos/stdio.h>)
44 size - size of buffer for buffered I/O (sizes less than 208 bytes
45 will be rounded up to 208), or -1.
47 RESULT
48 0 if operation succeeded.
50 *****************************************************************************/
52 AROS_LIBFUNC_INIT
54 struct FileHandle *fh = (struct FileHandle *)BADDR(file);
56 if (fh == NULL)
57 return EOF;
59 ASSERT_VALID_PTR( fh );
60 ASSERT_VALID_PTR_OR_NULL(buff);
62 D(bug("[SetVBuf] file=%p, buff=%p (was %p), mode=%d (flags 0x%x), size %d (was %d)\n", file, buff, BADDR(fh->fh_Buf), type, fh->fh_Flags, size, fh->fh_BufSize));
64 /* Ensure that buff is BPTR aligned */
65 if (buff != BADDR(MKBADDR(buff)))
66 return EOF;
68 switch (type)
70 case BUF_LINE:
71 fh->fh_Flags = (fh->fh_Flags & ~FHF_NOBUF) | FHF_LINEBUF;
72 break;
74 case BUF_FULL:
75 fh->fh_Flags = fh->fh_Flags & ~(FHF_NOBUF | FHF_LINEBUF);
76 break;
78 case BUF_NONE:
79 fh->fh_Flags = (fh->fh_Flags | FHF_NOBUF) & ~FHF_LINEBUF;
80 break;
82 default:
83 return EOF;
86 if (size >= 0)
88 if (fh->fh_OrigBuf == fh->fh_Buf) {
89 vbuf_free(fh);
90 } else {
91 /* Not ours, so we're not going to free it. */
93 if (!vbuf_alloc(fh, buff, size))
94 return EOF;
97 return 0;
99 AROS_LIBFUNC_EXIT
100 } /* SetVBuf */
103 void
104 vbuf_free(FileHandlePtr fh)
106 if (fh->fh_Flags & FHF_BUF)
108 /* free buffer allocated by system */
109 if (fh->fh_Flags & FHF_OWNBUF)
110 FreeMem(BADDR(fh->fh_Buf), fh->fh_BufSize);
112 fh->fh_Buf = BNULL;
113 fh->fh_Pos = fh->fh_End = 0;
114 fh->fh_BufSize = 0;
115 fh->fh_OrigBuf = BNULL;
118 fh->fh_Flags &= ~(FHF_BUF | FHF_OWNBUF);
121 APTR vbuf_alloc(FileHandlePtr fh, STRPTR buf, ULONG size)
123 ULONG flags = FHF_BUF;
125 if (size < 208)
126 size = 208;
128 if (!buf)
130 buf = AllocMem(size, MEMF_ANY);
131 fh->fh_OrigBuf = MKBADDR(buf);
132 flags |= FHF_OWNBUF;
135 if (NULL != buf)
137 fh->fh_BufSize = size;
138 fh->fh_Flags |= flags;
139 fh->fh_Buf = MKBADDR(buf);
140 fh->fh_Pos = 0;
141 fh->fh_End = (fh->fh_Flags & FHF_WRITE) ? fh->fh_BufSize : 0;
144 return buf;
147 BOOL vbuf_inject(BPTR fh, CONST_STRPTR argptr, ULONG size, struct DosLibrary *DOSBase)
149 FileHandlePtr fhinput;
150 STRPTR buf;
152 if (!fh || !argptr)
153 return FALSE;
154 fhinput = BADDR(fh);
156 /* Handle the trivial case, where we have enough room
157 * in the minimal buffer.
159 * For AOS 1.3 C:Run compatabilty, the injected buffer
160 * MUST start at Pos==0. Yes, that stupid command does
161 * not check that fh_Pos is nonzero.
163 if ((fhinput->fh_Flags & FHF_BUF) && size <= 208) {
164 CopyMem(argptr, BADDR(fhinput->fh_Buf), size);
165 fhinput->fh_Pos = 0;
166 fhinput->fh_End = size;
167 return TRUE;
170 /* Check to see if this FileHandle has been mangled
171 * by someone else. BCPL programs like to do this,
172 * to work around argument injection issues with the
173 * old BCPL version of RunCommand.
175 if (fhinput->fh_Flags & FHF_BUF) {
176 if (fhinput->fh_Flags & FHF_OWNBUF) {
177 if (fhinput->fh_Buf != fhinput->fh_OrigBuf) {
178 D(bug("%s: Not injecting to fh %p - nonstandard buffering detected\n", __func__, fhinput));
179 return FALSE;
185 /* Deallocate old filehandle's buffer (if any) */
186 vbuf_free(fhinput);
188 /* Must be always buffered or EndCLI won't work */
189 buf = vbuf_alloc(fhinput, NULL, size);
190 if (buf)
192 D(bug("[vbuf_inject] Handle 0x%p, buffer 0x%p, injecting string: %s, size: %u\n", fh, buf, argptr, size));
194 /* ugly hack */
195 fhinput->fh_Pos = 0;
196 if (size > 0)
198 CopyMem(argptr, buf, size);
199 DB2(bug("[vbuf_inject] Buffer contents:\n"); hexdump(buf, (IPTR)buf, size));
201 fhinput->fh_End = size;
204 return TRUE;