| 1106 | } |
| 1107 | |
| 1108 | func readConfig(filename string) error { |
| 1109 | f, err := os.Open(filename) |
| 1110 | if err != nil { |
| 1111 | return fmt.Errorf("unable to open config file %q: %w", filename, err) |
| 1112 | } |
| 1113 | defer f.Close() |
| 1114 | r := csv.NewReader(f) |
| 1115 | r.Comma = ' ' |
| 1116 | r.Comment = '#' |
| 1117 | r.FieldsPerRecord = -1 |
| 1118 | r.TrimLeadingSpace = true |
| 1119 | r.ReuseRecord = true |
| 1120 | for { |
| 1121 | record, err := r.Read() |
| 1122 | if err == io.EOF { |
| 1123 | break |
| 1124 | } |
| 1125 | if err != nil { |
| 1126 | return fmt.Errorf("configuration file parsing failed: %w", err) |
| 1127 | } |
| 1128 | switch len(record) { |
| 1129 | case 0: |
| 1130 | continue |
| 1131 | case 1: |
| 1132 | if err := flag.Set(record[0], "true"); err != nil { |
| 1133 | line, _ := r.FieldPos(0) |
| 1134 | return fmt.Errorf("error parsing config file %q at line %d (%#v): %w", filename, line, record, err) |
| 1135 | } |
| 1136 | case 2: |
| 1137 | if err := flag.Set(record[0], record[1]); err != nil { |
| 1138 | line, _ := r.FieldPos(0) |
| 1139 | return fmt.Errorf("error parsing config file %q at line %d (%#v): %w", filename, line, record, err) |
| 1140 | } |
| 1141 | default: |
| 1142 | unified := strings.Join(record[1:], " ") |
| 1143 | if err := flag.Set(record[0], unified); err != nil { |
| 1144 | line, _ := r.FieldPos(0) |
| 1145 | return fmt.Errorf("error parsing config file %q at line %d (%#v): %w", filename, line, record, err) |
| 1146 | } |
| 1147 | } |
| 1148 | } |
| 1149 | return nil |
| 1150 | } |
| 1151 | |
| 1152 | func main() { |
| 1153 | os.Exit(run()) |