tags:

views:

150

answers:

4

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;
}
+4  A: 

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].

Prasoon Saurav
I did have a prototype (per ANSI C) for getline, and several other functions (that are declared in `stdio.h`). What I don't get though is why this worked in RedHat exactly as I have it now, but not in Ubuntu. I am posting the code.
typoknig
@typoknig: If you've made an error, such as using `strlen` without providing a suitable prototype, the compiler may not be under any obligation to warn you. If you invoke undefined behavior, the standard allows anything to happen, including what you actually expect. It's rarely worthwhile analyzing why a faulty program worked on a particular system.
David Thornley
+1  A: 

This looks like a duplicate of this question: http://stackoverflow.com/questions/1161012/what-does-error-conflicting-types-for-mean. I think @brice answers your question.

Richard Cook
+2  A: 

Simplest soltuion would be to rename your function getline() ? my_getline() ?

Andy
This did get rid of most of my errors, but I wonder why `gcc` on RedHat allowed me to override those functions but `gcc` on Ubuntu did not... Seems strange to me.
typoknig
A: 
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.

msw
That it compiled at all under any gcc is the true puzzle.
msw
@msw, look I appreciate your help, but maybe you missed the "speak plainly" part of my question. I get what you are saying in some parts of your answer, but not all. I get the jest of what you and David are saying (which I already knew) that I have functions declared twice. It just does not seem like there should be such a huge difference between the two systems I am working on, and I have a hard time grasping why it works with no errors in RedHat but has lots of errors in Ubuntu. This is just a side project so I am not deeply concerned about it, I was just curious to know the "why".
typoknig