当前位置: 技术问答>linux和unix
linux c实现shell,但出现编译后,不能链接,望高手指点指点,谢谢啦
来源: 互联网 发布时间:2017-01-26
本文导语: 程序源码如下: #include #include #include #include #include #include #include #include #include #include #define MAX_COMMAND_LEN 250 #define JOB_STATUS_FORMAT "[%d] %-22s %.40sn" struct jobSet { struct job *head; struct job *fg; }; struct ...
程序源码如下:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define MAX_COMMAND_LEN 250
#define JOB_STATUS_FORMAT "[%d] %-22s %.40sn"
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 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] = '';
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 = '';
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 = '';
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] = '';
}
*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: %sn", 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] %dn",
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 numProgs &&
job->progs[progNum].pid != childpid)
progNum++;
if(progNum 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 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应用程序开发,有些地方还不太了解。望高手帮忙看一下,看看问题出在哪里,
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define MAX_COMMAND_LEN 250
#define JOB_STATUS_FORMAT "[%d] %-22s %.40sn"
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 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] = '';
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 = '';
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 = '';
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] = '';
}
*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: %sn", 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] %dn",
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 numProgs &&
job->progs[progNum].pid != childpid)
progNum++;
if(progNum 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 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。看看修改完会不会编译通过。
1、楼主的程序只是一个.c文件吗?(看样子像)
2、提示出现的是freeJob、removeJob没有定义,但你的函数名好像是小写的freejob、removejob。看看修改完会不会编译通过。
|
同意楼上,错字问题 freejob -> freeJob removejob -> removeJob