fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
at master 205 lines 4.5 kB view raw
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}