⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ipctest.c

📁 操作系统SunOS 4.1.3版本的源码
💻 C
字号:
/* * @(#)ipctest.c 1.1 7/30/92 * * ipctest.c:  Sundiag diagnostics for the IPC (Integrated PC) board. * * Ipctest is Sundiag's interface to the IPC tests.  Ipctest will fork/exec * pctool to run a set of tests in the /usr/pctool/sysex directory.  All * testing is done by the IPC software.    The ipctest must work together * with pctool-listener, which is invoked by pc.bat whenever pc.bat writes * to LPT1 (i.e., ipctest sets the LPT1 environment variable so that * pctool-listener would get invoked.) * * compile:  cc -g ipctest.c -o ipctest -I../include ../lib/libtest.a */#include <sys/types.h>#include <sys/socket.h>#include <sys/un.h>#include <stdio.h>#include <signal.h>#include "sdrtns.h"			/* sundiag standard include */#include "../../../lib/include/libonline.h"	/* online library include */#include "ipctest.h"int	timeout_code = 0;		/* reason for timeout (alarm signal) */int	pctool_pid = 1000;		/* process id of pctool		*/char	location[12][4] = {		/* location of pctool window	*/		"-Wp","0","810",	/*	board 0			*/		"-Wp","0","850",	/*	board 1			*/		"-Wp", "650","810",	/*	board 2			*/		"-Wp","650","850"	/*	board 3			*/	};char	sdmsg[MESSAGE_SIZE];	/* msg buffer for throwup()	*/char	sockname[20];		/* unix socket name (SOCKNAME + ipcnum */int	floppytest=FALSE;int	pportest=FALSE;int	descibetest = FALSE;int	ipcnum=0;		/* ipc board number 		*/char	env_buf[80];		/* environment variable buffer	*/main(argc, argv)	int	argc;	char	*argv[];{	extern int process_ipctest_args();	extern int routine_usage();	char	*test_usage_msg = "[ipc#] [D] [P]";	int	timeout();		/* routine to handle alarm signals   */	int	messagetype;		/* message type received from pctool */	char	pcdev[30];		/* string for /dev/pc#		*/	char	pctoolargs[80];		/* args to pass to pctool on startup */	char	currentpath[80];	/* abs path where sundiag resides    */	versionid = "1.1";		/* SCCS version id */        strcpy(device_name, "");				/* begin Sundiag test */	test_init (argc, argv, process_ipctest_args, routine_usage, 		test_usage_msg);	(void)signal(SIGALRM, timeout);	bzero(env_buf, 80);	if (descibetest) {	    test_description();	    exit(0);	}	sprintf(device_name, "/dev/pc%d", ipcnum);	sprintf(sockname, "%s%d", SOCKNAME, ipcnum);	if (strlen(env_buf) == 0) { /* if not user specified, set to default */	    getwd(currentpath);	    sprintf(env_buf, "LPT1=%s/%s", currentpath, LISTNER);	}	putenv(env_buf);	sprintf(pcdev, "%s%s/dev/pc%d",	    (hostname==NULL)?"":hostname, (hostname==NULL)?"":":", ipcnum);	sprintf(pctoolargs, "cd %s; pc %d sd %s%s%s", SYSEXDIR, ipcnum,			floppytest ? " f" : "",			pportest   ? " pp": "",			verbose    ? " d" : "");	if ((pctool_pid = vfork()) == -1) {		perror("ipctest: vfork() failed");		sprintf(sdmsg, "ipctest: vfork() failed");		writemsg(1, ERROR, sdmsg);	/* exit */	}	if (pctool_pid != 0) {	    /* parent */	    if (verbose) {		sprintf(sdmsg,"child will execlp:\n     pctool -d %s %s %s %s -c \"%s\"\n", pcdev,location[ipcnum*3], location[ipcnum*3+1], location[ipcnum*3+2], pctoolargs);		writemsg(0, VERBOSE, sdmsg);	    }	    messagetype = pctool_listen();	} else {	    /* child */	    execlp("./pctool", "./pctool", "-d", pcdev, location[ipcnum*3],		location[ipcnum*3+1], location[ipcnum*3+2],		"-c", pctoolargs, (char *)0);	    perror("ipctest: execlp() pctool failed");	    sprintf(sdmsg, "execlp pctool failed");	    writemsg(1, ERROR, sdmsg);	/* exit */	}	wait(0);	/* collect zombie process */	switch(messagetype) {	case VERBOS:	case DONE:	case TERMINATED:		test_end(); 		/* Sundiag normal exit */	case LISTEN_ERROR:	case READ_FAILED:	case PC_ERROR:	case INVALID:	default:		exit(1);	}}/* * Pctool_listen() receives the messages sent out by pc.bat (in pctool). *   The messages are actually received 1 line at a time by a separate *   process, pctool-listener, which then sends it to ipctest via a unix *   socket.  Pc.bat sends the messages to LPT1:, which we set as an *   environment variable (setenv LPT1 pctool-listener), and hence *   pctool-listener is invoked for each line of output be pc.bat. *   Note that pctool will send out only 1 message when not in debug *   mode (either ERROR or "completed").  In debug mode, pctool will *   send a "beginning" and "completed" message for each test, and *   a "Completed" message when all done. * * Problem in pctool:  in the source code, pctool calls a libsuntool routine *   seln_create() that will fail ocassionally whenever the system is very  *   busy.    In the libsuntool code, seln_create() calls other routines *   which will eventually call the RPC routine clnt_call();  this is the *   call that is actually failing because it has a time-out value of *   10 seconds.  This probably won't be fixed as there is no plan of *   releasing any more IPC software after 1.2.  Therefore, we'll ignore *   the condition of pctool dying prematurely. * * return value:  (int) message-type.  The type of message received from *		  pctool just before it exited. */pctool_listen(){	int	sock;			/* socket descrip to listen on	*/	int	ns;			/* sock desc to talk on		*/	int	addrlen;		/* length of client address	*/	struct sockaddr_un	name;	/* unix socket name		*/	struct sockaddr		addr;	/* addr of client process	*/	char	msgbuf[2*INFOSIZ];	char	pcinfo[INFOSIZ];	int	msgtype;		/* type of msg received from pctool */	int	nread;	int	timelimit;		/* alarm clock value		*/	if ( (sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1 ) {	    perror("ipctest socket() failed");	    exit(1);	}	name.sun_family = AF_UNIX;	strcpy(name.sun_path, sockname);	if (bind(sock, (struct sockaddr *)&name,		 sizeof(struct sockaddr_un)) == -1) {	    perror("ipctest bind() failed");	    exit(1);	}	addrlen = sizeof(struct sockaddr);	listen(sock, 1);  /* take only 1 connection at a time */	/* if not in debug mode, pctool sends only 1 message upon completion.	 * if debug, then get message upon start and end of each test.	 */	timelimit = (verbose) ? VERBOSE_TIMELIM : NORMAL_TIMELIM; 	/*	 * We will get a new connection for each line sent by pctool.	 * Continue to receive the messages until we get an ERROR or DONE.	 */	for (;;) {	    alarm(timelimit); /* don't wait forever to accept socket connect */	    if ((ns = accept(sock, &addr, &addrlen)) == -1) {	    	if (timeout_code == CONNECT_FAILED) {	    	   msgtype = READ_FAILED;		   if (verbose) {		       sprintf(sdmsg,"Pctool never wrote completion message. Pctool may have terminated abnormally.\ This condition is ignored.");		       writemsg(INTERRUPT_RETURN, INFO, sdmsg);	/* exit */		   }		   clean_up();	/* remove socket from file system */		   exit(INTERRUPT_RETURN);	        } else if (timeout_code == STILL_RUNNING)		   continue;	/* try accept() again */		else		   perror("ipctest accept() failed");		unlink(sockname);		exit(1);	    }	    alarm(0);	    bzero(pcinfo, sizeof(pcinfo));	    alarm(25);  /* if problem, don't want to block forever in read() */	    nread = read(ns, pcinfo, sizeof(pcinfo)); /* read from socket */	    alarm(0);	/* turn off after returning from read() */	    if (timeout_code == CONNECT_FAILED) {		if (verbose) {		    msgtype = READ_FAILED;		    sprintf(sdmsg, "Timed out waiting to read from pctool, \which may have terminated abnormally.  This condition is ignored.\n");		    writemsg(INTERRUPT_RETURN, INFO, sdmsg);	/* exit */		}		clean_up();  /* remove socket from file system */		exit(INTERRUPT_RETURN);	    }	    /*	     * Null terminate buffer.  The ^M from pctool does strange things	     * to our buffer if we try to sprintf it.  Better to be rid of it.	     */	    if (nread > 0) {		if ((nread == INFOSIZ) || (pcinfo[nread-1] == '
'))		    pcinfo[nread-1] = '\0';	    }	    close(ns);	    if (verbose) {		sprintf(msgbuf,			"ipctest read from pc%d: '%s'\n", ipcnum, pcinfo);		write(1, msgbuf, strlen(msgbuf));	    }	    msgtype = chk_ipc_msg(pcinfo); /* check each line received */	    if (msgtype != VERBOS)		break;	}	if (msgtype == PC_ERROR) {	   sprintf(sdmsg, "read from pctool: '%s'", pcinfo);	   writemsg(1, ERROR, sdmsg);	} else if (msgtype == INVALID) {	   sprintf(sdmsg,		"received unknown msgtype (%d) from pctool. read '%s'",		msgtype, pcinfo);	   writemsg(1, ERROR, sdmsg);	/* exit */	}	unlink(sockname);	/* remove socket from file system */	return(msgtype);}/* * chk_ipc_msg() compares 1 line of input (gotten from pctool) and looks for *   the key words "ERROR:" and "INFO:".  If "INFO:", then we look for the *   words "Completed" and "Terminated" in the message, telling us that *   pctool is done;  otherwise, it's just an information message. *   Note that in debug mode, the key word that tells us pctool is done *   is "Completed" while in non-debug mode, it's "completed".  Also, *   in non-debug mode, only 1 message is sent by pctool, after all tests *   are completed or an error condition occured. * * return value:  an integer (VERBOS, DONE, ERROR, TERMINATED, or INVALID) *		  specifying the type of message received. */chk_ipc_msg(msg)	char	*msg;{	char	*strtok();	char	*token, *msgptr;	char	*complete_string;	complete_string = (verbose) ? "Complete" : "complete";	msgptr = (char *)malloc(strlen(msg));	strcpy(msgptr, msg);	if (strncmp(msg, "ERROR:", 6) == 0)	    return(PC_ERROR);	else if (strncmp(msg, "INFO:", 5) == 0) {	    token = strtok(msgptr, " ");	    while (token != NULL) {		if (strncmp(token, "Completed", 9) == 0)		    return(DONE);		else if (strncmp(token, "Terminated", 10) == 0)		    return(TERMINATED);		else		    token = strtok((char *)0, " ");  /* get next word in msg */	    }	} else if (strncmp(msg, LISTEN_ERRMSG) == 0)		return(LISTEN_ERROR);	else	/* only ERROR:, INFO: and LISTEN_ERRMSG messages are valid. */	    return(INVALID);	return(VERBOS);}/* * timeout() is the handler for SIGALRM.  We use alarm() to time out after *   blocking on accept() system call waiting for the pctool-listener *   process to make a connection to the socket.  We also use alarm() to *   time out waiting to read from the socket. */timeout(){	if (kill(pctool_pid, 0) == 0)		/* pctool still running, system probably very loaded */	    timeout_code = STILL_RUNNING;	else	    timeout_code = CONNECT_FAILED;}/* * clean_up() is called by finish() (in sdrtns library) upon receipt of *   SIGHUP, SIGTERM, or SIGINT.  Clean_up() will kill pctool and then *   remove the unix socket from the file system. */clean_up(){	if (kill(pctool_pid, 0) == 0)		/* send signal to kill pctool */	    kill(pctool_pid, SIGKILL);	unlink(sockname);}writemsg(retcode, messgtype, message)	int	retcode, messgtype;	char	*message;{	if (exec_by_sundiag)	    send_message(retcode, messgtype, message);	else {	    write(1, message, strlen(message));	    if (retcode != 0) {		clean_up();		exit(retcode);	    }	}	return(1);}process_ipctest_args(argv, arrcount)   char         *argv[];   int          arrcount;{	if (strncmp(argv[arrcount], "ipc", 3) == 0) {	    ipcnum = atoi(&argv[arrcount][3]);	    if ((ipcnum < 0) || (ipcnum > 3)) {	        printf("%s: invalid ipc number %d.  Using ipc0.\n",		       test_name, ipcnum);	        ipcnum = 0;	    }	} else if (strncmp(argv[arrcount], "D", 1) == 0) {	    floppytest = TRUE;	} else if (strncmp(argv[arrcount], "P", 1) == 0) {	    pportest = TRUE;	} else if (strncmp(argv[arrcount], "LPT1", 4) == 0) {	    strcpy(env_buf, argv[arrcount]);	} else if (strncmp(argv[arrcount], "U", 1) == 0) {	    descibetest = TRUE;	} else {	    return(FALSE);	}	return(TRUE);}routine_usage(){   (void) printf("Vmem arguments:\n\        U      = test description.\n\        ipc#   = the IPC board number to test (default is ipc0)\n\        D      = include floppy disk test (floppy must be in drive B: only)\n\        P      = include parallel port test (must have loopback connector)\n");}test_description(){   (void) printf("\Test description:\n\   Ipctest is Sundiag's interface to the IPC tests, which are a part of the\n\   IPC software.  Ipctest will fork/exec pctool to run a set of tests in the\n\   /usr/pctool/sysex directory.  All testing is done by the IPC software.\n\   The ipctest must work together with pctool-listener, which is invoked\n\   by pc.bat whenever pc.bat writes to LPT1 (i.e., ipctest sets the LPT1\n\   environment variable so that pctool-listener would get invoked).\n");   (void) printf("\   The user can also choose to test the floppy disk drive and/or the\n\   parallel port.  If chosen, a floppy disk must be inserted in drive B: and\n\   a loopback connector be connected to the parallel port prior to testing.\n\   Only drive B: can be tested because any floppy left in drive A: prior\n\   to starting PCTOOL will cause it to assume the system disk is in drive\n\   A:.\n");}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -