/******************************************************************************* * * remShellTelnetDisconn - disconnect shell from telnet * * This routine is called from the telnetInTask either as a result of the * connection terminating from the remote host, or as a result of the logout() * command issued to our shell. It is therefore always run in the context of * the telnetInTask. * * The shell standard I/O is redirected back to the console, and the shell is * restarted. * * RETURNS: N/A */ void remShellTelnetDisconn ( int disconnArg ) { shellLogoutInstall ((FUNCPTR) NULL, 0); /* uninstall logout function */ if (logFdFromRlogin != NONE) { logFdDelete (logFdFromRlogin); /* cancel extra log device */ logFdFromRlogin = NONE; /* reset fd */ } #if VX_VERSION == 55 || VX_VERSION == 542 shellOrigStdSet (STD_IN, shellInFd); /* restore shell's stnd I/O */ shellOrigStdSet (STD_OUT, shellOutFd); shellOrigStdSet (STD_ERR, shellErrFd); #endif shellLock (FALSE); /* unlock shell */ /* For typical remote sessions, there is no need to restart the shell. * If we are in shell context, simply restoring the standard I/O * descriptors is enough to get the shell back on track upon return * from this function. If we are in telnetInTask context, the closing * of the pty device will cause the shell to unblock from its read() * and do subsequent I/O from the restored descriptors. * However, problems can occur upon logout if the remote user has * disabled the line editor and/or put the pty device in raw mode. * The problem caused is that the shell does not resume properly. * It is therefore deemed prudent to always restart the shell, thereby * avoiding any funny business. * * The previous version attempted to send a ctrl-D up the pty device * to wakeup and restart the shell. Unfortunately, ctrl-D only has * special meaning when the device is in line mode, and hence did * not work in raw mode. * * The pty device is closed after the shell is restarted, when called * from telnetInTask, to avoid waking the existing shell and causing an * additional prompt to appear on the console. */ activeFlag = FALSE; /* allow new connection */ #if (_WRS_VXWORKS_MAJOR >= 6) excJobAdd((VOIDFUNCPTR)shellRestart, (int)CURRENT_SHELL_SESSION , 0, 0, 0, 0, 0); #else excJobAdd(shellRestart, FALSE, 0, 0, 0, 0, 0); #endif } /* remShellTelnetDisconn */
void printExc( char *fmt, ARG arg0, ARG arg1, ARG arg2, ARG arg3, ARG arg4 ) { if (excJobAdd( (VOIDFUNCPTR) printErr, fmt, (ARG) arg0, (ARG) arg1, (ARG) arg2, (ARG) arg3, (ARG) arg4 ) != OK) { fprintf( stderr, fmt, (ARG) arg0, (ARG) arg1, (ARG) arg2, (ARG) arg3, (ARG) arg4 ); } }
LOCAL void dbgTyAbort( void ) { /* Generate exception to restart shell */ excJobAdd( (VOIDFUNCPTR) dbgTaskTyAbort, (ARG) 0, (ARG) 0, (ARG) 0, (ARG) 0, (ARG) 0, (ARG) 0 ); }
STATUS taskDestroy( int taskId, BOOL freeStack, unsigned timeout, BOOL forceDestroy ) { STATUS status; int i, level; TCB_ID tcbId; if (INT_RESTRICT() != OK) { errnoSet (S_intLib_NOT_ISR_CALLABLE); return ERROR; } /* Get task context */ tcbId = taskTcb(taskId); if (tcbId == NULL) return ERROR; /* If task self destruct and excption lib installed */ if (tcbId == taskIdCurrent) { /* Wait for safe to destroy */ while (tcbId->safeCount > 0) taskUnsafe(); /* Kill it */ status = excJobAdd( (VOIDFUNCPTR) taskDestroy, (ARG) tcbId, (ARG) freeStack, (ARG) WAIT_NONE, (ARG) FALSE, (ARG) 0, (ARG) 0 ); /* Block here and suspend */ while(status == OK) taskSuspend(0); } /* End if task self destruct and exception lib installed */ taskDestroyLoop: /* Lock interrupts */ INT_LOCK(level); /* Check id */ if (TASK_ID_VERIFY(tcbId) != OK) { /* errno set by taskIdVerify() */ /* Unlock interrupts */ INT_UNLOCK(level); return ERROR; } /* Mask all signals */ if (tcbId->pSignalInfo != NULL) tcbId->pSignalInfo->sigt_blocked = 0xffffffff; /* Block here for safe and running locked tasks */ while ( (tcbId->safeCount > 0) || ( (tcbId->status == TASK_READY) && (tcbId->lockCount > 0) ) ) { /* Enter kernel mode */ kernelState = TRUE; /* Unlock interrupts */ INT_UNLOCK(level); /* Check if force deletion, or suicide */ if (forceDestroy || (tcbId == taskIdCurrent)) { /* Remove protections */ tcbId->safeCount = 0; tcbId->lockCount = 0; /* Check if flush of safety queue is needed */ if (Q_FIRST(&tcbId->safetyQ) != NULL) vmxPendQFlush(&tcbId->safetyQ); /* Exit trough kernel */ vmxExit(); } else { /* Not forced deletion or suicide */ /* Put task on safe queue */ if (vmxPendQPut(&tcbId->safetyQ, timeout) != OK) { /* Exit trough kernel */ vmxExit(); errnoSet (S_taskLib_INVALID_TIMEOUT); return ERROR; } /* Exit trough kernel */ status = vmxExit(); /* Check for restart */ if (status == SIG_RESTART) { timeout = (sigTimeoutRecalc)(timeout); goto taskDestroyLoop; } /* Check if unsuccessful */ if (status == ERROR) { /* timer should have set errno to S_objLib_TIMEOUT */ return ERROR; } } /* End else forced or suicide */ /* Lock interrupts */ INT_LOCK(level); /* Now verify class id again */ if (TASK_ID_VERIFY(tcbId) != OK) { /* errno set by taskIdVerify() */ /* Unlock interrupts */ INT_UNLOCK(level); return ERROR; } } /* End while blocked by safety */ /* Now only one cadidate is selected for deletion */ /* Make myself safe */ taskSafe(); /* Protet deletion cadidate */ tcbId->safeCount++; /* Check if not suicide */ if (tcbId != taskIdCurrent) { /* Enter kernel mode */ kernelState = TRUE; /* Unlock interrupts */ INT_UNLOCK(level); /* Suspend victim */ vmxSuspend(tcbId); /* Exit trough kernel */ vmxExit(); } else { /* Unlock interrupts */ INT_UNLOCK(level); } /* Run deletion hooks */ for (i = 0; i < MAX_TASK_DELETE_HOOKS; i++) if (taskDeleteHooks[i] != NULL) (*taskDeleteHooks[i])(tcbId); /* Lock task */ taskLock(); /* If dealloc and options dealloc stack */ if ( freeStack && (tcbId->options & TASK_OPTIONS_DEALLOC_STACK) ) { #if (_STACK_DIR == _STACK_GROWS_DOWN) objFree(taskClassId, tcbId->pStackEnd); #else /* _STACK_GROWS_UP */ objFree(taskClassId, tbcId - TASK_EXTRA_BYTES); #endif /* _STACK_DIR */ } /* Lock interrupts */ INT_LOCK(level); /* Invalidate id */ objCoreTerminate(&tcbId->objCore); /* Enter kernel mode */ kernelState = TRUE; /* Unlock interrupts */ INT_UNLOCK(level); /* Delete task */ status = vmxDelete(tcbId); /* Check if safe quque needs to be flushed */ if (Q_FIRST(&tcbId->safetyQ) != NULL) vmxPendQFlush(&tcbId->safetyQ); /* Exit trough kernel */ vmxExit(); /* Unprotect */ taskUnlock(); taskUnsafe(); return OK; }
STATUS shellParserControl ( UINT32 remoteEvent, /* Starting or stopping a connection? */ UINT32 sessionId, /* Unique identifier for each session */ UINT32 slaveFd /* File descriptor for character i/o */ ) { if ((taskNameToId ("tShell")) == ERROR) /* Shell not started yet. */ return (ERROR); if (remoteEvent == REMOTE_START) { /* Handle a new telnet or rlogin session. */ if (remoteId != 0) /* Failed request - only one session allowed. */ return (ERROR); if (!shellLock (TRUE)) /* Shell is not available. */ { fdprintf (slaveFd, "The shell is currently in use.\n"); return (ERROR); } /* Let the user try to login */ if (shellLogin (slaveFd) != OK) { shellLock (FALSE); return (ERROR); } /* setup the slave device to act like a terminal */ (void) ioctl (slaveFd, FIOOPTIONS, OPT_TERMINAL); shellLogoutInstall ((FUNCPTR) telnetdExit, sessionId); /* get the shell's standard I/O fd's so we can restore them later */ shellInFd = ioGlobalStdGet (STD_IN); shellOutFd = ioGlobalStdGet (STD_OUT); shellErrFd = ioGlobalStdGet (STD_ERR); /* set shell's standard I/O to new device; add extra logging device */ shellOrigStdSet (STD_IN, slaveFd); shellOrigStdSet (STD_OUT, slaveFd); shellOrigStdSet (STD_ERR, slaveFd); logFdAdd (slaveFd); logFdFromRlogin = slaveFd; /* store new fd for logFdSet() */ /* Store the session identifier. */ remoteId = sessionId; /* notify the shell we have started a remote session */ shellIsRemoteConnectedSet (TRUE); printErr ("\ntelnetd: This system *IN USE* via telnet.\n"); /* Prevent network denial of service attacks by waiting a second */ taskDelay (sysClkRateGet() / 2); /* Restart the shell to access the redirected file descriptors. */ excJobAdd (shellRestart, TRUE, 0, 0, 0, 0, 0); return (OK); } else if (remoteEvent == REMOTE_STOP) { /* * End an active telnet or rlogin session. This event occurs * after the server closes the socket. */ if (remoteId != sessionId) /* Unknown remote session. */ return (ERROR); shellLogoutInstall ((FUNCPTR) NULL, 0); /* remove logout function */ if (logFdFromRlogin != NONE) { logFdDelete (logFdFromRlogin); /* cancel extra log device */ logFdFromRlogin = NONE; /* reset fd */ } shellOrigStdSet (STD_IN, shellInFd); /* restore shell's stnd I/O */ shellOrigStdSet (STD_OUT, shellOutFd); shellOrigStdSet (STD_ERR, shellErrFd); shellLock (FALSE); /* unlock shell */ /* * For typical remote sessions, restoring the standard I/O * descriptors is enough to reconnect the shell to the console * because closing the pty device will cause the shell to unblock * from its read() and use the restored descriptors. However, * problems can occur upon logout if the remote user has disabled * the line editor and/or put the pty device in raw mode, so the * shell is restarted in all cases. */ remoteId = 0; /* Allow a new session. */ /* notify the shell we have ended a remote session */ shellIsRemoteConnectedSet (FALSE); excJobAdd (shellRestart, FALSE, 0, 0, 0, 0, 0); return (OK); } return (ERROR); /* Ignore unknown control operations. */ }
/******************************************************************************* * * remShellTelnetConn - connect shell to telnet * * This routine is called by the telnet demon to connect the shell with the * remote telnet user. * Remote telnet requests will cause `stdin', `stdout', and `stderr' to be stolen * away from the console. When the remote user disconnects, `stdin', `stdout', * and `stderr' are restored, and the shell is restarted. * * RETURNS: OK or ERROR. */ STATUS remShellTelnetConn ( int interpConnArg, /* argument for interpConn () */ int slaveFd, int exitArg, /* */ int * disconnArg, char * msg ) { /* wait for shell to exist */ while (taskNameToId (telnetShellName) == ERROR) taskDelay (sysClkRateGet ()); /* check to see if there's already an active connection */ if (activeFlag) { strcpy(msg, "\r\nSorry, this system is engaged.\r\n"); return ERROR; } if (!shellLock (TRUE)) { strcpy(msg, "\r\nSorry, shell is locked.\r\n"); printErr ("telnetd: someone tried to login into.\n"); return ERROR; } printErr ("\ntelnetd: This system *IN USE* via telnet.\n"); shellLogoutInstall ((FUNCPTR) telnetdExit, exitArg); activeFlag = TRUE; /* get the shell's standard I/O fd's so we can restore them later */ shellInFd = ioGlobalStdGet (STD_IN); shellOutFd = ioGlobalStdGet (STD_OUT); shellErrFd = ioGlobalStdGet (STD_ERR); #ifndef BROADCOM_DEBUG #if VX_VERSION == 55 || VX_VERSION == 542 /* set shell's standard I/O to pty device; add extra logging device */ shellOrigStdSet (STD_IN, slaveFd); shellOrigStdSet (STD_OUT, slaveFd); shellOrigStdSet (STD_ERR, slaveFd); logFdAdd (slaveFd); logFdFromRlogin = slaveFd; /* store pty fd for logFdSet() */ #endif #endif /* BROADCOM_DEBUG */ /* the shell is currently stuck in a read from the console, so we * restart it */ #ifndef BROADCOM_DEBUG #if (_WRS_VXWORKS_MAJOR >= 6) excJobAdd((VOIDFUNCPTR)shellRestart, (int)CURRENT_SHELL_SESSION , 0, 0, 0, 0, 0); #else excJobAdd (shellRestart, TRUE, 0, 0, 0, 0, 0); #endif #else sp (copyStreams, slaveFd, slaveFd,0,0,0,0,0,0,0); /* !!! */ #endif /* BROADCOM_DEBUG */ (void) ioctl (slaveFd, FIOFLUSH, 0 /*XXX*/); return OK; } /* remShellTelnetConn */