c++ pobieranie znaku zachęty

Bash, C, C++, Java, PHP, Ruby, GTK, Qt i wiele innych - wszystko tutaj.
Awatar użytkownika
el.pescado
Zakręcona Traszka
Zakręcona Traszka
Posty: 734
Rejestracja: 26 maja 2005, 11:43
Płeć: Mężczyzna
Wersja Ubuntu: inny OS
Środowisko graficzne: GNOME
Architektura: x86
Kontakt:

Odp: c++ pobieranie znaku zachęty

Post autor: el.pescado »

Mój pomysł na pobieranie znaku zachęty (bez rozwijania specjalnych symboli) - uruchomić basha każąc mu wypisać zmienną $PS1 na wyjście komendą echo:

Kod: Zaznacz cały

#include <stdio.h>
#include <stdlib.h>

#define BUFFER_SIZE 1024

int main (int argc, char *argv[])
{
	char buffer[BUFFER_SIZE];

	FILE *p = popen ("sh -ic 'echo -n $PS1'", "r");
	if (p == NULL) {
		perror ("popen");
		return EXIT_FAILURE;
	}

	while (fgets (buffer, BUFFER_SIZE, p))
		;
	
	pclose (p);

	printf ("$PS1 = '%s'\n", buffer);

	return EXIT_SUCCESS;
}

Kod: Zaznacz cały

$ gcc -Wall -o printps1 printps1.c 
$ ./printps1 
$PS1 = '\h:\w>'

EDIT:
PS. Dla lepszych efektów trzeba poeksperymentować z opcjami wywołania basha (-i, -l) - znak zachęty zależy od skryptów startowych basha, a to, które pliki startowe są ładowane podczas startu basha, zależne jest od opcji wywołania.
Awatar użytkownika
sulti
Serdeczny Borsuk
Serdeczny Borsuk
Posty: 139
Rejestracja: 17 wrz 2007, 15:31
Płeć: Mężczyzna
Wersja Ubuntu: 12.10
Środowisko graficzne: Unity
Architektura: x86

Odp: c++ pobieranie znaku zachęty

Post autor: sulti »

Można by się pokusić o parsowanie zmiennej PS1 w postaci "\u@\h:\w" i zamianę odpowiednich 'zmiennych' na odczytane ze środowiska. Jest tego trochę, ale jak komuś bardzo zależy ;)

