├── LICENSE ├── README.md ├── cat └── aporcupine │ └── cat │ └── main.go ├── false └── sferrellaa │ └── false │ └── main.go ├── ls └── telegrammae │ └── ls │ └── main.go ├── mkdir ├── lucassha │ └── mkdir │ │ ├── mkdir.go │ │ └── mkdir_test.go └── telegrammae │ └── mkdir │ └── main.go ├── pwd └── sferrellaa │ └── pwd │ └── main.go ├── rm └── aporcupine │ └── rm │ └── main.go ├── tree └── lucassha │ └── tree │ └── main.go ├── true └── sferrellaa │ └── true │ └── main.go ├── whoami └── aporcupine │ └── whoami │ └── main.go └── yes └── aporcupine └── yes └── main.go /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 aporcupine 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GoUnix 2 | 3 | This project is a collection of many of the basic tools used on Unix-like operating systems implemented in Go as a learning exercize. 4 | 5 | The idea here is to implement as little or as many features as you want (or focus on optimization for example), keeping functionality mostly the same. 6 | 7 | ## Contributing 8 | 9 | If you're learning Go and want to contribute your own implementation, pull requests are welcome. 10 | 11 | ## Implementations 12 | 13 | - [cat](cat/) 14 | - [Example](cat/aporcupine/cat/main.go) 15 | - [false](false/) 16 | - [Example](false/sferrellaa/false/main.go) 17 | - [ls](ls/) 18 | - [Example](ls/telegrammae/ls/main.go) 19 | - [mkdir](mkdir/) 20 | - [Example](mkdir/telegrammae/mkdir/main.go) 21 | - [pwd](pwd/) 22 | - [Example](pwd/sferrellaa/pwd/main.go) 23 | - [rm](rm/) 24 | - [Example](rm/aporcupine/rm/main.go) 25 | - [true](true/) 26 | - [Example](true/sferrellaa/true/main.go) 27 | - [whoami](whoami/) 28 | - [Example](whoami/aporcupine/whoami/main.go) 29 | - [yes](yes/) 30 | - [Example](yes/aporcupine/yes/main.go) 31 | -------------------------------------------------------------------------------- /cat/aporcupine/cat/main.go: -------------------------------------------------------------------------------- 1 | // cat is a limited implementation of the standard UNIX cat utility 2 | package main 3 | 4 | import ( 5 | "bufio" 6 | "bytes" 7 | "flag" 8 | "fmt" 9 | "io" 10 | "log" 11 | "os" 12 | ) 13 | 14 | var numberNonblank = flag.Bool("number-nonblank", false, "number nonempty output lines, overrides -n") 15 | var showEnds = flag.Bool("show-ends", false, "display $ at end of each line") 16 | var number = flag.Bool("number", false, "number all output lines") 17 | var squeezeBlank = flag.Bool("squeeze-blank", false, "suppress repeated empty output lines") 18 | var showTabs = flag.Bool("show-tabs", false, "display TAB characters as ^I") 19 | 20 | func usage() { 21 | fmt.Println("Usage: cat [FLAG]... [FILE]...") 22 | fmt.Println("Concatenate FILE(s) to standard output") 23 | fmt.Println() 24 | fmt.Println("With no FILE, or when FILE is -, read standard input.") 25 | fmt.Println() 26 | flag.PrintDefaults() 27 | fmt.Println() 28 | fmt.Println("Examples:") 29 | fmt.Println(" cat f - g Output f's contents, then standard input, then g's contents.") 30 | fmt.Println(" cat Copy standard input to standard output.") 31 | } 32 | 33 | func main() { 34 | flag.Usage = usage 35 | flag.Parse() 36 | args := flag.Args() 37 | if len(args) == 0 { 38 | args = append(args, "-") 39 | } 40 | for _, arg := range args { 41 | file := os.Stdin 42 | if arg != "-" { 43 | var err error 44 | file, err = os.Open(arg) 45 | if err != nil { 46 | log.Fatal(err) 47 | } 48 | } 49 | if *numberNonblank || *showEnds || *number || *squeezeBlank || *showTabs { 50 | cat(file) 51 | } else { 52 | simpleCat(file) 53 | } 54 | file.Close() 55 | } 56 | } 57 | 58 | // Simple copy from file to stdout 59 | func simpleCat(file io.Reader) { 60 | _, err := io.Copy(os.Stdout, file) 61 | if err != nil { 62 | log.Fatal(err) 63 | } 64 | } 65 | 66 | // Read from file, complete some analysis and write to stdout 67 | func cat(file io.Reader) { 68 | reader := bufio.NewReader(file) 69 | line := 1 70 | partial := false 71 | lastBlank := false 72 | for { 73 | b, err := reader.ReadBytes('\n') 74 | if err != nil && err != bufio.ErrBufferFull && err != io.EOF { 75 | log.Fatal(err) 76 | } 77 | // Handle squeeze blank if requested 78 | if *squeezeBlank { 79 | lineBlank := len(b) > 0 && b[0] == '\n' 80 | if lastBlank && lineBlank { 81 | continue 82 | } 83 | lastBlank = lineBlank 84 | } 85 | // Add line numbers if required and not partial line suffix 86 | if (*number || *numberNonblank) && !partial && len(b) > 0 { 87 | if !(*numberNonblank && b[0] == '\n') { 88 | ln := fmt.Sprintf("%6v\t", line) 89 | b = append([]byte(ln), b...) 90 | line++ 91 | } 92 | } 93 | partial = false 94 | // Add $ to end of lines if requested and not partial line prefix 95 | if err == bufio.ErrBufferFull { 96 | partial = true 97 | } else if *showEnds && err != io.EOF { 98 | b = append(b[:len(b)-1], []byte("$\n")...) 99 | } 100 | // Replace tabs with ^I if requested 101 | if *showTabs { 102 | b = bytes.Replace(b, []byte("\t"), []byte("^I"), -1) 103 | } 104 | os.Stdout.Write(b) 105 | if err == io.EOF { 106 | break 107 | } 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /false/sferrellaa/false/main.go: -------------------------------------------------------------------------------- 1 | // "false" implementation by SferrellaA 2 | // File created 29 March, 2019 by SferrellaA 3 | // File edited 29 March, 2019 by SferrellaA 4 | 5 | package main 6 | 7 | import "os" 8 | 9 | func main() { 10 | 11 | // Return 1, for generic error 12 | os.Exit(1) 13 | } -------------------------------------------------------------------------------- /ls/telegrammae/ls/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "io/ioutil" 7 | "os" 8 | "strings" 9 | ) 10 | 11 | const versionNumber = 0.1 12 | 13 | var version = flag.Bool("v", false, "output version information") 14 | var all = flag.Bool("a", false, "list all items beginning with '.'") 15 | 16 | func usage() { 17 | fmt.Println("Usage:") 18 | fmt.Println("List the contents of a directory.") 19 | flag.PrintDefaults() 20 | } 21 | 22 | func main() { 23 | flag.Usage = usage 24 | 25 | flag.Parse() 26 | if *version { 27 | fmt.Printf("Version Number: %v\n", versionNumber) 28 | return 29 | } 30 | 31 | var dir string 32 | lenArgs := len(os.Args) 33 | if lenArgs > 1 { 34 | dir = os.Args[lenArgs-1] 35 | } else { 36 | dir = "." 37 | } 38 | 39 | files, err := ioutil.ReadDir(dir) 40 | if err != nil { 41 | fmt.Println(err) 42 | os.Exit(1) 43 | } 44 | for _, f := range files { 45 | if !*all && strings.HasPrefix(f.Name(), ".") { 46 | continue 47 | } 48 | fmt.Println(f.Name()) 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /mkdir/lucassha/mkdir/mkdir.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "errors" 5 | "flag" 6 | "fmt" 7 | "io/ioutil" 8 | "os" 9 | "path/filepath" 10 | "strconv" 11 | ) 12 | 13 | type errorString struct { 14 | s string 15 | } 16 | 17 | func (e *errorString) Error() string { 18 | return e.s 19 | } 20 | 21 | // New : returns new text error 22 | func New(text string) error { 23 | return &errorString{text} 24 | } 25 | 26 | func prepareTestDirTree(tree string) (string, error) { 27 | tmpDir, err := ioutil.TempDir("", "") 28 | if err != nil { 29 | return "", fmt.Errorf("error creating temp directory: %v\n", err) 30 | } 31 | 32 | err = os.MkdirAll(filepath.Join(tmpDir, tree), 0755) 33 | if err != nil { 34 | os.RemoveAll(tmpDir) 35 | return "", err 36 | } 37 | 38 | return tmpDir, nil 39 | } 40 | 41 | // octal : convert string to octal bits for proper dir permissions 42 | func octal(octStr string) uint32 { 43 | res, _ := strconv.ParseInt(octStr, 8, 32) 44 | return uint32(res) 45 | } 46 | 47 | // CreateDirs : Create directories for the passed in os.Args 48 | func CreateDirs(args []string) error { 49 | // flags 50 | var mode string 51 | var p string 52 | flag.StringVar(&mode, "mode", "0755", "set the file permission bits") 53 | flag.StringVar(&p, "p", "", "Create intermediate directories. Not implemented yet.") 54 | flag.Parse() 55 | 56 | // make sure dir/dirs not empty 57 | if len(args) == 0 { 58 | // fmt.Println("usage: mkdir [-pv] directory ...") 59 | return errors.New("usage: mkdir [-pv] directory ...") 60 | } 61 | 62 | for _, dir := range args { 63 | // create each directory 64 | err := os.Mkdir(dir, os.FileMode(octal(mode))) 65 | if err != nil { 66 | // fmt.Println("mkdir:", dir, "File exists") 67 | fmt.Printf("mkdir: %s: File exists\n", dir) 68 | } 69 | } 70 | 71 | return nil 72 | } 73 | 74 | func main() { 75 | err := CreateDirs(os.Args[1:]) 76 | if err != nil { 77 | fmt.Println(err) 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /mkdir/lucassha/mkdir/mkdir_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "os" 5 | "testing" 6 | ) 7 | 8 | func TestCreateDir(t *testing.T) { 9 | 10 | t.Run("Creating 2 directories", func(t *testing.T) { 11 | testDirs := []string{"test1", "test2"} 12 | err := CreateDirs(testDirs) 13 | if err == nil { 14 | for _, dir := range testDirs { 15 | err := os.Remove(dir) 16 | if err != nil { 17 | t.Errorf("directories not created") 18 | } 19 | } 20 | } 21 | }) 22 | 23 | } 24 | -------------------------------------------------------------------------------- /mkdir/telegrammae/mkdir/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "os" 7 | "strings" 8 | ) 9 | 10 | const versionNumber = 0.1 11 | 12 | var version = flag.Bool("v", false, "output version information") 13 | var path = flag.String("p", "", "create a path of directories") 14 | 15 | func usage() { 16 | fmt.Println("Usage:") 17 | fmt.Println("Create a directory.") 18 | flag.PrintDefaults() 19 | } 20 | 21 | func main() { 22 | flag.Usage = usage 23 | 24 | flag.Parse() 25 | if *version { 26 | fmt.Printf("Version Number: %v\n", versionNumber) 27 | return 28 | } 29 | 30 | var dir string 31 | lenArgs := len(os.Args) 32 | if lenArgs > 1 { 33 | dir = os.Args[lenArgs-1] 34 | } else { 35 | usage() 36 | return 37 | } 38 | 39 | if *path == "" { 40 | err := os.Mkdir(dir, os.ModePerm) 41 | handleCreate(err) 42 | } else { 43 | // TODO Handle Windows paths 44 | dirs := strings.Split(*path, "/") 45 | var p string 46 | for _, sub := range dirs { 47 | p += sub + "/" 48 | err := os.Mkdir(p, os.ModePerm) 49 | handleCreate(err) 50 | } 51 | } 52 | } 53 | 54 | func handleCreate(err error) { 55 | if err != nil { 56 | fmt.Println(err) 57 | os.Exit(1) 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /pwd/sferrellaa/pwd/main.go: -------------------------------------------------------------------------------- 1 | // pwd is a go implementation of the unix tool "pwd" 2 | // created 23 March 2019 by SferrellaA 3 | // edited 28 March 2019 by SferrellaA 4 | package main 5 | 6 | import ( 7 | "flag" 8 | "fmt" 9 | "path/filepath" 10 | ) 11 | 12 | // errFail() is a helper function to fail on errors 13 | func errFail(err error) { 14 | if nil != err { 15 | panic(err) 16 | } 17 | } 18 | 19 | // usage() defines the behavior of `pwd -h` 20 | func usage() { 21 | fmt.Println("Usage: pwd [-LP]") 22 | fmt.Println(" Print the name of the current working directory") 23 | fmt.Println("") 24 | fmt.Println("Options:") 25 | fmt.Println(" -L Logical path (symlinks allowed) (default true)") 26 | fmt.Println(" -P Physical/literal path (no symlinks)") 27 | fmt.Println("") 28 | fmt.Println("`pwd` assumes `-L` if no flag is given") 29 | fmt.Println("`-P` will override `-L` if both are given") 30 | } 31 | 32 | // getFlags() configures and parses flags, returns pwd mode 33 | func getFlags() bool { 34 | 35 | // Additional, hidden flags prevent user headache 36 | 37 | // Logical is assumed by default, so value not stored 38 | flag.Bool("L", false, "") 39 | flag.Bool("l", false, "") 40 | flag.Bool("logical", false, "") 41 | 42 | // Physical trumps logical 43 | P := flag.Bool("P", false, "") 44 | p := flag.Bool("p", false, "") 45 | physical := flag.Bool("physical", false, "") 46 | 47 | // Read flags 48 | flag.Usage = usage 49 | flag.Parse() 50 | 51 | // Return true for -P, false for -L 52 | if *P || *p || *physical { 53 | return true 54 | } 55 | return false 56 | } 57 | 58 | // absolute() returns the current absolute/logical PWD 59 | func absolute() string { 60 | abs, err := filepath.Abs(".") 61 | errFail(err) 62 | return abs 63 | } 64 | 65 | // PWD() provides `pwd` functionality as a callable function 66 | func PWD(physical bool) string { 67 | 68 | // Get the absolute (logical) path 69 | pwd := absolute() 70 | 71 | // If change logical to physical if argued for 72 | if physical { 73 | var err error 74 | pwd, err = filepath.EvalSymlinks(pwd) 75 | errFail(err) 76 | } 77 | 78 | // Return pwd 79 | return pwd 80 | } 81 | 82 | // main() calls on existing functions 83 | func main() { 84 | mode := getFlags() 85 | pwd := PWD(mode) 86 | fmt.Println(pwd) 87 | } 88 | -------------------------------------------------------------------------------- /rm/aporcupine/rm/main.go: -------------------------------------------------------------------------------- 1 | // rm is a limited implementation of the standard UNIX rm utility 2 | package main 3 | 4 | import ( 5 | "flag" 6 | "fmt" 7 | "io/ioutil" 8 | "os" 9 | "path" 10 | 11 | "github.com/aporcupine/multiflag" 12 | ) 13 | 14 | var ( 15 | recursive = multiflag.Bool(false, "remove directories and their contents recursively", "r", "R", "recursive") 16 | dir = multiflag.Bool(false, "remove empty directories", "d", "dir") 17 | verbose = multiflag.Bool(false, "explain what is being done", "v", "verbose") 18 | version = flag.Bool("version", false, "output version information and exit") 19 | noPreserveRoot = flag.Bool("no-preserve-root", false, "do not treat '/' specially") 20 | promptEvery = flag.Bool("i", false, "prompt before every removal") 21 | exitCode int 22 | ) 23 | 24 | func usage() { 25 | fmt.Println("Usage: rm [OPTION]... [FILE]...") 26 | fmt.Println("Remove (unlink) the FILE(s).") 27 | fmt.Println() 28 | flag.PrintDefaults() 29 | fmt.Println() 30 | fmt.Println("By default, rm does not remove directories. Use the --recursive (-r or -R)") 31 | fmt.Println("option to remove each listed directory, too, along with all of its contents.") 32 | } 33 | 34 | func main() { 35 | defer func() { 36 | os.Exit(exitCode) // Exit with value of the exitCode var rather than 0 37 | }() 38 | flag.Usage = usage 39 | flag.Parse() 40 | paths := flag.Args() 41 | if *version { 42 | fmt.Println("rm 1.0") 43 | fmt.Println("Limited implementation of the standard UNIX rm utility") 44 | fmt.Println("Written by Tom Hanson for https://github.com/aporcupine/GoUnix") 45 | return 46 | } 47 | if len(paths) == 0 { 48 | fmt.Fprintln(os.Stderr, "missing operand") 49 | fmt.Fprintln(os.Stderr, "Try 'rm --help' for more information.") 50 | exitCode = 1 51 | return 52 | } 53 | for _, p := range paths { 54 | removePath(p) 55 | } 56 | } 57 | 58 | // Removes the provided path, recursively if the recursive flag is true 59 | func removePath(p string) { 60 | p = path.Clean(p) 61 | f, err := os.Lstat(p) 62 | if err != nil { 63 | fmt.Fprintln(os.Stderr, err) 64 | exitCode = 1 65 | return 66 | } 67 | 68 | if !*noPreserveRoot && p == "/" { 69 | fmt.Println("it is dangerous to operate recursively on '/'") 70 | fmt.Println("use --no-preserve-root to override this failsafe") 71 | exitCode = 1 72 | return 73 | } 74 | 75 | if f.IsDir() && *recursive { // Descend into directory if recursive 76 | if *promptEvery { 77 | c, err := promptUser(fmt.Sprintf("descend into directory '%v'?", p)) 78 | if err != nil { 79 | fmt.Fprintf(os.Stderr, "error prompting user: %v\n", err) 80 | exitCode = 1 81 | return 82 | } 83 | if !c { 84 | return 85 | } 86 | } 87 | files, _ := ioutil.ReadDir(p) 88 | for _, file := range files { 89 | removePath(fmt.Sprintf("%v/%v", p, file.Name())) 90 | } 91 | } 92 | if !f.IsDir() || *dir || *recursive { // Remove files and empty directories if -d or recursive 93 | if *promptEvery { 94 | ft := fileType(f) 95 | prompt := fmt.Sprintf("remove %v '%v'?", ft, p) 96 | c, err := promptUser(prompt) 97 | if err != nil { 98 | fmt.Fprintf(os.Stderr, "error prompting user: %v\n", err) 99 | exitCode = 1 100 | return 101 | } 102 | if !c { 103 | return 104 | } 105 | } 106 | if err := os.Remove(p); err != nil { 107 | fmt.Fprintln(os.Stderr, err) 108 | exitCode = 1 109 | } else if *verbose { 110 | t := "removed '%v'\n" 111 | if f.IsDir() { 112 | t = "removed directory '%v'\n" 113 | } 114 | fmt.Printf(t, p) 115 | } 116 | } else { 117 | fmt.Fprintf(os.Stderr, "cannot remove '%v': Is a directory\n", p) 118 | exitCode = 1 119 | return 120 | } 121 | } 122 | 123 | // Prompts the user to confirm whether to continue 124 | // Returns true if response is yes or y, else false 125 | func promptUser(prompt string) (bool, error) { 126 | fmt.Print(prompt + " ") 127 | var r string 128 | _, err := fmt.Scanln(&r) 129 | if err != nil { 130 | return false, err 131 | } 132 | if r == "y" || r == "yes" { 133 | return true, nil 134 | } 135 | return false, nil 136 | } 137 | 138 | // Given a os.FileInfo argument, returns the type or file 139 | func fileType(f os.FileInfo) string { 140 | switch mode := f.Mode(); { 141 | case mode.IsRegular(): 142 | return "regular file" 143 | case mode.IsDir(): 144 | return "directory" 145 | case mode&os.ModeSymlink != 0: 146 | return "symbolic link" 147 | case mode&os.ModeNamedPipe != 0: 148 | return "named pipe" 149 | case mode&os.ModeDevice != 0: 150 | return "device file" 151 | default: 152 | return "file" 153 | } 154 | } 155 | -------------------------------------------------------------------------------- /tree/lucassha/tree/main.go: -------------------------------------------------------------------------------- 1 | // implementation of the UNIX command "tree" 2 | 3 | // currently, this only implements one level down 4 | // recursively add in a counter for proper spacing depth 5 | // and then recursively call the subDir function in itself 6 | 7 | // add the flags package for -I extension as well. 8 | // subDir to skip currently not implemented 9 | 10 | package main 11 | 12 | import ( 13 | "fmt" 14 | "io/ioutil" 15 | "os" 16 | "path/filepath" 17 | ) 18 | 19 | func main() { 20 | 21 | // add in flag components to test for this 22 | subDirToSkip := "" 23 | 24 | fileCount := numFilesInDir(".") 25 | fileNum := 1 26 | 27 | err := filepath.Walk(".", func(path string, info os.FileInfo, err error) error { 28 | if err != nil { 29 | return err 30 | } 31 | 32 | // skip the entire dir if it's the specified flag entered 33 | if info.IsDir() && info.Name() == subDirToSkip { 34 | return filepath.SkipDir 35 | } 36 | 37 | // check for subdirectory 38 | if info.IsDir() == true && info.Name() != "." { 39 | // walk into the subdirectory 40 | subDir(info.Name()) 41 | // skip the subdirectory as it's already been outputtted 42 | // within the function 43 | return filepath.SkipDir 44 | } 45 | 46 | if info.Name() == "." { 47 | fmt.Println(".") 48 | } else if fileNum != fileCount { 49 | fmt.Println("├──", info.Name()) 50 | } else { 51 | fmt.Println("└──", info.Name()) 52 | } 53 | 54 | fileNum++ 55 | 56 | return nil 57 | }) 58 | 59 | if err != nil { 60 | fmt.Printf("error walking the path %v\n", err) 61 | return 62 | } 63 | } 64 | 65 | // numFilesInDir : counts the number of files in a directory 66 | func numFilesInDir(dirName string) int { 67 | dir := "./" + dirName 68 | files, _ := ioutil.ReadDir(dir) 69 | // fileCount := len(files) 70 | return len(files) 71 | } 72 | 73 | // subDir : print out the files of a sub directory with Walk/WalkFunc 74 | func subDir(dirName string) { 75 | fileCount := numFilesInDir(dirName) 76 | fileNum := 1 77 | 78 | err := filepath.Walk(dirName, func(path string, info os.FileInfo, err error) error { 79 | if err != nil { 80 | return err 81 | } 82 | 83 | if info.IsDir() { 84 | fmt.Println("├──", info.Name()) 85 | } else if fileNum != fileCount { 86 | fmt.Println("│ └──", info.Name()) 87 | } else { 88 | fmt.Println("│ ├──", info.Name()) 89 | } 90 | 91 | fileNum++ 92 | 93 | return nil 94 | }) 95 | 96 | if err != nil { 97 | return 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /true/sferrellaa/true/main.go: -------------------------------------------------------------------------------- 1 | // "true" implementation by SferrellaA 2 | // File created 29 March, 2019 by SferrellaA 3 | // File edited 29 March, 2019 by SferrellaA 4 | 5 | package main 6 | 7 | import "os" 8 | 9 | func main() { 10 | 11 | // Return 0 for no error 12 | os.Exit(0) 13 | } -------------------------------------------------------------------------------- /whoami/aporcupine/whoami/main.go: -------------------------------------------------------------------------------- 1 | // whoami is an implementation of the standard UNIX whoami utility 2 | package main 3 | 4 | import ( 5 | "flag" 6 | "fmt" 7 | "log" 8 | "os/user" 9 | ) 10 | 11 | const versionNumber = 0.1 12 | 13 | var version = flag.Bool("version", false, "output version information and exit") 14 | 15 | func usage() { 16 | fmt.Println("Usage: whoami [OPTION]...") 17 | fmt.Println("Print the user name associated with the current effective user ID.") 18 | fmt.Println("Same as id -un.") 19 | fmt.Println() 20 | flag.PrintDefaults() 21 | } 22 | 23 | func main() { 24 | flag.Usage = usage 25 | flag.Parse() 26 | if *version { 27 | fmt.Printf("Version Number: %v\n", versionNumber) 28 | return 29 | } 30 | cu, err := user.Current() 31 | if err != nil { 32 | log.Fatal(err) 33 | } 34 | fmt.Println(cu.Username) 35 | } 36 | -------------------------------------------------------------------------------- /yes/aporcupine/yes/main.go: -------------------------------------------------------------------------------- 1 | // yes is an implementation of the standard UNIX yes utility 2 | package main 3 | 4 | import ( 5 | "flag" 6 | "fmt" 7 | "strings" 8 | ) 9 | 10 | const versionNumber = 0.1 11 | 12 | var version = flag.Bool("version", false, "output version information and exit") 13 | 14 | func usage() { 15 | fmt.Println("Usage: yes [STRING]...") 16 | fmt.Println(" or: yes OPTION") 17 | fmt.Println("Repeatedly output a line with all specified STRING(s), or 'y'.") 18 | fmt.Println() 19 | flag.PrintDefaults() 20 | } 21 | 22 | func main() { 23 | flag.Usage = usage 24 | flag.Parse() 25 | if *version { 26 | fmt.Printf("Version Number: %v\n", versionNumber) 27 | return 28 | } 29 | out := "y" 30 | if len(flag.Args()) > 0 { 31 | out = strings.Join(flag.Args(), " ") 32 | } 33 | for { 34 | fmt.Println(out) 35 | } 36 | } 37 | --------------------------------------------------------------------------------