fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
1/*****************************************************************************
2 * pce *
3 *****************************************************************************/
4
5/*****************************************************************************
6 * File name: src/drivers/char/char-stdio.c *
7 * Created: 2009-03-06 by Hampa Hug <hampa@hampa.ch> *
8 * Copyright: (C) 2009-2020 Hampa Hug <hampa@hampa.ch> *
9 *****************************************************************************/
10
11/*****************************************************************************
12 * This program is free software. You can redistribute it and / or modify it *
13 * under the terms of the GNU General Public License version 2 as published *
14 * by the Free Software Foundation. *
15 * *
16 * This program is distributed in the hope that it will be useful, but *
17 * WITHOUT ANY WARRANTY, without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General *
19 * Public License for more details. *
20 *****************************************************************************/
21
22
23#include <config.h>
24
25#include <stdlib.h>
26#include <stdio.h>
27#include <string.h>
28
29#ifdef HAVE_SYS_STAT_H
30#include <sys/stat.h>
31#endif
32
33#include <drivers/options.h>
34#include <drivers/char/char.h>
35#include <drivers/char/char-stdio.h>
36
37
38static
39int stdio_check_reopen (char_stdio_t *drv)
40{
41#ifdef HAVE_SYS_STAT_H
42 struct stat st;
43
44 if (drv->reopen == 0) {
45 return (0);
46 }
47
48 if (drv->write_name == NULL) {
49 return (0);
50 }
51
52 if (stat (drv->write_name, &st) == 0) {
53 return (0);
54 }
55
56 if ((drv->write_fp != NULL) && (drv->write_fp != stdout)) {
57 fclose (drv->write_fp);
58 }
59
60 drv->write_fp = fopen (drv->write_name, "wb");
61#endif
62
63 return (0);
64}
65
66static
67void chr_stdio_fclose (char *name, FILE *fp)
68{
69 if (name != NULL) {
70 free (name);
71 }
72
73 if ((fp != NULL) && (fp != stdin) && (fp != stdout) && (fp != stderr)) {
74 fclose (fp);
75 }
76}
77
78static
79void chr_stdio_close (char_drv_t *cdrv)
80{
81 char_stdio_t *drv;
82
83 drv = cdrv->ext;
84
85 chr_stdio_fclose (drv->write_name, drv->write_fp);
86 chr_stdio_fclose (drv->read_name, drv->read_fp);
87
88 free (drv);
89}
90
91static
92unsigned chr_stdio_read (char_drv_t *cdrv, void *buf, unsigned cnt)
93{
94 char_stdio_t *drv;
95
96 drv = cdrv->ext;
97
98 if (drv->read_fp == NULL) {
99 return (0);
100 }
101
102 cnt = fread (buf, 1, cnt, drv->read_fp);
103
104 return (cnt);
105}
106
107static
108unsigned chr_stdio_write (char_drv_t *cdrv, const void *buf, unsigned cnt)
109{
110 char_stdio_t *drv;
111
112 drv = cdrv->ext;
113
114 stdio_check_reopen (drv);
115
116 if (drv->write_fp == NULL) {
117 return (cnt);
118 }
119
120 cnt = fwrite (buf, 1, cnt, drv->write_fp);
121
122 if (drv->flush) {
123 fflush (drv->write_fp);
124 }
125
126 return (cnt);
127}
128
129static
130int chr_stdio_init (char_stdio_t *drv, const char *name)
131{
132 const char *mode;
133
134 chr_init (&drv->cdrv, drv);
135
136 drv->cdrv.close = chr_stdio_close;
137 drv->cdrv.read = chr_stdio_read;
138 drv->cdrv.write = chr_stdio_write;
139
140 drv->read_name = NULL;
141 drv->read_fp = NULL;
142 drv->write_name = NULL;
143 drv->write_fp = NULL;
144
145 drv->flush = drv_get_option_bool (name, "flush", 1);
146 drv->reopen = drv_get_option_bool (name, "reopen", 0);
147 drv->append = drv_get_option_bool (name, "append", 0);
148
149 drv->write_name = drv_get_option (name, "write");
150
151 if (drv->write_name == NULL) {
152 drv->write_name = drv_get_option (name, "file");
153 }
154
155 if (drv->write_name != NULL) {
156 if (strcmp (drv->write_name, "-") == 0) {
157 drv->write_fp = stdout;
158 drv->reopen = 0;
159 }
160 else {
161 mode = drv->append ? "ab" : "wb";
162
163 drv->write_fp = fopen (drv->write_name, mode);
164
165 if (drv->write_fp == NULL) {
166 return (1);
167 }
168 }
169 }
170
171 drv->read_name = drv_get_option (name, "read");
172
173 if (drv->read_name != NULL) {
174 if (strcmp (drv->read_name, "-") == 0) {
175 drv->read_fp = stdin;
176 }
177 else {
178 drv->read_fp = fopen (drv->read_name, "rb");
179
180 if (drv->read_fp == NULL) {
181 return (1);
182 }
183 }
184 }
185 return (0);
186}
187
188char_drv_t *chr_stdio_open (const char *name)
189{
190 char_stdio_t *drv;
191
192 drv = malloc (sizeof (char_stdio_t));
193
194 if (drv == NULL) {
195 return (NULL);
196 }
197
198 if (chr_stdio_init (drv, name)) {
199 chr_stdio_close (&drv->cdrv);
200
201 return (NULL);
202 }
203
204 return (&drv->cdrv);
205}