Even though I’ve been using *nix based OSs for about twelve years I only recently came across .netrc when reading through the man pages for OfflineIMAP and msmtp - I wanted to start synchronising and backing up my .offlineimaprc
and .msmtprc
files via snose, but didn’t really want to do that with my passwords in the file, so was reading up on how I could reference a password from some external source.
So I thought it would be great if snose could also do this, as I liked the idea of consolidating passwords into .netrc
if I was going to have to store them in a file; up until now, snose required it’s own .snoseauth
file with username and password in json format. Adding this was easy, thanks to the netrc file processing standard library:
if not options.username or not options.password:
#Check to see if stored somewhere
try:
options.username = netrc.netrc().authenticators("simple-note.appspot.com")[0]
options.password = netrc.netrc().authenticators("simple-note.appspot.com")[2]
except IOError as e:
print 'Username and password must be supplied or exist .netrc file under domain of simple-note.appspot.com'
exit()
And I also thought it would be great if Haskerdeux could use .netrc
. Before this, username and password had to be supplied as command line arguments. This implementation “works well enough for me”. As more of a note to myself on the code then anything else: it reads the lines of the .netrc
into a list; drops items off from the front of the list until it gets to one containing the domain/machine of interest; then checks if that list item also contains “login”, if it does the format of the .netrc
entry is all on one line so it uses the getcred
function to split up that line into words ((words $ head netrc')
) and removes items from that list until it finds “login”, etc, at which point it gets the succeeding list item; otherwise it assumes the next two lines (netrc' !! 1
, etc) contain the login and password and simply splits up these lines into lists of words and gets the last item from each list.
readnetrc = do
home <- getHomeDirectory
netrc <- fmap lines $ readFile (home ++ "/.netrc")
let netrc' = dropWhile (not . isInfixOf "teuxdeux") netrc
let (username, password) = if "login" `isInfixOf` head netrc'
-- if entry is on one line
then (getcred "login", getcred "password")
-- if entry is on multiple lines
else (last $ words $ netrc' !! 1, last $ words $ netrc' !! 2)
where getcred c = dropWhile (not . isInfixOf c) (words $ head netrc') !! 1
return (username, password)
Whilst I was at it, I thought I should try to implement similarly for Vim as well so I could do things like this in my .vimrc
(this example for Simplenote.vim):
let g:SimplenoteUsername = GetCredFromNetrc("simple-note.appspot.com")[0]
let g:SimplenotePassword = GetCredFromNetrc("simple-note.appspot.com")[1]
As until now, I either had to include my password in my .vimrc
or source it from yet another separate password file. This uses exactly the same approach as the Haskell one, except it isn’t possible to “drop” items off a list so it just keeps track of the index as it is going through the lines of the .netrc
.
function! GetCredFromNetrc(machine)
let filename = $HOME.'/.netrc'
let login = ""
let password = ""
if filereadable(filename)
let lines = readfile(filename)
let i = match(lines, "machine ".a:machine)
if lines[i] =~ "login"
"get username and password"
let login = split(split(line[i], "login")[-1], " ")[0]
let password = split(split(lines[i], "password")[-1], " ")[0]
else
"Assume on next two lines. It will be for me
let login = split(split(lines[i+1], "login")[-1], " ")[0]
let password = split(split(lines[i+2], "password")[-1], " ")[0]
endif
endif
return [login, password]
endfunction
I just include that function in my .vimrc
just before the point where I want to use it.