char * gets(char *buf) { int c; char *s; _DIAGASSERT(buf != NULL); FLOCKFILE(stdin); for (s = buf; (c = getchar_unlocked()) != '\n'; ) { if (c == EOF) { if (s == buf) { FUNLOCKFILE(stdin); return (NULL); } else { break; } } else { *s++ = (char)c; } } *s = 0; FUNLOCKFILE(stdin); return (buf); }
/* read a single line from stdin, replace the '\n' with '\0' */ char * gets(char *buf) { char *ptr = buf; ssize_t n; char *p; Uchar *bufend; rmutex_t *lk; FLOCKFILE(lk, stdin); _SET_ORIENTATION_BYTE(stdin); if (!(stdin->_flag & (_IOREAD | _IORW))) { errno = EBADF; FUNLOCKFILE(lk); return (0); } if (stdin->_base == NULL) { if ((bufend = _findbuf(stdin)) == 0) { FUNLOCKFILE(lk); return (0); } } else bufend = _bufend(stdin); for (;;) /* until get a '\n' */ { if (stdin->_cnt <= 0) /* empty buffer */ { if (__filbuf(stdin) != EOF) { stdin->_ptr--; /* put back the character */ stdin->_cnt++; } else if (ptr == buf) { /* never read anything */ FUNLOCKFILE(lk); return (0); } else break; /* nothing left to read */ } n = stdin->_cnt; if ((p = (char *)memccpy(ptr, (char *)stdin->_ptr, '\n', (size_t)n)) != 0) n = p - ptr; ptr += n; stdin->_cnt -= n; stdin->_ptr += n; if (_needsync(stdin, bufend)) _bufsync(stdin, bufend); if (p != 0) /* found a '\n' */ { ptr--; /* step back over the '\n' */ break; } } *ptr = '\0'; FUNLOCKFILE(lk); return (buf); }
int fseek(FILE *iop, long offset, int ptrname) { off_t p; rmutex_t *lk; FLOCKFILE(lk, iop); iop->_flag &= ~_IOEOF; if (!(iop->_flag & _IOREAD) && !(iop->_flag & (_IOWRT | _IORW))) { errno = EBADF; FUNLOCKFILE(lk); return (-1); } if (iop->_flag & _IOREAD) { if (ptrname == 1 && iop->_base && !(iop->_flag&_IONBF)) { offset -= iop->_cnt; } } else if (iop->_flag & (_IOWRT | _IORW)) { if (_fflush_u(iop) == EOF) { FUNLOCKFILE(lk); return (-1); } } iop->_cnt = 0; iop->_ptr = iop->_base; if (iop->_flag & _IORW) { iop->_flag &= ~(_IOREAD | _IOWRT); } p = lseek(FILENO(iop), (off_t)offset, ptrname); FUNLOCKFILE(lk); return ((p == (off_t)-1) ? -1: 0); }
/* * Read at most n-1 characters from the given file. * Stop when a newline has been read, or the count runs out. * Return first argument, or NULL if no characters were read. */ EXPORT_C char * fgets(char *buf, int n, FILE *fp) { size_t len; char *s; unsigned char *p, *t; if (n <= 0) /* sanity check */ return (NULL); FLOCKFILE(fp); ORIENT(fp, -1); s = buf; n--; /* leave space for NUL */ while (n != 0) { /* * If the buffer is empty, refill it. */ if ((len = fp->_r) <= 0) { if (__srefill(fp)) { /* EOF/error: stop with partial or no line */ if (s == buf) { FUNLOCKFILE(fp); return (NULL); } break; } len = fp->_r; } p = fp->_p; /* * Scan through at most n bytes of the current buffer, * looking for '\n'. If found, copy up to and including * newline, and stop. Otherwise, copy entire chunk * and loop. */ if (len > n) len = n; t = memchr((void *)p, '\n', len); if (t != NULL) { len = ++t - p; fp->_r -= len; fp->_p = t; (void)memcpy((void *)s, (void *)p, len); s[len] = 0; FUNLOCKFILE(fp); return (buf); } fp->_r -= len; fp->_p += len; (void)memcpy((void *)s, (void *)p, len); s += len; n -= len; } *s = 0; FUNLOCKFILE(fp); return (buf); }
int getpw(uid_t uid, char buf[]) { int n, c; char *bp; FILE *fp; rmutex_t *lk; if (pwf == NULL) { fp = fopen(PASSWD, "rF"); lmutex_lock(&_pwlock); if (pwf == NULL) { if ((pwf = fp) == NULL) { lmutex_unlock(&_pwlock); return (1); } fp = NULL; } lmutex_unlock(&_pwlock); if (fp != NULL) /* someone beat us to it */ (void) fclose(fp); } FLOCKFILE(lk, pwf); _rewind_unlocked(pwf); for (;;) { bp = buf; while ((c = GETC(pwf)) != '\n') { if (c == EOF) { FUNLOCKFILE(lk); return (1); } *bp++ = (char)c; } *bp = '\0'; bp = buf; n = 3; while (--n) while ((c = *bp++) != ':') if (c == '\n') { FUNLOCKFILE(lk); return (1); } while ((c = *bp++) != ':') if (isdigit(c)) n = n*10+c-'0'; else continue; if (n == uid) { FUNLOCKFILE(lk); return (0); } } }
/* * ftell: return current offset. */ long ftell(FILE *fp) { off_t pos; FLOCKFILE(fp); if (fp->_seek == NULL) { FUNLOCKFILE(fp); errno = ESPIPE; /* historic practice */ return -1L; } /* * Find offset of underlying I/O object, then * adjust for buffered bytes. */ (void)__sflush(fp); /* may adjust seek offset on append stream */ if (fp->_flags & __SOFF) pos = fp->_offset; else { pos = (*fp->_seek)(fp->_cookie, (off_t)0, SEEK_CUR); if (pos == -1L) { FUNLOCKFILE(fp); return (long)pos; } } if (fp->_flags & __SRD) { /* * Reading. Any unread characters (including * those from ungetc) cause the position to be * smaller than that in the underlying object. */ pos -= fp->_r; if (HASUB(fp)) pos -= fp->_ur; } else if (fp->_flags & __SWR && fp->_p != NULL) { /* * Writing. Any buffered characters cause the * position to be greater than that in the * underlying object. */ pos += fp->_p - fp->_bf._base; } FUNLOCKFILE(fp); if (__long_overflow(pos)) { errno = EOVERFLOW; return -1L; } return (long)pos; }
void clearerr(FILE *fp) { FLOCKFILE(fp); __sclearerr(fp); FUNLOCKFILE(fp); }
void perror(const char *s) { char msgbuf[NL_TEXTMAX]; struct iovec *v; struct iovec iov[4]; v = iov; if (s != NULL && *s != '\0') { v->iov_base = (char *)s; v->iov_len = strlen(s); v++; v->iov_base = ": "; v->iov_len = 2; v++; } strerror_r(errno, msgbuf, sizeof(msgbuf)); v->iov_base = msgbuf; v->iov_len = strlen(v->iov_base); v++; v->iov_base = "\n"; v->iov_len = 1; FLOCKFILE(stderr); __sflush(stderr); (void)_writev(stderr->_file, iov, (v - iov) + 1); stderr->_flags &= ~__SOFF; FUNLOCKFILE(stderr); }
/* Finish a warning with a newline and a flush of stderr. */ static void warnfinish(FILE *fp, rmutex_t *lk) { (void) fputc('\n', fp); (void) fflush(fp); FUNLOCKFILE(lk); }
int fclose(FILE *fp) { int r; if (fp->_flags == 0) { /* not open! */ errno = EBADF; return (EOF); } FLOCKFILE(fp); WCIO_FREE(fp); r = fp->_flags & __SWR ? __sflush(fp) : 0; if (fp->_close != NULL && (*fp->_close)(fp->_cookie) < 0) r = EOF; if (fp->_flags & __SMBF) free((char *)fp->_bf._base); if (HASUB(fp)) FREEUB(fp); if (HASLB(fp)) FREELB(fp); fp->_r = fp->_w = 0; /* Mess up if reaccessed. */ fp->_flags = 0; /* Release this FILE for reuse. */ FUNLOCKFILE(fp); return (r); }
/* * Write the given string to the given file. */ int fputs(const char *s, FILE *fp) { struct __suio uio; struct __siov iov; int r; _DIAGASSERT(s != NULL); _DIAGASSERT(fp != NULL); if(fp == NULL) { errno = EINVAL; return (EOF); } if (s == NULL) s = "(null)"; iov.iov_base = __UNCONST(s); uio.uio_resid = (int)(iov.iov_len = strlen(s)); uio.uio_iov = &iov; uio.uio_iovcnt = 1; FLOCKFILE(fp); _SET_ORIENTATION(fp, -1); r = __sfvwrite(fp, &uio); FUNLOCKFILE(fp); return r; }
int fdclose(FILE *fp, int *fdp) { int r, err; if (fdp != NULL) *fdp = -1; if (fp->_flags == 0) { /* not open! */ errno = EBADF; return (EOF); } FLOCKFILE(fp); r = 0; if (fp->_close != __sclose) { r = EOF; errno = EOPNOTSUPP; } else if (fp->_file < 0) { r = EOF; errno = EBADF; } if (r == EOF) { err = errno; (void)cleanfile(fp, true); errno = err; } else { if (fdp != NULL) *fdp = fp->_file; r = cleanfile(fp, false); } FUNLOCKFILE(fp); return (r); }
/* * Write the given string to stdout, appending a newline. */ int puts(char const *s) { size_t c; struct __suio uio; struct __siov iov[2]; int r; _DIAGASSERT(s != NULL); if (s == NULL) s = "(null)"; c = strlen(s); iov[0].iov_base = __UNCONST(s); iov[0].iov_len = c; iov[1].iov_base = __UNCONST("\n"); iov[1].iov_len = 1; uio.uio_resid = (int)(c + 1); uio.uio_iov = &iov[0]; uio.uio_iovcnt = 2; FLOCKFILE(stdout); r = __sfvwrite(stdout, &uio); FUNLOCKFILE(stdout); return (r ? EOF : '\n'); }
int fclose(FILE *fp) { int r; if (fp->_flags == 0) /* not open! */ { errno = EBADF; return (EOF); } FLOCKFILE(fp); r = fp->_flags & __SWR ? __sflush(fp) : 0; if (fp->_close != NULL && (*fp->_close)(fp->_cookie) < 0) r = EOF; if (fp->_flags & __SMBF) FREE((char *)fp->_bf._base); if (HASUB(fp)) FREEUB(fp); if (HASLB(fp)) FREELB(fp); fp->_file = -1; fp->_r = fp->_w = 0; /* Mess up if reaccessed. */ fp->_flags = 0; /* Release this FILE for reuse. */ osal_mutex_delete(fp->_extra->fl_mutex); FUNLOCKFILE(fp); return (r); }
int erts_fprintf(FILE *filep, const char *format, ...) { int res; va_list arglist; va_start(arglist, format); errno = 0; if (erts_printf_stdout_func && filep == stdout) res = (*erts_printf_stdout_func)((char *) format, arglist); else if (erts_printf_stderr_func && filep == stderr) res = (*erts_printf_stderr_func)((char *) format, arglist); else { int (*fmt_f)(void*, char*, size_t); if (erts_printf_add_cr_to_stdout && filep == stdout) fmt_f = write_f_add_cr; else if (erts_printf_add_cr_to_stderr && filep == stderr) fmt_f = write_f_add_cr; else fmt_f = write_f; FLOCKFILE(filep); res = erts_printf_format(fmt_f,(void *)filep,(char *)format,arglist); FUNLOCKFILE(filep); } va_end(arglist); return res; }
/* * Flush a single file, or (if fp is NULL) all files. * MT-safe version */ int fflush(FILE *fp) { int retval; if (fp == NULL) return (_fwalk(sflush_locked)); FLOCKFILE(fp); /* * There is disagreement about the correct behaviour of fflush() * when passed a file which is not open for reading. According to * the ISO C standard, the behaviour is undefined. * Under linux, such an fflush returns success and has no effect; * under Windows, such an fflush is documented as behaving instead * as fpurge(). * Given that applications may be written with the expectation of * either of these two behaviours, the only safe (non-astonishing) * option is to return EBADF and ask that applications be fixed. */ if ((fp->pub._flags & (__SWR | __SRW)) == 0) { errno = EBADF; retval = EOF; } else { retval = __sflush(fp); } FUNLOCKFILE(fp); return (retval); }
/* * Write `count' objects (each size `size') from memory to the given file. * Return the number of whole objects written. */ size_t fwrite(const void *buf, size_t size, size_t count, FILE *fp) { size_t n; struct __suio uio; struct __siov iov; int ret; /* * ANSI and SUSv2 require a return value of 0 if size or count are 0. */ if ((n = count * size) == 0) return (0); iov.iov_base = (void *)buf; uio.uio_resid = iov.iov_len = n; uio.uio_iov = &iov; uio.uio_iovcnt = 1; /* * The usual case is success (__sfvwrite returns 0); * skip the divide if this happens, since divides are * generally slow and since this occurs whenever size==0. */ FLOCKFILE(fp); _SET_ORIENTATION(fp, -1); ret = __sfvwrite(fp, &uio); FUNLOCKFILE(fp); if (ret == 0) return (count); return ((n - uio.uio_resid) / size); }
int fwide(FILE *fp, int mode) { struct wchar_io_data *wcio; /* * this implementation use only -1, 0, 1 * for mode value. * (we don't need to do this, but * this can make things simpler.) */ if (mode > 0) mode = 1; else if (mode < 0) mode = -1; FLOCKFILE(fp); wcio = WCIO_GET(fp); if (!wcio) return 0; /* XXX */ if (wcio->wcio_mode == 0 && mode != 0) wcio->wcio_mode = mode; else mode = wcio->wcio_mode; FUNLOCKFILE(fp); return mode; }
/* * FreeBSD had both a MT safe and non-MT safe version. For whatever reason, * we don't need the non-MT safe version. We do this because its faster, * since we don't have to lock the file while doing the potentially expensive * conversion from wide to mb. * * Solaris also has XPG5 and legacy semantics. The new standard requires * that the stream orientation change, but legacy calls don't do that. * * Note that we had the source for the XPG5 version of this, but it relied * on closed implementation bits that we lack, so we supply replacements * here. */ static wint_t __fputwc_impl(wchar_t wc, FILE *fp, int orient) { char buf[MB_LEN_MAX]; size_t i, len; rmutex_t *mx; /* If we are given WEOF, then we have to stop */ if (wc == WEOF) return (WEOF); if (MB_CUR_MAX == 1 && wc > 0 && wc <= UCHAR_MAX) { /* * Assume single-byte locale with no special encoding. */ *buf = (unsigned char)wc; len = 1; } else { /* * FreeBSD used restartable wcrtomb. I think we can use * the simpler wctomb form here. We should have a complete * decode. */ if ((len = wctomb(buf, wc)) == (size_t)-1) { fp->_flag |= _IOERR; errno = EILSEQ; return (WEOF); } } FLOCKFILE(mx, fp); /* * This is used for XPG 5 semantics, which requires the stream * orientation to be changed when the function is called. */ if (orient && GET_NO_MODE(fp)) { _setorientation(fp, _WC_MODE); } for (i = 0; i < len; i++) { if (PUTC((unsigned char)buf[i], fp) == EOF) { FUNLOCKFILE(mx); return (WEOF); } } FUNLOCKFILE(mx); return ((wint_t)wc); }
int ungetc(int c, FILE *fp) { FLOCKFILE(fp); c = __sungetc(c, fp); FUNLOCKFILE(fp); return (c); }
size_t fread(void *buf, size_t size, size_t count, FILE *fp) { size_t resid; char *p; int r; size_t total; _DIAGASSERT(fp != NULL); if(fp == NULL) { errno = EINVAL; return (0); } /* * The ANSI standard requires a return value of 0 for a count * or a size of 0. Whilst ANSI imposes no such requirements on * fwrite, the SUSv2 does. */ if ((resid = count * size) == 0) return (0); _DIAGASSERT(buf != NULL); FLOCKFILE(fp); if (fp->_r < 0) fp->_r = 0; total = resid; p = buf; while (resid > (size_t)(r = fp->_r)) { (void)memcpy((void *)p, (void *)fp->_p, (size_t)r); fp->_p += r; /* fp->_r = 0 ... done in __srefill */ p += r; resid -= r; if (__srefill(fp)) { /* no more input: return partial result */ FUNLOCKFILE(fp); return ((total - resid) / size); } } (void)memcpy((void *)p, (void *)fp->_p, resid); fp->_r -= (int)resid; fp->_p += resid; FUNLOCKFILE(fp); return (count); }
int ferror(FILE* fp) { int ret; FLOCKFILE(fp); ret = __sferror(fp); FUNLOCKFILE(fp); return (ret); }
int fileno(FILE* fp) { int fd; FLOCKFILE(fp); fd = __sfileno(fp); FUNLOCKFILE(fp); return (fd); }
/* * __vfscanf - MT-safe version */ int __vfscanf(FILE* fp, char const* fmt0, va_list ap) { int ret; FLOCKFILE(fp); ret = __svfscanf(fp, fmt0, ap); FUNLOCKFILE(fp); return (ret); }
/*VARARGS1*/ int printf(const char *format, ...) { ssize_t count; rmutex_t *lk; va_list ap; va_start(ap, format); /* Use F*LOCKFILE() macros because printf() is not async-safe. */ FLOCKFILE(lk, stdout); _SET_ORIENTATION_BYTE(stdout); if (!(stdout->_flag & _IOWRT)) { /* if no write flag */ if (stdout->_flag & _IORW) { /* if ok, cause read-write */ stdout->_flag |= _IOWRT; } else { /* else error */ FUNLOCKFILE(lk); errno = EBADF; return (EOF); } } count = _ndoprnt(format, ap, stdout, 0); va_end(ap); /* check for errors or EOF */ if (FERROR(stdout) || count == EOF) { FUNLOCKFILE(lk); return (EOF); } FUNLOCKFILE(lk); /* check for overflow */ if ((size_t)count > MAXINT) { errno = EOVERFLOW; return (EOF); } else { return ((int)count); } }
int getchar(void) { int retval; FLOCKFILE(stdin); retval = __sgetc(stdin); FUNLOCKFILE(stdin); return (retval); }
int fputc(int c, FILE *fp) { int retval; FLOCKFILE(fp); retval = __sputc(c, fp); FUNLOCKFILE(fp); return (retval); }
static int sflush_locked(FILE *fp) { int ret; FLOCKFILE(fp); ret = __sflush(fp); FUNLOCKFILE(fp); return (ret); }
int putc(int c, FILE *fp) { int ret; FLOCKFILE(fp); ret = putc_unlocked(c, fp); FUNLOCKFILE(fp); return (ret); }
int vfprintf(FILE *fp, const char *fmt0, __va_list ap) { int ret; FLOCKFILE(fp); ret = __vfprintf(fp, fmt0, ap); FUNLOCKFILE(fp); return (ret); }