📄 rloglib.c
字号:
curUser); shellLogoutInstall ((FUNCPTR)rlogExit, TRUE); activeFlag = TRUE; rlogindSocket = client; rlogindM = masterFd; rlogindS = slaveFd; /* flush out pty device */ ioctl (slaveFd, FIOFLUSH, 0 /*XXX*/); /* save 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 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() */ /* Notify shell of remote connection */ shellIsRemoteConnectedSet (TRUE); /* the shell is currently stuck in a read from the console, * so restart it */ excJobAdd (shellRestart, TRUE, 0, 0, 0, 0, 0); /* spawn the process which transfers data from the master pty * to the socket; * spawn the process which transfers data from the client socket * to the master pty. */ if (((rlogOutTaskId = taskSpawn("tRlogOutTask", rlogTaskPriority, rlogTaskOptions, rlogTaskStackSize, (FUNCPTR)rlogOutTask, client, masterFd, 0, 0, 0, 0, 0, 0, 0, 0)) == ERROR) || ((rlogInTaskId = taskSpawn ("tRlogInTask", rlogTaskPriority, rlogTaskOptions, rlogTaskStackSize, (FUNCPTR)rlogInTask, client, masterFd, 0, 0, 0, 0, 0, 0, 0, 0)) == ERROR)) { printErr ("rlogind: error spawning %s child - status = 0x%x\n", (rlogOutTaskId != ERROR) ? "output" : "input", errnoGet ()); if (rlogOutTaskId != ERROR) taskDelete (rlogOutTaskId); rlogExit (FALSE); /* try to do tidy clean-up */ } } }/********************************************************************************* rlogOutTask - stdout to socket process** This routine gets spawned by the rlogin daemon to move* data between the client socket and the pseudo terminal.* The task exits when the pty has been closed.** NOMANUAL* but not LOCAL for i()*/void rlogOutTask ( FAST int sock, /* socket to copy output to */ int ptyMfd /* pty Master fd */ ) { int n; char buf [STDOUT_BUF_SIZE]; while ((n = read (ptyMfd, buf, sizeof (buf))) > 0) write (sock, buf, n); }/********************************************************************************* rlogInTask - socket to stdin process** This routine gets spawned by the rlogin daemon to move* data between the pseudo terminal and the client socket.* The task exits, calling rlogExit(), when the client disconnects.** NOMANUAL* but not LOCAL for i()*/void rlogInTask ( FAST int sock, /* socket to copy input from */ int ptyMfd /* pty Master fd */ ) { FAST int n; char buf [STDIN_BUF_SIZE]; cleanupFlag = FALSE; /* exit cleanup has not been done... */ /* Loop, reading from the socket and writing to the pty. */ while ((n = read (sock, buf, sizeof (buf))) > 0) write (ptyMfd, buf, n); /* Exit and cleanup. The above loop will exit when the socket is * closed. The socket can be closed as a result of the connection * terminating from the remote host, or as a result of the logout() * command issued to our shell. When the logout() command is used, * the rlogExit() routine below is called and the socket is explicitly * closed. In this case, there is no need to call rlogExit() again. * We use the cleanupFlag to determine this case. To summarize, if the * cleanupFlag is set, we are here because the connection was terminated * remotely and cleanup is required. */ if (!cleanupFlag) rlogExit (FALSE); }/********************************************************************************* rlogExit - exit and cleanup for rlogind** This is the support routine for logout().* The client socket is closed, shell standard I/O is redirected* back to the console, and the shell is restarted.*/LOCAL void rlogExit ( BOOL usedLogout /* true if called by logout() */ ) { /* This routine is called either as a result of the logout() command * being issued from the shell, or from the rlogInTask above. It is * therefore run in the context of the shell or rlogInTask. The * caller indicates itself to us by the usedLogout argument. The * state of this argument affects our behavior, as explained below. */ cleanupFlag = TRUE; /* release rlogInTask() from duty */ shellLogoutInstall ((FUNCPTR) NULL, 0); /* uninstall 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 */ /* Notify shell of remote disconnection */ shellIsRemoteConnectedSet (FALSE); write (rlogindSocket, "\r\n", 2); close (rlogindSocket); /* close the socket */ /* 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 rlogInTask 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 rlogInTask, to avoid waking the existing shell and causing an * additional prompt to appear on the console. */ if (usedLogout) /* called from shell */ { close (rlogindM); close (rlogindS); activeFlag = FALSE; /* allow new connection */ taskRestart (0); /* never returns */ } else /* called from rlogInTask */ { excJobAdd (shellRestart, FALSE, 0, 0, 0, 0, 0); close (rlogindM); close (rlogindS); activeFlag = FALSE; /* allow new connection */ } }/********************************************************************************* recvStr - receive a null terminated string from a socket** Similar to fioRdString, but for sockets.** RETURNS: OK or ERROR.*/LOCAL STATUS recvStr ( FAST int sd, /* socket */ FAST char *buf /* where to put the string */ ) { do { if (read (sd, buf, 1) != 1) return (ERROR); } while (*(buf++) != EOS); return (OK); }/********************************************************************************* childTaskSpawn - spawn rlogChildTask via netJob queue** RETURNS: N/A*/LOCAL void childTaskSpawn ( int priority, int options, int stackSize ) { rlogChildTaskId = taskSpawn ("tRlogChildTask", priority, options, stackSize, (FUNCPTR)rlogChildTask, 0,0,0,0,0,0,0,0,0,0); if (rlogChildTaskId == ERROR) { printErr ("rlogin: trouble spawning child - status = 0x%x\n", errnoGet ()); close (rloginSocket); } }/********************************************************************************* rlogin - log in to a remote host** This routine allows users to log in to a remote host. It may be called from* the VxWorks shell as follows:* .CS* -> rlogin "remoteSystem"* .CE* where <remoteSystem> is either a host name, which has been previously added* to the remote host table by a call to hostAdd(), or an Internet address in* dot notation (e.g., "90.0.0.2"). The remote system will be logged into* with the current user name as set by a call to iam().** The user disconnects from the remote system by typing:* .CS* ~.* .CE* as the only characters on the line, or by simply logging out from the remote* system using logout().** RETURNS:* OK, or ERROR if the host is unknown, no privileged ports are available,* the routine is unable to connect to the host, or the child process cannot* be spawned.** SEE ALSO: iam(), logout()*/STATUS rlogin ( char *host /* name of host to connect to */ ) { char remUser [MAX_IDENTITY_LEN]; char remPasswd [MAX_IDENTITY_LEN]; struct sockaddr_in hostAddr; int port; char ch; int quitFlag; int status; int nTries; /* connect to host */ if (((hostAddr.sin_addr.s_addr = hostGetByName (host)) == ERROR) && ((hostAddr.sin_addr.s_addr = inet_addr (host)) == ERROR)) { printErr ("rlogin: unknown host.\n"); return (ERROR); } hostAddr.sin_family = AF_INET; hostAddr.sin_port = htons (LOGIN_SERVICE); remCurIdGet (remUser, remPasswd); port = 1000; status = ERROR; for (nTries = 0; status == ERROR && nTries < MAX_CONNECT_TRIES; nTries++) { if ((rloginSocket = rresvport (&port)) == ERROR) { printErr ("rlogin: no available privileged ports.\n"); return (ERROR); } status = connect (rloginSocket, (struct sockaddr *)&hostAddr, sizeof(hostAddr)); port--; } if (status == ERROR) { printErr ("rlogin: could not connect to host.\n"); close (rloginSocket); return (ERROR); } /* send a null (no seperate STDERR) */ write (rloginSocket, "", 1); /* send the local and remote user names */ write (rloginSocket, remUser, strlen (remUser) + 1); write (rloginSocket, remUser, strlen (remUser) + 1); /* send the terminal type */ write (rloginSocket, rlogTermType, strlen (rlogTermType) + 1); /* spawn a process to handle stdin */ status = netJobAdd ((FUNCPTR)childTaskSpawn, rlogTaskPriority, rlogTaskOptions, rlogTaskStackSize, 0, 0); if (status != OK) /* netJob queue overflow, error printed by panic */ { close (rloginSocket); return (ERROR); } /* force shell to be locked, shellLock is FALSE if already locked */ shellLock (TRUE); /* set console to RAW mode except with XON-XOFF and 7 bit */ ioctl (STD_IN, FIOOPTIONS, OPT_TANDEM | OPT_7_BIT); quitFlag = 0; while ((rloginSocket != ERROR) && (read (STD_IN, &ch, 1) == 1)) { /* track input of "<CR>~.<CR>" to terminate connection */ if ((quitFlag == 0) && (ch == '~')) quitFlag = 1; else if ((quitFlag == 1) && (ch == '.')) quitFlag = 2; else if ((quitFlag == 2) && (ch == '\r')) break; /* got "<CR>~.<CR>" */ else quitFlag = (ch == '\r') ? 0 : -1; write (rloginSocket, &ch, 1); } /* wait for other tasks to finish up, i.e. rlogind */ taskDelay (sysClkRateGet () / 2); if (rloginSocket != ERROR) { taskDelete (rlogChildTaskId); close (rloginSocket); } /* reset console */ ioctl (STD_IN, FIOOPTIONS, OPT_TERMINAL); printf ("\nClosed connection.\n"); shellLock (FALSE); return (OK); }/********************************************************************************* rlogChildTask - rlogin child** This routine gets spawned by rlogin() to read data from* the rloginSocket and write it to stdout.* The task exits when the client disconnects;* rlogin is informed by setting rloginSocket to ERROR.** NOMANUAL* but not LOCAL for i()*/void rlogChildTask (void) { char buf [STDOUT_BUF_SIZE]; int n; while ((n = read (rloginSocket, buf, sizeof (buf))) > 0) write (STD_OUT, buf, n); close (rloginSocket); /* indicate that client side caused termination, * and stop rlogin from reading stdin */ rloginSocket = ERROR; ioctl (STD_IN, FIOCANCEL, 0 /*XXX*/); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -