mirror of
https://gitlab.com/prpl-foundation/intel/dsl_cpe_control.git
synced 2025-12-10 06:44:37 +01:00
489 lines
12 KiB
C
489 lines
12 KiB
C
/******************************************************************************
|
|
|
|
Copyright 2018, Intel Corporation
|
|
|
|
Copyright (c) 2007-2015
|
|
Lantiq Beteiligungs-GmbH & Co. KG
|
|
|
|
For licensing information, see the file 'LICENSE' in the root folder of
|
|
this software module.
|
|
|
|
******************************************************************************/
|
|
|
|
#ifdef LINUX
|
|
|
|
#include "dsl_pipe_client.h"
|
|
|
|
#define PIPE_PREFIX "/tmp/pipe/dsl_cpe"
|
|
#define SYS_NAME_PREFIX "/tmp"
|
|
|
|
#undef DSL_DBG_BLOCK
|
|
#define DSL_DBG_BLOCK DSL_DBG_OS
|
|
|
|
static char Result[20000];
|
|
static int sema;
|
|
|
|
#if defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED)
|
|
/* union semun is defined by including <sys/sem.h> */
|
|
#else
|
|
/* according to X/OPEN we have to define it ourselves */
|
|
union semun {
|
|
int val; /* value for SETVAL */
|
|
struct semid_ds *buf; /* buffer for IPC_STAT, IPC_SET */
|
|
unsigned short *array; /* array for GETALL, SETALL */
|
|
/* Linux specific part: */
|
|
struct seminfo *__buf; /* buffer for IPC_INFO */
|
|
};
|
|
#endif
|
|
|
|
#ifndef DSL_DEBUG_DISABLE
|
|
static void print_sem_error(int err)
|
|
{
|
|
switch(err)
|
|
{
|
|
case E2BIG:
|
|
printf( "DSL[Pipe]: The value of nsops is greater than the system-"
|
|
"imposed maximum." DSL_PIPE_CRLF);
|
|
break;
|
|
|
|
case EACCES:
|
|
printf( "DSL[Pipe]: Operation permission is denied to the calling "
|
|
"process, see IPC." DSL_PIPE_CRLF);
|
|
break;
|
|
|
|
case EAGAIN:
|
|
printf( "DSL[Pipe]: The operation would result in suspension of the "
|
|
"calling process but (sem_flg&IPC_NOWAIT) is non-zero." DSL_PIPE_CRLF);
|
|
break;
|
|
|
|
case EFBIG:
|
|
printf( "DSL[Pipe]: The value of sem_num is less than 0 or greater "
|
|
"than or equal to the number of semaphores in the set associated "
|
|
"with semid. " DSL_PIPE_CRLF);
|
|
break;
|
|
|
|
case EIDRM:
|
|
printf( "DSL[Pipe]: The semaphore identifier semid is removed from "
|
|
"the system. " DSL_PIPE_CRLF);
|
|
break;
|
|
|
|
case EINTR:
|
|
printf( "DSL[Pipe]: The semop() function was interrupted by a signal." DSL_PIPE_CRLF);
|
|
break;
|
|
|
|
case EINVAL:
|
|
printf( "DSL[Pipe]: The value of semid is not a valid semaphore "
|
|
"identifier, or the number of individual semaphores for which the "
|
|
"calling process requests a SEM_UNDO would exceed the system-"
|
|
"imposed limit. " DSL_PIPE_CRLF);
|
|
break;
|
|
|
|
case ENOSPC:
|
|
printf( "DSL[Pipe]: The limit on the number of individual processes "
|
|
"requesting a SEM_UNDO would be exceeded. " DSL_PIPE_CRLF);
|
|
break;
|
|
|
|
case ERANGE:
|
|
printf( "DSL[Pipe]: An operation would cause a semval to overflow "
|
|
"the system-imposed limit, or an operation would cause a semadj "
|
|
"value to overflow the system-imposed limit." DSL_PIPE_CRLF);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
#endif /* DSL_DEBUG_DISABLE */
|
|
|
|
/** signal handler, will abort blocking semop() call */
|
|
static void DSL_PIPE_SemAlarm(int val)
|
|
{
|
|
}
|
|
|
|
static int DSL_PIPE_SemaphoreGlobalCreate(DSL_char_t *pName)
|
|
{
|
|
/* Semaphore ID used in further semaphore operations */
|
|
int semid = -1;
|
|
int fd;
|
|
/* Used to generate the semaphore key in case pName is not a number */
|
|
DSL_char_t *sempath = DSL_NULL;
|
|
/* the name should be an integer if not the key for semaphore is generated at
|
|
runtime*/
|
|
DSL_int_t nsemkey;
|
|
union semun arg;
|
|
|
|
arg.val = 0;
|
|
|
|
if (pName == DSL_NULL)
|
|
pName = "";
|
|
|
|
nsemkey = atoi(pName);
|
|
|
|
/*incase atoi fails generate a tmp string and try to generate a key
|
|
at runtime */
|
|
if (nsemkey == 0)
|
|
{
|
|
sempath = DSL_PIPE_Malloc(strlen(SYS_NAME_PREFIX"/") + strlen(pName) + 1);
|
|
if (sempath == DSL_NULL)
|
|
{
|
|
printf( "DSL: No Mem." DSL_PIPE_CRLF);
|
|
return -1;
|
|
}
|
|
mkdir(SYS_NAME_PREFIX, 0777);
|
|
fd = open(SYS_NAME_PREFIX, O_RDONLY);
|
|
fchmod(fd, 0777);
|
|
close(fd);
|
|
cpe_control_pipe_strncpy_s(sempath, strlen(SYS_NAME_PREFIX"/") + strlen(pName) + 1,
|
|
SYS_NAME_PREFIX"/\0", strlen(SYS_NAME_PREFIX"/"));
|
|
strcat(sempath, pName);
|
|
strcat(sempath, "\0");
|
|
|
|
/* creat(sempath, 0666); */
|
|
creat(sempath, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
|
|
/* Access to all */
|
|
/*chmod(sempath, 0777);*/
|
|
|
|
/* generate key */
|
|
if ( (nsemkey = ftok(sempath, 5)) < 0)
|
|
{
|
|
switch(errno)
|
|
{
|
|
case EBADF:
|
|
printf( "DSL: filedes is bad." DSL_PIPE_CRLF);
|
|
break;
|
|
|
|
case ENOENT:
|
|
printf( "DSL: A component of the path file_name does not exist, "
|
|
"or the path is an empty string." DSL_PIPE_CRLF);
|
|
break;
|
|
|
|
case ENOTDIR:
|
|
printf( "DSL: A component of the path is not a directory." DSL_PIPE_CRLF);
|
|
break;
|
|
|
|
case ELOOP:
|
|
printf( "DSL: Too many symbolic links encountered while "
|
|
"traversing the path." DSL_PIPE_CRLF);
|
|
break;
|
|
|
|
case EFAULT:
|
|
printf( "DSL: Bad address." DSL_PIPE_CRLF);
|
|
break;
|
|
|
|
case EACCES:
|
|
printf( "DSL: Permission denied." DSL_PIPE_CRLF);
|
|
break;
|
|
|
|
case ENOMEM:
|
|
printf( "DSL: Out of memory (i.e. kernel memory)." DSL_PIPE_CRLF);
|
|
break;
|
|
|
|
case ENAMETOOLONG:
|
|
printf( "DSL: File name too long." DSL_PIPE_CRLF);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
DSL_PIPE_Free(sempath);
|
|
return -1;
|
|
}
|
|
DSL_PIPE_Free(sempath);
|
|
}
|
|
|
|
if ( ((semid = semget(nsemkey, 1, 0666|IPC_CREAT|IPC_EXCL)) < 0) )
|
|
{
|
|
/* ERROR: check errno */
|
|
if (errno == EEXIST)
|
|
{
|
|
/* get without create */
|
|
if ( ((semid = semget(nsemkey, 1, 0666|IPC_EXCL)) < 0) )
|
|
{
|
|
printf( "DSL: create semaphore - semget(0x%X,0), errno=%d\n\r",
|
|
nsemkey, errno );
|
|
#ifndef DSL_DEBUG_DISABLE
|
|
print_sem_error(errno);
|
|
#endif
|
|
return -1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
#ifndef DSL_DEBUG_DISABLE
|
|
print_sem_error(errno);
|
|
#endif
|
|
return -1;
|
|
}
|
|
}
|
|
else
|
|
arg.val = 1;
|
|
|
|
if (arg.val == 1)
|
|
{
|
|
/* set the value of semaphore to 1 ie released or free to use */
|
|
if (semctl(semid, 0, SETVAL, arg) < 0 )
|
|
{
|
|
printf( "DSL: create semaphore - semctl(0x%X,0), errno=%d\n\r",
|
|
semid, errno );
|
|
#ifndef DSL_DEBUG_DISABLE
|
|
print_sem_error(errno);
|
|
#endif
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
return semid;
|
|
}
|
|
|
|
DSL_Error_t DSL_PIPE_SemaphoreGet(int sem, DSL_uint32_t nTimeout)
|
|
{
|
|
struct sigaction sa;
|
|
struct sembuf sb;
|
|
struct timespec timeout;
|
|
|
|
sb.sem_num = 0;
|
|
/* specifies the operation ie to get the semaphore */
|
|
sb.sem_op = -1;
|
|
sb.sem_flg = SEM_UNDO;
|
|
|
|
switch(nTimeout)
|
|
{
|
|
case 0xFFFFFFFF:
|
|
/* Blocking call */
|
|
break;
|
|
|
|
case 0:
|
|
/* Non Blocking */
|
|
sb.sem_flg |= IPC_NOWAIT;
|
|
break;
|
|
|
|
default:
|
|
/* Blocking call */
|
|
/* Initialize timer expiration value */
|
|
timeout.tv_sec = (nTimeout/1000);
|
|
timeout.tv_nsec = (nTimeout%1000) * 1000 * 1000;
|
|
|
|
sa.sa_flags = 0;
|
|
sa.sa_handler = DSL_PIPE_SemAlarm;
|
|
sigaction(SIGALRM, &sa, DSL_NULL);
|
|
alarm(timeout.tv_sec + 1);
|
|
|
|
break;
|
|
}
|
|
|
|
/* Acquire semaphore */
|
|
if (semop(sem, &sb, 1) == 0)
|
|
{
|
|
alarm(0);
|
|
return DSL_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
alarm(0);
|
|
if(errno == EINTR)
|
|
{
|
|
printf( "DSL: semaphore timeout." DSL_PIPE_CRLF);
|
|
return DSL_ERR_TIMEOUT;
|
|
}
|
|
else
|
|
{
|
|
#ifndef DSL_DEBUG_DISABLE
|
|
print_sem_error(errno);
|
|
#endif
|
|
printf( "DSL: get semaphore %x failed (errno=%d)" DSL_PIPE_CRLF, sem, errno);
|
|
return DSL_ERROR;
|
|
}
|
|
}
|
|
}
|
|
|
|
DSL_Error_t DSL_PIPE_SemaphoreSet(int sem)
|
|
{
|
|
struct sembuf sb;
|
|
|
|
sb.sem_num = 0;
|
|
/* specifies the operation ie to set the semaphore */
|
|
sb.sem_op = 1;
|
|
sb.sem_flg = SEM_UNDO;
|
|
|
|
if (semop(sem, &sb, 1) == 0)
|
|
{
|
|
return DSL_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
#ifndef DSL_DEBUG_DISABLE
|
|
print_sem_error(errno);
|
|
#endif
|
|
printf( "DSL: set semaphore %x failed (errno=%d)" DSL_PIPE_CRLF, sem, errno);
|
|
return DSL_ERROR;
|
|
}
|
|
}
|
|
|
|
/* 1 colon means there is a required parameter */
|
|
/* 2 colons means there is an optional parameter */
|
|
static const char GETOPT_LONG_OPTSTRING[] = "hve:";
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
char *pCommand = DSL_NULL;
|
|
int i, k=0, len=0, ret;
|
|
FILE *pipe_cmd, *pipe_ack;
|
|
DSL_int8_t instance = 0;
|
|
DSL_char_t nameBuf[64], *pChar;
|
|
|
|
i = 1;
|
|
pChar = argv[1];
|
|
if (pChar)
|
|
{
|
|
if (pChar[0] == '-')
|
|
{
|
|
switch(pChar[1])
|
|
{
|
|
case 'h':
|
|
printf(DSL_PIPE_CRLF);
|
|
printf("Client for the pipe interface of the \"DSL CPE API\"" DSL_PIPE_CRLF);
|
|
printf("\t%s [-hv] [pipe_no] cmd [params]" DSL_PIPE_CRLF, argv[0]);
|
|
printf(DSL_PIPE_CRLF);
|
|
printf("\t-h\tthis help" DSL_PIPE_CRLF);
|
|
printf("\tpipe_no\tpipe number (default 0)" DSL_PIPE_CRLF);
|
|
printf("\tcmd\tcommand to execute" DSL_PIPE_CRLF);
|
|
printf("\tparams\tparameters of the command" DSL_PIPE_CRLF);
|
|
printf(DSL_PIPE_CRLF);
|
|
return 0;
|
|
case 'v':
|
|
printf("\tdsl_pipe_client v0.0.2" DSL_PIPE_CRLF);
|
|
return 0;
|
|
}
|
|
}
|
|
else if (isdigit(pChar[0]))
|
|
{
|
|
if (argc >= 3)
|
|
{
|
|
instance = atoi(argv[1]);
|
|
if ((instance >= MAX_CLI_PIPES) || (instance < 0))
|
|
{
|
|
printf("\tpipe_no\toption requires parameter in range [0;%d]"
|
|
DSL_PIPE_CRLF, (MAX_CLI_PIPES - 1));
|
|
return -1;
|
|
}
|
|
i = 2;
|
|
}
|
|
}
|
|
|
|
k = i;
|
|
for(;i<argc;i++)
|
|
{
|
|
len += strlen(argv[i]) + 1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
len = 0;
|
|
}
|
|
|
|
|
|
if(len == 0)
|
|
{
|
|
pCommand = DSL_PIPE_Malloc(16);
|
|
|
|
if(pCommand == DSL_NULL)
|
|
{
|
|
printf( "Memory allocation failed" DSL_PIPE_CRLF);
|
|
return -1;
|
|
}
|
|
|
|
cpe_control_pipe_strncpy_s(pCommand, 16, "help all", sizeof("help all"));
|
|
}
|
|
else
|
|
{
|
|
pCommand = DSL_PIPE_Malloc(len + 1);
|
|
|
|
if(pCommand == DSL_NULL)
|
|
{
|
|
printf( "Memory allocation failed" DSL_PIPE_CRLF);
|
|
return -1;
|
|
}
|
|
|
|
pCommand[0] = 0;
|
|
for(i=k;i<argc;i++)
|
|
{
|
|
strcat(pCommand, argv[i]);
|
|
strcat(pCommand, " ");
|
|
}
|
|
}
|
|
|
|
sema = DSL_PIPE_SemaphoreGlobalCreate("dsl_pipe");
|
|
if (sema == -1)
|
|
{
|
|
printf( "dsl_pipe already running!" DSL_PIPE_CRLF);
|
|
/* semaphore not created */
|
|
DSL_PIPE_Free(pCommand);
|
|
return -1;
|
|
}
|
|
|
|
if (DSL_PIPE_SemaphoreGet(sema, 100) != DSL_SUCCESS)
|
|
{
|
|
printf( "dsl_pipe already running!" DSL_PIPE_CRLF);
|
|
printf( "Please delete /tmp/dsl_pipe to clean up "
|
|
"if dsl_pipe is not running anymore!" DSL_PIPE_CRLF);
|
|
DSL_PIPE_Free(pCommand);
|
|
return -1;
|
|
}
|
|
|
|
snprintf(nameBuf, sizeof(nameBuf), "%s%d_cmd", PIPE_PREFIX, instance);
|
|
|
|
pipe_cmd = DSL_PIPE_FOpen(nameBuf, "w");
|
|
if (pipe_cmd == DSL_NULL)
|
|
{
|
|
printf( "fopen %s failed (errno=%d)\r\n", nameBuf, errno);
|
|
goto error;
|
|
}
|
|
|
|
/* execute command */
|
|
DSL_PIPE_FPrintf(pipe_cmd, "%s\r\n", pCommand);
|
|
DSL_PIPE_FClose(pipe_cmd);
|
|
|
|
snprintf(nameBuf, sizeof(nameBuf), "%s%d_ack", PIPE_PREFIX, instance);
|
|
pipe_ack = DSL_PIPE_FOpen(nameBuf, "r");
|
|
|
|
if (pipe_ack == DSL_NULL)
|
|
{
|
|
printf( "fdopen %s failed (errno=%d)" DSL_PIPE_CRLF, nameBuf, errno);
|
|
goto error;
|
|
}
|
|
|
|
/* read answer */
|
|
do
|
|
{
|
|
ret = DSL_PIPE_FRead(Result,1,sizeof(Result)-1,pipe_ack);
|
|
if (ret>0)
|
|
{
|
|
Result[ret] = '\0';
|
|
printf( "%s", Result);
|
|
}
|
|
}
|
|
while ((ret > 0));
|
|
|
|
DSL_PIPE_FClose(pipe_ack);
|
|
|
|
DSL_PIPE_SemaphoreSet(sema);
|
|
|
|
printf( DSL_PIPE_CRLF );
|
|
|
|
DSL_PIPE_Free(pCommand);
|
|
|
|
return 0;
|
|
|
|
error:
|
|
DSL_PIPE_SemaphoreSet(sema);
|
|
|
|
printf( "There were errors!" DSL_PIPE_CRLF);
|
|
|
|
DSL_PIPE_Free(pCommand);
|
|
|
|
return -1;
|
|
}
|
|
|
|
#endif /* LINUX */
|
|
|