github.com/endophage/docker@v1.4.2-0.20161027011718-242853499895/runconfig/opts/envfile.go (about) 1 package opts 2 3 import ( 4 "bufio" 5 "bytes" 6 "fmt" 7 "os" 8 "strings" 9 "unicode" 10 "unicode/utf8" 11 ) 12 13 // ParseEnvFile reads a file with environment variables enumerated by lines 14 // 15 // ``Environment variable names used by the utilities in the Shell and 16 // Utilities volume of IEEE Std 1003.1-2001 consist solely of uppercase 17 // letters, digits, and the '_' (underscore) from the characters defined in 18 // Portable Character Set and do not begin with a digit. *But*, other 19 // characters may be permitted by an implementation; applications shall 20 // tolerate the presence of such names.'' 21 // -- http://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap08.html 22 // 23 // As of #16585, it's up to application inside docker to validate or not 24 // environment variables, that's why we just strip leading whitespace and 25 // nothing more. 26 func ParseEnvFile(filename string) ([]string, error) { 27 fh, err := os.Open(filename) 28 if err != nil { 29 return []string{}, err 30 } 31 defer fh.Close() 32 33 lines := []string{} 34 scanner := bufio.NewScanner(fh) 35 currentLine := 0 36 utf8bom := []byte{0xEF, 0xBB, 0xBF} 37 for scanner.Scan() { 38 scannedBytes := scanner.Bytes() 39 if !utf8.Valid(scannedBytes) { 40 return []string{}, fmt.Errorf("env file %s contains invalid utf8 bytes at line %d: %v", filename, currentLine+1, scannedBytes) 41 } 42 // We trim UTF8 BOM 43 if currentLine == 0 { 44 scannedBytes = bytes.TrimPrefix(scannedBytes, utf8bom) 45 } 46 // trim the line from all leading whitespace first 47 line := strings.TrimLeftFunc(string(scannedBytes), unicode.IsSpace) 48 currentLine++ 49 // line is not empty, and not starting with '#' 50 if len(line) > 0 && !strings.HasPrefix(line, "#") { 51 data := strings.SplitN(line, "=", 2) 52 53 // trim the front of a variable, but nothing else 54 variable := strings.TrimLeft(data[0], whiteSpaces) 55 if strings.ContainsAny(variable, whiteSpaces) { 56 return []string{}, ErrBadEnvVariable{fmt.Sprintf("variable '%s' has white spaces", variable)} 57 } 58 59 if len(data) > 1 { 60 61 // pass the value through, no trimming 62 lines = append(lines, fmt.Sprintf("%s=%s", variable, data[1])) 63 } else { 64 // if only a pass-through variable is given, clean it up. 65 lines = append(lines, fmt.Sprintf("%s=%s", strings.TrimSpace(line), os.Getenv(line))) 66 } 67 } 68 } 69 return lines, scanner.Err() 70 } 71 72 var whiteSpaces = " \t" 73 74 // ErrBadEnvVariable typed error for bad environment variable 75 type ErrBadEnvVariable struct { 76 msg string 77 } 78 79 func (e ErrBadEnvVariable) Error() string { 80 return fmt.Sprintf("poorly formatted environment: %s", e.msg) 81 }