0

I am creating a new CLI application, where I want to get some sensitive input from the user. Since, this input can be quite descriptive as well as the information is a bit sensitive, I wanted to allow user to enter a command like this from this app:

app new entry

after which, I want to provide user with a VIM session where he can write this descriptive input, which when he exits from this VIM session, will be captured by my script and used for further processing.

Can someone tell me a way (probably some hidden VIM feature - since, I am always amazed by them) so that I can do so, without creating any temporary file? As explained in a comment below, I would prefer a some-what in-memory file, since the information can be a bit sensitive, and hence, I would like to process it first via my script and then only, write it to disk in an encrypted manner.

Stoic
  • 10,536
  • 6
  • 41
  • 60
  • Not sure I got the question. Maybe http://vim.wikia.com/wiki/User_input_from_a_script ? – lucapette Jan 08 '13 at 14:55
  • @lucapette: I have edited the question. I hope this should clarify what I intend to do. – Stoic Jan 08 '13 at 15:22
  • why do you want to avoid a temp file? there's nothing bad about that... – eckes Jan 08 '13 at 15:42
  • @eckes: I was wondering if there was a way I could 'virtually' create a file in the system memory. I am using ruby, if this helps. The reason is that the user will be providing some sensitive information that I would prefer to write on the disk only after the information has been encrypted. Is this a valid excuse, or I am being paranoid here? – Stoic Jan 08 '13 at 17:33
  • You can mitigate risk of physical recovery with full disk encryption. In a virtualized server environment this is not a commonly considered measure (but still valuable when the hypervisor is breached). Alternatively, mount a ramdisk and put the tempfiles on it. Now the OS treats it like filesystem but stores it in RAM. – Joe Atzberger Jun 22 '16 at 19:06

3 Answers3

6

Git actually does this: when you type git commit, a new Vim instance is created and a temporary file is used in this instance. In that file, you type your commit message

Once Vim gets closed again, the content of the temporary file is read and used by Git. Afterwards, the temporary file gets deleted again.

So, to get what you want, you need the following steps:

That's it.

Community
  • 1
  • 1
eckes
  • 64,417
  • 29
  • 168
  • 201
1

You can make shell create file descriptors attached to your function and make vim write there, like this: (but you need to split script in two parts: one that calls vim and one that processes its input):

# First script
…
vim --cmd $'aug ScriptForbidReading\nau BufReadCmd /proc/self/fd/* :' --cmd 'aug END' >(second-script)

. Notes:

  1. second-script might actually be a function defined in first script (at least in zsh). This also requires bash or zsh (tested only on the latter).
  2. Requires *nix, maybe won’t work on some OSes considered to be *nix.
  3. BufReadCmd is needed because vim hangs when trying to read write-only descriptor.
  4. It is suggested that you set filetype (if needed) right away, without using ftdetect plugins: in case your script is not the only one which will use this method.
  5. Zsh will wait for second-script to finish, so you may continue script right after vim command in case information from second-script is not needed (it would be hard to get from there).
  6. Second script will be launched from a subshell. Thus no variable modifications will be seen in code running after vim call.
  7. Second script will receive whatever vim saves on standard input. Parent standard input is not directly accessible, but using </dev/tty will probably work.

This is for zsh/bash script. Nothing will really prevent you from using the same idea in ruby (it is likely more convenient and does not require splitting into two scripts), but I do not know ruby enough to say how one can create file descriptors in ruby.

ZyX
  • 52,536
  • 7
  • 114
  • 135
0

Using vim for this seems like overkill.

The highline ruby gem might do what you need:

require 'highline'
irb> pw = HighLine.new.ask('info: ') {|q| q.echo = false }
info: 
=> "abc"

The user's text is not displayed when you set echo to false.

This is also safer than creating a file and then deleting it, because then you'd have to ensure that the delete was secure (overwriting the file several times with random data so it can't be recovered; see the shred or srm utilities).

Kelvin
  • 20,119
  • 3
  • 60
  • 68
  • How is using a Ruby gem less of an overkill than using vim? Every machine has vim. – Artur Sapek Aug 20 '13 at 03:00
  • @ArturSapek I think you're misunderstanding. I'm not saying the mere using of vim is overkill. I'm also not saying it's overkill because someone would need to install it (let's not even get started with Windows). I'm saying it's overkill because of the complexity of getting vim to do what the OP is asking. Seems like a square-peg-in-round-hole solution. Consider the number of steps and possible security holes in the other answers. – Kelvin Aug 20 '13 at 16:44