Use of execle with wget command - c

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]);
}
}
}
}

A big problem is that the exec family of function replaces your process with that of the new program. That means that if the call to execle succeeds your program no longer exists.
You need to fork a new process if you want your own program to continue.

Related

Using a Pipe file to transfer names

I have 3 ".c" files called pre, sort and pipe. Pre takes a user input of names and GPA from a console. If the GPA is greater than or equal to 3.0, the name is stored into a struct.
Here's the pre.c file:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct student{
char temp_name[50];
char names[50];
};
int main()
{
int read_index = 0;
float check_gpa;
struct student data[read_index];
printf("Enter student name and GPA: \n");
scanf("%s %f\n", data[read_index].temp_name, &check_gpa);
read_index++;
while(scanf("%s %f\n", data[read_index].temp_name, &check_gpa) != EOF)
{
if (check_gpa >= 3.0)
{
strcpy(data[read_index].names, data[read_index].temp_name);
read_index++;
}
}
return 0;
}
The pipe file links the pre and sort files so that data from pre is sent to sort.
Here is the pipe.c file:
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<string.h>
#include<sys/wait.h>
int main()
{
char *args[] = {"./sort", NULL};
char *argv[] = {"./pre", NULL};
int pipe_end[2];
int pipe_id;
pipe(pipe_end);
if (pipe(pipe_end)==-1) // Check for pipe functionality
{
perror("Pipe Failed");
return 1;
}
pipe_id = fork();
if (pipe_id < 0) //Check for fork functionality
{
printf("Fork failed");
return 1;
}
else if(pipe_id == 0)//Child
{
close(pipe_end[0]);
dup(pipe_end[0]);
execvp(argv[0], argv);
}
else //Parent
{
wait(NULL);
close(pipe_end[1]);
dup2(pipe_end[1], 0);
close(pipe_end[0]);
execvp(args[0], args);
}
return 0;
}
The sort file takes names from a struct array and sorts them alphabetically and prints them to the console. And this is where the problem starts, because when I run the pipe file i get to enter names and GPA's But when ever I initiate an EOF (which is required and cannot change) by pressing Ctrl+D, I'm expecting the strings to be sent over to sort and displayed alphabetically, however this doesn't happen.
Here's the sort.c file:
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<string.h>
#include<sys/wait.h>
struct student{
char temp_name[50];
char names[50];
};
int main()
{
int print_index1 = 0,
print_index2,
read_index,
SIZE;
struct student data[print_index1];
SIZE = print_index1;
printf("Students with GPA's greater than or equal to 3.0, listed in alphabetical order:\n ");
for(print_index1 = 0; print_index1 < SIZE; print_index1++)
{
for(print_index2 = print_index1 + 1; print_index2 < SIZE; print_index2++)
{
if(strcmp(data[print_index1].names, data[print_index2].names) > 0)
{
strcpy(data[print_index1].temp_name, data[print_index2].names);
strcpy(data[print_index2].names, data[print_index1].names);
strcpy(data[print_index1].names, data[print_index1].temp_name);
}
}
printf("%s\n", data[print_index1].names);
}
return 0;
}
I've tested both files independently with user input and they worked. But a new problem has showed up, if you look at the sort file and notice I have a while loop that takes a for loop condition that I thought made sense> It worked a week ago but now it doesn't (unless it was a fluke). But that's my dilemma, I can't seem to get user input from "pre.c" over to "sort.c" I would really appreciate some help.
I also think the while loop in the "sort.c" file is causing an issue with printing the names.

Auto-completion visual not good (readline.h)

I would like to add the auto completion on the shell I created. I could not put the entire code but I can tell you my shell is working!
So I tried to implement auto-completion by using the readline function but the result is not that great (see the code in commentary I tried): the auto-completion works but the problems are:
1. I need to press twice enter to get the command executed now. 2. I need to type twice the command (like "ls") to get it executed! Can you help me to fix this? thank you :)
#include <readline/readline.h>
#include <readline/history.h>
#include <stdlib.h>
#include <stdio.h>
#include "includes/ft_sh1.h"
int main(int ac, char **av, char **envp)
{
char *line;
t_env *e = NULL;
char *add;
if (!(e = (t_env *)malloc(sizeof(t_env))))
return (0);
e->envp = env_cpy(envp, 0, 0);
init_env(e);
while (1)
{
--> My question is only about this part below <--
ft_printf("shell$> ");
// add = readline( "shell ");
// add_history(add);
// printf("%s", add);
--> My question is only about this part above <--
get_next_line(0, &line);
get_pwd_env(e);
e->cmd = get_cmd(e, line);
if (ft_strcmp(line, "exit") == 0)
exit(0);
else if (ft_strncmp(e->cmd[0], "cd", 2) == 0)
cd_cmd(e);
else
ft_execute(av, line, e);
}
}
When you just uncomment the part of code in question, you still have the call
get_next_line(0, &line);
in your program, so no wonder that you need to type two command lines.

