功能:
能够实现命令控制且能获取命令后面全部的完整的字符串(含带空格的)
/*
*gcc -o getopt getopt.c
*./getopt --help
*./getopt -h
*/
#include <stdio.h>
#include <getopt.h>
#include <stdlib.h>
#include <syslog.h>
#include <unistd.h>
#include <time.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <fcntl.h>
#define VERSION 0 /*version, 当前为0 -v*/
char *short_opts = "hvn:r:s:d:l:i:m:u:a:";
struct option long_options[] = {
{"help", no_argument, NULL, 'h'},
{"version", no_argument, NULL, 'v'},
{"process_num", required_argument, NULL, 'n'},
{"send_rate", required_argument, NULL, 'r'},
{"log_size", required_argument, NULL, 's'},
{"log_data", required_argument, NULL, 'd'},
{"log_level", required_argument, NULL, 'l'},
{"log_id_enable", required_argument, NULL, 'i'},
{"model_name", required_argument, NULL, 'm'},
{"device_num", required_argument, NULL, 'u'},
{"server_addr", required_argument, NULL, 'a'},
{NULL, 0, NULL, 0}
};
typedef struct syslog_command syslog_command_t;
typedef struct
{
int process_num; /*进程数 -n*/
int send_rate; /*发送时间间隔,多少ms发送一次 -r*/
int log_size; /*每条log字节数 -s*/
char log_data[256]; /*每条log的内容 -d*/
int log_level; /*日志级别 -l*/
int log_id_enable; /*每条log的序号标识 -i*/
char model_name[128]; /*模块名称 -m*/
int device_num; /*子设备个数 -u*/
char server_addr[50]; /*服务器地址 -a*/
int (*write)(syslog_command_t *command);
}syslog_command;
/*获取随机数*/
void genRandomString(char* buff, int length)
{
char metachar[] = "abc.defghij,klmn opqr[]stu=vwxyz+01234()5!6789";
int i = 0;
srand((unsigned)time(NULL)); //用时间做种,每次产生随机数不一样
for (i = 0; i < length; i++)
{
buff[i] = metachar[rand() % 46];
}
buff[length] = '\0';
}
int mylog(syslog_command *command)
{
openlog(command->model_name, LOG_CONS | LOG_PID, 128);
//printf("1\n");
send_syslogd(command->log_data, command);
return 0;
}
int fork_num(int num, syslog_command *command)
{
int status,i;
for (i = 0; i < num; i++)
{
status = fork();
if (status == 0 || status == -1) break;//每次循环时,假设发现是子进程就直接从创建子进程的循环中跳出来。不让你进入循环,这样就保证了每次仅仅有父进程来做循环创建子进程的工作
}
if (status == -1)
{
printf("error in fork!");//error
}
else if (status == 0) //每一个子进程都会运行的代码
{
command->write(command);
}
}
int init_command(syslog_command *command)
{
command->process_num = 20;
command->send_rate = 1000 * 100;
command->log_level = 6;
command->log_id_enable = 1;
strcpy(command->log_data, "hello world!, test logger ok");
command->log_size = strlen(command->log_data);
strcpy(command->model_name, "mylog");
command->device_num = 0;
return 0;
}
/*次函数用于获取命令后面携带的带空格的字符串*/
int get_command_string(char *data, int argc,char **argv)
{
int i = 0;
for (i = 0;; i++)
{
if (optarg == argv[argc - 1] || *optarg == '-')
{
while(*argv[argc - 1] != '\0')
{
data[i] = *argv[argc - 1];
*argv[argc - 1]++;
i++;
}
break;
}
else
{
data[i] = *optarg;
if (*optarg == '\0')
{
data[i] = ' ';
}
optarg++;
}
}
return i;
}
int sock_tcp_connect()
{
int sock = -1;
sock = socket (AF_INET, SOCK_STREAM, 0);
if (sock < 0)
{
printf ("SOCKET error. /n");
return -1;
}
printf("sock tcp ok\n");
return sock;
}
int sock_tcp_close(int sockfd)
{
if (sockfd > 0)
{
close(sockfd);
sockfd = -1;
}
printf("sock_tcp_close\n");
return 0;
}
/*将嵌套字设为非阻塞的*/
int setnonblocking(int fd, int nonblocking)
{
int flags, newflags;
flags = fcntl(fd, F_GETFL, 0);
if (flags < 0) {
perror("fcntl(F_GETFL)");
return -1;
}
if (nonblocking)
newflags = flags | (int) O_NONBLOCK;
else
newflags = flags & ~((int) O_NONBLOCK);
if (newflags != flags)
{
if (fcntl(fd, F_SETFL, newflags) < 0)
{
perror("fcntl(F_SETFL)");
return -1;
}
}
return 0;
}
int sock_tcp_write(int sockfd, syslog_command *command)
{
int ret = -1;
int err = 0;
socklen_t errlen = sizeof(err);
char buf[BUFSIZ];
time_t time_s = 0, time_ns = 0, time_now = 0, time_long = 0;
struct tm *tm;
//printf("%s\n" , command->log_data);
snprintf(buf, sizeof(buf), "%s %s%s", "<134>Nov 2 17:05:58 mylog[1233]:", command->log_data, "\n");
printf("Local buf is %s/n", buf);
//strcpy(buf, "hello world!, test logger\n");
for (;;)
{
usleep(command->send_rate);
ret = send(sockfd, buf, strlen(buf), 0);
}
return 0;
ERROR:
printf("====to close\n");
sock_tcp_close(sockfd);
return -1;
}
int sock_tcp(syslog_command *command)
{
int ret = -1, sockfd = -1;
struct sockaddr_in server_addr;
sockfd = sock_tcp_connect();
memset(&server_addr,0,sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(514);
server_addr.sin_addr.s_addr = inet_addr(command->server_addr);
//printf("0x%08x\n" , inet_addr(command->server_addr));
//printf("%s\n" , command->server_addr);
ret = connect(sockfd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr));
if (ret < 0)
{
perror("client : connect error\n");
goto ERROR;
}
printf("sock tcp connected\n");
sock_tcp_write(sockfd, command);
return 0;
ERROR:
sock_tcp_close(sockfd);
return ret;
}
int main(int argc,char **argv)
{
int opt;
char *l_optarg;
syslog_command command;
char data[256] = {0};
init_command(&command);
while((opt = getopt_long(argc , argv, short_opts, long_options, NULL)) != -1)
{
switch(opt)
{
case 'h':
printf("\nOptions:"
"\n -h help"
"\n -v version"
"\n -s Each log bytes(Content randomly generated)"
"\n -n Number of processes"
"\n -r Send time interval(ms)"
"\n -d The content of log"
"\n -l Log level(0-6)"
"\n -i Enable serial number(0-unable, 1-enable)"
"\n -m The name of the module"
"\n -u Child device num(0-8)"
"\n -a Server addr(x.x.x.x)"
"\n"
);
break;
case 'v':
printf("current version is %d\n", VERSION);
break;
case 's':
command.log_size = atoi(optarg);
genRandomString(data, command.log_size);
strcpy(command.log_data, data);
printf("%d\n" , command.log_size);
break;
case 'n':
command.process_num = atoi(optarg);
printf("%d\n" , command.process_num);
break;
case 'r':
command.send_rate = atoi(optarg) * 1000;
printf("%d\n" , command.send_rate/1000);
break;
case 'd':
command.log_size = get_command_string(data, argc, argv);
strcpy(command.log_data, data);
break;
case 'l':
command.log_level = atoi(optarg);
printf("%d\n" , command.log_level);
break;
case 'i':
command.log_id_enable = atoi(optarg);
printf("%d\n" , command.log_id_enable);
break;
case 'm':
get_command_string(data, argc, argv);
strcpy(command.model_name, data);
break;
case 'u':
command.device_num = atoi(optarg);
printf("%d\n" , command.device_num);
break;
case 'a':
strcpy(command.server_addr, optarg);
printf("%s\n" , command.server_addr);
break;
}
}
#if 0
sock_tcp(&command);
#else
if (command.device_num > 0)
{
command.write = sock_tcp;
fork_num(command.device_num, &command);
}
else
{
command.write = mylog;
fork_num(command.process_num, &command);
}
#endif
return 0;
}