I am currently using Kubuntu 8.04. Although I do not know any bash, I altered the bash shell (via internet guides) to append history instead of truncating the history file. After editing the shell, the default way to clear the history only clears the interactive history and not the actual history file (since it is no longer truncated upon closing the shell). I then wrote a c++ script to clear the contents of the history file (or an alternative file if one is presented as an argument). It works when I try to access the $HOME environmental variable using getenv("HOME"), but I receive a segmentation fault when I try to use getenv("HISTFILE") which is the current file that the bash shell stores its history to. I also wanted to clear the interactive history at the same time. The bash command is "history -c", but I do not know how to incorporate this. I tried system("history -c") but I received an error as "history" could not be found. I was wondering if there is a way to directly access the environment variable $HISTFILE and also call the shell command history -c. Here is my current c++ script

#include <string>
#include <iostream>
#include <fstream>
#include <stdlib.h>
#include "/mydocuments/Documents/c++/headers/stringcaps.h"
using namespace std;




int main (int argc, char * argv[])
{
	string file, input = getenv("HOME");		 //input is set to $HOME variable for use with file
	if (argc == 1)				 //I would prefer to use $HISTFILE if possible
		file = input + "/.bash_history"; 	 //set file to default $HOME/.bash_history
	else
		file = argv[1]; //file becomes offered argument
	ifstream file_check;			 //open file to check
	file_check.open(file.c_str());		 //if it exists
	if (file_check.fail())			 //if not, abort
		cout << file << " does not exist\nNothing was cleared" << endl;
	else					 //if file exists, continue
	{
		file_check.close();		 //close test file before continuing
		cout << "The contents of " << file 
		<< " will be cleared" << endl;
		cout << "Action cannot be reversed\nContinue? [y/n] -> ";
		getline(cin, input);
		if (input == "")
			input = "y";
		lowercase(input);		 //function that changes a string to all lowercase letters found in stringcaps.h
		if (input[0] == 'y')
		{
			ofstream hist_file;
			hist_file.open(file.c_str(), ios::trunc); //open file and erase contents
			hist_file.close();
			/* Next line is currently removed until the problem is solved
			system("history -c");*/
			cout << file << " has been cleared" << endl;
		}
		else
			cout << file << " not cleared" << endl;
	}
	return 0;
}

I would appreciate any help you can offer me or any advice on optimizing or improving the code.

Recommended Answers

All 18 Replies

do you know if $HISTFILE actually exists in the environment ? My guess is that getenv() returns NULL and your program is not checking for a NULL return.

I would assume it does. When I run "echo $HISTFILE" (the bash command for displaying variable for those that don't know) in the bash shell, it returns the file that I am intending to reach. For "echo $HOME" I also receive the directory for the .bash_history file. Is there any way that you know of to check for it?

BTW The script I presented up there currently compiles, and executes successfully clearing the file. I am just hoping to replace $HOME/.bash_history with $HISTFILE because that will directly access the file. I'm not sure if I conveyed that clearly enough in my previous message.

line 17: that will only work if there are no spaces in the path or filename. The shell treats the words seperated by spaces as seperate arguments

Put a print statement after getenv("HISTFILE") to see if it returns NULL or not. Print out its value if it doesn't return NULL.

I tried to run this

input = getenv("HISTFILE");
cout << input << endl;

It dropped and I received a segmentation fault.

>>It dropped and I received a segmentation fault.
Try this one instead

input = getenv("HISTFILE");
if( input == NULL)
   cout << "input is NULL\n";
else
   cout << input << "\n";

I am receiving an error, no match for 'operator==' in 'input == 0' on the line input=getenv("HISTFILE");

post code exactly as you tried to compile it.

#include <iostream>
#include <string>
using namespace std;



int main(int argc,char *argv[])
{
    string input;
    input = getenv("HISTFILE");
    if (input == NULL)
        cout << "input is NULL\n";
    else
        cout << input << "\n";
    return(0);
}

line 11: make input a char* char* input std::string crashes when attempting to assign it a NULL

It did indeed return NULL. I've tried looking other places for answers and still no luck. Thank for your help up until now and for any further help Dragon, I really appreciate it.

That leads me to think that the program is not running in the same shall as you were when you tested echo $HISTFILE from the command line.

I don't remember how to run a program in the same shell. *nix is not my os and its been several years since I've used it.

commented: Ancient Dragon was very helpful +1

I ran a few other shells to see if a few other variables would be acquired successfully, and oddly, $PWD (the current directory of the open shell) was acquired successfully... even after being run from codeblocks without an actual command prompt. Ah well, I will continue to try to find answers elsewhere. Thank you very much Ancient Dragon.

For anyone reading this who may be looking for an answer ( or possibly just to let Ancient Dragon know ) I found an answer through pure speculation. I looked at the alias I used to run the program and erase and added one line on right before running the program. "export HISTFILE" After exporting $HISTFILE I successfully acquired it from within the c++ script. Thanks again for all your help Dragon. As for the other question, if anyone knows how to get the c++ script to run the bash script "history -c" it would greatly be appreciated.

you can use

system ("sh scriptname");

I'm sorry, I didn't write that correctly. I didn't mean bash script; I meant bash command. From what I have read, it is not an actual Linux command. "history -c" is actually a bash command that bash uses for self-modification. Is there any way to export the results of the answer when asked about clearing out to the bash shell? That could be another option. Thank you two for all your help.

Does anyone know if there is a way to catch a c++ scripts main function return value in the bash shell and use it to determine whether or not to run an additional line of bash code? (I can work out the bash code, I just need to catch the return value)

Fantastic, thank you very much. I got it all working. I replaced the alias based calls to the c++ code with a function based call and now everything is working exactly how I wanted it to. Thank you everybody.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.