built in command to change prompt in custom linux/unix shell - c

I have looked all over google and I find how to change in the bash config files, but my project requires a built in command to change the prompt.
I declared char pointer outside any function, my command modifies it, but when the function returns (int to continue a do while loop) and the prompt is displayed again, it is blank.
I have tried using a structure, union, and even a second char pointer and got the same issue.
I thought using a global char pointer that could be accessed and modified in any function would be the solution to this part of my project.
I would appreciate and will try any response.
Edit:
posted on my phone, tried to ask w/o code, but here it is
Code:
char *prmpt;
...
int main(int argc, char **argv)
prmpt="$$ ";
do
{
printf("%s ", prmpt);
}while(1)
int cmd_prompt(char **args)
{
prmpt = (char*)args[1];
return 1;
}

Essentially one needs to use fgets or getline or better yet they might use readline or editline. Here is an example using getline:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char *prompt;
size_t len = 256;
size_t i = 0;
if (!(prompt = malloc(256 * sizeof(char))))
return 1;
strcpy(prompt, "$");
while ( 1 )
{
printf("[[%s]] ", prompt);
i = getline(&prompt, &len, stdin);
prompt[i-1] = '\0';
}
}
Or if you might try implementing getline on your own using getchar ( perhaps if getline is not available on your system, or you just want to know how it works). And eventually move on to writing your own editline library if you continue to be interested in writing shells.

Related

Download a certain file from a certain directory using Wget in c

I am trying to write a basic script in C that I can use to download files off of a webserver. It would use wget, but I want to find a way where I can specify the directory and file that I want to download using a arguments. I'm just very new to C and I don't know how that would work. If anyone can show me how to write that or just point me in the write direction that would be amazing, thank you!
The simple solution to this is, as I already commented, to use snprintf to format the command-string, and then pass it to system for execution.
Something like
void download(const char *path, const char *file)
{
char command[1024];
// Create the command
snprintf(command, sizeof command, "wget https://1.1.1.1/%s/%s", path, file);
// Execute the command
system(command);
}
#include <stdlib.h>
#include <string.h>
char *joinstrings(char const *s1, char const *s2)
{
char *s3;
if (!s1 && !s2)
return (NULL);
if (!s1)
return (strdup(s2));
if (!s2)
return (strdup(s1));
if (!(s3 = malloc(sizeof(char) * (strlen(s1) + strlen(s2)))))
return (NULL);
strcpy(s3, s1);
strcat(s3, s2);
return (s3);
}
int main(int ac, char **av)
{
char *str;
if (ac < 2)
return (1);
if (!(str = joinstrings("wget ", (const char *)av[1])))
return (1);
system(str);
free(str);
str = NULL;
return (0);
}
$~> gcc p.c -o prog
$~> ./prog https://website/folder/file.txt
The string containing the address and the file location is given in argument as a single parameter, but using a function to join strings you can do it the way you want,
using snprintf to fill a buffer as sayed in the comment on you'r post is also a good solution but it's less begginner friendly i guess
The function joinstrings will also be very helpful for you, you always have to concatenate strings when programming
Just remember to check if it's result is not NULL, and also call function free on it when you are done using it, then set pointer to NULL

How to switch from char * to const char *[pwm in beaglebone]?

