1
2
3
4
5 package main
6
7 import (
8 "./file"
9 "flag"
10 "fmt"
11 "os"
12 )
13
14 var rot13Flag = flag.Bool("rot13", false, "rot13 the input")
15
16 func rot13(b byte) byte {
17 if 'a' <= b && b <= 'z' {
18 b = 'a' + ((b-'a')+13)%26
19 }
20 if 'A' <= b && b <= 'Z' {
21 b = 'A' + ((b-'A')+13)%26
22 }
23 return b
24 }
25
26 type reader interface {
27 Read(b []byte) (ret int, err os.Error)
28 String() string
29 }
30
31 type rotate13 struct {
32 source reader
33 }
34
35 func newRotate13(source reader) *rotate13 {
36 return &rotate13{source}
37 }
38
39 func (r13 *rotate13) Read(b []byte) (ret int, err os.Error) {
40 r, e := r13.source.Read(b)
41 for i := 0; i < r; i++ {
42 b[i] = rot13(b[i])
43 }
44 return r, e
45 }
46
47 func (r13 *rotate13) String() string {
48 return r13.source.String()
49 }
50
51
52 func cat(r reader) {
53 const NBUF = 512
54 var buf [NBUF]byte
55
56 if *rot13Flag {
57 r = newRotate13(r)
58 }
59 for {
60 switch nr, er := r.Read(buf[:]); {
61 case nr < 0:
62 fmt.Fprintf(os.Stderr, "cat: error reading from %s: %s\n", r.String(), er.String())
63 os.Exit(1)
64 case nr == 0:
65 return
66 case nr > 0:
67 nw, ew := file.Stdout.Write(buf[0:nr])
68 if nw != nr {
69 fmt.Fprintf(os.Stderr, "cat: error writing from %s: %s\n", r.String(), ew.String())
70 os.Exit(1)
71 }
72 }
73 }
74 }
75
76 func main() {
77 flag.Parse()
78 if flag.NArg() == 0 {
79 cat(file.Stdin)
80 }
81 for i := 0; i < flag.NArg(); i++ {
82 f, err := file.Open(flag.Arg(i))
83 if f == nil {
84 fmt.Fprintf(os.Stderr, "cat: can't open %s: error %s\n", flag.Arg(i), err)
85 os.Exit(1)
86 }
87 cat(f)
88 f.Close()
89 }
90 }