Last active
February 1, 2019 08:34
-
-
Save master-q/c22a158a4865e106c1da8ba3aaa97a78 to your computer and use it in GitHub Desktop.
corrodeにBSDなcatをかけてみた
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* $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; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$ 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