读书人

linux c实现shell,但出现编译后不能

发布时间: 2012-02-14 19:19:19 作者: rapoo

linux c实现shell,但出现编译后,不能链接,望高手指点指点,谢谢啦
程序源码如下:
#include <stdio.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/wait.h>
#include <unistd.h>

#define MAX_COMMAND_LEN 250
#define JOB_STATUS_FORMAT "[%d] %-22s %.40s\n"

struct jobSet
{
struct job *head;
struct job *fg;
};

struct childProgram
{
pid_t pid;
char **argv;
};

struct job
{
int jobId;
int numProgs;
int runningProgs;
char *text;
char *cmdBuf;
pid_t pgrp;
struct childProgram *progs;
struct job *next;
};

void freejob(struct job *cmd)
{
int i;

for(i = 0; i < cmd->numProgs; i++)
{
free(cmd->progs[i].argv);
}
free(cmd->progs);
if(cmd->text)
free(cmd->text);
free(cmd->cmdBuf);
}

int getCommand(FILE *source, char *command)
{
if(source == stdin)
{
printf("#");
fflush(stdout);
}

if(!fgets(command, MAX_COMMAND_LEN, source))
{
if(source == stdin)
printf("\n");
return 1;
}

command[strlen(command) - 1] = '\0';
return 0;

}

int praseCommand(char **commandPtr, struct job *job, int *isBg)
{
char *command;
char *returnCommand = NULL;
char *src, *buf;
int argc = 0;
int done = 0;
int argvAlloced;
char quote = '\0';
int count;
struct childProgram *prog;

while(**commandPtr &&isspace(**commandPtr))
(*commandPtr)++;

if(!**commandPtr || (**commandPtr == '#'))
{
job->numProgs = 0;
*commandPtr = NULL;
return 0;
}

*isBg = 0;
job->numProgs = 1;
job->progs = malloc(sizeof(*job->progs));

job->cmdBuf = command = calloc(1, strlen(*commandPtr) + 1);
job->text = NULL;
prog = job->progs;

argvAlloced = 5;
prog->argv = malloc(sizeof(*prog->argv) * argvAlloced);
prog->argv[0] = job->cmdBuf;

buf = command;
src = *commandPtr;
while(*src && !done)
{

if(quote == *src)
quote = '\0';

else if(quote)
{
if(*src == '\\')
{
src++;
if(!*src)
{
fprintf(stderr, "character expected after \\\n");
freeJob(job);
return 1;
}
if(*src != quote)
*buf++ = '\\';
}

*buf++ = *src;
}
else if(isspace(*src))
{
if(*prog->argv[argc])
{
buf++, argc++;
if((argc + 1) == argvAlloced)
{
argvAlloced += 5;
prog->argv = realloc(prog->argv,
sizeof(*prog->argv) * argvAlloced);
}
prog->argv[argc] = buf;
}
}
else switch(*src)
{
case '"':
case '\'': quote = *src; break;
case '#': done = 1; break;
case '&': *isBg = 1;
case ';': done = 1; returnCommand = *commandPtr + (src - *commandPtr) + 1; break;
case '\\': src++;
if(!*src)
{
freeJob(job);
fprintf(stderr,"charecter expected after \\\n");
return 1;
}
default: *buf++ = *src;
}
src++;
}

if(*prog->argv[argc])
{
argc++;
}
if(!argc)
{
freeJob(job);
return 0;
}
prog->argv[argc] = NULL;

if(!returnCommand)
{
job->text = malloc(strlen(*commandPtr) + 1);
strcpy(job->text, *commandPtr);


}
else
{
count = returnCommand - *commandPtr;
job->text = malloc(count + 1);
strncpy(job->text, *commandPtr, count);
job->text[count] = '\0';
}

*commandPtr = returnCommand;
return 0;
}

