4
\$\begingroup\$

Using various answers from Stack Overflow and Ask Ubuntu, I've hacked together this simple C program that wipes terminal history. It works but I'm relatively new to C so I'm not sure if everything is correct.

#include <stdio.h>

int main(void) {
  // check if the program is being executed in a terminal
  if (isatty(0)) {
    // if the program is being executed in a 
    // terminal just start the wiper
    system("cat /dev/null > ~/.bash_history;history -c;history -w;rm -r ~/.bash_history;exit;");
  } else {
    // if the program is being executed as a stand-alone
    // open a new terminal window and then start the wiper
    system("gnome-terminal -x sh -c 'cat /dev/null > ~/.bash_history;history -c;history -w;rm -r ~/.bash_history;exit;'");
  }
  // stop the program
  return 0;
}
\$\endgroup\$
  • 8
    \$\begingroup\$ Why make this a C program instead of a shell script? After all, the only thing C does is testing if it's running in a terminal, delegating all the functionality back to the shell via the system call. So it's practically a shell script wrapped in a C program. \$\endgroup\$ – CodesInChaos Feb 17 '16 at 13:21
  • \$\begingroup\$ I don't know just prefer C... \$\endgroup\$ – user97943 Feb 17 '16 at 13:23
  • \$\begingroup\$ I'd extract the actual command into a macro and reference concatenate it with the invocation of the terminal, so you don't have a redundant wiping command in the program. \$\endgroup\$ – CodesInChaos Feb 17 '16 at 13:36
  • 1
    \$\begingroup\$ I'm pretty sure this will only perform as expected on a linux system running gnome due to its reliance on the gnome-terminal command being present. \$\endgroup\$ – DemonessJess Feb 17 '16 at 16:25
3
\$\begingroup\$

That's a lot of shell commands to do very little.

You could replace all those shell commands to get the equivalent effect with just this:

rm ~/.bash_history; HISTFILE=

Let me explain step by step why this is equivalent:

  • cat /dev/null > ~/.bash_history - truncate the file. Exactly the same as the shorter > ~/.bash_history. This is pointless, because later you delete the file anyway.
  • history -c - clear the history. Pointless because later you delete the file anyway
  • history -w - write the content of the history to the file. Pointless because later you delete the file anyway
  • rm -r ~/.bash_history - delete the file, recursively. The recursive flag is pointless, as the history file is never a directory
  • exit - This is pointless, as the system function will exit automatically anyway

All this can be reduced to what I gave above, by benefiting from the fact that if HISTFILE is unset, history is not saved anywhere.

Btw, I don't understand why you need a gnome terminal at all. I think you can simply remove that special treatment.

Lastly, using system is generally not recommended, it should be avoided as much as possible. If you must use it for some reason, you should call commands by their absolute paths, otherwise the program will be vulnerable to path injection attacks.

\$\endgroup\$
1
\$\begingroup\$

This program is useful in a very narrow context of someone using bash as their command shell, and using gnome-terminal for terminal windows. And as suggested in comments I would rather have programmed this a bash function or similar shell script to improve a little on portability and usage options.

With that out of the question, the main issue I'm having with your code is that you wrap series of commands and blatantly ignore any error codes returned from anything. Any or all of the subcommands can fail, and you ignore it. Not good. And you finalize your code returning 0 (which by the way is unnecessary as it is the default) indicating everything is OK.

A secondary minor issue is that you've duplicated the command in the two cases, and if you at some point in time decide to change it, there is a certain possibility that you'll change one of the two, and forget about the other. I would rather have used some variant with sprintf() on the second case, referencing the command from a constant string.

\$\endgroup\$
  • \$\begingroup\$ Thank you for all the advice, I really appreciate it, I didn't think string interpolation mattered but there always the possibility of human error. \$\endgroup\$ – user97943 Feb 22 '16 at 18:42
1
\$\begingroup\$

You caught my attention with cat /dev/null >. That's an odd command; /dev/null discards any data sent to it, so it's good for testing system commands, data disposal... and, apparently, disk reading tests.

Were you trying to overwrite the file with null bytes? That should be a good way to erase a file and prevent any data recovery program from recovering it. If that's the case, you'd want /dev/zero, and even then, just doing a cat is too risky: it keeps appending null bytes until you interrupt the process or you run out of disk space. Using dd you can limit how much data you send to the file.

That said, overwriting a file is much slower than simply deleting it. It's a good solution for sensitive data, however.

Usually people recommend /dev/random over /dev/zero; if you only use null bytes, it's easier to know someone tried hard to wipe files, and an external machine could recover the file even if a regular computer can't. Or you could just use the command shred - with the correct flags, it overwrites the file before deleting it.

However...

modern OSs and professional servers have several systems to prevent loss of data. If you use disk journaling, you might not be writing random bytes somewhere else than your file - so you'd be doing just a slow and costly rm. (man shred explains this more in depth).

\$\endgroup\$
  • \$\begingroup\$ (Welcome to CR!) cat /dev/null >. That's an odd command indeed. See janos' answer. "The read side" of /dev/null is documented, too. Interesting guesswork about the intentions - alas, user97943 seems inactive. \$\endgroup\$ – greybeard Mar 7 '18 at 5:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy