#!/bin/sh # shar: Shell Archiver # Run the following text with /bin/sh to create: # vxRshd.c # This archive created: Tue Aug 27 11:13:24 1991 echo shar: extracting vxRshd.c '(25618 characters)' cat << \SHAR_EOF > vxRshd.c /* vxRshd.c - vxRsh server source */ /* modification history * vxRshd.c * * This module implements the server running on the target. * * ROUTINES: * E vxRshd() - The daemon - Must be spawned during boot. * E vxRshdInit() - Init routine. * S vxRshdSession() - A session of one client server. * S vxRshdCheck() - Verify the we can activate a session. * E vxRshConnectWho() - Find who is connected to the target. * S vxRshdWriteClientStr() - Write a string back to the client. * S vxRshdSession() - shell session with redirected I/O. * S vxRshdCheck() - Check if the shell can be locked. * S vxRshdSLG() - Action routine - Start log file. * S vxRshdELG() - Action routine - End log file. * S vxRshdHRS() - Action routine - Hardware reset. * S vxRshdSRS() - Action routine - Software reset. * S vxRshdSES() - Action routine - Shell session. * S vxRshdBPS() - Action routine - Bypass the shell. * S vxRshdWHO() - Action routine - Find who is locking the shell. * * AUTHORS * Benny Schnaider benny@vlss.amdahl.com (408) 746-3440 * * HISTORY: * 10/07/91 bxs20: Support shell bypass. * 09/01/89 bxs20: Created. */ /* DESCRIPTION vxRshd is the server for the vxRsh tool. It is spawn during the initialization process of the target. vxRshd waits for a connection on a TCP socket. Once a connection is received a new task is spawned and the server is ready for a new session. Thus, more than one vxRsh sessions can be active at the same time. The module is initialized by calling vxRshdInit() (typically from usrConfig()). The implementation is based on strings that are received from the client. Each string is decoded and a corresponding action routine is started. It should be relatively easy to add new commands and action routines by setting entries in vxRshCmdTbl[] array. BUS vxRsh is not compatible with the standard UNIX rshd. The search for the peer which is locking the shell should be part of shellLib(1) AUTHORS Benny Schnaider: benny@vlss.amdahl.com (408) 746-3440 SEE ALSO vxRsh(4) vxRsh.h */ #include #include #include #include #include #include #include #include #include #include #include /* * static data */ static int vxRshdLogSocket = ERROR; /* Socket FD for the connected peer */ static int vxRshdOldStdOut = ERROR; /* Original STDOUT FD before redirection */ /* * Forward declaration */ static STATUS vxRshdWriteClientStr(); static STATUS vxRshdSession(); static STATUS vxRshdCheck(); static STATUS vxRshdSLG(); static STATUS vxRshdELG(); static STATUS vxRshdHRS(); static STATUS vxRshdSRS(); #ifndef VXRSH_VXWORK_4.X static STATUS vxRshdSES(); #endif /* VXRSH_VXWORK_4.X */ static STATUS vxRshdBPS(); static STATUS vxRshdWHO(); typedef struct { char cmd_str[VXRSH_CMD_LEN]; /* The command string */ FUNCPTR cmd_rtn; /* Command per routine */ } vxRshTblElement; static vxRshTblElement vxRshCmdTbl[] = { {VXRSH_CMD_START_LOG, vxRshdSLG}, {VXRSH_CMD_END_LOG, vxRshdELG}, {VXRSH_CMD_HW_RESET, vxRshdHRS}, {VXRSH_CMD_SW_RESET, vxRshdSRS}, #ifndef VXRSH_VXWORK_4.X {VXRSH_CMD_SESSION, vxRshdSES}, #endif /* VXRSH_VXWORK_4.X */ {VXRSH_CMD_BYPASS, vxRshdBPS}, {VXRSH_CMD_WHO, vxRshdWHO}, }; /* vxRshCmdTbl[] */ #define VXRSH_CMD_TBL_SIZE (sizeof(vxRshCmdTbl) / sizeof(vxRshTblElement)) /***************************************************************************** * vxRshd * * This is the main entry routine for the vxRsh client. The server is invoked * only once from vxRshdInit(2). * It first initializes a TCP socket and then wait forever for a new connection. * Once a connection is established, the protocol-command string is decoded - * vxRshdDecode() and a new task is spawned. The task entry is an * action routine determined by vxRsdhdDecode(). For debugging the action * routine can be called (#undef VXRSH_SP), instead of being spawned. * * RETURNS * ERROR. This routine should never return. It return only in case of error * which can result from socket operation errors, or if the module was already * initialized * */ STATUS vxRshd() { static int sock = -1; /* socket fd's */ int snew; /* socket fd's - per connection */ struct sockaddr_in serverAddr; /* server's address */ struct sockaddr_in clientAddr; /* client's address */ int clientLen; /* length of clientAddr */ FUNCPTR rtnP; /* A pointer to action routine */ /* * Check if module is initialized */ if (sock != -1) { printf("vxRshd: Module is already initialized\n"); return(ERROR); } /* init check */ /* * Zero out the sock_addr structures. * This MUST be done before the socket calls. */ bzero (&serverAddr, sizeof (serverAddr)); bzero (&clientAddr, sizeof (clientAddr)); /* * Open the socket. * Use ARPA Internet address format and stream sockets. * Format described in "socket.h". */ if ((sock = socket (AF_INET, SOCK_STREAM, 0)) == ERROR) { perror("vxRshd: Can not create a socket.\n"); printErrno(errnoGet()); return(ERROR); } /* * Set up our internet address, and bind it to enable connect. */ serverAddr.sin_family = AF_INET; serverAddr.sin_port = VXRSH_PORT_NUM; #ifdef VXRSH_DEBUG (void)printf("\nvxRshd: Binding SERVER socket = %d\n", sock); #endif VXRSH_DEBUG if (bind(sock, (SOCKADDR *)&serverAddr, sizeof (serverAddr)) == ERROR) { perror("vxRshd: bind failed\n"); printErrno(errnoGet()); close(sock); return(ERROR); } /* * Listen, for the client to connect to us. */ #ifdef VXRSH_DEBUG (void)printf ("vxRshd: Listening to client\n"); #endif VXRSH_DEBUG if (listen (sock, 2) == ERROR) { perror("vxRshd: listen failed\n"); printErrno(errnoGet()); close (sock); return(ERROR); } /* * Receive new Clients */ FOREVER { #ifdef VXRSH_DEBUG (void)printf ("vxrshd: Accepting CLIENTS\n"); #endif VXRSH_DEBUG clientLen = sizeof (clientAddr); snew = accept (sock, (SOCKADDR *)&clientAddr, &clientLen); if (snew == ERROR) { perror("vxRshd: accept failed\n"); printErrno(errnoGet()); close(sock); break; } /* * Decode the command */ if (vxRshdDecode(snew, &clientAddr, &rtnP) == ERROR) { close(snew); continue; } /* is shell in use */ /* * New client session. */ #ifdef VXRSH_SP sp(rtnP, snew); #else /* VXRSH_SP */ rtnP(snew); #endif /* VXRSH_SP */ } /* FOREVER */ close(sock); return(ERROR); } /* vxRshdr() */ /*************************************************************************** * vxRshdInit * * Spawn the deamon. The input parameter - stackSize is set to the default * value if it is zero. * * RETURNS * OK/ERROR - according to taskSpawn return value. * */ STATUS vxRshdInit(stackSize) int stackSize; /* Stack size to be used for the server */ { stackSize = (stackSize == 0) ? VXRSH_STACK_SIZE : stackSize; if (taskSpawn("vxRshd", VXRSH_PRIORITY, VX_STDIO, stackSize, vxRshd) == ERROR) return(ERROR); else return(OK); } /* vxRshdInit() */ #ifndef VXRSH_VXWORK_4.X /************************************************************************** * vxRshdSession() * * This routine reads lines from the input stream. Each line is passed * to execute(2). The global STDOUT is redirected to clntSock. This * enables the peer to read the results back from the target. * * RETURN * OK/ERROR. ERROR on socket I/O errors. * */ LOCAL STATUS vxRshdSession(clntSock) int clntSock; /* client socket */ { char command[BUFF_LEN]; char buff[BUFF_LEN]; int oldStdOut, n, index; char c; STATUS st = OK; /* * Set IO redirection. */ oldStdOut = ioGlobalStdGet (STD_OUT); /* save original std out */ ioGlobalStdSet (STD_OUT, clntSock); /* set std out for execute() */ index = 0; while ((n = read(clntSock, &c, 1)) == 1) { if ((c == '\n') || (c == '\0')) { command[index] = '\0'; (void)printf("vxRshd: executing: %s\n", command); if (execute(command) == ERROR) { (void)printf(buff, "\nRemote execution error in command %s\n", command); printErrno(errnoGet()); (void)printf("value = -1 = 0xffffffff (server - %d)\n", VXRSH_ERR_EXEC); st = ERROR; break; } /* error while executing command */ index = 0; if (c == '\0') break; } /* end of line was detected */ else { /* * Ignore leading space blanks and tabs... */ if ((index == 0) && ((c == ' ') || (c == '\0') || (c == '\t'))) continue; command[index] = c; index++; } /* not end of line */ } /* read from socket */ if (n == -1) { perror("vxRshd: Can not read from server.\n"); printErrno(errnoGet()); st = ERROR; } /* if read error */ ioGlobalStdSet(STD_OUT, oldStdOut); /* restore original std out */ /* * Release the shell */ if (shellLock(FALSE) == FALSE) { perror("vxRshd: Can not release the shell\n"); st = ERROR; } #ifdef VXRSH_DEBUG (void)printf("vxRshd: End of session\n"); taskDelay (sysClkRateGet () / 2); #endif VXRSH_DEBUG return(st); } /* vxRshdSession() */ #endif /* VXRSH_VXWORK_4.X */ /*********************************************************************** * vxRshdCheck() * * Check if a new shell can be spawned, mainly, check that * no one is using the shell (rlogin telent vxRshd). * If the shell can be spawned: * - Lock the shell access * - Kill the existing shell (if any) * If the shell is locked: * - Find the peer which is locking the shell. * - Send a message on the client socket consisting of the problem and the * IP address of the peer. If a peer was not found UNKNOWN is sent. * * RETURN * OK/ERROR * */ LOCAL STATUS vxRshdCheck(clntSock) int clntSock; /* Client socket */ { int shellId; STATUS st; char buff[BUFF_LEN]; char buff1[BUFF_LEN]; if (shellLock(TRUE) == FALSE) { st = vxRshConnectWho(buff1, VXRSH_SEARCH_PEER_LOW, VXRSH_SEARCH_PEER_HIGH); if (st != OK) { strcpy(buff1, "UNKNOWN"); } (void)sprintf(buff, "Sorry, shell is in use\nvalue = -1 = 0xffffffff (server - %d) client - %s\n", VXRSH_ERR_INUSE, buff1); if (vxRshdWriteClientStr(clntSock, buff) == ERROR) { return(ERROR); } /* * Wait for synchronization */ if (read(clntSock, buff, BUFF_LEN) == ERROR) { perror("vxRshd: Can not read from server.\n"); printErrno(errnoGet()); return(ERROR); } return(ERROR); } /* Can not lock the shell */ if ((shellId = taskNameToId("shell")) == -1) return(OK); else if (taskDelete(shellId) == -1) { perror("vxRshd: Can not delete shell\n"); return(ERROR); } /* Can not delete the shell */ return(OK); } /* vxRshdCheck() */ /************************************************************************** * vxRshConnectWho * * This routine implements an heuristics to find who is logged into the * target. The implementation is based on a search in the global FD table * in a predefined range. The first FD which is connected is selected. * The routine detects the peer for the given socket and formats it into * buff. If the range is NULL the default values are assumed. * * CAUTION * Each and every one of the FDs in the range MUST BE A VALID socket. * This routine should really be part of the shelLib(1). * It is possible to control the search in the FD table by modifying * VXRSH_SEARCH_PEER_[LOW|HIGH] in vxRsh.h. * * RETURN * OK/ERROR & buff which consists of the formatted peer address. * ERROR - If can not find any valid peer. */ STATUS vxRshConnectWho(buffIn, rangeLow, rangeHigh) char *buffIn; /* Output buffer */ int rangeLow; /* Lower limit for FD search */ int rangeHigh; /* Higher limit for FD search */ { STATUS st = ERROR; int i; struct sockaddr_in peerAddr; char buff[BUFF_LEN]; int sockLen = sizeof(peerAddr); /* * Initialization */ buff[0] = NULL; rangeLow = (rangeLow == 0) ? VXRSH_SEARCH_PEER_LOW : rangeLow; rangeHigh = (rangeHigh == 0) ? VXRSH_SEARCH_PEER_HIGH : rangeHigh; for (i = rangeLow; i < rangeHigh; i++) { if (getpeername(i, &peerAddr, &sockLen) == OK) { inet_ntoa_b(peerAddr.sin_addr, buff); st = OK; break; } /* If socket is connected */ } if ((st == OK) && (buffIn != NULL)) { strcpy(buffIn, buff); } else if ((st == OK) && (buffIn == NULL)) { (void)printf("socket %d is connected from %s\n", i, buff); } return(st); } /* vxRshConnectWho() */ /************************************************************************** * vxRshdDecode() * * Decode the command coming from the host. * * RETURN * OK/ERROR. ERROR if: */ /*ARGSUSED*/ LOCAL STATUS vxRshdDecode(clntSock, clntAddr, rtnP) int clntSock; /* Client socket to read from */ struct sockaddr_in *clntAddr; /* Client address - for debug */ FUNCPTR *rtnP; /* Routine pointer */ { char command[BUFF_LEN]; char buff[BUFF_LEN]; STATUS st = ERROR; int i; /* * Read the command from the stream */ command[0] = NULL; if (read(clntSock, command, VXRSH_CMD_LEN) == VXRSH_CMD_LEN) { command[VXRSH_CMD_LEN] = NULL; for (i = 0; i < VXRSH_CMD_TBL_SIZE; i++) { if (strncmp(command, vxRshCmdTbl[i].cmd_str, VXRSH_CMD_LEN) == 0) { #ifdef VXRSH_DEBUG inet_ntoa_b(clntAddr -> sin_addr , buff); (void)printf("vxRshd: executing: %s from %s\n", command, buff); #endif VXRSH_DEBUG st = OK; *rtnP = vxRshCmdTbl[i].cmd_rtn; break; } /* A command was found */ } /* Search the command table */ } /* Read from socket */ else { perror("vxRshd: Can not read from server.\n"); printErrno(errnoGet()); st = ERROR; } /* if read error */ if ((st == ERROR) && (command[0] != NULL)) { (void)sprintf(buff, "Illegal client protocol command %s\nvalue = -1 = 0xffffffff (server - %d)\n", command, VXRSH_ERR_CLIENT_CMD); if (vxRshdWriteClientStr(clntSock, buff) == ERROR) { return(ERROR); } } /* Illegal client protocol command */ return(st); } /* vxRshdDecode() */ /*************************************************************************** * vxRshdSLG * Start log file. Stop the previous log session if it is in progress. * When started the shell must be unlocked and unused by others. * Before redirecting STDOUT the previous redirection (if any) is restored. * * xxBS - The operations here should be protected by a semaphore - see vxRshdSLG.. * * RETURN * ERROR if the shell can not be locked. Otherwise OK. * */ LOCAL STATUS vxRshdSLG(clientSock) int clientSock; /* client socket */ { STATUS st = OK; /* * Check if we a new shell can be spawned */ if (vxRshdCheck(clientSock) == ERROR) { close(clientSock); st = ERROR; return(st); } /* is shell in use */ /* * Close previous log session, just in case: * restore original std out. */ if (vxRshdOldStdOut != ERROR) { ioGlobalStdSet(STD_OUT, vxRshdOldStdOut); } if (vxRshdLogSocket != ERROR) { close(vxRshdLogSocket); } /* * Set IO redirection. */ vxRshdOldStdOut = ioGlobalStdGet (STD_OUT); /* save original std out */ ioGlobalStdSet (STD_OUT, clientSock); /* set std out for execute() */ /* * Release the shell */ if (shellLock(FALSE) == FALSE) { perror("vxRshd: Can not release the shell\n"); st = ERROR; } /* * CleanUp and return */ vxRshdLogSocket = clientSock; return(st); } /* vxRshdSLG() */ /*************************************************************************** * vxRshdELG * Stop log file. Restore the STDOUT redirection (if any) as done in * vxRshdSLG(). * * xxBS - The operations here should be protected by a semaphore - see vxRshdSLG. * * RETURN * OK */ LOCAL STATUS vxRshdELG(clientSock) int clientSock; /* client socket */ { STATUS st = OK; /* * restore original std out */ if (vxRshdOldStdOut != ERROR) { ioGlobalStdSet(STD_OUT, vxRshdOldStdOut); } vxRshdOldStdOut = ERROR; /* * Close the socket used to collect log data. */ if (vxRshdLogSocket != ERROR) { close(vxRshdLogSocket); } vxRshdLogSocket = ERROR; /* * Restart the shell if needed. */ if (shellLock(FALSE) == FALSE) { shellInit(0, TRUE); } /* * CleanUp and return */ close(clientSock); return(st); } /* vxRshdELG() */ /*************************************************************************** * vxRshdHRS * * Generate HW reset to the board. This features requires hardware assist * and the right interface in the BSP (Board Support Packet). Typically * the board can be rest by accessing a register. * If your board does not support this feature - #undef VXRSH_RESET at the * beginning of this file. The latest will call reboot(BOOT_COLD); * * RETURN * OK (Probably will not return) * */ LOCAL STATUS vxRshdHRS(clientSock) int clientSock; /* client socket */ { STATUS st = OK; /* * CleanUp and return */ close(clientSock); #ifdef VXRSH_RESET reset(); #else /* VXRSH_RESET */ reboot(BOOT_COLD); #endif /* VXRSH_RESET */ return(st); } /* vxRshdHRS() */ /*************************************************************************** * vxRshdSLG * Generate SW reset to the board by calling reboot(BOOT_WARM_QUICK_AUTOBOOT) * * SEE ALSO * reboot(2) * * RETURN * OK (Probably will not return) * */ LOCAL STATUS vxRshdSRS(clientSock) int clientSock; /* client socket */ { STATUS st = OK; /* * CleanUp and return */ close(clientSock); reboot(BOOT_WARM_QUICK_AUTOBOOT); return(st); } /* vxRshdSRS() */ #ifndef VXRSH_VXWORK_4.X /*************************************************************************** * vxRshdSES * Execute a shell command(s) by calling execute(2) and redirecting * STDOUT. Not that the shell must be unlocked during the entire session. * Before exit restart the shell. * * RETURN * ERROR if can not lock the shell. */ LOCAL STATUS vxRshdSES(clientSock) int clientSock; /* client socket */ { STATUS st = OK; /* * Check if we a new shell can be spawned */ if (vxRshdCheck(clientSock) == ERROR) { close(clientSock); st = ERROR; } /* is shell in use */ /* * Start the vxRsh session */ if (st == OK) { st = vxRshdSession(clientSock); } /* vxRshSession() */ /* * Restart the shell and return */ shellInit(0, TRUE); close(clientSock); return(st); } /* vxRshdSES() */ #endif /* VXRSH_VXWORK_4.X */ /*************************************************************************** * vxRshdBPS * Execute a command without using vxWorks shell - Bypass the shell. * The idea is to decode the line in the input line. For each string: * If it is a number: convert it to binary * If it is a name : Look for it in the symbol table. * If it is a string: Pass it as is (the address) * This is a "poor imitation" of the shell. It is designed to overcome * the fact the the shell is not reentrant. * Up to 10 arguments are parsed. * * RETURN * OK/ERROR * In addition it prints the return line just like the shell does. */ LOCAL STATUS vxRshdBPS(clientSock) int clientSock; /* client socket */ { STATUS st = OK; char buff[BUFF_LEN + 1]; char buff1[BUFF_LEN + 1]; char *cmdArgStr[VXRSH_MAX_CMD_ARG]; char *cmdArgVal[VXRSH_MAX_CMD_ARG]; int i, val, oldStdOut; int stringc = 0; register char *s, *p; char *pAdrs; unsigned char type; /* * Initialization */ for (i = 0; i < VXRSH_MAX_CMD_ARG; i++) { cmdArgStr[i] = NULL; cmdArgVal[i] = NULL; } /* for cmdArg[] */ oldStdOut = ioGlobalStdGet (STD_OUT); /* save original std out */ ioGlobalStdSet (STD_OUT, clientSock); /* set std out for execute() */ /* * Read the command line from the input */ i = 0; while ((i < BUFF_LEN) && (read(clientSock, &buff[i], 1) == 1)) { if ((buff[i] == '\n') || (buff[i] == '\0')) { buff[i] = '\0'; break; } i++; } /* Read input */ buff[BUFF_LEN - 1] = NULL; /* * Split the line into strings ignore ',' */ s = buff; stringc = 0; while ((*s != NULL) && (stringc < VXRSH_MAX_CMD_ARG)) { /* * ignore white spaces and ',' */ while ((*s == ' ') || (*s == '\t') || (*s == ',')) { s++; } /* * update the pointer of the substring in the array */ cmdArgStr[stringc] = s; /* find the end of the current substring */ while ((*s != ' ') && (*s != '\t') && (*s != NULL) && (*s != ',')) { if (*s == '\"') { s++; while ((*s) && (*s != '\"')) { if (*s == '\\') { switch(*(s + 1)) { case 'n': *s = '\n'; break; case 't': *s = '\t'; break; defualt : *s = *(s + 1); } /* switch(*s) */ p = s + 1; while((*p) && ((p - buff) < BUFF_LEN)) { *p = *(p + 1); p++; } /* Shift the rest of the string */ } /* if (*s == '\\') */ s++; } /* While in string */ break; } /* A string */ else { s++; } /* Non string */ } /* Continue reading */ /* * If this is not the end of the string * terminate the substring with a NULL */ if ((cmdArgStr[stringc][0] != NULL) && (strcmp(cmdArgStr[stringc], ","))) { *s++ = NULL; stringc++; } } /* While more to tokens */ /* * Parse each string */ for (i = 0; ((st == OK) && (i < stringc)); i++) { /* * Check for symbol in the symbol table */ (void)sprintf(buff1, "_%s", cmdArgStr[i]); if (symFindByName(sysSymTbl, cmdArgStr[i], &pAdrs, &type) == OK) { cmdArgVal[i] = pAdrs; } else if (symFindByName(sysSymTbl, buff1, &pAdrs, &type) == OK) { cmdArgVal[i] = pAdrs; } /* * Check for a string */ else if ((cmdArgStr[i][0] == '\"') && (cmdArgStr[i][strlen(cmdArgStr)] == '\"')) { cmdArgVal[i] = &cmdArgStr[i][1]; cmdArgStr[i][strlen(cmdArgStr[i])] = NULL; } /* Check for string */ /* * Check for a number */ else if (sscanf(cmdArgStr[i], "%i", &cmdArgVal[i])) { } /* Check for a number */ /* * Error */ else { (void)printf("undefined symbol: %s\n", cmdArgStr[i]); st = ERROR; } /* Error */ /* * The first one MUST be a TEXT type */ if ((i == 0) && (st == OK) && (type != (N_EXT | N_TEXT))) { (void)printf("undefined routine: %s\n", cmdArgStr[i]); st = ERROR; } /* Check all input strings */ } /* Parse each parameter */ /* * Trigger the call */ if (st == OK) { val = (int)(((FUNCPTR)cmdArgVal[0]) (cmdArgVal[1], cmdArgVal[2], cmdArgVal[3], cmdArgVal[4], cmdArgVal[5], cmdArgVal[6], cmdArgVal[7], cmdArgVal[8], cmdArgVal[9], cmdArgVal[10])); } /* Command trigger */ /* * Set the return value */ if (st == OK) { (void)printf("value = %d = 0x%x\n", val, val); } /* set the return value */ ioGlobalStdSet(STD_OUT, oldStdOut); /* restore original std out */ close(clientSock); return(st); } /* vxRshdBPS() */ /*************************************************************************** * vxRshdWHO * Checks who is locking the shell. If found, the IP address of the locking * peer is printed (see vxRshdCheck()). Otherwise, print the message: * "shell is not locked". * * RETURN * ERROR for write error on the client socket. * */ LOCAL STATUS vxRshdWHO(clientSock) int clientSock; /* client socket */ { STATUS st = OK; char buff[BUFF_LEN]; /* * Check who is locking the shell */ if (vxRshdCheck(clientSock) == OK) { (void)sprintf(buff, "Shell is not locked\nvalue = 0 = 0x0\n"); st = vxRshdWriteClientStr(clientSock, buff); /* * Release the shell - vxRshdCheck is also locking the shell. */ if (shellLock(FALSE) == FALSE) { perror("vxRshd: Can not release the shell\n"); st = ERROR; } } /* Shell is not locked */ /* * CleanUp and return */ close(clientSock); return(st); } /* vxRshdWHO() */ /***************************************************************************** * vxRshdWriteClientStr * Writes a (NULL terminated) string to the client socket. * * RETURN * ERROR if WRITE error is detected. * */ LOCAL STATUS vxRshdWriteClientStr(clientSock, buff) int clientSock; /* client socket */ char *buff; /* A pointer to NULL terminated string */ { STATUS st = OK; int strLen = strlen(buff); if (strLen >= BUFF_LEN) { perror("vxRshd: Sanity error - strLen\n"); st = ERROR; } else if (write(clientSock, buff, strLen) != strLen) { perror("vxRshd: Can not write to client\n"); printErrno(errnoGet()); st = ERROR; } return(st); } /* vxRshdWriteClientStr() */ #ifdef VXRSH_TEST /*************************************************************************** * vxRshdTest * * This routine is used to check the logging feature of vxRshd. It only * purpose is to generate messages to the client. However, it can be useful * for logging to generate a message once every hour (or so) to keep it alive. * vxRshdTest() should be spawned with (very) low priority. * * RETURN * VOID Should never return. * */ void vxRshdTest() { int i = 1; FOREVER { (void)printf("Loop #%d\n", i++); taskDelay(200); } /* FOREVER */ /* return(ERROR); */ } /* vxRshdTest() */ #endif VXRSH_TEST SHAR_EOF if test 25618 -ne "`wc -c vxRshd.c`" then echo shar: error transmitting vxRshd.c '(should have been 25618 characters)' fi # End of shell archive exit 0