int runCommand(struct job newJob, struct jobSet *jobList, int inBg)
{
struct job *job;

if(!strcmp(newJob.progs[0].argv[0], "exit"))
exit(0);
else if(!strcmp(newJob.progs[0].argv[0], "jobs"))
{
for(job = jobList->head; job; job = job->next)
printf(JOB_STATUS_FORMAT, job->jobId, "Running", job->text);
return 0;
}

if(!(newJob.progs[0].pid = fork()))
{
execvp(newJob.progs[0].argv[0], newJob.progs[0].argv);
fprintf(stderr, "exec() of %s failed: %s\n", newJob.progs[0].argv[0], strerror(errno));
exit(1);
}
setpgid(newJob.progs[0].pid, newJob.progs[0].pid);

newJob.pgrp = newJob.progs[0].pid;
newJob.jobId = 1;
for(job = jobList->head; job; job->next)
if(job->jobId >= newJob.jobId)
newJob.jobId = job->jobId + 1;

if(!jobList->head)
job = jobList->head = malloc(sizeof(*job));
else
{
for(job = jobList->head; job->next; job = job->next)
job->next = malloc(sizeof(*job));
job = job->next;
}

*job = newJob;
job->next = NULL;
job->runningProgs = job->numProgs;

if(inBg)
{
printf("[%d] %d\n",
job->jobId, newJob.progs[newJob.numProgs - 1].pid);
}
else
{
jobList->fg = job;

if(tcsetpgrp(0, newJob.pgrp))
perror("tcsetpgrp");
}

return 0;

}

void removejob(struct jobSet *jobList, struct job *job)
{
struct job *prevJob;

freeJob(job);
if(job == jobList->head)
jobList->head = job->next;
else
{
prevJob = jobList->head;
while(prevJob->next != job)
prevJob = prevJob->next;
prevJob->next = job->next;
}

free(job);
}

void checkJobs(struct jobSet *jobList)
{
struct job *job;
pid_t childpid;
int status;
int progNum;

while((childpid = waitpid(-1, &status, WNOHANG)) > 0)
{
for(job = jobList->head; job; job = job->next)
progNum = 0;
while(progNum < job->numProgs &&
job->progs[progNum].pid != childpid)
progNum++;
if(progNum < job->numProgs)
break;
}

job->runningProgs--;
job->progs[progNum].pid = 0;

if(!job->runningProgs)
{
printf(JOB_STATUS_FORMAT, job->jobId, "Done", job->text);
removeJob(jobList, job);
}

if(childpid == -1 && errno != ECHILD)
perror("waitpid");

}

int main(int argc, const char **argv)
{
char command[MAX_COMMAND_LEN + 1];
char *nextCommand = NULL;
struct jobSet jobList = {NULL, NULL};
struct job newJob;
FILE *input = stdin;
int i;
int status;
int inBg;

if(argc > 2)
{
fprintf(stderr, "unexpected arguments; usage: ladshl <command>\n");
exit(1);
}
else if(argc == 2)
{
input = fopen(argv[1], "r");
if(!input)
{
perror("fopen");
exit(1);
}
}

while(1)
{
if(!jobList.fg)
{
checkJobs(&jobList);
if(!nextCommand)
{
if(getCommand(input, command))
break;
nextCommand = command;
}

if(!praseCommand(&nextCommand, &newJob, &inBg) && newJob.numProgs)
runCommand(newJob, &jobList, inBg);


}
else
{
i = 0;
while(!jobList.fg->progs[i].pid)
i++;

waitpid(jobList.fg->progs[i].pid, &status, 0);
jobList.fg->runningProgs--;
jobList.fg->progs[i].pid = 0;

if(!jobList.fg->runningProgs)
{
removeJob(&jobList, jobList.fg);
jobList.fg = NULL;
if(tcsetpgrp(0, getpid()))
perror("tcsrtpgrp");
}
}
}
return 0;
}


用gcc编译 gcc -o shell shell.c
/tem/cc4GxdCN.o: In function 'praseCommand':
shell.c(.text+0x2bb): undefined referenced to 'freeJob'
shell.c(.text+0x409): undefined referenced to 'freeJob'
shell.c(.text+0x48e): undefined referenced to 'freeJob'
/tmp//cc4GxdCN.o: In function 'removejob':
shell.c(.text+0x820): undefined referenced to 'freeJob'
/tmp//cc4GxdCN.o: In function 'checkJobs':
shell.c(.text+0x953): undefined referenced to 'removeJob'
/tmp//cc4GxdCN.o: In function 'main':
shell.c(.text+0x2bb): undefined referenced to 'removeJob'
collected2: ld returned 1 exit status

小弟最近在学习linux应用程序开发,有些地方还不太了解。望高手帮忙看一下,看看问题出在哪里,

[解决办法]
大致看了下,有两点:
1、楼主的程序只是一个.c文件吗?(看样子像)
2、提示出现的是freeJob、removeJob没有定义,但你的函数名好像是小写的freejob、removejob。看看修改完会不会编译通过。
[解决办法]
同意楼上,错字问题 freejob -> freeJob removejob -> removeJob

读书人网 >UNIXLINUX

热点推荐