Errors with gcc when compiling C program - c

I have a custom shell program in which I have included signal.h, unistd.h, and stdio.h. I was originally working on this in RedHat Enterprise (not sure exactly what version, but not too old) and I was able to use gcc on my program and it compiled fine and ran fine. Now I moved it over to Ubuntu and gcc is giving me some errors, the first of which is conflicting types for 'getline()'. Some other errors say incompatible implicit declaration of built-in function strlen. I have overridden the functions in question, why was this working in RedHat but not in Ubuntu? Linux is not my thing so please speak plainly. Let me know if you need more error details.
/* define a global input buffer */
#include <signal.h>
#include <unistd.h>
#include <stdio.h>
#define MAXARG 512
#define MAXBUF 512
#define BUFFER_SIZE 50
#define MAX_COMMANDS 10
char buffer [BUFFER_SIZE];
static char *prompt = "MYSHELL>";
static char inpbuf[MAXBUF];
static char *arg[MAXARG+1];
static char tokbuf[2*MAXBUF];
static char *tok = tokbuf;
char history[MAX_COMMANDS][MAXBUF];
int cmd_num;
void getline(void);
void getline() {
int length;
length = read(0, inpbuf, MAXBUF);
if (length == 0) {
printf("\n");
exit(0);
}
inpbuf[length] = '\0';
}
void processline() {
char *ptr = inpbuf;
int narg;
for (narg=0;;) {
arg[narg] = tok;
for (; *ptr == ' ' || *ptr == '\t'; ptr++)
;
while(*ptr != ' ' && *ptr != '\t' && *ptr != '\n' &&
*ptr != '\0' && *ptr != ';' && *ptr != '&')
*tok++ = *ptr++;
*tok++ = '\0';
if (narg < MAXARG)
narg++;
if (*ptr == '\n')
break;
}
// clear the input buffer
for (ptr = inpbuf; *ptr != '\n'; ptr++)
*ptr = ' ';
if (narg != 0) {
arg[narg] = NULL;
}
}
void handle_SIGINT()
{
write(STDOUT_FILENO, buffer, strlen(buffer));
}
int main()
{
int pid, exitstat, ret;
struct sigaction handler;
handler.sa_handler = handle_SIGINT;
handler.sa_flags = 0;
sigemptyset(&handler.sa_mask);
sigaction(SIGINT, &handler, NULL);
strcpy(buffer, "Caught Control C\n");
while (1) {
printf("%s ", prompt);
fflush(stdout);
getline();
processline();
if ((pid = fork()) < 0){
fprintf(stderr, "myshell: error\n");
return (-1);
}
if (pid == 0) {
execvp(*arg, arg);
fprintf(stderr, "%s\n", *arg);
exit(127);
}
waitpid(pid, &exitstat, 0);
}
return 0;
}

Simplest solution would be to rename your getline() function, e.g. to my_getline()

incompatible implicit declaration of built-in function strlen
Include <string.h>
conflicting types for 'getline()
<stdio.h> already contains a declaration of getline, so make sure that nowhere in your code you have redeclared/redefined getline()[with a different prototype].

gcc -Wall typoknig.c
typoknig.c:19: error: conflicting types for ‘getline’
//usr/include/stdio.h:671: note: previous declaration of ‘getline’ was here
typoknig.c:21: error: conflicting types for ‘getline’
//usr/include/stdio.h:671: note: previous declaration of ‘getline’ was here
Two separate declarations of getline which Andy had recommended that you use my_getline() since the former is already part of stdio.h.
typoknig.c: In function ‘getline’:
typoknig.c:27: warning: implicit declaration of function ‘exit’
typoknig.c:27: warning: incompatible implicit declaration of built-in function ‘exit’
That can't be good, man exit says right at the top:
#include <stdlib.h>
void exit(int status);
perhaps you need to include stdlib.h? What does gcc assume is the signature of an undeclared function?
typoknig.c: In function ‘handle_SIGINT’:
typoknig.c:59: warning: implicit declaration of function ‘strlen’
typoknig.c:59: warning: incompatible implicit declaration of built-in function ‘strlen’
Ouch, man strlen to the rescue:
#include <string.h>
Fortunately, string.h will help out with the next one and we already nailed exit:
typoknig.c: In function ‘main’:
typoknig.c:70: warning: implicit declaration of function ‘strcpy’
typoknig.c:70: warning: incompatible implicit declaration of built-in function ‘strcpy’
typoknig.c:85: warning: incompatible implicit declaration of built-in function ‘exit’
Ain't that pre-processor nifty?
typoknig.c:87: warning: implicit declaration of function ‘waitpid’
typoknig.c:64: warning: unused variable ‘ret’
Sayeth man waitpid:
#include <sys/types.h>
#include <sys/wait.h>
Line 64 is left as an exercise for the reader.

Getline() is not part of C standard. It is a GNU extension. In c++ Getline() is standard.
So adding to your code right before your #includes
#define _GNU_SOURCE
should fix the warning. Also see "man getline" on linux.

Related

Encountering compiling issues with implicit declaration using the strlwr function for this code

I am writing code that accepts a command-line argument and determines whether or not the argument is in order based on the ASCII values of the argument. Here is what I have as of now:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int in_order(char *word){
int i = 1;
while(word[i] != '\0'){
if(word[i] < word[i-1]){
return 0;
}
i++;
}
return 1;
}
int main(int argc, char *argv[]) {
if (argc < 2){
exit(0);
}
else{
char *word = argv[1];
if(in_order(strlwr(word)) == 1){
printf("In order\n");
}
else{
printf("Not in order\n");
}
}
return 0;
}
When I try to compile this code with the C99 standard, I receive the following warnings and errors:
warning: implicit declaration of function 'strlwr' [-Wimplicit-function-declaration]
if(in_order(strlwr(word)) == 1){
^
warning: passing argument 1 of 'in_order' makes pointer from integer without a cast [enabled by default]
note: expected 'char *' but argument is of type 'int'
int in_order(char *word){
^
undefined reference to 'strlwr'
How can I make use of the strlwr function without having this error occur, and are there any other mistakes I should be aware of? Thanks.
strlwr is not a standard function; it is only found in some versions of string.h. You can find one such string.h online and copy the function’s code into your program.
You could also implement it yourself:
char* strlwr (char* s) {
for (int i = 0; i < strlen(s); ++i)
if (s[i] >= 'A' && s[i] <= 'Z')
s[i] += 'a' - 'A';
return s;
}
the function strlwr is available on cygwin string.h but it is NOT C99
see in /usr/include/string.h
#if __MISC_VISIBLE
char *strlwr (char *);
char *strupr (char *);
#endif
instead of
$ gcc -Wall -std=c99 prova.c -o prova
prova.c: In function ‘main’:
prova.c:25:21: warning: implicit declaration of function ‘strlwr’; did you mean ‘strstr’? [-Wimplicit-function-declaration]
25 | if(in_order(strlwr(word)) == 1){
just drop the -std=c99.
$ gcc -Wall prova.c -o prova
$ ./prova.exe ARD
Not in order
$ ./prova.exe ADR
In order

Conflicting types with a declared int func

Reading Kernigan, and the given code doesn't seem to work because of 'conflicting types' error for the user function.
The compiler I'm using is cc 7.4.0. I've declared the function in the beginning and have been checking and re-checking the types seemingly forever. Guess I'm missing something.
#include <stdio.h>
#define MAXLINE 1000
int getline(char line[], int maxline);
main()
{
int len;
char line[MAXLINE];
while((len = getline(line, MAXLINE)) > 0)
;
return 0;
}
int getline(char s[], int lim)
{
int i, c;
for (i = 0; i < (lim-1) && (c = getchar())!=EOF && c != '\n'; ++i)
s[i] = c;
if (c == '\n') {
s[i] = c;
++i;
}
s[i] = '\0';
return i;
}
The error I'm getting is
func.c:4:5: error: conflicting types for ‘getline’
int getline(char line[], int maxline);
^~~~~~~
In file included from func.c:1:0:
/usr/include/stdio.h:616:20: note: previous declaration of ‘getline’ was here
extern _IO_ssize_t getline (char **__restrict __lineptr,
^~~~~~~
^~~~
func.c:25:5: error: conflicting types for ‘getline’
int getline(char s[], int lim)
^~~~~~~
In file included from func.c:1:0:
/usr/include/stdio.h:616:20: note: previous declaration of ‘getline’ was here
extern _IO_ssize_t getline (char **__restrict __lineptr,
getline is already declared (in error actually) in <stdio.h> and its signature differs from yours.
The simplest thing to do is to rename your version to something different.
You need to block the compiler from spewing non-standard crap into standard headers. You are using some compiler which has defined a non-standard getline function inside the standard library header stdio.h, which is non-conforming.
With gcc you should compile as for example gcc -std=c17 -pedantic-errors to prevent this from happening.

How can I make my program compile without warning?

I should compile my program with spec flags to gcc. Then gcc complained about return values not taken care of. WhenI use variables to take the return values then gcc complains again:
$ gcc -pedantic -Wall -ansi -O4 miniShell.c
miniShell.c: In function ‘cd’:
miniShell.c:108:9: warning: variable ‘other_return’ set but not used [-Wunused-but-set-variable]
int other_return;
^
miniShell.c:107:12: warning: variable ‘return_value’ set but not used [-Wunused-but-set-variable]
char * return_value;
^
How can I resolve the warnings? My program is as follows.
#include <sys/stat.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <dirent.h>
#include <errno.h>
#include <stdarg.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#define BUFFER_LEN 1024
#define BUFFERSIZE 1024
int mystrcmp(char const *, char const *);
void err_syserr(char *fmt, ...)
{
int errnum = errno;
va_list args;
va_start(args, fmt);
vfprintf(stderr, fmt, args);
va_end(args);
if (errnum != 0)
fprintf(stderr, "(%d: %s)\n", errnum, strerror(errnum));
exit(EXIT_FAILURE);
}
int main() {
char line[BUFFER_LEN];
char* argv[100];
char* path= "/bin/";
char progpath[20];
int argc;
size_t length;
char *token;
int i=0;
int pid;
while(1) {
i = 0;
printf("miniShell>> ");
if(!fgets(line, BUFFER_LEN, stdin)) {
break;
}
length = strlen(line);
if (line[length - 1] == '\n') {
line[length - 1] = '\0';
}
if(strcmp(line, "exit")==0) {
break;
}
token = strtok(line," ");
while(token!=NULL) {
argv[i]=token;
token = strtok(NULL," ");
i++;
}
argv[i]=NULL;
argc=i;
for(i=0; i<argc; i++) {
printf("%s\n", argv[i]);
}
strcpy(progpath, path);
strcat(progpath, argv[0]);
for(i=0; i<strlen(progpath); i++) {
if(progpath[i]=='\n') {
progpath[i]='\0';
}
}
pid= fork();
if(pid==0) {
execvp(progpath,argv);
fprintf(stderr, "Child process could not do execvp\n");
} else {
wait(NULL);
printf("Child exited\n");
}
}
return (0);
}
int mystrcmp(char const *p, char const *q)
{
int i = 0;
for(i = 0; q[i]; i++)
{
if(p[i] != q[i])
return -1;
}
return 0;
}
int cd(char *pth) {
char path[BUFFERSIZE];
char cwd[BUFFERSIZE];
char * return_value;
int other_return;
strcpy(path,pth);
if(pth[0] != '/')
{
return_value = getcwd(cwd,sizeof(cwd));
strcat(cwd,"/");
strcat(cwd,path);
other_return = chdir(cwd);
} else {
other_return = chdir(pth);
}
printf("Spawned foreground process: %d\n", getpid());
return 0;
}
Reading between the lines, I guess the original problem you were trying to solve was a warning along the lines of:
warning: ignoring return value of ‘chdir’
And you've tried to fix that by assigning the return value to a variable (which itself is now unused).
getcwd and chdir can both return error codes if they fail, which are the return values GCC is warning you about. If you want to fix the warning properly you should add logic to your code to detect and handle these error cases. Otherwise, you are potentially continuing with a state inconsistent with your assumptions (for example, you may be in an unexpected directory if getcwd failed and left your buffer in an incorrectly initialised state).
I had thought that this could be over-ridden by casting the result of the function call to void, but this does not work (you can still play tricks, but they get messy!). The GCC documentation for the warn_unused_result attribute says:
The warn_unused_result attribute causes a warning to be emitted if a
caller of the function with this attribute does not use its return
value. This is useful for functions where not checking the result is
either a security problem or always a bug,
Which suggests that you don't want to find a workaround for the warning, and should really be checking the return value for error conditions.
If you really want to do it, assign the result to a variable as you have done, then add a single use of that variable, cast to void:
int res = chdir (cwd);
/* I promise I don't need to check this return value. */
(void) res;
The other users have answered how you can get rid of the warning by fixing your code, but just for reference: If you want to 'ignore' the warnings, compile with the flag:
-Wno-unused-but-set-variable
The compiler usually gives you a tag at the end of a warning (in your case, it's -Wunused-but-set-variable). To ignore it, just change the -W to a -Wno-
Hope this helps!
There are actually 2 things wrong here in your code. The first one probably caused you to change your code, which then caused the warning you are now asking about.
I bet you the first initial warning was about chdir. As the documents say:
man chdir(3): "Upon successful completion, 0 shall be returned.
Otherwise, -1 shall be returned, the current working
directory shall remain unchanged, and errno shall be set to
indicate the error."
As it says, chdir can return an error code stating if anything went wrong and the first initial warning was caused due to the fact you simply ignored that value.
Then you changed your code and assigned the value to another variable and got:
warning: variable ‘other_return’ set but not used [-Wunused-but-set-variable]
int other_return;
and you can see in this function that you are only setting a value to that variable but don't actually use it later which means you can delete it:
int cd(char *pth) {
char path[BUFFERSIZE];
char cwd[BUFFERSIZE];
char * return_value;
int other_return;
strcpy(path,pth);
if(pth[0] != '/')
{
return_value = getcwd(cwd,sizeof(cwd));
strcat(cwd,"/");
strcat(cwd,path);
other_return = chdir(cwd);
} else {
other_return = chdir(pth);
}
printf("Spawned foreground process: %d\n", getpid());
return 0;
}
Same thing for return_value. You can simply delete them both since they are not in use.
In case you want to avoid the first initial warnings you can always do something like this:
int res = chdir (cwd);
(void) res;
This is an assurance made by you to the compiler that everything is fine and he can ignore the warning.

Why is my C program not compiling?

I'm studying C with K&R book. There is an exercise, here it is: "Write a program to print all input lines that are longer than 80 characters". So I wrote this code:
#include <stdio.h>
#include <stdlib.h>
int getline(char s[], int lim);
#define MINLINE 80
#define MAXLINE 1000
/*
*
*/
int main(int argc, char** argv) {
int len; //current line length
char line[MAXLINE]; //current input line
int proceed=0;
while((len=getline(line, MAXLINE))>0)
if(line[len-1]!='\n'){
printf("%s", line);
proceed=1;}
else if(proceed==1){
printf("%s", line);
proceed=0;}
else if(len>MINLINE){
printf("%s", line);
}
return 0;
}
int getline(char s[], int lim){
int i, c;
for(i=0; i<lim-1 && (c=getline())!='*' && c!='\n'; i++){
s[i]=c;
}
if(c=='\n'){
if(i<=lim-1){
s[i]=c;}
i++;}
s[i]='\0';
return i;
}
I can't compile it and I have no idea how to fix it. Could you help me?
This is the error message:
main.c:11:5: error: conflicting types for ‘getline’
In file included from /usr/include/stdio.h:62:0,
from main.c:8:
/usr/include/sys/stdio.h:37:9: note: previous declaration of ‘getline’ was here
main.c:38:5: error: conflicting types for ‘getline’
In file included from /usr/include/stdio.h:62:0,
from main.c:8:
/usr/include/sys/stdio.h:37:9: note: previous declaration of ‘getline’ was here
main.c: In function ‘getline’:
main.c:40:5: error: too few arguments to function ‘getline’
main.c:38:5: note: declared here
make[2]: *** [build/Debug/Cygwin_4.x_1-Windows/main.o] Error 1
make[1]: *** [.build-conf] Error 2
make: *** [.build-impl] Error 2
getline() function is already declared in stdio.h header file.if you want to redefine it in your file. just modify as my_getline()
In this for loop you need to use getchar() not getline()
for(i=0; i<lim-1 && (c=getline())!='*' && c!='\n'; i++)
for(i=0; i<lim-1 && (c=getchar())!='*' && c!='\n'; i++)
You need to use pointer in your function to get the input into line.other wise s is become local to the function.
int my_getline(char *, int); //declaration
int my_getline(char *s, int lim) //defination
{
//....
}
function call is same
len= my_getline(line, MAXLINE)
Finally use some conditional mechanism to get out of while loop in the main.
The function getline is already declared in stdio.h. Rename your function to something else.
getline is a function of the C standard library defined in stdio.h. The compiler want to use that version instead of yours.
Rename your function, for instance into my_getline and you should be fine.
Change the function name, getline exists already

C - listing files contained in folder and all subfolders

I have a function that reads all files contained in a single input directory.
I wanted to make that function read not only files in "main" directory, but also ones contained in all subdirectories.
In order to do so, i wrote this code:
#include <sys/types.h>
#include <dirent.h>
#include <errno.h>
#include <stdio.h>
struct dirent *readdir(DIR *dirp);
char * percorso;
DIR *cartella;
struct dirent *elemento;
char * scrivi(char * a, char * b)
{
char *targetdir = malloc(2048);
strcpy(targetdir,a);
strcat(targetdir,"/");
strcat(targetdir,b);
printf("%s \n", targetdir);
return targetdir;
}
void scorriFolder(char* nome)
{
if ((cartella = opendir(nome)) == NULL)
perror("opendir() error");
else {
printf("contents of root: \n");
while ((elemento = readdir(cartella)) != NULL)
{
if(elemento->d_type == DT_DIR)
{
if(elemento->d_name != ".." || elemento->d_name != ".")
{
percorso = scrivi(nome, elemento->d_name);
scorriFolder(percorso);
}
}
else
{
printf(" %s\n", elemento->d_name);
}
}
closedir(cartella);
}
}
main(int argc, char * argv[]) {
scorriFolder(argv[1]);
}
But it doesn't even compile, saying:
warning: incompatible implicit declaration of built-in function ‘malloc’
warning: incompatible implicit declaration of built-in function ‘strcpy’
warning: incompatible implicit declaration of built-in function ‘strcat’
As far as I know, this issue is due to a wrong format of variables passed into malloc, strcpy and strcat functions. (elemento->d_name has type char and not char*
What can I do, in order to get this code work?
Thanks.
EDIT
This is a working while snippet:
while ((elemento = readdir(cartella)) != NULL)
{
if ( strcmp(elemento->d_name, ".") == 0)
{
continue;
}
if ( strcmp(elemento->d_name, "..") == 0)
{
continue;
}
if(elemento->d_type == DT_DIR)
{
{
percorso = scrivi(nome, elemento->d_name);
scorriFolder(percorso);
}
}
else
{
printf(" %s\n", elemento->d_name);
}
}
Once it scans a subdirectory it crashes because path it is not updated as the program exits from subdirectory. I am trying to fix it.
You need to add #include <stdlib.h> and #include <string.h> to the beginning of the file.
warning: incompatible implicit declaration of built-in function ‘malloc’
This error message is telling you that the compiler can't determine the return type and parameters to malloc. I think the compiler assumes int for the return type if it can't find one. Which is not void * which malloc actually returns.
malloc is defined in <stdlib.h>
strcpy and strcat are defined in <string.h>
To find out where these functions are defined you can read the man page by typing man malloc , man strcpy, or man strcat

Resources