I am working on a quadcopter project with Beaglebone.
I need help with using pwm on Beaglebone through a C program.
I have attached the following code,
#include <stdio.h>
#include <string.h>
#include <unistd.h>
struct pwm
{
char period[100];
char duty[100];
char polarity[100];
char run[100];
}pwm1,pwm2,pwm3,pwm4;
char pwm_1[]="P9_21";
char pwm_2[]="P9_14";
char pwm_3[]="P8_13";
char pwm_4[]="P9_42";
int initialize(struct pwm &pwmi, char pwm_i[])
{
sprintf(path,"echo \"bone_pwm_%s\" >> /sys/devices/bone_capemgr.9/slots",pwm_i);
fp = popen(path,"r");
fflush(fp);
usleep(1000);
sprintf(path,"ls /sys/devices/ocp.3/pwm_test_%s.*/period",pwm_i);
fp = popen(path,"r");
while(fgets(path,100,fp)!=NULL)
strcpy(pwmi.period,path);
fflush(fp);
sprintf(path,"ls /sys/devices/ocp.3/pwm_test_%s.*/duty",pwm_i);
fp = popen(path,"r");
while(fgets(path,100,fp)!=NULL)
strcpy(pwmi.duty,path);
fflush(fp);
sprintf(path,"ls /sys/devices/ocp.3/pwm_test_%s.*/polarity",pwm_i);
fp = popen(path,"r");
while(fgets(path,100,fp)!=NULL)
strcpy(pwmi.polarity,path);
fflush(fp);
sprintf(path,"ls /sys/devices/ocp.3/pwm_test_%s.*/run",pwm_i);
fp = popen(path,"r");
while(fgets(path,100,fp)!=NULL)
strcpy(pwmi.run,path);
fflush(fp);
pclose(fp);
return 0;
printf("%s%s%s%s",pwmi.period,pwmi.duty,pwmi.polarity,pwmi.run)
}
int pwmperiod(struct pwm &pwmi, unsigned int period)
{
sprintf(path,"echo %d > %s", period, pwm.period);
fp = popen(path,"r");
usleep(1000);
pclose(fp);
return 0;
}
int main()
{
unsigned int period = 200000;
initialize(pwm1,pwm_1);
initialize(pwm2,pwm_2);
initialize(pwm3,pwm_3);
initialize(pwm4,pwm_4);
pwmperiod(pwm1,period);
return 0;
}
Now the above code works perfectly fine. But I want to use the pwmperiod() function a little differently. Instead of using popen() all the way, I want to use fopen() and fprintf() for the function pwmperiod() . Something like this,
int pwmperiod(struct pwm &pwmi, unsigned int period)
{
fp = fopen(pwmi.period,"r+");
fseek(fp,0,SEEK_SET);
fprintf(fp,"%d",period);
fclose(fp);
return 0;
}
I tried the modified code but when it attempts to write the period value, it outputs "segmentation fault".
I realized that fopen() takes a const char while pwmi.period is just char. Another problem popen() and sprint() are not compatible with const char.
So is there a way to resolve the conversion?
Also how often is popen() used in C/C++ programs?
PS:
Not an expert coder and I am not from a computer science background. I am learning progressively.
Again, the code works with popen() perfectly. But then I am comfortable with file handling in C. So I would prefer personally fopen() over popen() . Moreover I feel it would be pointless to use popen() in C. Might as well use a shell script for pwm.
Leaving aside for a moment the issue of char* vs. const char* (since a char* can anyway be passed to any function taking a const char*).
Have you checked that the return value from fopen is non-NULL?
Note that the file must exist when fopen is called with r+. If it doesn't, fopen will return NULL, generating a segfault.
Since the file is only being written, not read, consider using
fp = fopen(pwmi.period,"w");
which will create a new file if one doesn't already exist.

How can I transfer files from one folder to another folder using (C) under UNIX?

I have a text file with the names of about 800 files I want to transfer from one folder to another. Basically, the text file looks like this :
file1.aaa (End of line)
file2.aaa
..
etc
I made this code, using the function 'rename' as everyone suggests on the internet :
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main ( void )
{
FILE *file = fopen ( "C:\\Users\\blabla\\ListOfFiles.txt", "r" );
char path1[100] = "C:\\blabla\\folder1\\";
char path2[100] = "C:\\blabla\\folder2\\";
char *s1;
char *s2;
char line [20]; /* the file names won't be any longer than that */
while(fgets(line, sizeof line,file) != NULL)
{
char *filePath1 = (char *) malloc((strlen(path1) + strlen(line) + 1) * sizeof(char));
char *filePath2 = (char *) malloc((strlen(path2) + strlen(line) + 1) * sizeof(char));
filePath1 = strcpy(filePath1, path1);
filePath2 = strcpy(filePath2, path2);
strcat(filePath1,line);
strcat(filePath2,line);
if (rename(filePath1, filePath2) != 0)
{
perror("wrong renaming");
getchar();
}
free(filePath1);
free(filePath2);
}
fclose (file);
return 0;
}
Now, when I print the filepaths I get the expected results, but the program stops running when it's supposed to run the 'rename' function, because of an invalid argument problem.
I looked at http://www.cplusplus.com/ and noticed that it says the arguments of rename() should be const char*, could this be where the problem come from ? But if so, I don't see how I could turn my arguments into 'const', since I need to update them as I read my initial text file.
The code that builds the file paths is horribly over-complicated but should work. To simplify it, remove the malloc() and just use two statically-sized arrays. Also, for the future, please don't cast the return value of malloc() in C.
You're misunderstanding the const thing, it means that rename() won't change the characters pointed at by its two arguments. It's a way to say "these two pointers point at data which is input-only to this function, there will be no attempt to modify that data from inside the function". You should always const argument pointers when possible, it helps make the code much clearer.
If you're getting "invalid argument", that probably means the files aren't being found. Print out the filenames to help you verify.
I suggest you to take a look at:
How can I copy a file on Unix using C?
And replace "/bin/cp" for "/bin/mv" in that code.
Hope it helps!

execl and wget command in a loop

