Changeset 366


Ignore:
Timestamp:
Mar 11, 2009, 3:34:37 AM (9 years ago)
Author:
khorben
Message:

Merge from upstream

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/System/Sources/libc/src/stdio.c

    r330 r366  
    1 /* $Id: stdio.c,v 1.75 2008/10/22 14:19:14 khorben Exp $ */
     1/* $Id: stdio.c,v 1.80 2009/02/24 14:20:57 khorben Exp $ */
    22/* Copyright (c) 2009 Pierre Pronchery <khorben@defora.org> */
    33/* This file is part of DeforaOS System libc */
     
    2929
    3030
     31/* private */
    3132/* types */
    3233typedef enum _FILEDirection { FD_READ = 0, FD_WRITE = 1 } FILEDirection;
     
    6667
    6768
    68 /* functions */
    69 /* private */
    70 /* PRE
    71  * POST
    72  *      -1      error
    73  *      else    corresponding mode */
    74 static int _fopen_mode(char const * mode)
    75 {
    76         int flags;
    77 
    78         if(*mode == 'r')
    79         {
    80                 flags = O_RDONLY;
    81                 if(*++mode == 'b')
    82                         ++mode;
    83                 if(*mode == '\0')
    84                         return flags;
    85                 if(*mode == '+' && ++mode)
    86                         flags = O_RDWR;
    87         }
    88         else if(*mode == 'w')
    89         {
    90                 flags = O_WRONLY | O_CREAT;
    91                 if(*++mode == 'b')
    92                         ++mode;
    93                 if(*mode == '\0')
    94                         return flags;
    95                 if(*mode == '+' && ++mode)
    96                         flags = O_RDWR | O_CREAT;
    97         }
    98         else if(*mode == 'a')
    99         {
    100                 flags = O_APPEND;
    101                 if(*++mode == 'b')
    102                         ++mode;
    103                 if(*mode == '\0')
    104                         return flags;
    105                 if(*mode == '+' && ++mode)
    106                         flags |= O_CREAT;
    107         }
    108         else
    109         {
    110                 errno = EINVAL;
    111                 return -1;
    112         }
    113         if(*mode == 'b')
    114                 ++mode;
    115         if(*mode != '\0')
    116         {
    117                 errno = EINVAL;
    118                 return -1;
    119         }
    120         return flags;
    121 }
     69/* prototypes */
     70static int _fopen_mode(char const * mode);
     71static FILE * _fopen_new(int fd, int flags, int fbuf);
    12272
    12373
     
    14595FILE * fdopen(int fd, char const * mode)
    14696{
    147         FILE * file;
    148 
    149         if((file = malloc(sizeof(FILE))) == NULL)
    150                 return NULL;
    151         if((file->flags = _fopen_mode(mode)) == -1)
    152         {
    153                 free(file);
    154                 return NULL;
    155         }
    156         file->fd = fd;
    157         file->len = 0;
    158         file->pos = 0;
    159         file->eof = 0;
    160         file->error = 0;
    161         file->dir = file->flags & O_WRONLY ? FD_WRITE : FD_READ;
    162         file->fbuf = isatty(file->fd) ? _IONBF : _IOFBF;
    163         return file;
     97        return _fopen_new(fd, _fopen_mode(mode), isatty(fd) ? _IONBF : _IOFBF);
    16498}
    16599
     
    264198
    265199/* fopen */
    266 /* FIXME factor code with fdopen() */
    267200FILE * fopen(char const * path, char const * mode)
    268201{
    269202        FILE * file;
    270 
    271         if((file = malloc(sizeof(FILE))) == NULL)
    272                 return NULL;
    273         if((file->flags = _fopen_mode(mode)) == -1
    274                         || (file->fd = open(path, file->flags, 0777)) < 0)
    275         {
    276                 free(file);
    277                 return NULL;
    278         }
    279         file->len = 0;
    280         file->pos = 0;
    281         file->eof = 0;
    282         file->error = 0;
    283         file->dir = file->flags & O_WRONLY ? FD_WRITE : FD_READ;
    284         file->fbuf = isatty(file->fd) ? _IONBF : _IOFBF;
     203        int flags;
     204        int fd;
     205
     206        if((flags = _fopen_mode(mode)) == -1
     207                        || (fd = open(path, file->flags, 0777)) < 0)
     208                return NULL;
     209        if((file = _fopen_new(fd, flags, isatty(fd) ? _IONBF : _IOFBF)) == NULL)
     210        {
     211                close(fd);
     212                return NULL;
     213        }
    285214        return file;
    286215}
     
    512441        if(s != NULL && *s != '\0')
    513442                fprintf(stderr, "%s%s", s, ": ");
     443        /* strerror() never returns NULL */
    514444        fputs(strerror(errno), stderr);
    515445        fputc('\n', stderr);
     
    518448
    519449/* popen */
     450static void _popen_child(char const * command, int flags, int * fd);
     451
    520452FILE * popen(char const * command, char const * mode)
    521453{
    522         /* FIXME implement */
    523         errno = ENOSYS;
    524         return NULL;
     454        int flags;
     455        pid_t pid;
     456        int fd[2];
     457        int res;
     458
     459        if((flags = _fopen_mode(mode)) == -1)
     460                return NULL;
     461        if((res = pipe(fd)) != 0)
     462                return NULL;
     463        if((pid = fork()) == -1)
     464        {
     465                close(fd[0]);
     466                close(fd[1]);
     467                return NULL;
     468        }
     469        if(pid == 0) /* child */
     470                _popen_child(command, flags, fd);
     471        if(flags & O_WRONLY)
     472                close(fd[0]);
     473        else
     474                close(fd[1]);
     475        return _fopen_new(flags & O_WRONLY ? fd[1] : fd[0], flags, _IONBF);
     476}
     477
     478static void _popen_child(char const * command, int flags, int * fd)
     479{
     480        if(flags & O_WRONLY)
     481        {
     482                close(fd[1]);
     483                if(dup2(fd[0], 0) == -1)
     484                        exit(127);
     485        }
     486        else
     487        {
     488                close(fd[0]);
     489                if(dup2(fd[1], 1) == -1)
     490                        exit(127);
     491        }
     492        execlp("/bin/sh", "sh", "-c", command, NULL);
     493        exit(127);
    525494}
    526495
     
    11281097        return ret;
    11291098}
     1099
     1100
     1101/* private */
     1102/* functions */
     1103/* fopen_mode */
     1104/* PRE
     1105 * POST
     1106 *      -1      error
     1107 *      else    corresponding mode */
     1108static int _fopen_mode(char const * mode)
     1109{
     1110        int flags;
     1111
     1112        if(*mode == 'r')
     1113        {
     1114                flags = O_RDONLY;
     1115                if(*++mode == 'b')
     1116                        ++mode;
     1117                if(*mode == '\0')
     1118                        return flags;
     1119                if(*mode == '+' && ++mode)
     1120                        flags = O_RDWR;
     1121        }
     1122        else if(*mode == 'w')
     1123        {
     1124                flags = O_WRONLY | O_CREAT;
     1125                if(*++mode == 'b')
     1126                        ++mode;
     1127                if(*mode == '\0')
     1128                        return flags;
     1129                if(*mode == '+' && ++mode)
     1130                        flags = O_RDWR | O_CREAT;
     1131        }
     1132        else if(*mode == 'a')
     1133        {
     1134                flags = O_APPEND;
     1135                if(*++mode == 'b')
     1136                        ++mode;
     1137                if(*mode == '\0')
     1138                        return flags;
     1139                if(*mode == '+' && ++mode)
     1140                        flags |= O_CREAT;
     1141        }
     1142        else
     1143        {
     1144                errno = EINVAL;
     1145                return -1;
     1146        }
     1147        if(*mode == 'b')
     1148                ++mode;
     1149        if(*mode != '\0')
     1150        {
     1151                errno = EINVAL;
     1152                return -1;
     1153        }
     1154        return flags;
     1155}
     1156
     1157
     1158/* fopen_new */
     1159static FILE * _fopen_new(int fd, int flags, int fbuf)
     1160{
     1161        FILE * file;
     1162
     1163        if(flags == -1)
     1164                return NULL;
     1165        if((file = malloc(sizeof(*file))) == NULL)
     1166                return NULL;
     1167        file->flags = flags;
     1168        file->fd = fd;
     1169        file->len = 0;
     1170        file->pos = 0;
     1171        file->eof = 0;
     1172        file->error = 0;
     1173        file->dir = file->flags & O_WRONLY ? FD_WRITE : FD_READ;
     1174        file->fbuf = fbuf;
     1175        return file;
     1176}
Note: See TracChangeset for help on using the changeset viewer.