Example #1
0
int cmd_call(int argc, CmdArg* argv) {
    cmd_start();

    if (argc < 2) {
        puts("usage: call <address> <args>\n");
        puts("  <address> is subroutine address (pair=ARM, odd=THUMB)\n");
        puts("  <args> are subroutine arguments (integers), if any.\n");
        puts("  [!] limited to 4 args max subroutines at the moment.\n");
        return 0;
    } else if (argc > 6) {
        puts("[!] Sorry, call is limited to 4 args max subroutines ATM.\n");
        return -1;
    } else if (argv[1].type!=CMDARG_TYPE_INTEGER) {
        puts("[!] <address> needs to be an integer !\n");
        return -1;
    }

    int addr = argv[1].uinteger;
    int r0, r1, r2, r3;

    if (argc >= 3) r0 = cmd_get_arg(argv[2]);
    if (argc >= 4) r1 = cmd_get_arg(argv[3]);
    if (argc >= 5) r2 = cmd_get_arg(argv[4]);
    if (argc >= 6) r3 = cmd_get_arg(argv[5]);

    int (*pSub)(int, int, int, int) = (int (*)(int, int, int, int)) addr;
    int ret = pSub(r0, r1, r2, r3);

    printf("returned: %08x\n", ret);

    return 0;
}
Example #2
0
File: console.c Project: barmi/bxos
void cons_runcmd(char *cmdline, struct CONSOLE *cons, int *fat, int memtotal)
{
	if (strcmp(cmdline, "mem") == 0 && cons->sht != 0) {
		cmd_mem(cons, memtotal);
	} else if (strcmp(cmdline, "cls") == 0 && cons->sht != 0) {
		cmd_cls(cons);
	} else if (strcmp(cmdline, "dir") == 0 && cons->sht != 0) {
		cmd_dir(cons, cmdline);
	} else if (strcmp(cmdline, "task") == 0) {
		cmd_task();
	} else if (strcmp(cmdline, "exit") == 0) {
		cmd_exit(cons, fat);
	} else if (strncmp(cmdline, "start ", 6) == 0) {
		cmd_start(cons, cmdline, memtotal);
	} else if (strncmp(cmdline, "ncst ", 5) == 0) {
		cmd_ncst(cons, cmdline, memtotal);
	} else if (strncmp(cmdline, "langmode ", 9) == 0) {
		cmd_langmode(cons, cmdline);
	} else if (strncmp(cmdline, "taskmgr", 7) == 0) {
		open_taskmgr(memtotal);
	} else if (cmdline[0] != 0) {
		if (cmd_app(cons, fat, cmdline) == 0) {
			/* Ŀ�ǵ嵵 �ƴϰ�, ���ø����̼ǵ� �ƴϰ�, �� �൵ �ƴϴ� */
			cons_putstr0(cons, "Bad command or file name.\n\n");
		}
	}
	return;
}
Example #3
0
/*
** DBus method call: "RoomStart"
*/
gboolean on_handle_room_start(Warfacebot *object,
                              GDBusMethodInvocation *invocation)
{
    cmd_start();

    warfacebot_complete_room_start(object, invocation);

    return TRUE;
}
Example #4
0
int fbimg_cmd(int argc, CmdArg* argv) {
	cmd_start();
	if (argc < 2) {
		puts("usage: fbimg <address>\n");
		return 0;
	}

	fb_draw_image((unsigned int*)argv[1].uinteger, 0, 0, gFbTWidth, gFbTHeight);
}
Example #5
0
/**
 * Send Prepare Flash request
 *
 * @param ucMBaddr
 * @param ucBank
 * @return
 */
UCHAR cmd_prepareflash(UCHAR ucMBaddr, UCHAR ucBank)
{
    UCHAR    buf[8];
    cmdFrameHeader *pFrame = (cmdFrameHeader *)buf;
    DEBUG_PUTSTRING1("PREPARE_FLASH addr=", ucMBaddr);
    pFrame->mbAddr = ucMBaddr;
    pFrame->cmdId = MB_FUNC_BOOT_PREPAREFLASH;
    pFrame->subcmdId = ucBank;
    pFrame->status = 0;
    cmd_start();
    eMBSendFrame(buf, MB_FUNC_BOOT_PREPAREFLASH_SIZE + 1);
    return cmd_status_wait();
}
Example #6
0
int cmd_md(int argc, CmdArg* argv) {
    cmd_start();

    if(argc != 2) {
        puts("usage: md <address>\n");
        return 0;
    }

    unsigned int value = GETREG32(argv[1].uinteger);
    enter_critical_section();
    printf("%p\n", value);
    exit_critical_section();
    return value;
}
Example #7
0
int cmd_mw(int argc, CmdArg* argv) {
    cmd_start();

    if(argc != 3) {
        puts("usage: mw <address> <value>\n");
        return 0;
    }

    unsigned int address = argv[1].uinteger;
    unsigned int value = argv[2].uinteger;
    SETREG32(address, value);
    //clear_cpu_caches();
    return 0;
}
Example #8
0
int fb_cmd(int argc, CmdArg* argv) {
	cmd_start();
	int i = 0;
	if (argc < 2) {
		puts("usage: fbecho <message>\n");
		return 0;
	}

	//enter_critical_section();
	for (i = 1; i < argc; i++) {
		fb_print(argv[i].string);
		fb_print(" ");
	}
	//exit_critical_section();
	fb_print("\n");
	return 0;
}
Example #9
0
/**
 * @brief       read data through register port, one of the two 
    ports to transfer data. the other one is l2 port
 * @author      Yang Yiming
 * @date        2012-12-25
 * @param       [in]pBuf
 * @param       [in]nBufLen
 * @return      T_U32
 */
static T_U32 reg_read(T_U8 *pBuf, T_U8 nBufLen)
{
    T_U8 i;
    T_U32 nRet = 0;
    
    clear_interface_status();
    REG32(NFC_CMD_REG) = ((nBufLen - 1) << NFC_CMD_REG_INFO_POS) | NFC_CMD_REG_REG_IN_CONF | NFC_CMD_REG_LAST_BIT;
    cmd_start();

    if (AK_FALSE == cmd_end())
        return NAND_FAIL_NFC_TIMEOUT;
    
    for (i = 0; i < nBufLen; i++)
    {
        if (i < 4)
        {
            pBuf[i] = (T_U8)(0xFF & (REG32(NFC_DAT_REG1) >> (i << 3))) ;
            //akerror("Reg_\n",pBuf[i],1);
        }
        else
        {
Example #10
0
void cons_runcmd(char *cmdline, struct CONSOLE *cons, int *fat, int memtotal)
{
	if (strcmp(cmdline, "mem") == 0 && cons->sht != 0) {
		cmd_mem(cons, memtotal);
	} else if (strcmp(cmdline, "cls") == 0 && cons->sht != 0) {
		cmd_cls(cons);
	} else if (strcmp(cmdline, "dir") == 0 && cons->sht != 0) {
		cmd_dir(cons);
	} else if (strncmp(cmdline, "type ", 5) == 0 && cons->sht != 0) {
		cmd_type(cons, fat, cmdline);
	} else if (strcmp(cmdline, "exit") == 0) {
		cmd_exit(cons, fat);
	} else if (strncmp(cmdline, "start ", 6) == 0) {
		cmd_start(cons, cmdline, memtotal);
	} else if (strncmp(cmdline, "ncst ", 5) == 0) {
		cmd_ncst(cons, cmdline, memtotal);
	} else if (cmdline[0] != 0) {
		if (cmd_app(cons, fat, cmdline) == 0) {
			/* コマンドではなく、アプリでもなく、さらに空行でもない */
			cons_putstr0(cons, "Bad command.\n\n");
		}
	}
	return;
}
Example #11
0
int main (int argc, char *argv[]) {
    setpgrp();  // Become the leader of its group.
    // Child's CMD line
    int m = sysconf(_SC_ARG_MAX);           // Maximum CMD line length
    char *cmd;                              // Store child's CMD line
    cmd = (char *) calloc(m, sizeof(char));

    // Child's parameters
    int *child_delay = mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
    *child_delay = 0;                       // Delay before starting (shared between parent and child)
    int child_pid = -1;                     // PID after the fork()
    int child_status = -1;                  // Used during waitpid()
    char *child_file = NULL;                // Binary file

    // Telnet server
    int ts_port = -1;                       // TCP (console) and UDP (serial converter) port
    char *xtitle = "Terminal Server";       // Title for telnet clients

    // Select parameters
    int *infd = calloc(2, sizeof(int));     // Array of integers [0] is for reading, [1] is for writing
    int *outfd = calloc(2, sizeof(int));    // Array of integers [0] is for reading, [1] is for writing
    fd_set active_fd_set;                   // Contains active FD using in select()
    FD_ZERO(&active_fd_set);
    fd_set read_fd_set;                     // Contains FD selected in current loop
    FD_ZERO(&read_fd_set);

    // Other parameters
    int i = -1;                             // Counter
    int j = -1;                             // Counter
    int opt = NULL;                         // Store CMD options
    int rc = -1;                            // Generic return code
    char *tmp = NULL;                       // Generic char string
    struct sigaction sa;                    // Manage signals (SIGHUP, SIGTERM...)

    // Wrapper parameters
    int child_afsocket[100];                // Store AF_UNIX child sockets
    memset(&child_afsocket, 0, sizeof(child_afsocket));
    int ser_remoteid[64];                   // Store Remote Device ID (used for UDP communication)
    memset(&ser_remoteid, 0, sizeof(ser_remoteid));
    int ser_remoteif[64];                   // Store Remote Interface ID (used for UDP communication)
    memset(&ser_remoteif, 0, sizeof(ser_remoteif));
    int udpserver_socket = -1;              // UDP socket for serial communications
    int wrapper_afsocket[100];              // Store AF_UNIX wrapper sockets
    memset(&wrapper_afsocket, 0, sizeof(wrapper_afsocket));

    // Parsing options
    while ((opt = getopt(argc, argv, ":vT:D:d:t:F:x")) != -1) {
        switch (opt) {
            default:
                usage(argv[0]);
                exit(1);
            // Begin standard parameters
            case 'v':
                printf("%s\n", VERSION);
                exit(0);
            case 'T':
                // Mandatory: Tenant ID
                tenant_id = atoi(optarg);
                if (tenant_id < 0) {
                    UNLLog(LLERROR,"Tenant_id must be integer.\n");
                    exit(1);
                }
                UNLLog(LLINFO, "Tennant_id = %i\n", tenant_id);
                break;
            case 'D':
                // Mandatory: Device ID
                device_id = atoi(optarg);
                if (tenant_id < 0) {
                    UNLLog(LLERROR,"Device_id must be integer.\n");
                    exit(1);
                }
                UNLLog(LLINFO, "Device_id = %i\n", device_id);
                break;
            case 'F':
                // Mandatory: IOS
                child_file = optarg;
                if (is_file(child_file) != 0) {
                    UNLLog(LLERROR,"File '%s' does not exist.\n", child_file);
                    exit(1);
                }
                break;
            case 'd':
                // Optional: child's startup delay (default 0)
                *child_delay = atoi(optarg);
                if (*child_delay < 0) {
                    UNLLog(LLERROR,"Delay must be integer.\n");
                    exit(1);
                }
                break;
            case 't':
                // Optional: telnet window title (default "Terminal Server")
                xtitle = optarg;
                break;
        }
    }

    // Checking if tenant_id is set
    if (tenant_id < 0) {
        UNLLog(LLERROR,"Tenant ID not set.\n");
        exit(1);
    }

    // Checking if device_id is set
    if (device_id < 0) {
        UNLLog(LLERROR,"Device ID not set.\n");
        exit(1);
    }

    // Checking if child_file is set
    if (child_file == NULL) {
        UNLLog(LLERROR,"Subprocess executable not set.\n");
        exit(1);
    }

    // Building the CMD line
    ts_port = 32768 + 128 * tenant_id + device_id;
    tmp = (char *) malloc(m * sizeof(char));
    sprintf(tmp, "/usr/bin/dynamips -N '%s' -T %i", xtitle, ts_port);
    cmd_add(&cmd, tmp);
    free(tmp);

    // Adding parameters after "--"
    j = 0;
    for (i = 1; i < argc; i++) {
        if (j == 1) {
            // Adding parameter given after "--"
            cmd_add(&cmd, " ");
            cmd_add(&cmd, argv[i]);
        }
        if (strcmp(argv[i], "--") == 0) {
            // Found "--"
            j = 1;
        }
    }

    // Adding the IOS filename
    cmd_add(&cmd, " ");
    cmd_add(&cmd, child_file);

    // Creating PIPEs for select()
    if ((pipe(infd)) < 0 || pipe(outfd) < 0) {
         UNLLog(LLERROR, "Failed to create PIPEs (%s).\n", strerror(errno));
         exit(1);
    }

    // Forking
    if ((rc = fork()) == 0) {
        // Child: stating subprocess
        UNLLog(LLINFO, "Starting child (%s).\n", cmd);
        if (*child_delay > 0) {
            // Delay is set, waiting
            for (; *child_delay > 0;) {
                rc = write(outfd[1], ".", 1);
                *child_delay = *child_delay - 1;
                sleep(1);
            }
            rc = write(outfd[1], "\n", 1);
        }
        close(STDIN_FILENO);            // Closing child's stdin
        close(STDOUT_FILENO);           // Closing child's stdout
        dup2(infd[0], STDIN_FILENO);    // Linking stdin to PIPE
        dup2(outfd[1], STDOUT_FILENO);  // Linking stdout to PIPE
        dup2(outfd[1], STDERR_FILENO);  // Redirect child's stderr to child's stdout
        close(infd[0]);
        close(infd[1]);
        close(outfd[0]);
        close(outfd[1]);
        // Start process
        rc = cmd_start(cmd);
        // Subprocess terminated, killing the parent
        UNLLog(LLERROR,"Child terminated (%i).\n", rc);
    } else if (rc > 0) {
        // Parent
        close(infd[0]);                     // Used by the child
        close(outfd[1]);                    // Used by the child

        // Handling Signals
        signal(SIGPIPE,SIG_IGN);            // Ignoring SIGPIPE when a client terminates
        sa.sa_handler = &signal_handler;    // Setup the sighub handler
        sa.sa_flags = SA_RESTART;           // Restart the system call, if at all possible
        sigemptyset(&sa.sa_mask);           // Signals blocked during the execution of the handler
        sigaddset(&sa.sa_mask, SIGHUP);     // Signal 1
        sigaddset(&sa.sa_mask, SIGINT);     // Signal 2
        sigaddset(&sa.sa_mask, SIGTERM);    // Signal 15
        sigfillset(&sa.sa_mask);

        // Intercept SIGHUP, SIGINT, SIGUSR1 and SIGTERM
        if (sigaction(SIGHUP, &sa, NULL) == -1) {
            UNLLog(LLERROR, "Cannot handle SIGHUP (%s).\n", strerror(errno));
        }
        if (sigaction(SIGINT, &sa, NULL) == -1) {
            UNLLog(LLERROR, "Cannot handle SIGINT (%s).\n", strerror(errno));
        }
        if (sigaction(SIGTERM, &sa, NULL) == -1) {
            UNLLog(LLERROR, "Cannot handle SIGTERM (%s).\n", strerror(errno));
        }

        // Preparing select()
        FD_ZERO(&active_fd_set);
        FD_ZERO(&read_fd_set);
        if (udpserver_socket > 0) {
            FD_SET(udpserver_socket, &active_fd_set); // Adding UDP socket
        }

        // While subprocess is running, check IO from subprocess, telnet clients, socket and network
        waitpid(child_pid, &child_status, 0);
        // Child is no more running
        UNLLog(LLERROR, "Child is no more running.\n");
    } else {
        UNLLog(LLERROR, "Failed to fork (%s).\n", strerror(errno));
        exit(1);
    }
    exit(0);
}
Example #12
0
/**
 * @brief       issue nand cycles including command cycle, address cycle, RB cycle etc.
 * @author      Yang Yiming
 * @date        2012-12-25
 * @param       [in]nCmdSeq the cycle sequence
 * @return      T_BOOL
 */
T_BOOL nfc_cycle(T_U32 nCmdSeq,...)
{
    volatile T_U32 *pCmdReg = (T_U32 *)NFC_CMD_REG;
    T_VOID *pArg = (T_VOID *)&nCmdSeq;
    T_U32   nCycleVal;
    T_U16   nCycle;
    T_U8    nCycleType;
    T_BOOL  bArr = AK_FALSE;
    T_U8    nDataCnt = 0;
    T_U8    aWdata[10];
    
    clear_interface_status();

    //this block is added in purpose of saving device code text compiled.
    //course pushing every parameter in stack take more instruction than 
    //just pushing an array and a flag in.
    if (nCmdSeq == NAND_CYCLE_ARR_FLAG)
    {
        pArg = (T_VOID *)((T_U32)pArg + 4);
        pArg = (T_VOID *)(*(T_U32 *)pArg);
        bArr = AK_TRUE;
    }

    while (1)
    {
        nCycle = *(T_U16 *)pArg;
        
        if (AK_TRUE == bArr)
        {
            pArg = (T_VOID *)((T_U32)pArg + 2);
        }
        else
        {
            pArg = (T_VOID *)((T_U32)pArg + 4);
        }
        
        nCycleType = GET_NAND_CYCLY_TYPE(nCycle);
        nCycleVal = (nCycle & NAND_CYCLE_VALUE_MASK) << NFC_CMD_REG_INFO_POS;

        switch (nCycleType)
        {
            case COMMAND_C://command cycle
            {
                nCycleVal |= NFC_CMD_REG_CMD_CONF;
            }
            break;
            case ADDRESS_C://address cycle
            {
                nCycleVal |= NFC_CMD_REG_ADD_CONF;
            }
            break;
            case DELAY_C://delay several k asic. will it be used?
            {
                 nCycleVal |= NFC_CMD_REG_DELAY_BIT;
            }
            break;
            case WDATA_C://output data cycle
            {
                nCycleVal = (0 << NFC_CMD_REG_INFO_POS) | NFC_CMD_REG_WDATA_CONF;
                aWdata[nDataCnt] = nCycle & NAND_CYCLE_VALUE_MASK;//get the data value
                nDataCnt++;
            }
            break;
            case READYB_C://wait for the RB signal
            {
                nCycleVal = NFC_CMD_REG_WAIT_JUMP_BIT;
            }
            break;
            case NULL_C://do nothing
            {
                continue;
            }
            break;
            case END_C://ending flag , way to exit
            {
                pCmdReg[-1] |=  NFC_CMD_REG_LAST_BIT;
                
                if (nDataCnt > 0)//we use ecc sub module to deliver the data
                {
                    //config and enable the ECC sub-Module
                    REG32(ECC_CTRL_REG1) = ECC_CTRL_REG1_WRITE_BIT | ECC_CTRL_REG1_NFC_EN_BIT | ECC_CTRL_REG1_ADDR_CLR_BIT | ECC_CTRL_REG1_RESULT_NO_OK_BIT | ECC_CTRL_REG1_NO_ERR_BIT | ECC_CTRL_REG1_END_BIT;
                    REG32(ECC_CTRL_REG2) = (nDataCnt << ECC_CTRL_REG2_SECTSIZE_POS) | (1 << ECC_CTRL_REG2_SECTCNT_POS);
                    REG32(ECC_CTRL_REG3) = MMU_Vaddr2Paddr((T_U32)aWdata) & 0x3FFFF;
                    REG32(ECC_CTRL_REG1) = ECC_CTRL_REG1_WRITE_BIT | ECC_CTRL_REG1_NFC_EN_BIT | ECC_CTRL_REG1_ADDR_CLR_BIT | ECC_CTRL_REG1_RESULT_NO_OK_BIT | ECC_CTRL_REG1_NO_ERR_BIT | ECC_CTRL_REG1_END_BIT | ECC_CTRL_REG1_START_BIT;
                } 

                cmd_start();
                
                return cmd_end();
            }

        }
        
        *pCmdReg = nCycleVal;
        pCmdReg++;
    }

}
Example #13
0
void
child_deliver_cmd_hook(pid_t pid, struct account *a, unused struct msg *msg,
    struct child_deliver_data *data, int *result)
{
	struct mail_ctx			*mctx = data->mctx;
	struct mail			*m = data->mail;
	struct match_command_data	*cmddata = data->cmddata;
	int				 flags, status, found = 0;
	char				*s, *cause, *lbuf, *out, *err, tag[24];
	size_t				 llen;
	struct cmd		 	*cmd = NULL;
	struct rmlist			 rml;
	u_int				 i;

	/* If this is the parent, do nothing. */
	if (pid != 0) {
		xfree(mctx);
		return;
	}

	/* Sort out the command. */
	s = replacepath(
	    &cmddata->cmd, m->tags, m, &m->rml, find_tag(m->tags, "home"));
        if (s == NULL || *s == '\0') {
		log_warnx("%s: empty command", a->name);
		goto error;
        }

	log_debug2("%s: %s: started (ret=%d re=%s)", a->name, s, cmddata->ret,
	    cmddata->re.str == NULL ? "none" : cmddata->re.str);
	flags = CMD_ONCE;
	if (cmddata->pipe)
		flags |= CMD_IN;
	if (cmddata->re.str != NULL)
		flags |= CMD_OUT;
	cmd = cmd_start(s, flags, m->data, m->size, &cause);
	if (cmd == NULL) {
		log_warnx("%s: %s: %s", a->name, s, cause);
		goto error;
	}

	llen = IO_LINESIZE;
	lbuf = xmalloc(llen);

	for (;;) {
		/* Stop early if looking for regexp only. */
		if (found && cmddata->ret == -1) {
			log_debug3("%s: %s: found. stopping early", a->name, s);
			status = 1;
			break;
		}

		status = cmd_poll(
		    cmd, &out, &err, &lbuf, &llen, conf.timeout, &cause);
		if (status == -1) {
			log_warnx("%s: %s: %s", a->name, s, cause);
			goto error;
		}
       		if (status != 0)
			break;
		if (err != NULL)
			log_warnx("%s: %s: %s", a->name, s, err);
		if (out == NULL)
			continue;
		log_debug3("%s: %s: out: %s", a->name, s, out);
		if (found)
			continue;

		found = re_string(&cmddata->re, out, &rml, &cause);
		if (found == -1) {
			log_warnx("%s: %s", a->name, cause);
			goto error;
		}
		if (found != 1)
			continue;
		/* Save the matches. */
		if (!rml.valid)
			continue;
		for (i = 0; i < NPMATCH; i++) {
			if (!rml.list[i].valid)
				break;
			xsnprintf(tag, sizeof tag, "command%u", i);
			add_tag(&m->tags, tag, "%.*s", (int) (rml.list[i].eo -
			    rml.list[i].so), out + rml.list[i].so);
		}
	}
	status--;

	log_debug2("%s: %s: returned %d, found %d", a->name, s, status, found);

	cmd_free(cmd);
	xfree(s);
	xfree(lbuf);

	status = cmddata->ret == status;
	if (cmddata->ret != -1 && cmddata->re.str != NULL)
		*result = (found && status) ? MATCH_TRUE : MATCH_FALSE;
	else if (cmddata->ret != -1 && cmddata->re.str == NULL)
		*result = status ? MATCH_TRUE : MATCH_FALSE;
	else if (cmddata->ret == -1 && cmddata->re.str != NULL)
		*result = found ? MATCH_TRUE : MATCH_FALSE;
	else
		*result = MATCH_ERROR;
	return;

error:
	if (cause != NULL)
		xfree(cause);
	if (cmd != NULL)
		cmd_free(cmd);
	if (s != NULL)
		xfree(s);
	if (lbuf != NULL)
		xfree(lbuf);
	*result = MATCH_ERROR;
}
Example #14
0
int main (int argc, char *argv[]) {
    // Child's CMD line
    int m = sysconf(_SC_ARG_MAX);           // Maximum CMD line length
    char *cmd;                              // Store child's CMD line
    cmd = (char *) calloc(m, sizeof(char));

    // Child's parameters
    int *child_delay = mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
    *child_delay = 0;                       // Delay before starting (shared between parent and child)
    int child_pid = -1;                     // PID after the fork()
    int child_status = -1;                  // Used during waitpid()
    char *child_file = NULL;                // Binary file

    // Telnet server
    int ts_port = -1;                       // TCP (console) and UDP (serial converter) port
    int ts_socket = -1;                     // Telnet server socket
    char child_output = '\0';               // Store single char from child
    char client_input = '\0';               // Store single char from client
    char *xtitle = "Terminal Server";       // Title for telnet clients

    // Select parameters
    int *infd = calloc(2, sizeof(int));     // Array of integers [0] is for reading, [1] is for writing
    int *outfd = calloc(2, sizeof(int));    // Array of integers [0] is for reading, [1] is for writing
    int active_fd = -1;                     // Contains current active FD
    fd_set active_fd_set;                   // Contains active FD using in select()
    FD_ZERO(&active_fd_set);
    fd_set read_fd_set;                     // Contains FD selected in current loop
    FD_ZERO(&read_fd_set);

    // Wrapper parameters
    int child_afsocket = -1;                // Store AF_UNIX child socket
    int *eth_socket = calloc(64, sizeof(int));  // Store FD of ethernet intefaces
    int *ser_remoteid = calloc(64, sizeof(int));// Store Remote Device ID (used for UDP communication)
    int *ser_remoteif = calloc(64, sizeof(int));// Store Remote Interface ID (used for UDP communication)
    int *ser_socket = calloc(64, sizeof(int));  // Store FD of serial intefaces
    int udpserver_socket = -1;              // UDP socket for serial communications
    int wrapper_afsocket = -1;              // Store AF_UNIX wrapper socket

    // Other parameters
    int af_ready = 0;                       // 1 = AF_UNIX files are configured (needed if IOL is delayed)
    int i = -1;                             // Counter
    int j = -1;                             // Counter
    int opt = NULL;                         // Store CMD options
    int rc = -1;                            // Generic return code
    char *tmp = NULL;                       // Generic char string
    struct sigaction sa;                    // Manage signals (SIGHUP, SIGTERM...)

    setpgrp();

    // Check for iourc file
    tmp = (char *) malloc(m * sizeof(char));
    sprintf(tmp, "iourc");
    if (is_file(tmp) != 0) {
        printf("ERR: file '%s' does not exist.\n", tmp);
        exit(1);
    }
    free(tmp);

    // Adding options to child's CMD line
    while ((opt = getopt(argc, argv, ":vT:D:d:t:F:e:s:l:")) != -1) {
        switch (opt) {
            default:
                usage(argv[0]);
                exit(1);
            // Begin standard parameters
            case 'v':
                version();
                exit(0);
            case 'T':
                // Mandatory: Tenant ID
                tenant_id = atoi(optarg);
                if (tenant_id < 0) {
                    printf("ERR: tenant_id must be integer.\n");
                    exit(1);
                }
                break;
            case 'D':
                // Mandatory: Device ID
                device_id = atoi(optarg);
                if (tenant_id < 0) {
                    printf("ERR: device_id must be integer.\n");
                    exit(1);
                }
                break;
            case 'F':
                child_file = optarg;
                if (is_file(child_file) != 0) {
                    printf("ERR: file '%s' does not exist.\n", child_file);
                    exit(1);
                }
                break;
            case 'd':
                // Optional: child's startup delay (default 0)
                *child_delay = atoi(optarg);
                if (*child_delay < 0) {
                    printf("ERR: delay must be integer.\n");
                    exit(1);
                }
                break;
            case 't':
                // Optional: telnet window title (default "Terminal Server")
                xtitle = optarg;
                break;
            // End standard parameters
            // Optional: number of Ethernet progroups (default: 2)
            case 'e':
                child_eth = atoi(optarg);
                if (child_eth < 0) {
                    printf("ERR: Ethernet portgroup must be integer.\n");
                    exit(1);
                }
                break;
            // Optional: number of Serial progroups (default: 2)
            case 's':
                child_ser = atoi(optarg);
                if (child_ser < 0) {
                    printf("ERR: Serial portgroup must be numeric.\n");
                    exit(1);
                }
                break;
            // Optional: Serial link end-point (no default)
            case 'l':
                if (udpserver_socket == -1 && tenant_id != -1 && device_id != -1) {
                    // First Serial2UDP definition, must listen()
                    if ((rc = serial2udp_listen(32768 + 128 * tenant_id + device_id, &udpserver_socket)) != 0) {
                        printf("%u:%u ERR: failed to open UDP socket (%i).\n", tenant_id, device_id, rc);
                        exit(1);
                    }
                    // Now add serial end-point
                    if ((rc = serial2udp_add(ser_socket, ser_remoteid, ser_remoteif, optarg)) != 0) {
                        printf("%u:%u ERR: failed to add serial end-point (%i).\n", tenant_id, device_id, rc);
                        exit(1);
                    }
                } else if (udpserver_socket > 0) {
                    // Serial2UDP wrapper already started, add serial end-point
                    if ((rc = serial2udp_add(ser_socket, ser_remoteid, ser_remoteif, optarg)) != 0) {
                        printf("%u:%u ERR: failed to add serial end-point (%i).\n", tenant_id, device_id, rc);
                        exit(1);
                    }
                } else {
                    printf("ERR: flag '-l' must be after '-T' and '-D'.\n");
                    exit(1);
                }
                break;
        }
    }

    // Checking if tenant_id is set
    if (tenant_id < 0) {
        printf("ERR: tenant ID not set.\n");
        exit(1);
    }

    // Checking if device_id is set
    if (device_id < 0) {
        printf("ERR: device ID not set.\n");
        exit(1);
    }

    // Checking if child_file is set
    if (child_file == NULL) {
        printf("%u:%u ERR: subprocess executable not set.\n", tenant_id, device_id);
        exit(1);
    }

    // Checking total interfaces
    if (child_eth + child_ser > 16) {
        printf("%u:%u ERR: Ethernet + Serial portgroups must lower equal than 16.\n", tenant_id, device_id);
        exit(1);
    }

    // Building the CMD line
    cmd_add(&cmd, "LD_LIBRARY_PATH=/opt/unetlab/addons/iol/lib ");
    cmd_add(&cmd, child_file);

    // Adding interfaces
    tmp = (char *) malloc(m * sizeof(char));
    sprintf(tmp, " -e %i -s %i", child_eth, child_ser);
    cmd_add(&cmd, tmp);
    free(tmp);

    // Adding parameters after "--"
    j = 0;
    for (i = 1; i < argc; i++) {
        if (j == 1) {
            // Adding parameter given after "--"
            cmd_add(&cmd, " ");
            cmd_add(&cmd, argv[i]);
        }
        if (strcmp(argv[i], "--") == 0) {
            // Found "--"
            j = 1;
        }
    }

    // Adding device_id as last
    tmp = (char *) malloc(m * sizeof(char));
    sprintf(tmp, "%i", device_id);
    cmd_add(&cmd, " ");
    cmd_add(&cmd, tmp);
    free(tmp);

    // Creating NETMAP
    if ((rc = mk_netmap()) != 0) {
        printf("%u:%u ERR: failed to create NETMAP file (%i).\n", tenant_id, device_id, rc);
        exit(1);
    }

    // Creating PIPEs for select()
    if ((pipe(infd)) < 0 || pipe(outfd) < 0) {
         printf("%u:%u ERR: failed to create PIPEs (%s).\n", tenant_id, device_id, strerror(errno));
         exit(1);
    }

    // Telnet listen
    ts_port = 32768 + 128 * tenant_id + device_id;
    tsclients_socket[0] = 0;
    if ((rc = ts_listen(ts_port, &ts_socket)) != 0) {
        printf("%u:%u ERR: failed to open TCP socket (%i).\n", tenant_id, device_id, rc);
        exit(1);
    }

    // Creating TAP interfaces
    if ((rc = mk_tap(child_eth, eth_socket)) != 0) {
        printf("%u:%u ERR: failed to create TAP interfaces (%i).\n", tenant_id, device_id, rc);
        kill(0, SIGTERM);
        exit(1);
    }

    // Forking
    if ((rc = fork()) == 0) {
        // Child: starting subprocess
        if (DEBUG > 0) printf("DEBUG: starting child (%s).\n", cmd);
        if (*child_delay > 0) {
            // Delay is set, waiting
            for (; *child_delay > 0;) {
                rc = write(outfd[1], ".", 1);
                *child_delay = *child_delay - 1;
                sleep(1);
            }
            rc = write(outfd[1], "\n", 1);
        }
        close(STDIN_FILENO);            // Closing child's stdin
        close(STDOUT_FILENO);           // Closing child's stdout
        dup2(infd[0], STDIN_FILENO);    // Linking stdin to PIPE
        dup2(outfd[1], STDOUT_FILENO);  // Linking stdout to PIPE
        dup2(outfd[1], STDERR_FILENO);  // Redirect child's stderr to child's stdout
        close(infd[0]);
        close(infd[1]);
        close(outfd[0]);
        close(outfd[1]);
        // Start process
        rc = cmd_start(cmd);
        // Subprocess terminated, killing the parent
        printf("%u:%u ERR: child terminated (%i).\n", tenant_id, device_id, rc);
    } else if (rc > 0) {
        // Parent
        close(infd[0]);                     // Used by the child
        close(outfd[1]);                    // Used by the child

        // Handling Signals
        signal(SIGPIPE,SIG_IGN);            // Ignoring SIGPIPE when a client terminates
        sa.sa_handler = &signal_handler;    // Setup the sighub handler
        sa.sa_flags = SA_RESTART;           // Restart the system call, if at all possible
        sigemptyset(&sa.sa_mask);           // Signals blocked during the execution of the handler
        sigaddset(&sa.sa_mask, SIGHUP);     // Signal 1
        sigaddset(&sa.sa_mask, SIGINT);     // Signal 2
        sigaddset(&sa.sa_mask, SIGTERM);    // Signal 15
        sigfillset(&sa.sa_mask);

        // Intercept SIGHUP, SIGINT, SIGUSR1 and SIGTERM
        if (sigaction(SIGHUP, &sa, NULL) == -1) {
            printf("%u:%u ERR: cannot handle SIGHUP (%s).\n", tenant_id, device_id, strerror(errno));
        }
        if (sigaction(SIGINT, &sa, NULL) == -1) {
            printf("%u:%u ERR: cannot handle SIGINT (%s).\n", tenant_id, device_id, strerror(errno));
        }
        if (sigaction(SIGTERM, &sa, NULL) == -1) {
            printf("%u:%u ERR: cannot handle SIGTERM (%s).\n", tenant_id, device_id, strerror(errno));
        }

        // Preparing select()
        FD_ZERO(&active_fd_set);
        FD_ZERO(&read_fd_set);
        if (DEBUG > 0) printf("DEBUG: adding subprocess stdout descriptor (%i).\n", outfd[0]);
        FD_SET(outfd[0], &active_fd_set);         // Adding subprocess stdout
        if (DEBUG > 0) printf("DEBUG: adding telnet socket descriptor (%i).\n", ts_socket);
        FD_SET(ts_socket, &active_fd_set);        // Adding telnet socket
        if (udpserver_socket > 0) {
            if (DEBUG > 0) printf("DEBUG: adding UDP socket descriptor (%i).\n", udpserver_socket);
            FD_SET(udpserver_socket, &active_fd_set); // Adding UDP socket
        }

        // Adding TAP interfaces for select()
        for (i = 0; i <= 63; i++) {
            if (eth_socket[i] > 0) {
                if (DEBUG > 0) printf("DEBUG: adding TAP interface descriptor (%i).\n", eth_socket[i]);
                FD_SET(eth_socket[i], &active_fd_set);
            }
        }

        // While subprocess is running, check IO from subprocess, telnet clients, socket and network
        while (waitpid(child_pid, &child_status, WNOHANG|WUNTRACED) == 0) {
            // Creating AF communication from child
            if (af_ready == 0 && *child_delay == 0) {
                // wait 3 seconds for AF_UNIX
                sleep(3);
                if ((rc = mk_afsocket(&wrapper_afsocket, &child_afsocket)) != 0) {;
                    printf("%u:%u ERR: failed to create AF_UNIX socket file (%i).\n", tenant_id, device_id, rc);
                    kill(0, SIGTERM);
                    break;
                }
                af_ready = 1;
                if (DEBUG > 0) printf("DEBUG: adding wrapper socket descriptor (%i).\n", wrapper_afsocket);
                FD_SET(wrapper_afsocket, &active_fd_set);   // Adding subprocess AF_UNIX socket
            }

            // Check if select() is valid
            read_fd_set = active_fd_set;
            if ((active_fd = select(FD_SETSIZE, &read_fd_set, NULL, NULL, NULL)) <= 0) {
                printf("%u:%u ERR: failed to select().\n", tenant_id, device_id);
                kill(0, SIGTERM);
                break;
            }
            if (DEBUG > 2) printf("DEBUG: data from select descriptor (%i).\n", active_fd);

            // Check if output from child
            if (FD_ISSET(outfd[0], &read_fd_set)) {
                if (read(outfd[0], &child_output, 1) <= 0) {
                    printf("%u:%u ERR: error while reading data from the subprocess, killing it.\n", tenant_id, device_id);
                    kill(0, SIGTERM);
                    break;
                }
                // Writing to all telnet clients
                ts_broadcast(child_output, &active_fd_set, tsclients_socket);
            }

            // Check if new client is coming
            if (FD_ISSET(ts_socket, &read_fd_set)) {
                if ((rc = ts_accept(&active_fd_set, ts_socket, xtitle, tsclients_socket,1)) != 0) {
                    printf("%u:%u ERR: failed to accept a new client (%i).\n", tenant_id, device_id, rc);
                }
            }

            // Check for output from all telnet clients
            if (ts_receive(&client_input, &read_fd_set, &active_fd_set, tsclients_socket) == 0) {
                // Write to child
                rc = write(infd[1], &client_input, 1);
                if (rc < 0) {
                    printf("%u:%u ERR: error writing to the subprocess, closing.\n", tenant_id, device_id);
                    kill(0, SIGTERM);
                    break;
                }
            }

            // If AF, UDP and TAP sockets are configured, check for packets
            if (af_ready == 1) {
                // Check for packets from subprocess
                if (FD_ISSET(wrapper_afsocket, &read_fd_set)) {
                    if ((rc = packet_af(wrapper_afsocket, eth_socket, ser_socket, ser_remoteid, ser_remoteif)) != 0) {
                        printf("%u:%u ERR: error forwarding packet from AF_UNIX socket to TAP/UDP (%i).\n", tenant_id, device_id, rc);
                        kill(0, SIGTERM);
                        break;
                    }
                }

                // Check for packets from TAP interfaces
                for (i = 0; i <= 63; i++) {
                    if (eth_socket[i] > 0 && FD_ISSET(eth_socket[i], &read_fd_set)) {
                        if ((rc = packet_tap(eth_socket[i], child_afsocket, i)) != 0) {
                            if (rc == 3) {
                              af_ready = 0;
                              printf("Failed to forward TAP => AF_UNIX. Will try to recreate it later...\n");
                            } else {
                              printf("%u:%u ERR: error forwarding packet from TAP to AF_UNIX socket (%i).\n", tenant_id, device_id, rc);
                              kill(0, SIGTERM);
                              break;
                            }
                        }
                    }
                }

                // Check for incoming serial (UDP) packets
                if (udpserver_socket > 0) {
                    if (FD_ISSET(udpserver_socket, &read_fd_set)) {
                        if ((rc = packet_udp(udpserver_socket, child_afsocket)) != 0) {
                            if (rc == 3) {
                                af_ready = 0;
                                printf("Failed to forward UDP => AF_UNIX. Will try to recreate it later...\n");
                            } else {
                                printf("%u:%u ERR: error forwarding packet from UDP to AF_UNIX (%i).\n", tenant_id, device_id, rc);
                                kill(0, SIGTERM);
                                break;
                            }
                        }
                    }
                }
            }

            // We should not have other active dscriptor
        }

        // Child is no more running
        printf("%u:%u ERR: child is no more running.\n", tenant_id, device_id);
    } else {
        printf("%u:%u ERR: failed to fork.\n", tenant_id, device_id);
        exit(1);
    }
    close(ts_socket);
    close(wrapper_afsocket);
    exit(0);
}
Example #15
0
void cmd_start_wrapper(void)
{
    cmd_start();
}
Example #16
0
int
deliver_pipe_deliver(struct deliver_ctx *dctx, struct actitem *ti)
{
	struct account			*a = dctx->account;
	struct mail			*m = dctx->mail;
	struct deliver_pipe_data	*data = ti->data;
	char				*s, *cause, *err;
	int				 status;
	struct cmd			*cmd = NULL;
	char				*lbuf;
	size_t				 llen;

	s = replacepath(&data->cmd, m->tags, m, &m->rml, dctx->udata->home);
	if (s == NULL || *s == '\0') {
		log_warnx("%s: empty command", a->name);
		goto error;
	}

	if (data->pipe) {
		log_debug2("%s: piping to \"%s\"", a->name, s);
		cmd = cmd_start(s, CMD_IN|CMD_ONCE, m->data, m->size, &cause);
	} else {
		log_debug2("%s: executing \"%s\"", a->name, s);
		cmd = cmd_start(s, 0, NULL, 0, &cause);
	}
	if (cmd == NULL)
		goto error_cause;
	log_debug3("%s: %s: started", a->name, s);

	llen = IO_LINESIZE;
	lbuf = xmalloc(llen);

	do {
		status = cmd_poll(
		    cmd, NULL, &err, &lbuf, &llen, conf.timeout, &cause);
		if (status == -1) {
			xfree(lbuf);
			goto error_cause;
		}
		if (status == 0 && err != NULL)
			log_warnx("%s: %s: %s", a->name, s, err);
	} while (status == 0);
	status--;

	xfree(lbuf);

	if (status != 0) {
		log_warnx("%s: %s: command returned %d", a->name, s, status);
		goto error;
	}

	cmd_free(cmd);
	xfree(s);
	return (DELIVER_SUCCESS);

error_cause:
	log_warnx("%s: %s: %s", a->name, s, cause);
	xfree(cause);

error:
	if (cmd != NULL)
		cmd_free(cmd);
	if (s != NULL)
		xfree(s);
	return (DELIVER_FAILURE);
}
Example #17
0
int main (int argc, char *argv[]) {
    setpgrp();  // Become the leader of its group.
    // Child's CMD line
    int m = sysconf(_SC_ARG_MAX);           // Maximum CMD line length
    char *cmd;                              // Store child's CMD line
    cmd = (char *) calloc(m, sizeof(char));

    // Child's parameters
    char *child_file = NULL;                // Binary file
    int child_pid = -1;                     // PID after the fork()
    int child_status = -1;                  // Used during waitpid()

    // Telnet server
    int ts_socket = -1;                     // Telnet server socket
    int ts_port = -1;                       // TCP (console) and UDP (serial converter) port
    char child_output = '\0';               // Store single char from child
    unsigned char client_input = '\0';		// Store single char from client
    char *xtitle = "Terminal Server";       // Title for telnet clients

    // Select parameters
    int *infd = calloc(2, sizeof(int));     // Array of integers [0] is for reading, [1] is for writing
    int *outfd = calloc(2, sizeof(int));    // Array of integers [0] is for reading, [1] is for writing
    fd_set active_fd_set;                   // Contains active FD using in select()
    FD_ZERO(&active_fd_set);
    fd_set read_fd_set;                     // Contains FD selected in current loop
    FD_ZERO(&read_fd_set);

    // Other parameters
    int i = -1;                             // Counter
    int j = -1;                             // Counter
    int opt = NULL;                         // Store CMD options
    int rc = -1;                            // Generic return code
    struct sigaction sa;                    // Manage signals (SIGHUP, SIGTERM...)

    // Parsing options
    while ((opt = getopt(argc, argv, ":vT:D:t:F:")) != -1) {
        switch (opt) {
            default:
                usage(argv[0]);
                exit(1);
            // Begin standard parameters
            case 'v':
                printf("%s\n", VERSION);
                exit(0);
            case 'T':
                // Mandatory: Tenant ID
                tenant_id = atoi(optarg);
                if (tenant_id < 0) {
                    UNLLog(LLERROR,"Tenant_id must be integer.\n");
                    exit(1);
                }
                UNLLog(LLINFO, "Tennant_id = %i\n", tenant_id);
                break;
            case 'D':
                // Mandatory: Device ID
                device_id = atoi(optarg);
                if (device_id < 0) {
                    UNLLog(LLERROR,"Device_id must be integer.\n");
                    exit(1);
                }
                UNLLog(LLINFO, "Device_id = %i\n", device_id);
                break;
            case 'F':
                // Mandatory: subprocess executable
                child_file = optarg;
                if (is_file(child_file) != 0) {
                    UNLLog(LLERROR,"File '%s' does not exist.\n", child_file);
                    exit(1);
                }
                break;
            case 't':
                // Optional: telnet window title (default "Terminal Server")
                xtitle = optarg;
                break;
        }
    }

    // Checking if tenant_id is set
    if (tenant_id < 0) {
        UNLLog(LLERROR, "Tenant ID not set.\n");
        exit(1);
    }

    // Checking if device_id is set
    if (device_id < 0) {
        UNLLog(LLERROR, "Device ID not set.\n");
        exit(1);
    }

    // Checking if child_file is set
    if (child_file == NULL) {
        UNLLog(LLERROR, "Subprocess executable not set.\n");
        exit(1);
    }

    // Building the CMD line
    cmd_add(&cmd, child_file);

    // Adding parameters after "--"
    j = 0;
    for (i = 1; i < argc; i++) {
        if (j == 1) {
            // Adding parameter given after "--"
            cmd_add(&cmd, " ");
            cmd_add(&cmd, argv[i]);
        }
        if (strcmp(argv[i], "--") == 0) {
            // Found "--"
            j = 1;
        }
    }

    // Creating PIPEs for select()
    if ((pipe(infd)) < 0 || pipe(outfd) < 0) {
         UNLLog(LLERROR, "Failed to create PIPEs (%s).\n", strerror(errno));
         exit(1);
    }

    // Telnet listen
	ts_port = 32768 + 128 * tenant_id + device_id;
	tsclients_socket[0] = 0;
	if ((rc = ts_listen(ts_port, &ts_socket)) != 0) {
		UNLLog(LLERROR, "Failed to open TCP socket (%i).\n", rc);
		exit(1);
	}

    // Forking
    if ((rc = fork()) == 0) {
        // Child: stating subprocess
        UNLLog(LLINFO, "Starting child (%s).\n", cmd);
        close(STDIN_FILENO);            // Closing child's stdin
        close(STDOUT_FILENO);           // Closing child's stdout
        dup2(infd[0], STDIN_FILENO);    // Linking stdin to PIPE
        dup2(outfd[1], STDOUT_FILENO);  // Linking stdout to PIPE
        dup2(outfd[1], STDERR_FILENO);  // Redirect child's stderr to child's stdout
        close(infd[0]);
        close(infd[1]);
        close(outfd[0]);
        close(outfd[1]);
        // Start process
		while (rc == -1 || rc == 0) {
			// Start console until it fail
			rc = cmd_start(cmd);
		}
        // Subprocess terminated, killing the parent
        UNLLog(LLERROR, "Child terminated (%i).\n", rc);
    } else if (rc > 0) {
        // Parent
        close(infd[0]);     // Used by the child
        close(outfd[1]);    // Used by the child

        // Handling Signals
        signal(SIGPIPE,SIG_IGN);            // Ignoring SIGPIPE when a client terminates
        sa.sa_handler = &signal_handler;    // Setup the sighub handler
        sa.sa_flags = SA_RESTART;           // Restart the system call, if at all possible
        sigemptyset(&sa.sa_mask);           // Signals blocked during the execution of the handler
        sigaddset(&sa.sa_mask, SIGHUP);     // Signal 1
        sigaddset(&sa.sa_mask, SIGINT);     // Signal 2
        sigaddset(&sa.sa_mask, SIGTERM);    // Signal 15
        sigfillset(&sa.sa_mask);

        // Intercept SIGHUP, SIGINT, SIGUSR1 and SIGTERM
        if (sigaction(SIGHUP, &sa, NULL) == -1) {
            UNLLog(LLERROR, "Cannot handle SIGHUP (%s).\n", strerror(errno));
        }
        if (sigaction(SIGINT, &sa, NULL) == -1) {
            UNLLog(LLERROR, "Cannot handle SIGINT (%s).\n", strerror(errno));
        }
        if (sigaction(SIGTERM, &sa, NULL) == -1) {
            UNLLog(LLERROR, "Cannot handle SIGTERM (%s).\n", strerror(errno));
        }

        // Preparing select()
		FD_ZERO(&active_fd_set);
		FD_ZERO(&read_fd_set);
		FD_SET(outfd[0], &active_fd_set);         // Adding subprocess stdout
		FD_SET(ts_socket, &active_fd_set);        // Adding telnet socket

		// While subprocess is running, check IO from subprocess, telnet clients, socket and network
		while (waitpid(child_pid, &child_status, WNOHANG|WUNTRACED) == 0) {
			// Check if select() is valid
			read_fd_set = active_fd_set;
			if (select(FD_SETSIZE, &read_fd_set, NULL, NULL, NULL) <= 0) {
				UNLLog(LLERROR, "Failed to select().\n");
				kill(0, SIGTERM);
				break;
			}

			// Check if output from child
			if (FD_ISSET(outfd[0], &read_fd_set)) {
				if (read(outfd[0], &child_output, 1) <= 0) {
					UNLLog(LLERROR, "Error while reading data from the subprocess, killing it.\n");
					kill(0, SIGTERM);
					break;
				}
				// Writing to all telnet clients
				ts_broadcast(child_output, &active_fd_set, tsclients_socket);
			}

			// Check if new client is coming
			if (FD_ISSET(ts_socket, &read_fd_set)) {
				if ((rc = ts_accept(&active_fd_set, ts_socket, xtitle, tsclients_socket,1)) != 0) {
					UNLLog(LLERROR, "Failed to accept a new client (%i).\n", rc);
				}
			}

			// Check for output from all telnet clients
			if (ts_receive(&client_input, &read_fd_set, &active_fd_set, tsclients_socket) == 0) {
				// Write to child
				rc = write(infd[1], &client_input, 1);
				if (rc < 0) {
					UNLLog(LLERROR, "Error writing to the subprocess, closing.\n");
					kill(0, SIGTERM);
					break;
				}
			}
		}
    } else {
        UNLLog(LLERROR, "Failed to fork.\n" );
        exit(1);
    }
    close(ts_socket);
    exit(0);
}