I have edited my previous question.
As I had got the problem and the changed the code, now I have a different problem. If I use execle command, it only downloads one image using the wget command, otherwise it prints all the image names on the screen if the wget command does not execute. I do not understand when there is a while loop, then why does it only print one image.
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<limits.h>
#include<fcntl.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<stdio.h>
void main(int argc, char*argv[])
{
int iFlag;
char cline[100];
FILE*fil = fopen("index.html","rt");
if(fil==NULL)
{
printf("Error in opening file");
}
char*tmpLine;
char*tok;
const char check[10] = "<img";
const char check2[10] = "src=";
char images[50];
strcpy(images,argv[1]);
while(fgets(cline,100,fil)!=NULL)
{
if(strstr(cline,check)!=NULL)
{
tmpLine=strstr(cline,check);
if(strstr(cline,check2)!=NULL)
{
tmpLine=strstr(cline,check2);
tok = strtok(tmpLine,"\"");
while(tok!=NULL)
{
tok = strtok(NULL,"\"");
if(tok[0]!='/')
{
strcat(images,"/");
strcat(images,tok);
printf("\nimage: %s\n",images);
iFlag = execle("/usr/bin/wget","wget","-o","logfile",images,NULL);
if(iFlag<0)
perror("EXECLE ERROR");
break;
}
else
break;
}
memset(&images[0], 50, sizeof(images));
strcpy(images,argv[1]);
}
}
}
}
fil is probably NULL. Why?
FILE*fil = fopen("index.hmtl","rt");
Because you typo-ed the filename. This is why checking for errors is a good idea.
This line
printf("%s\n",tok[0]);
does not make sense, as you pass a char where are char * is expected.
Either do
printf("%s\n", tok);
or
printf("%c\n", tok[0]);
Also this line
char*images = (char*)malloc(100);
creates a memory leak, as the reference to the memory allocated to images is lost when leaving the context images is declared in without having free()ed it.
Also^2 :
In C there is no need to cast the result of malloc/calloc/realloc, nor is it recommended.
So the above line should just better be:
char * images = malloc(100);
Also^3: Always check the outcome of system calls, at least if the code relies on the values returned. Here: Check if fopen() failed, as on error NULL is returned, which will make the program choke if used as a valid file-pointer.
As a general advise on how to find a bug: Compile the code in question using symbols (option -g for gcc), then step through the "running" code using a debugger as gcc.
you should check the return value of fopen(), as others already pointed it out.
printf("%s\n",tok[0]); should be printf("%s\n",tok);, if you want to print a string.
more serious,
while(tok!=NULL)
{
strcat(images,tok);
}
tok = strtok(NULL,quote);
this tok = strtok(...); should be put inside that while loop, otherwise that tok will never be changed, and your program will crash finally.

Where does tmpfile() store the files it creates (in mingw-gcc/windows 7)?

I'm testing tmpfile() with mingw-gcc (CodeBlocks, latest) and program works as expected: opens 10 temp files, write 10 random strings, then read-back those 10 strings and close each *fp.
Like I said, works as expected but reading some articles about temporarily locations on win7, I begun to search where actually the files are stored, before auto-erase. On UNIX, the default location would be /tmp
On windows 7, I'm running out of ideas...
- the program folder
- the user/appdata/local/tmp/
- windows/temp
I cannot find those files and I searched even with total commander from some known strings inside. None. Any idea?
I've had the same question, and after reviewing the thread linked here:
http://sourceforge.net/p/mingw/bugs/666/
... I think the MinGW guys rolled a special version that keeps the temporary file entirely in memory.
I don't know how complete their solution is without combing through MinGW's source and/or asking on the mailing lists. In either case, it is probably a better idea to use some function other than tmpfile() anyway, given its problems.
I used Process Explorer to monitor the open handles on this program:
#include <stdio.h>
int main(int argc, char *argv[]) {
int a;
scanf("%d", &a);
printf("%p", tmpfile());
scanf("%d", &a);
return 0;
}
After printf("%p", tmpfile()); was executed, a new file handle was opened, and the file path was C:\Users\sashoalm\AppData\Local\VirtualStore\t9mc. I ran the program again and this time it was C:\Users\sashoalm\AppData\Local\VirtualStore\t728. So it places them in C:\Users\sashoalm\AppData\Local\VirtualStore\, and the name is some randomly generated string starting with "t".
See Why do files get placed in "C:\Users\<username>AppData\Local\VirtualStore\Program Files(x86)"? about the "Virtual Store" folder.
/ I tested Dev-C++ 5.11 (Mngv) gcc, and dont work. With Borland 5.5 in Code:: Block no problem.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
int main(int argc, char *argv[]) {
char filename[L_tmpnam];
char *strs[] = {"Hello\n","Goodbye\n","Cat\n","Dog\n",NULL};
char **mover = strs;
char line[80],command[80];
FILE *fp;
fp = tmpfile();
for(; *mover != NULL; mover++) fputs(*mover,fp);
rewind(fp);
while(fgets(line,80,fp))printf("%s",line);
fclose(fp);
if(tmpnam(filename) == NULL){
printf("Could not get non-conflicting file name\n");
exit(EXIT_FAILURE);
}
printf("\nFilename obtained is: %s\n\n",filename);
fp = fopen(filename, "w+");
for(mover = strs; *mover != NULL; mover++) fputs(*mover, fp);
rewind(fp);
while(fgets(line,80,fp)) printf("%s",line);
putchar('\n');
fclose(fp);
return 0;
}

Resources