// Command lsf provides functions to use the lsf with the commandline. package main import ( "flag" "fmt" "io/ioutil" "log" "os" "path" "strings" "syscall" "git.marceltransier.de/lsf" "github.com/pkg/errors" "golang.org/x/crypto/ssh/terminal" ) var ( sessionCache string username string ) func init() { homeDir, err := os.UserHomeDir() if err != nil { log.Fatal(err) } defaultCacheDir := path.Join(homeDir, ".cache/go-lsf/sessions") flag.StringVar(&sessionCache, "session-cache", defaultCacheDir, "path where the session tokens are located") flag.StringVar(&username, "username", "", "username to login with in lsf") flag.Parse() err = os.MkdirAll(sessionCache, os.ModePerm) if err != nil { log.Fatal(err) } } func main() { if len(username) == 0 { var err error username, err = readUsername() if err != nil { log.Fatal(err) } } s, err := session(username) if err != nil { log.Fatal(err) } fmt.Printf("s: %+v\n", s) } func readUsername() (string, error) { var username string fmt.Print("Username: ") _, err := fmt.Scanf("%s", &username) if err != nil { return "", errors.Wrap(err, "could not read username") } return username, nil } func readPassword() (string, error) { var password string fmt.Print("Password: ") b, err := terminal.ReadPassword(int(syscall.Stdin)) if err != nil { return "", errors.Wrap(err, "could not read password") } fmt.Print("\n") password = string(b) return password, nil } func session(username string) (*lsf.Session, error) { sessionPath := path.Join(sessionCache, username) sessionFile, err := os.Open(sessionPath) if err != nil { pErr, ok := err.(*os.PathError) if !ok { return nil, err } errno, ok := pErr.Unwrap().(syscall.Errno) if !ok { return nil, err } if errno != syscall.ENOENT { log.Fatal(err) } log.Printf("no session for %s cached\n", username) return login(username) } defer sessionFile.Close() b, err := ioutil.ReadAll(sessionFile) if err != nil { return nil, errors.Wrapf(err, "could not read session file %s", sessionPath) } sid := strings.TrimSuffix(string(b), "\n") s := &lsf.Session{ SID: sid, } valid, err := s.Valid() if err != nil { return nil, errors.Wrap(err, "could not check session") } if !valid { fmt.Println("session is not valid") err := os.Remove(sessionPath) if err != nil { log.Println(errors.Wrap(err, "could not remove invalid session file")) } return login(username) } return s, nil } func login(username string) (*lsf.Session, error) { password, err := readPassword() if err != nil { return nil, errors.Wrap(err, "could not login") } s, err := lsf.Login(username, password) if err != nil { return nil, err } sessionPath := path.Join(sessionCache, username) err = ioutil.WriteFile(sessionPath, []byte(s.SID), 0666) if err != nil { log.Println(errors.Wrap(err, "could not cache session id")) } return s, nil }