func main() { flag.Usage = func() { fmt.Printf("Usage: %s [OPTION]... [FILE]\n", flag.Program) fmt.Printf(`Output who is currently logged in according to FILE. If FILE is not specified, use %s. %s as FILE is common. `, utmp.UtmpxFile, utmp.Wtmpxfile) flag.PrintDefaults() fmt.Printf(` Report %s bugs to [email protected] Go coreutils home page: <https://www.github.com/EricLagergren/go-coreutils/> `, flag.Program) os.Exit(0) } flag.Parse() switch flag.NArg() { case 0: users(utmp.UtmpxFile, utmp.CheckPIDs) case 1: users(flag.Arg(0), 0) default: log.Fatalf("extra operand(s) %v", flag.Args()[1:]) } }
func main() { flag.Usage = func() { fmt.Printf(`Usage: %s [OPTION]... [FILE]... or: wc [OPTION]... --files0-from=F Print newline, word, and byte counts for each FILE, and a total line if more than one FILE is specified. A word is a non-zero-length sequence of characters delimited by white space. With no FILE, or when FILE is -, read standard input. The options below may be used to select which counts are printed, always in the following order: newline, word, character, byte, maximum line length. `, flag.Program) flag.PrintDefaults() fmt.Printf(` Report %s bugs to [email protected] Go coreutils home page: <https://www.github.com/EricLagergren/go-coreutils/> `, flag.Program) os.Exit(0) } flag.ProgVersion = "2.2" flag.Parse() if *constVersion { fmt.Printf("Unicode Version: %s\n", unicode.Version) os.Exit(0) } if !(*printBytes || *printChars || *printLines || *printWords || *printLineLength) { *printLines = true *printBytes = true *printWords = true } // This is a gross attempt to simulate this... // (print_lines + print_words + print_chars + // print_bytes + print_linelength) == 1 // // Since Go can't add booleans (e.g. false + true == 1) // and checking that *only* one of 5 bool variables would be sloppy, // we check the number of set flags and the remaining non-'print' flags // which is a much smaller set of conditions to check // // I could just use a loop, but this also removes a branch soooo... printOne = // 1 flag and it's not *filesFrom OR *tabWidth ((flag.NFlag() == 1 && *filesFrom == "" && *tabWidth == 8) || // 2 flags and one is *filesFrom OR *tabWidth (flag.NFlag() == 2 && (*filesFrom != "" || *tabWidth != 8)) || // 3 flags and two are *filesFrom AND *tabWidth (flag.NFlag() == 3 && *filesFrom != "" && *tabWidth != 8)) var ( ok int // Return status. files = flag.Args() // List of files. numFiles = len(files) // Number of files to wc. reasonable = true // Can we read file list into memory? size int64 ) if *filesFrom != "" { // Cannot specify files with --files0-from. if flag.NArg() > 0 { fatal("file operands cannot be combined with --files0-from") } // --files0-from is small enough to fit into RAM. if reasonable, size = isReasonable(*filesFrom); reasonable { files, numFiles = getFileList(*filesFrom, size) } } fs := getFileStatus(files) numberWidth = findNumberWidth(fs) if reasonable { if files == nil || len(files) == 0 { files = []string{"-"} } for i, file := range files { ok ^= wcFile(file, fs[i]) } } else { var err error file := os.Stdin if *filesFrom != "-" { file, err = os.Open(*filesFrom) } if err != nil { fatal("cannot open %q for reading: No such file or directory", *filesFrom) } defer file.Close() s := bufio.NewScanner(file) s.Split(func(data []byte, atEOF bool) (advance int, token []byte, err error) { if atEOF && len(data) == 0 { return 0, nil, nil } if i := bytes.IndexByte(data, nullByte); i >= 0 { // We have a full newline-terminated line. return i + 1, dropnullByte(numFiles, data[0:i]), nil } // If we're at EOF, we have a final, non-terminated line. Return it. if atEOF { return len(data), dropnullByte(numFiles, data), nil } // Request more data. return 0, nil, nil }) for ; s.Scan(); numFiles++ { ok ^= wcFile(s.Text(), fstatus{}) } if err := s.Err(); err != nil { fatal("%v", err) } } if numFiles > 1 { writeCounts(totalLines, totalWords, totalChars, totalBytes, maxLineLength, "total") } // Return status. os.Exit(ok) }