📄 ftpdaemon.c
字号:
#include "ftpdaemon.h"
#include <signal.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <ctype.h>
#include "ftppub.h"
//#define MAX_BUFF_LEN 1024
#define SHORT_STR_LEN 256
//根据程序名获得其所有进程id号 由于要通过pidof这个命令来查询,为了获取pidof这个命令的结果,因此要用管道来保存查询结果
int getthispids(const char *appname,char *strpids,int bufflen)
{
int pips[2];//pips是存来存管道的输入输出描述符
pipe(pips);
switch (fork())
{
case 0:
close(1);//关闭掉标准输出流描述符
if (dup(pips[1])==-1)//dup函数这个是复制管道的输出流描述符,新描述符会从0来始查找还没有被使用的描述符做为新描述符
{
perror("dup");
}
close(pips[1]);//关闭管道的输出流描述符
close(pips[0]);//关闭管道的输入流描述符
//通过pidof这个命令来取得指定程 序名的所有进程id号
execlp("pidof","pidof",appname,0);//用pidof这个命令程序来替换当前进程里边的代码
exit(-1);
break;
case -1:
exit(-1);
break;
default:
close(pips[1]);
read(pips[0],strpids,bufflen);
close(pips[0]);
return 0;
break;
}
}
int daemon_ctrl(int argc,char *argv[],int (*startfun)(void))
{
//这个的作用是毕免子进程发生僵死进程
signal(SIGCHLD, SIG_IGN);//当子进程发生子进程运行结束消息时,忽略掉这个消息
if (argc !=2)
{
printf("Usage:miniftpd {start|stop|restart}\n");
return -1;
}
if (strcmp(argv[1],"start")==0) //程序后连跟start参数 时执行startfun这个函数
{
return daemon_start(argv[0],startfun);
}
else if (strcmp(argv[1],"stop")==0) //程序后连跟stop参数 时执行startfun这个函数
{
return daemon_stop(argv[0]);
}
else if (strcmp(argv[1],"restart")==0) //程序后连跟restart参数 时执行startfun这个函数
{
return daemon_restart(argv[0],startfun);
}
else
printf("Usage:ftpd {start|stop|restart}\n"); //程序后连跟其它字符串做参数 时执行提示只能跟这三个参数
return -1;
}
//当参数为start时执行这个程 序
int daemon_start(char *app,int (*startfun)(void))
{
//由于pidof这个命令只能在root用户下使用,所以这里要判断一下看看是不是以root用户启动
if (getuid()!=0)
{
printf("请用root用户启动\n");
exit(1);
}
int thisid=0;
thisid=getpid();
//printf("pid before invoke daemon=%d\n",thisid);
char buff[BUFSIZ+1]={0};
//获取这个程序所执行的所有进程号
getthispids(app,buff,BUFSIZ);
char tmppid[SHORT_STR_LEN];
char *p=buff;
int tmpid,i=0;
while (*p)
{
while (*p&&isspace(*p))
p++;
i=0;
while (*p&&!isspace(*p))
tmppid[i++]=*p++;
if (*p=='\0')
break;
tmpid=atoi(tmppid);
if (thisid!=tmpid)
{
printf( "[ Service has been launched ]\n");
return -1;
}
}
char *strtmp="Ftp Server Start";
write(1,strtmp,strlen(strtmp));
int pointcount=30;
for (;pointcount>0;pointcount--) {
write(1,".",1);
usleep(10000);
}
daemon(1,1);//这个是让当前进程变成守护进程
//printf("pid after invoke daemon=%d\n",getpid());
write(1,"[ OK ]\n",strlen("[ OK ]\n"));
CreateShm();// 开启共享内存
Create_Sem(4);//创建一个信号集,该 信号集中有4个信号量
startfun();
return 0;
}
//当参数为stop后就执行这个程 序
int daemon_stop(char *app)
{
int thisid=0;
thisid=getpid();
char buff[BUFSIZ+1]={0};
getthispids(app,buff,BUFSIZ);
char tmppid[SHORT_STR_LEN];
char *p=buff;
int tmpid,i=0;
if (!strchr(buff,' '))
{
//当前只有一个进程
printf( "[ Services are not running ]\n");
return -1;
}
char *strtmp="Ftp Server Stop ";
write(1,strtmp,strlen(strtmp));
while (*p)
{
while (*p&&isspace(*p))p++;
i=0;
while (*p&&!isspace(*p))
tmppid[i++]=*p++;
tmpid=atoi(tmppid);
if (tmpid!=0&&thisid!=tmpid)
{
kill(tmpid,SIGTERM); //杀死进程
}
memset(tmppid,0,SHORT_STR_LEN);
if(*p=='\0') break;
}
CreateShm();//在关闭进程中这个是一个新的进程
Removeshm(g_shmid);//关闭掉共享内存
Create_Sem(4);
del_semvalue(sem_id);
int pointcount=10;
for (;pointcount>0;pointcount--) {
write(1,".",1);
usleep(10000);
}
write(1,"[ OK ]\n",strlen("[ OK ]\n"));
return 0;
}
//当参数为restart后就执行这个程 序
int daemon_restart(char *app,int (*startfun)(void))
{
daemon_stop(app);
usleep(100000);//??????????kill需要一定时间
return daemon_start(app,startfun);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -