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

📄 postio.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 3 页
字号:
    setupline();			/* configure the communications line */    setupstdin(0);			/* save current stdin terminal settings */}   /* End of initialize *//*****************************************************************************/start(){/* * * Tries to put the printer in the IDLE state before anything important is sent. * Run as a single process no matter what has been assigned to splitme. Separate * read and write processes, if requested, will be created after we're done here. * */    logit("printer startup\n");    currentstate = START;    clearline();    while ( 1 )	switch ( getstatus(1) )  {	    case IDLE:	    case INTERACTIVE:		    if ( postbegin != NULL && *postbegin != '\0' )			Write(ttyo, postbegin, strlen(postbegin));		    clearline();		    return;	    case BUSY:		    if ( sendctrlC == TRUE ) {			Write(ttyo, "\003", 1);			Rest(1);		    }	/* End if */		    break;	    case WAITING:	    case ERROR:	    case FLUSHING:		    Write(ttyo, "\004", 1);		    Rest(1);		    break;	    case PRINTERERROR:		    Rest(15);		    break;	    case DISCONNECT:		    error(FATAL, "Disconnected - printer may be offline");		    break;	    case ENDOFJOB:	    case UNKNOWN:		    clearline();		    break;	    default:		    Rest(1);		    break;	}   /* End switch */}   /* End of start *//*****************************************************************************/split(){    int		pid;    void	interrupt();/* * * If splitme is TRUE we fork a process, make the parent handle reading, and let * the child take care of writing. resetline() (file ifdef.c) contains all the * system dependent code needed to reset the communications line for separate * read and write processes. For now it's expected to return TRUE or FALSE and * that value controls whether we try the fork. I've only tested the two process * stuff for System V. Other versions of resetline() may just be dummy procedures * that always return FALSE. If the fork() failed previous versions continued as * a single process, although the implementation wasn't quite right, but I've now * decided to quit. The main reason is a Datakit channel may be configured to * flow control data in both directions, and if we run postio over that channel * as a single process we likely will end up in deadlock. * */    if ( splitme == TRUE )	if ( resetline() == TRUE )  {	    pid = getpid();	    signal(joinsig, interrupt);	    if ( (otherpid = fork()) == -1 )		error(FATAL, "can't fork");	    else if ( otherpid == 0 )  {		whatami = WRITE;		nostatus = WRITEPROCESS;		otherpid = pid;		setupstdin(1);	    } else whatami = READ;	} else if ( interactive == TRUE || tostdout == TRUE )	    error(FATAL, "can't create two process - check resetline()"); 	else error(NON_FATAL, "running as a single process - check resetline()");    canread = (whatami & READ) ? TRUE : FALSE;    canwrite = (whatami & WRITE) ? TRUE : FALSE;}   /* End of split *//*****************************************************************************/arguments(){    int		fd_in;			/* next input file *//* * * Makes sure all the non-option command line arguments are processed. If there * aren't any arguments left when we get here we'll send stdin. Input files are * only read and sent to the printer if canwrite is TRUE. Checking it here means * we won't have to do it in send(). If interactive mode is TRUE we'll stay here * forever sending stdin when we run out of files - exit with a break. Actually * the loop is bogus and used at most once when we're in interactive mode because * stdin is in a pseudo raw mode and the read() in readblock() should never see * the end of file. * */    if ( canwrite == TRUE )	do				/* loop is for interactive mode */	    if ( argc < 1 )		send(fileno(stdin), "pipe.end");	    else  {		while ( argc > 0 )  {		    if ( (fd_in = open(*argv, O_RDONLY)) == -1 )			error(FATAL, "can't open %s", *argv);		    send(fd_in, *argv);		    close(fd_in);		    argc--;		    argv++;		}   /* End while */	    }	/* End else */	while ( interactive == TRUE );}   /* End of arguments *//*****************************************************************************/send(fd_in, name)    int		fd_in;			/* next input file */    char	*name;			/* and it's pathname */{/* * * Sends file *name to the printer. There's nothing left here that depends on * sending and receiving status reports, although it can be reassuring to know * the printer is responding and processing our job. Only the writer gets here * in the two process implementation, and in that case split() has reset nostatus * to WRITEPROCESS and that's what getstatus() always returns. For now we accept * the IDLE state and ENDOFJOB as legitimate and ignore the INITIALIZING state. * */    if ( interactive == FALSE )	logit("sending file %s\n", name);    currentstate = SEND;    if ( useslowsend == TRUE )  {	slowsend(fd_in);	return;    }	/* End if */    while ( readblock(fd_in) )	switch ( getstatus(0) )  {	    case IDLE:	    case BUSY:	    case WAITING:	    case PRINTING:	    case ENDOFJOB:	    case PRINTERERROR:	    case UNKNOWN:	    case NOSTATUS:	    case WRITEPROCESS:	    case INTERACTIVE:		    writeblock();		    break;	    case ERROR:		    fprintf(stderr, "%s", mesg);	/* for csw */		    error(USER_FATAL, "PostScript Error");		    break;	    case FLUSHING:		    error(USER_FATAL, "Flushing Job");		    break;	    case DISCONNECT:		    error(FATAL, "Disconnected - printer may be offline");		    break;	}   /* End switch */}   /* End of send *//*****************************************************************************/done(){    int		sleeptime = 15;		/* for 'out of paper' etc. *//* * * Tries to stay connected to the printer until we're reasonably sure the job is * complete. It's the only way we can recover error messages or data generated by * the PostScript program and returned over the communication line. Actually doing * it correctly for all possible PostScript jobs is more difficult that it might * seem. For example if we've sent several jobs, each with their own EOF mark, then * waiting for ENDOFJOB won't guarantee all the jobs have completed. Even waiting * for IDLE isn't good enough. Checking for the WAITING state after all the files * have been sent and then sending an EOF may be the best approach, but even that * won't work all the time - we could miss it or might not get there. Even sending * our own special PostScript job after all the input files has it's own different * set of problems, but probably could work (perhaps by printing a fake status * message or just not timing out). Anyway it's probably not worth the trouble so * for now we'll quit if writedone is TRUE and we get ENDOFJOB or IDLE. * * If we're running separate read and write processes the reader gets here after * after split() while the writer goes to send() and only gets here after all the * input files have been transmitted. When they're both here the writer sends the * reader signal joinsig and that forces writedone to TRUE in the reader. At that * point the reader can begin looking for an indication of the end of the job. * The writer hangs around until the reader kills it (usually in cleanup()) sending * occasional status requests. * */    if ( canwrite == TRUE )	logit("waiting for end of job\n");    currentstate = DONE;    writedone = (whatami == READWRITE) ? TRUE : FALSE;    while ( 1 )  {	switch ( getstatus(1) )  {	    case WRITEPROCESS:		    if ( writedone == FALSE )  {			sendsignal(joinsig);			Write(ttyo, "\004", 1);			writedone = TRUE;			sleeptime = 1;		    }	/* End if */		    Rest(sleeptime++);		    break;	    case WAITING:		    Write(ttyo, "\004", 1);		    Rest(1);		    sleeptime = 15;		    break;	    case IDLE:	    case ENDOFJOB:		    if ( writedone == TRUE )  {			logit("job complete\n");			return;		    }	/* End if */		    break;	    case BUSY:	    case PRINTING:	    case INTERACTIVE:		    sleeptime = 15;		    break;	    case PRINTERERROR:		    Rest(sleeptime++);		    break;	    case ERROR:		    fprintf(stderr, "%s", mesg);	/* for csw */		    error(USER_FATAL, "PostScript Error");		    return;	    case FLUSHING:		    error(USER_FATAL, "Flushing Job");		    return;	    case DISCONNECT:		    error(FATAL, "Disconnected - printer may be offline");		    return;	    default:		    Rest(1);		    break;	}   /* End switch */	if ( sleeptime > 60 )	    sleeptime = 60;    }	/* End while */}   /* End of done *//*****************************************************************************/cleanup(){    int		w;/* * * Only needed if we're running separate read and write processes. Makes sure the * write process is killed after the read process has successfully finished with * all the jobs. sendsignal() returns a -1 if there's nobody to signal so things * work when we're running a single process. * */    while ( sendsignal(SIGKILL) != -1 && (w = wait((int *)0)) != otherpid && w != -1 ) ;}   /* End of cleanup *//*****************************************************************************/readblock(fd_in)    int		fd_in;			/* current input file */{    static long	blocknum = 1;/* * * Fills the input buffer with the next block, provided we're all done with the * last one. Blocks from fd_in are stored in array block[]. head is the index * of the next byte in block[] that's supposed to go to the printer. tail points * one past the last byte in the current block. head is adjusted in writeblock() * after each successful write, while head and tail are reset here each time * a new block is read. Returns the number of bytes left in the current block. * Read errors cause the program to abort. The fake status message that's put out * in quiet mode is only so you can look at the log file and know something's * happening - take it out if you want. * */    if ( head >= tail )  {		/* done with the last block */	if ( (tail = read(fd_in, block, blocksize)) == -1 )	    error(FATAL, "error reading input file");	if ( quiet == TRUE && tail > 0 )	/* put out a fake message? */	    logit("%%%%[ status: busy; block: %d ]%%%%\n", blocknum++);	head = 0;    }	/* End if */    return(tail - head);}   /* End of readblock *//*****************************************************************************/writeblock(){    int		count;			/* bytes successfully written *//* * * Called from send() when it's OK to send the next block to the printer. head * is adjusted after the write, and the number of bytes that were successfully * written is returned to the caller. * */    if ( (count = write(ttyo, &block[head], tail - head)) == -1 )	error(FATAL, "error writing to %s", line);    else if ( count == 0 )	error(FATAL, "printer appears to be offline");    head += count;    return(count);}   /* End of writeblock *//*****************************************************************************/getstatus(t)    int		t;			/* sleep time after sending '\024' */{

⌨️ 快捷键说明

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