creating multiple recursive directories in c

I am completing cs50x (the edX (free) version of the Harvard cs50) course and am trying to be a bit tricky/lazy/test myself.
I am trying to use a C program to create all the directories I will need for my psets.
I have looked online and found that <sys/stat.h> includes the mkdir() function and therefore tried creating some nested loops to create all the necessary folders by doing something similar to mkdir {pset1,pset1/{standard,hacker},pset2,pset2{standard... to give me a directory structure like this:
pset1/Standard
pset1/Hacker
pset2/Standard
etc...
I came up with this:
#include <cs50.h>
#include <stdio.h>
#include <sys/stat.h>
int main(int argc, string argv[])
{
for(int i = 1; i <=8; i++)
{
string dir = argv[1];
sprintf(dir,"%s%i", argv[1], i);
mkdir(dir, 0777);
for(int j = 0; j<2; j++)
{
string subDir[] = {"Standard","Hacker"};
sprintf(dir,"%s%i/%s", argv[1], i, subDir[j]);
mkdir(dir, 0777);
}
}
}
However, the program only creates pset1 and completes, there are no subfolders, no pset2 etc.
Yes, you're being lazy since you seem to have very little knowledge of C, yet try to program in it. :)
C is not Python, there is no string interpolation/formatting operator. You have to call a function, specificially snprintf(). Read that manual page.
Also, you can't create a bunch of nested directories with a single call to mkdir(). Read the manual page.
To create nested directories, you're either going to have to build each's absolute path (i.e. each successive time you call mkdir() the path will be longer than the previous time), or actually enter each directory as you create it, and go from there.
To create a full path you can call mkdir() recursivly like this:
#include <limits.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
int mkdirr(const char * path, const mode_t mode, const int fail_on_exist)
{
int result = 0;
char * dir = NULL;
do
{
if (NULL == path)
{
errno = EINVAL;
result = -1;
break;
}
if ((dir = strrchr(path, '/')))
{
*dir = '\0';
result = mkdirr(path, mode, fail_on_exist);
*dir = '/';
if (result)
{
break;
}
}
if (strlen(path))
{
if ((result = mkdir(path, mode)))
{
char s[PATH_MAX];
sprintf(s, "mkdir() failed for '%s'", path);
perror(s);
if ((EEXIST == result) && (0 == fail_on_exist))
{
result = 0;
}
else
{
break;
}
}
}
} while (0);
return result;
}
And then call mkdirr() like this;
int main(void)
{
char p[] = "test/1/2/3";
if (-1 == mkdirr(p, 0777, 0))
{
perror("mkdirr() failed()");
}
return 0;
}

My Program Keeps Failing With - Error While Loading Shared Libraries

I wrote a program "run_coffee.c" to implement fork() and exec() system calls. It fundamentally calls exec to start another process "coffee" built through "coffee.c" multiple times. The problem is I am running this program on cygwin64 in windows environment and it keeps failing with the following error -
**
error while loading shared libraries: ?: cannot open shared object
file: no such file or directory
**
I also ran cygcheck to see wether dependencies are being met or not. This is the output -
C:\cygwin64\home\Admin\run_coffee.exe C:\cygwin64\bin\cygwin1.dll
C:\Windows\system32\KERNEL32.dll
C:\Windows\system32\API-MS-Win-Core-RtlSupport-L1-1-0.dll
C:\Windows\system32\ntdll.dll C:\Windows\system32\KERNELBASE.dll
C:\Windows\system32\API-MS-Win-Core-ProcessThreads-L1-1-0.dll
C:\Windows\system32\API-MS-Win-Core-Heap-L1-1-0.dll
C:\Windows\system32\API-MS-Win-Core-Memory-L1-1-0.dll
C:\Windows\system32\API-MS-Win-Core-Handle-L1-1-0.dll
C:\Windows\system32\API-MS-Win-Core-Synch-L1-1-0.dll
C:\Windows\system32\API-MS-Win-Core-File-L1-1-0.dll
C:\Windows\system32\API-MS-Win-Core-IO-L1-1-0.dll
C:\Windows\system32\API-MS-Win-Core-ThreadPool-L1-1-0.dll
C:\Windows\system32\API-MS-Win-Core-LibraryLoader-L1-1-0.dll
C:\Windows\system32\API-MS-Win-Core-NamedPipe-L1-1-0.dll
C:\Windows\system32\API-MS-Win-Core-Misc-L1-1-0.dll
C:\Windows\system32\API-MS-Win-Core-SysInfo-L1-1-0.dll
C:\Windows\system32\API-MS-Win-Core-Localization-L1-1-0.dll
C:\Windows\system32\API-MS-Win-Core-ProcessEnvironment-L1-1-0.dll
C:\Windows\system32\API-MS-Win-Core-String-L1-1-0.dll
C:\Windows\system32\API-MS-Win-Core-Debug-L1-1-0.dll
C:\Windows\system32\API-MS-Win-Core-ErrorHandling-L1-1-0.dll
C:\Windows\system32\API-MS-Win-Core-Fibers-L1-1-0.dll
C:\Windows\system32\API-MS-Win-Core-Util-L1-1-0.dll
C:\Windows\system32\API-MS-Win-Core-Profile-L1-1-0.dll
C:\Windows\system32\API-MS-Win-Security-Base-L1-1-0.dll
No error or unmet dependency showed up so I guess all dependencies are being met. So what is causing this problem? Please Help.
Here are the two programs -
coffee.c
#include<stdio.h>
#include<stdlib.h>
int main(int argc, char *argv[])
{
char *w = getenv("EXTRA");
if (!w)
w = getenv("FOOD");
if (!w)
w = argv[argc-1];
char *c = getenv("EXTRA");
if (!c)
c = argv[argc-1];
printf("%s with %s\n", c, w);
return 0;
}
run_coffee.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
struct food_options
{
char *food;
char *extra;
};
int main()
{
int i;
char **env;
env[0] = (char*)malloc(sizeof(char) * 20);
env[1] = (char*)malloc(sizeof(char) * 20);
env[2] = (char*)malloc(sizeof(char) * 20);
struct food_options *opts = (struct food_options *)malloc(sizeof(struct food_options) * 3);
opts[0].food = "coffee";
opts[0].extra = "donuts";
opts[1].food = "fish";
opts[1].extra = "chips";
opts[2].food = "kabab";
opts[2].extra = "parantha";
for (i = 0; i < 3; i++)
{
pid_t pid = fork();
if (pid == -1)
{
fprintf(stderr, "Cannot fork process. Fatal Error %s\n", strerror(errno));
return 1;
}
else if (!pid)
{
sprintf(env[0], "FOOD=%s", opts[0].food);
sprintf(env[1], "EXTRA=%s", opts[0].extra);
env[2] = NULL;
if (execle("coffee.exe","coffee.exe",NULL,env) == -1)
{
fprintf(stderr, "Cannot execute coffee.exe. Error %s\n", strerror(errno));
}
}
}
free(opts);
free(env[0]);
free(env[1]);
free(env[2]);
return 0;
}
There is a memory bug in your program which can cause undefined behavior: you declared env to be an array of char*'s, but you did not initialize env. Hence, env[0], env[1], and env[2] point to random locations in memory. When you do sprintf(env[0], ...) and sprintf(env[1], ...), you are writing data to some random location in memory (where ever env[0] and env[1] points to). This can cause almost anything to happen, including modification of the names of libraries, making you unable to load them.

How do I get headers from a LightTPD CGI app?

I have this simple CGI script (which I compile):
#include <stdio.h>
int main(int argc, char *argv[]) {
printf("Content-Type: text/plain\n\nHello world!\n");
for(register unsigned short i=argc; i>0;) {
--i; printf("argv[%d]=%s ", i, argv[i]);
}
}
But I can't figure out how to get any of the header information.
Here are the differences I've made to my default lighttpd.conf:
server.modules = ("mod_access", "mod_accesslog", "mod_alias",
"mod_cgi", "mod_compress", "mod_status", )
server.port = 8000
#### CGI module
$HTTP["url"] =~ "/cgi-bin/" {
cgi.assign = ( "" => "" )
}
cgi.assign = ( ".cgi" => "")
How do I get header information and arguments?
BTW: Is this the most efficient way of serving compiled C code?
Both #Stefan's links are broken, so decided to write the answer I found from research:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
printf("Content-Type: text/plain\n\nHello world!\n");
const char *method_str = getenv("REQUEST_METHOD");
for(register unsigned short i=argc; i>0;) {
--i; printf("argv[%d]=%s ", i, argv[i]);
}
printf("REQUEST_METHOD = %s", method_str);
}
Just read how CGI works. FastCGI is a variant that keeps the backend process running for multiple requests and doesn't involve forking on every request. There are many similar protocols (SCGI, uwsgi, ...).

Resources