Kod: Zaznacz cały

              \a     an ASCII bell character (07)
              \d     the date in "Weekday Month Date" format (e.g., "Tue May 26")
              \D{format}
                     the format is passed to strftime(3) and the result is inserted into the prompt string; an empty format results in a  locale-specific
                     time representation.  The braces are required
              \e     an ASCII escape character (033)
              \h     the hostname up to the first `.'
              \H     the hostname
              \j     the number of jobs currently managed by the shell
              \l     the basename of the shell's terminal device name
              \n     newline
              \r     carriage return
              \s     the name of the shell, the basename of $0 (the portion following the final slash)
              \t     the current time in 24-hour HH:MM:SS format
              \T     the current time in 12-hour HH:MM:SS format
              \@     the current time in 12-hour am/pm format
              \A     the current time in 24-hour HH:MM format
              \u     the username of the current user
              \v     the version of bash (e.g., 2.00)
              \V     the release of bash, version + patch level (e.g., 2.00.0)
              \w     the current working directory, with $HOME abbreviated with a tilde (uses the $PROMPT_DIRTRIM variable)
              \W     the basename of the current working directory, with $HOME abbreviated with a tilde
              \!     the history number of this command
              \#     the command number of this command
              \$     if the effective UID is 0, a #, otherwise a $
              \nnn   the character corresponding to the octal number nnn
              \\     a backslash
              \[     begin a sequence of non-printing characters, which could be used to embed a terminal control sequence into the prompt
              \]     end a sequence of non-printing characters
You tried, and you failed, so the lesson is, never try.
mikolajs
Wytworny Kaczor
Wytworny Kaczor
Posty: 352
Rejestracja: 15 paź 2008, 18:30
Płeć: Mężczyzna
Wersja Ubuntu: 9.04
Środowisko graficzne: KDE Plasma

Odp: c++ pobieranie znaku zachęty

Post autor: mikolajs »

Mój pomysł na pobieranie znaku zachęty (bez rozwijania specjalnych symboli) - uruchomić basha każąc mu wypisać zmienną $PS1 na wyjście komendą echo:
Można by się pokusić o parsowanie zmiennej PS1 w postaci "\u@\h:\w" i zamianę odpowiednich 'zmiennych' na odczytane ze środowiska. Jest tego trochę, ale jak komuś bardzo zależy
Oba sposoby nie będą skuteczne, lepiej przeczytajcie dokładnie to co napisałem wcześniej. Po uruchomieniu programu w procesie potomnym nie ma takiej zmiennej, przekazywane jest tylko środowisko, a $PS1 w ubuntu nie jest zmienną środowiskową.
Awatar użytkownika
el.pescado
Zakręcona Traszka
Zakręcona Traszka
Posty: 734
Rejestracja: 26 maja 2005, 11:43
Płeć: Mężczyzna
Wersja Ubuntu: inny OS
Środowisko graficzne: GNOME
Architektura: x86
Kontakt:

Odp: c++ pobieranie znaku zachęty

Post autor: el.pescado »

lepiej przeczytajcie dokładnie to co napisałem wcześniej
Lepiej przeczytaj dokładnie mój kod źródłowy, a najlepiej skompiluj go i uruchom. Owszem, PS1 nie jest zmienną środowiskową i nie odczytamy jej z procesu macierzystego, i dlatego mój program robi zupełnie co innego - znak zachęty pobiera nie z procesu macierzystego lecz potomnego, którym to procesem potomnym jest nic innego jak bash, któremu każę wypisać wartość zmiennej powłoki tak, by móc odczytać ją w moim programie.

EDIT:
PS. Mam nowy, prosty pomysł, dziwięsię że wsześniej na to nie wpadłem - utworzyć skrypt startowy dla programu o treści:

Kod: Zaznacz cały

#!/bin/bash
export $PS1
./uruchomprogram
W ten sposób zmienna PS1 powinna być dostępna dla uruchomionego programu, jako że polecenie export doda ją do środowiska.
mikolajs
Wytworny Kaczor
Wytworny Kaczor
Posty: 352
Rejestracja: 15 paź 2008, 18:30
Płeć: Mężczyzna
Wersja Ubuntu: 9.04
Środowisko graficzne: KDE Plasma

Odp: c++ pobieranie znaku zachęty

Post autor: mikolajs »

To zmień sh na bash
Awatar użytkownika
maly_wariat
Sędziwy Jeż
Sędziwy Jeż
Posty: 73
Rejestracja: 25 sie 2009, 21:41
Płeć: Mężczyzna
Wersja Ubuntu: 9.10
Środowisko graficzne: GNOME
Architektura: x86

Odp: c++ pobieranie znaku zachęty

Post autor: maly_wariat »

uu nie doczytałem
el.pescado pisze:Mój pomysł na pobieranie znaku zachęty (bez rozwijania specjalnych symboli) - uruchomić basha każąc mu wypisać zmienną $PS1 na wyjście komendą echo:

Kod: Zaznacz cały

#include <stdio.h>
#include <stdlib.h>

#define BUFFER_SIZE 1024

int main (int argc, char *argv[])
{
	char buffer[BUFFER_SIZE];

	FILE *p = popen ("sh -ic 'echo -n $PS1'", "r");
	if (p == NULL) {
		perror ("popen");
		return EXIT_FAILURE;
	}

	while (fgets (buffer, BUFFER_SIZE, p))
		;
	
	pclose (p);

	printf ("$PS1 = '%s'\n", buffer);

	return EXIT_SUCCESS;
}

Kod: Zaznacz cały

$ gcc -Wall -o printps1 printps1.c 
$ ./printps1 
$PS1 = '\h:\w>'

EDIT:
PS. Dla lepszych efektów trzeba poeksperymentować z opcjami wywołania basha (-i, -l) - znak zachęty zależy od skryptów startowych basha, a to, które pliki startowe są ładowane podczas startu basha, zależne jest od opcji wywołania.
to rozwiązanie mi się podoba i działa tak jak bym mniej więcej chciał, zaraz zmodyfikuje to co przedstawiłem poniżej:)

Kod: Zaznacz cały

#include <iostream>
#include <stdlib.h>
#include <fstream>
#include <string>
#include <string.h>
#include <vector>
#include <time.h>
using namespace std;

void read_config_shell(const char * shell_file,string default_prompt);
string prompt();
void decode(string to_decode);


int main()
{	
	string shell=prompt();	
	shell+="p";
	//system(shell.c_str());	
	return 0;
}
string prompt()
{
	string shell_set;
	string shell=getenv("SHELL");
	if (shell=="/bin/bash")
	{	
		read_config_shell(".bashrc","\\u@\\h:\\w$");
		shell_set="bash -c ";
	}
	if (shell=="/bin/tsh")
	read_config_shell(".cshrc",">");
	if (shell=="/bin/sh")
	read_config_shell(".profile","$");
	if (shell=="/bin/csh")
	read_config_shell(".cshrc",">");
	if (shell=="/bin/zsh")
	read_config_shell(".zprofile","['\'w]%");
	return shell_set;
}
void read_config_shell(const char * shell_file,string default_prompt)
{
	char * prompt=getenv("PS1");
	if (prompt==NULL)
	{
		prompt=getenv("prompt");
		if (prompt==NULL)
		{
			/*string st,prompt;//usunac prompt jak bedzie robiona dekodacja
			vector<string>vec_s;	
			string home=getenv("HOME");
			string sc_plik=home+"/"+shell_file;
			ifstream plik(sc_plik.c_str());
			if (!plik) return decode(default_prompt);		
			while (!plik.eof())
			{
				getline(plik,st);
				char *wzr =new char[st.length()+1];
				strcpy(wzr,st.c_str());				
				unsigned int j,n;
				unsigned int ok=0;				
				for (j=0;j<st.length()+1;j++)
				{					
					while(wzr[j]==' ') j++;					
					switch (wzr[j])
					* 
					{
						case 'p': ok++; break;
						case 'r': ok++; break;
						case 'o': ok++; break;
						case 'm': ok++; break;
						case 't': ok++; break;
						case 'P': ok++; break;
						case 'S': ok++; break;
						case '1': ok++; break;
						case '=': ok++; break;
						default: ok=0;n=1;break;
					}
					if (((ok==4)&&(n==0))||((ok==7)&&(n==0)))
					prompt=st;					
					if (n==1) 
					{
						n=0;
						break;
					}
				}
				delete [] wzr;
				vec_s.push_back(st);
				decode(default_prompt);
			}
			if(prompt==NULL)
			decode(default_prompt);
			else
			decode(prompt);
			plik.close();*/
			decode(default_prompt);
		}
		else decode(prompt);
	}
	else decode (prompt);
}
void decode(string to_decode)
{

	int c;
	struct tm *tm;
	time_t the_time;
	char timebuf[128];
	
	string y;
	int ile=to_decode.length()+1;
	char *znak = new char [ile];
	strcpy(znak,to_decode.c_str());
	for (c=0; c<ile;c++,znak++)
	{
		//while(*znak==' ')znak++;
		if (*znak=='\\')
		{
			znak++;
			switch(*znak)
			{
				case 'u':
				case 'U':
					cout<<getenv("USER");
					break;
				case 'h':
				case 'H':
				{
					cout<<getenv("HOSTNAME");
					
					break;
				}
				case 'w':
				case 'W':
					{
					string pwd=getenv("PWD");
					string home=getenv("HOME");
					char *pwd_char = new char [pwd.length()+1];
					char *home_char = new char [home.length()+1];
					strcpy(pwd_char,pwd.c_str());
					strcpy(home_char,home.c_str());
					unsigned int z;
					string tmp;
					for (z=0; z<home.length()+1;z++,pwd_char++,home_char++)
					{
						if (*home_char==*pwd_char) tmp="~";
						
					}
					if (tmp.empty()&&(z>6)) cout<<home;									else
					{
						cout<<tmp;
						unsigned int g;
						pwd_char--;
						for (g=z; g<pwd.length()+1;g++,pwd_char++)
						{
							cout<<*pwd_char;
						}
					}
					break;
					}
				case 'd':
				case 't':
				case 'T':
				case '@':
				case 'A':
					{
						int n;
						(void) time (&the_time);
						tm=localtime(&the_time);
						if (*znak=='d')
						n=strftime(timebuf,sizeof(timebuf),"%a %b %d",tm);
						if (*znak=='t')
						n=strftime(timebuf,sizeof(timebuf), "%H:%M:%S",tm);
						if (*znak=='T')
						n=strftime(timebuf,sizeof(timebuf), "%I:%M:%S",tm);
						if (*znak=='@')
						n=strftime(timebuf,sizeof(timebuf), "%I:%M ",tm);
						if (*znak=='A')
						n=strftime(timebuf,sizeof(timebuf), "%H:%M",tm);
						if ( n==0)
						timebuf[0]='\0';
						else
						timebuf[sizeof(timebuf) -1] = '\0';
						cout<<timebuf;
						break;
					}
				default:break;
							
			}		
		}else cout<<*znak;
	}
	cout<<endl;
	
}
Ja za to wymyśliłem jak na razie coś takiego.
W sles działa, w ubuntu wyświetla mi user@user@host: pwd

Kod: Zaznacz cały

#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <string>
#include <string.h>
#include <time.h>
using namespace std;
#define BUFFER_SIZE 1024
string default_prompt;
int c,ile;
string detect_shell();
void decode(char* to_decode);
int main (int argc, char *argv[])
{
	char buffer[BUFFER_SIZE];
	string shell_seting=detect_shell();
	string prompt_popen=shell_seting+" -ic 'echo -n $PS1'";
	FILE *p = popen (prompt_popen.c_str(), "r");
	if (p == NULL) {
		perror ("popen");
		return EXIT_FAILURE;
	}
	while (fgets (buffer, BUFFER_SIZE, p));
	pclose (p);
	
	
	decode(buffer);
	return EXIT_SUCCESS;
}
string detect_shell()
{
	string shell_set;
	string shell=getenv("SHELL");
	if (shell=="/bin/bash") shell_set="bash";
	if (shell=="/bin/tsh") shell_set="tsh";
	if (shell=="/bin/sh")	shell_set="sh";
	if (shell=="/bin/csh") shell_set="csh";
	if (shell=="/bin/zsh")	shell_set="zsh";
	return shell_set;
}
void decode(char* to_decode)
{	
	int us,ho,ww,mal,yy;
	struct tm *tm;
	time_t the_time;
	char timebuf[128];
	string y;
	us=0;
	ho=0;
	ww=0;
	mal=0;
	yy=0;
	ile=strlen(to_decode);
	for (c=0; c<=ile;c++)
	{
		//while(*znak==' ')znak++;
		if (to_decode[c]=='\\')
		{
			c++;
			
			switch(to_decode[c])
			{
				case 'u':
				case 'U':
						{
							if(us==0) 
							cout<<getenv("USER");
							us=1;
						}
					break;
				case 'h':
				case 'H':
						
						cout<<getenv("HOST");
						break;
					
				case 'w':
				case 'W':
					{
					if(ww==0)
						{
						char* pwd=getenv("PWD");
						char* home=getenv("HOME");
						unsigned int pwd_ile = strlen(pwd);
						unsigned int home_ile =strlen(home);
						unsigned int z;
						string tmp;
						for (z=0; z<home_ile;z++)
						{
							if (home[z]==pwd[z]) tmp="~";
							
						}
						if (tmp.empty()&&(z>6)) cout<<home;
						else
						{
							cout<<tmp;
							unsigned int g;
							
							for (g=z; g<pwd_ile;g++)
							{
								cout<<pwd[g];
							}
						}
						ww=1;
					}
					break;
					}

				
				case 'd':
				case 't':
				case 'T':
				case '@':
				case 'A':
					{
						int n;
						(void) time (&the_time);
						tm=localtime(&the_time);
						if (to_decode[c]=='d')
						n=strftime(timebuf,sizeof(timebuf),"%a %b %d",tm);
						if (to_decode[c]=='t')
						n=strftime(timebuf,sizeof(timebuf), "%H:%M:%S",tm);
						if (to_decode[c]=='T')
						n=strftime(timebuf,sizeof(timebuf), "%I:%M:%S",tm);
						if (to_decode[c]=='@')
						n=strftime(timebuf,sizeof(timebuf), "%I:%M ",tm);
						if (to_decode[c]=='A')
						n=strftime(timebuf,sizeof(timebuf), "%H:%M",tm);
						if ( n==0)
						timebuf[0]='\0';
						else
						timebuf[sizeof(timebuf) -1] = '\0';
						cout<<timebuf;
						break;
					}

					
				default:break;
							
		}
		}else 
		{
			switch (to_decode[c])
			{
					case '0':
					case '}':
					case ']':
					case ';':			
								break;
					case ':':
							{
								if(yy==0)
								{
									cout<<to_decode[c];
									yy=1;
								}
								break;
							}
					case '@':
	
							{
								if(mal==0) 
								{
									cout<<to_decode[c];
									mal=1;
								}
								break;
							}
					case '[':
					case '{':
						{
							
								for (;c<=ile;c++)
								{
									if((to_decode[c]=='}')||(to_decode[c]==']')||to_decode[c]==')')
									break;
								} 
								break;
						}
					default: cout<<to_decode[c];
			
			}
		}
		
	}
		cout<<" ";
}
Dlaczego nie działa cout<<getenv("HOSTNAME");?
"Dopóki nie skorzystałem z internetu, nie wiedziałem że na świecie żyje tylu idiotów " - S.Lem.
mikolajs
Wytworny Kaczor
Wytworny Kaczor
Posty: 352
Rejestracja: 15 paź 2008, 18:30
Płeć: Mężczyzna
Wersja Ubuntu: 9.04
Środowisko graficzne: KDE Plasma

Odp: c++ pobieranie znaku zachęty

Post autor: mikolajs »

Niestety ta sama sytuacja

Kod: Zaznacz cały

#include <stdio.h>
#include <stdlib.h>

extern char **environ;

int main (int argc, char **argv, char **envp) {
    int i;

    printf("Srodowisko procesu:\n");
    for (i = 0; envp[i] != NULL;i++)
  printf("%s\n", envp[i]);

    return(0);
}
tylko te dane w tablicy są widziane przez getenv
Awatar użytkownika
maly_wariat
Sędziwy Jeż
Sędziwy Jeż
Posty: 73
Rejestracja: 25 sie 2009, 21:41
Płeć: Mężczyzna
Wersja Ubuntu: 9.10
Środowisko graficzne: GNOME
Architektura: x86

Odp: c++ pobieranie znaku zachęty

Post autor: maly_wariat »

hmm
to co zostało czytanie z pliku? hosts?
Bo nie w każdej dystrybucji linuxa jest taki plik jak hostname, tak samo jak zmienna.
Chociaż kiedy dam echo $HOSTNAME to normalnie zwraca nazwę hosta.
"Dopóki nie skorzystałem z internetu, nie wiedziałem że na świecie żyje tylu idiotów " - S.Lem.
ODPOWIEDZ

Wróć do „Programowanie”

Kto jest online

Użytkownicy przeglądający to forum: Obecnie na forum nie ma żadnego zarejestrowanego użytkownika i 9 gości