Skip to content

Instantly share code, notes, and snippets.

@master-q master-q/cat.c
Last active Feb 1, 2019

Embed
What would you like to do?
corrodeにBSDなcatをかけてみた
/* $OpenBSD: cat.c,v 1.26 2016/10/19 18:20:25 schwarze Exp $ */
/* $NetBSD: cat.c,v 1.11 1995/09/07 06:12:54 jtc Exp $ */
/*
* Copyright (c) 1989, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Kevin Fall.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <ctype.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define MAXIMUM(a, b) (((a) > (b)) ? (a) : (b))
extern char *__progname;
int bflag, eflag, nflag, sflag, tflag, vflag;
int rval;
char *filename;
void cook_args(char **argv);
void cook_buf(FILE *);
void raw_args(char **argv);
void raw_cat(int);
int
main()
{
int argc;
char **argv;
int ch;
#if 0
if (pledge("stdio rpath", NULL) == -1)
err(1, "pledge");
#endif
while ((ch = getopt(argc, argv, "benstuv")) != -1)
switch (ch) {
case 'b':
bflag = nflag = 1; /* -b implies -n */
break;
case 'e':
eflag = vflag = 1; /* -e implies -v */
break;
case 'n':
nflag = 1;
break;
case 's':
sflag = 1;
break;
case 't':
tflag = vflag = 1; /* -t implies -v */
break;
case 'u':
setvbuf(stdout, NULL, _IONBF, 0);
break;
case 'v':
vflag = 1;
break;
default:
(void)fprintf(stderr,
"usage: %s [-benstuv] [file ...]\n", __progname);
return 1;
}
argv += optind;
if (bflag || eflag || nflag || sflag || tflag || vflag)
cook_args(argv);
else
raw_args(argv);
if (fclose(stdout))
err(1, "stdout");
return rval;
}
void
cook_args(char **argv)
{
FILE *fp;
fp = stdin;
filename = "stdin";
do {
if (*argv) {
if (!strcmp(*argv, "-"))
fp = stdin;
else if ((fp = fopen(*argv, "r")) == NULL) {
warn("%s", *argv);
rval = 1;
++argv;
continue;
}
filename = *argv++;
}
cook_buf(fp);
if (fp == stdin)
clearerr(fp);
else
(void)fclose(fp);
} while (*argv);
}
void
cook_buf(FILE *fp)
{
int ch, gobble, line, prev;
line = gobble = 0;
for (prev = '\n'; (ch = getc(fp)) != EOF; prev = ch) {
if (prev == '\n') {
if (sflag) {
if (ch == '\n') {
if (gobble)
continue;
gobble = 1;
} else
gobble = 0;
}
if (nflag) {
if (!bflag || ch != '\n') {
(void)fprintf(stdout, "%6d\t", ++line);
if (ferror(stdout))
break;
} else if (eflag) {
(void)fprintf(stdout, "%6s\t", "");
if (ferror(stdout))
break;
}
}
}
if (ch == '\n') {
if (eflag && putchar('$') == EOF)
break;
} else if (ch == '\t') {
if (tflag) {
if (putchar('^') == EOF || putchar('I') == EOF)
break;
continue;
}
} else if (vflag) {
if (!isascii(ch)) {
if (putchar('M') == EOF || putchar('-') == EOF)
break;
ch = toascii(ch);
}
if (iscntrl(ch)) {
if (putchar('^') == EOF ||
putchar(ch == '\177' ? '?' :
ch | 0100) == EOF)
break;
continue;
}
}
if (putchar(ch) == EOF)
break;
}
if (ferror(fp)) {
warn("%s", filename);
rval = 1;
clearerr(fp);
}
if (ferror(stdout))
err(1, "stdout");
}
void
raw_args(char **argv)
{
int fd;
fd = fileno(stdin);
filename = "stdin";
do {
if (*argv) {
if (!strcmp(*argv, "-"))
fd = fileno(stdin);
else if ((fd = open(*argv, O_RDONLY, 0)) < 0) {
warn("%s", *argv);
rval = 1;
++argv;
continue;
}
filename = *argv++;
}
raw_cat(fd);
if (fd != fileno(stdin))
(void)close(fd);
} while (*argv);
}
void
raw_cat(int rfd)
{
int wfd;
ssize_t nr, nw, off;
static size_t bsize;
static char *buf = NULL;
struct stat sbuf;
wfd = fileno(stdout);
if (buf == NULL) {
if (fstat(wfd, &sbuf))
err(1, "stdout");
bsize = MAXIMUM(sbuf.st_blksize, BUFSIZ);
if ((buf = malloc(bsize)) == NULL)
err(1, "malloc");
}
while ((nr = read(rfd, buf, bsize)) != -1 && nr != 0)
for (off = 0; nr; nr -= nw, off += nw)
if ((nw = write(wfd, buf + off, (size_t)nr)) == 0 ||
nw == -1)
err(1, "stdout");
if (nr < 0) {
warn("%s", filename);
rval = 1;
}
}
extern {
static mut __progname : *mut u8;
fn clearerr(__stream : *mut _IO_FILE);
fn close(__fd : i32) -> i32;
fn err(__status : i32, __format : *const u8, ...);
fn fclose(__stream : *mut _IO_FILE) -> i32;
fn ferror(__stream : *mut _IO_FILE) -> i32;
fn fileno(__stream : *mut _IO_FILE) -> i32;
fn fopen(
__filename : *const u8, __modes : *const u8
) -> *mut _IO_FILE;
fn fprintf(
__stream : *mut _IO_FILE, __format : *const u8, ...
) -> i32;
fn fstat(__fd : i32, __buf : *mut stat) -> i32;
fn getc(__stream : *mut _IO_FILE) -> i32;
fn getopt(
___argc : i32, ___argv : *const *mut u8, __shortopts : *const u8
) -> i32;
fn isascii(__c : i32) -> i32;
fn iscntrl(arg1 : i32) -> i32;
fn malloc(__size : usize) -> *mut ::std::os::raw::c_void;
fn open(__file : *const u8, __oflag : i32, ...) -> i32;
static mut optind : i32;
fn putchar(__c : i32) -> i32;
fn read(
__fd : i32, __buf : *mut ::std::os::raw::c_void, __nbytes : usize
) -> isize;
fn setvbuf(
__stream : *mut _IO_FILE,
__buf : *mut u8,
__modes : i32,
__n : usize
) -> i32;
static mut stderr : *mut _IO_FILE;
static mut stdin : *mut _IO_FILE;
static mut stdout : *mut _IO_FILE;
fn strcmp(__s1 : *const u8, __s2 : *const u8) -> i32;
fn toascii(__c : i32) -> i32;
fn warn(__format : *const u8, ...);
fn write(
__fd : i32, __buf : *const ::std::os::raw::c_void, __n : usize
) -> isize;
}
enum _IO_FILE {
}
#[no_mangle]
pub static mut bflag : i32 = 0i32;
#[no_mangle]
pub static mut eflag : i32 = 0i32;
#[no_mangle]
pub static mut nflag : i32 = 0i32;
#[no_mangle]
pub static mut sflag : i32 = 0i32;
#[no_mangle]
pub static mut tflag : i32 = 0i32;
#[no_mangle]
pub static mut vflag : i32 = 0i32;
#[no_mangle]
pub static mut rval : i32 = 0i32;
#[no_mangle]
pub static mut filename : *mut u8 = 0 as (*mut u8);
fn main() {
let ret = unsafe { _c_main() };
::std::process::exit(ret);
}
#[no_mangle]
pub unsafe extern fn _c_main() -> i32 {
let mut _currentBlock;
let mut argc : i32;
let mut argv : *mut *mut u8;
let mut ch : i32;
'loop1: loop {
if !({
ch = getopt(
argc,
argv as (*const *mut u8),
(*b"benstuv\0").as_ptr()
);
ch
} != -1i32) {
_currentBlock = 2;
break;
}
if ch == b'v' as (i32) {
vflag = 1i32;
} else if ch == b'u' as (i32) {
setvbuf(
stdout,
0i32 as (*mut ::std::os::raw::c_void) as (*mut u8),
2i32,
0usize
);
} else if ch == b't' as (i32) {
tflag = {
vflag = 1i32;
vflag
};
} else if ch == b's' as (i32) {
sflag = 1i32;
} else if ch == b'n' as (i32) {
nflag = 1i32;
} else if ch == b'e' as (i32) {
eflag = {
vflag = 1i32;
vflag
};
} else {
if !(ch == b'b' as (i32)) {
_currentBlock = 15;
break;
}
bflag = {
nflag = 1i32;
nflag
};
}
}
if _currentBlock == 2 {
argv = argv.offset(optind as (isize));
if bflag != 0 || eflag != 0 || nflag != 0 || sflag != 0 || tflag != 0 || vflag != 0 {
cook_args(argv);
} else {
raw_args(argv);
}
if fclose(stdout) != 0 {
err(1i32,(*b"stdout\0").as_ptr());
}
rval
} else {
fprintf(
stderr,
(*b"usage: %s [-benstuv] [file ...]\n\0").as_ptr(),
__progname
);
1i32
}
}
#[no_mangle]
pub unsafe extern fn cook_args(mut argv : *mut *mut u8) {
let mut _currentBlock;
let mut fp : *mut _IO_FILE;
fp = stdin;
filename = (*b"stdin\0").as_ptr() as (*mut u8);
'loop1: loop {
if !(*argv).is_null() {
if strcmp(*argv as (*const u8),(*b"-\0").as_ptr()) == 0 {
fp = stdin;
_currentBlock = 6;
} else if {
fp = fopen(*argv as (*const u8),(*b"r\0").as_ptr());
fp
} == 0i32 as (*mut ::std::os::raw::c_void) as (*mut _IO_FILE) {
warn((*b"%s\0").as_ptr(),*argv);
rval = 1i32;
argv = argv.offset(1isize);
_currentBlock = 10;
} else {
_currentBlock = 6;
}
if _currentBlock == 10 {
} else {
filename = *{
let _old = argv;
argv = argv.offset(1isize);
_old
};
_currentBlock = 7;
}
} else {
_currentBlock = 7;
}
if _currentBlock == 7 {
cook_buf(fp);
if fp == stdin {
clearerr(fp);
} else {
fclose(fp);
}
}
if (*argv).is_null() {
break;
}
}
}
#[no_mangle]
pub unsafe extern fn cook_buf(mut fp : *mut _IO_FILE) {
let mut _currentBlock;
let mut ch : i32;
let mut gobble : i32;
let mut line : i32;
let mut prev : i32;
line = {
gobble = 0i32;
gobble
};
prev = b'\n' as (i32);
'loop1: loop {
if !({
ch = getc(fp);
ch
} != -1i32) {
break;
}
if prev == b'\n' as (i32) {
if sflag != 0 {
if ch == b'\n' as (i32) {
if gobble != 0 {
_currentBlock = 30;
} else {
gobble = 1i32;
_currentBlock = 8;
}
} else {
gobble = 0i32;
_currentBlock = 8;
}
} else {
_currentBlock = 8;
}
if _currentBlock == 30 {
} else if nflag != 0 {
if bflag == 0 || ch != b'\n' as (i32) {
fprintf(
stdout,
(*b"%6d\t\0").as_ptr(),
{
line = line + 1;
line
}
);
if ferror(stdout) != 0 {
break;
}
} else if eflag != 0 {
fprintf(stdout,(*b"%6s\t\0").as_ptr(),(*b"\0").as_ptr());
if ferror(stdout) != 0 {
break;
}
}
_currentBlock = 13;
} else {
_currentBlock = 13;
}
} else {
_currentBlock = 13;
}
if _currentBlock == 13 {
if ch == b'\n' as (i32) {
if eflag != 0 && (putchar(b'$' as (i32)) == -1i32) {
break;
}
_currentBlock = 24;
} else if ch == b'\t' as (i32) {
if tflag != 0 {
if putchar(b'^' as (i32)) == -1i32 || putchar(
b'I' as (i32)
) == -1i32 {
break;
}
_currentBlock = 30;
} else {
_currentBlock = 24;
}
} else if vflag != 0 {
if isascii(ch) == 0 {
if putchar(b'M' as (i32)) == -1i32 || putchar(
b'-' as (i32)
) == -1i32 {
break;
}
ch = toascii(ch);
}
if iscntrl(ch) != 0 {
if putchar(b'^' as (i32)) == -1i32 || putchar(
if ch == b'\x7F' as (i32) {
b'?' as (i32)
} else {
ch | 0o100i32
}
) == -1i32 {
break;
}
_currentBlock = 30;
} else {
_currentBlock = 24;
}
} else {
_currentBlock = 24;
}
if _currentBlock == 30 {
} else if putchar(ch) == -1i32 {
break;
}
}
prev = ch;
}
if ferror(fp) != 0 {
warn((*b"%s\0").as_ptr(),filename);
rval = 1i32;
clearerr(fp);
}
if ferror(stdout) != 0 {
err(1i32,(*b"stdout\0").as_ptr());
}
}
#[no_mangle]
pub unsafe extern fn raw_args(mut argv : *mut *mut u8) {
let mut _currentBlock;
let mut fd : i32;
fd = fileno(stdin);
filename = (*b"stdin\0").as_ptr() as (*mut u8);
'loop1: loop {
if !(*argv).is_null() {
if strcmp(*argv as (*const u8),(*b"-\0").as_ptr()) == 0 {
fd = fileno(stdin);
_currentBlock = 6;
} else if {
fd = open(*argv as (*const u8),0o0i32,0i32);
fd
} < 0i32 {
warn((*b"%s\0").as_ptr(),*argv);
rval = 1i32;
argv = argv.offset(1isize);
_currentBlock = 9;
} else {
_currentBlock = 6;
}
if _currentBlock == 9 {
} else {
filename = *{
let _old = argv;
argv = argv.offset(1isize);
_old
};
_currentBlock = 7;
}
} else {
_currentBlock = 7;
}
if _currentBlock == 7 {
raw_cat(fd);
if fd != fileno(stdin) {
close(fd);
}
}
if (*argv).is_null() {
break;
}
}
}
#[derive(Copy)]
#[repr(C)]
pub struct timespec {
pub tv_sec : isize,
pub tv_nsec : isize,
}
impl Clone for timespec {
fn clone(&self) -> Self { *self }
}
#[derive(Copy)]
#[repr(C)]
pub struct stat {
pub st_dev : usize,
pub st_ino : usize,
pub st_nlink : usize,
pub st_mode : u32,
pub st_uid : u32,
pub st_gid : u32,
pub __pad0 : i32,
pub st_rdev : usize,
pub st_size : isize,
pub st_blksize : isize,
pub st_blocks : isize,
pub st_atim : timespec,
pub st_mtim : timespec,
pub st_ctim : timespec,
pub __glibc_reserved : [isize; 3],
}
impl Clone for stat {
fn clone(&self) -> Self { *self }
}
#[no_mangle]
pub unsafe extern fn raw_cat(mut rfd : i32) {
let mut wfd : i32;
let mut nr : isize;
let mut nw : isize;
let mut off : isize;
static mut bsize : usize = 0usize;
static mut buf
: *mut u8
= 0i32 as (*mut ::std::os::raw::c_void) as (*mut u8);
let mut sbuf : stat;
wfd = fileno(stdout);
if buf == 0i32 as (*mut ::std::os::raw::c_void) as (*mut u8) {
if fstat(wfd,&mut sbuf as (*mut stat)) != 0 {
err(1i32,(*b"stdout\0").as_ptr());
}
bsize = if sbuf.st_blksize > 8192isize {
sbuf.st_blksize
} else {
8192isize
} as (usize);
if {
buf = malloc(bsize) as (*mut u8);
buf
} == 0i32 as (*mut ::std::os::raw::c_void) as (*mut u8) {
err(1i32,(*b"malloc\0").as_ptr());
}
}
'loop5: loop {
if !({
nr = read(rfd,buf as (*mut ::std::os::raw::c_void),bsize);
nr
} != -1isize && (nr != 0isize)) {
break;
}
off = 0isize;
'loop10: loop {
if nr == 0 {
break;
}
if {
nw = write(
wfd,
buf.offset(off) as (*const ::std::os::raw::c_void),
nr as (usize)
);
nw
} == 0isize || nw == -1isize {
err(1i32,(*b"stdout\0").as_ptr());
}
nr = nr - nw;
off = off + nw;
}
}
if nr < 0isize {
warn((*b"%s\0").as_ptr(),filename);
rval = 1i32;
}
}
$ rustc --version
$ rustc 1.33.0-beta.5 (1045131c1 2019-01-31)
rustc cat.rs
warning: type `_IO_FILE` should have a camel case name
--> cat.rs:46:6
|
46 | enum _IO_FILE {
| ^^^^^^^^ help: convert the identifier to camel case: `IoFile`
|
= note: #[warn(non_camel_case_types)] on by default
error[E0446]: private type `_IO_FILE` in public interface
--> cat.rs:200:1
|
46 | enum _IO_FILE {
| - `_IO_FILE` declared as private
...
200 | / pub unsafe extern fn cook_buf(mut fp : *mut _IO_FILE) {
201 | | let mut _currentBlock;
202 | | let mut ch : i32;
203 | | let mut gobble : i32;
... |
318 | | }
319 | | }
| |_^ can't leak private type
error: aborting due to previous error
For more information about this error, try `rustc --explain E0446`.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.