xref: /original-bsd/local/local.cmd/cpr.c (revision 39c8fdd5)
1 # include <stdio.h>
2 # include <sgtty.h>
3 # include <signal.h>
4 
5 static char	SccsId[] =	"@(#)cpr.c	1.8		11/14/82";
6 
7 /*
8 **  CPR -- print on concept 108
9 **
10 **	This filter arranges to output onto a printer connected
11 **	to a Concept 108 terminal.  It probably works on other
12 **	models in the Concept 100 series also.
13 **
14 **	Usage:
15 **		cpr [-f] [file ...]
16 **
17 **	Flags:
18 **		-f	form feed following to print.
19 */
20 
21 #define LINELEN	132			/* carriage width */
22 
23 typedef char	bool;
24 #define TRUE	1
25 #define FALSE	0
26 
27 struct sgttyb	tbuf;
28 int		SysLinePid;		/* pid of sysline process */
29 bool		FormFeedFollowing;	/* print form feed following print */
30 bool		EchoDuringPrint;	/* echo on terminal while printing */
31 
32 main(argc, argv)
33 	int argc;
34 	char **argv;
35 {
36 	register char *p;
37 	extern cleanterm();
38 	extern char *getenv();
39 
40 	/* arrange to stop the sysline program during printing */
41 	p = getenv("SYSLINE");
42 	if (p != NULL)
43 		SysLinePid = atoi(p);
44 
45 	/* process arguments */
46 	while (--argc > 0)
47 	{
48 		p = *++argv;
49 		if (*p != '-')
50 			break;
51 		switch (*++p)
52 		{
53 		  case 'f':
54 			FormFeedFollowing = TRUE;
55 			break;
56 
57 		  case 'e':
58 			EchoDuringPrint = TRUE;
59 			break;
60 		}
61 	}
62 
63 	/* be nice on interrupts, etc. */
64 	signal(SIGINT, cleanterm);
65 
66 	/* set the terminal to output to printer */
67 	setupterm();
68 
69 	/* print the appropriate files */
70 	if (argc < 1)
71 		copyfile();
72 	else
73 	{
74 		while (argc-- > 0)
75 		{
76 			p = *argv++;
77 			if (freopen(p, "r", stdin) == NULL)
78 				perror(p);
79 			else
80 				copyfile();
81 		}
82 	}
83 
84 	/* reset terminal to a nice state */
85 	cleanterm();
86 }
87 
88 copyfile()
89 {
90 	int c;
91 	int col;
92 	register char *p;
93 	char bufa[LINELEN + 1];
94 	char bufb[LINELEN + 2];
95 	char bufc[LINELEN + 1];
96 	char bufd[LINELEN + 2];
97 
98   clearbuf:
99 	for (col = 0; col <= LINELEN; col++)
100 		bufa[col] = bufb[col] = bufc[col] = bufd[col] = ' ';
101 	col = 0;
102 	while ((c = getchar()) != EOF)
103 	{
104 		switch (c)
105 		{
106 		  case '\b':
107 			if (col > 0)
108 				col--;
109 			break;
110 
111 		  case '\r':
112 			col = 0;
113 			break;
114 
115 		  case ' ':
116 			col++;
117 			break;
118 
119 		  case '\t':
120 			col = (col + 8) & ~07;
121 			break;
122 
123 		  case '\n':
124 			putout(bufa, FALSE);
125 			putout(bufb, TRUE);
126 			putout(bufc, TRUE);
127 			putout(bufd, TRUE);
128 			col = 0;
129 			putchar('\n');
130 			goto clearbuf;
131 
132 		  default:
133 			if (col >= LINELEN)
134 				col++;
135 			else if (bufa[col] == ' ')
136 				bufa[col++] = c;
137 			else if (bufb[col] == ' ')
138 				bufb[col++] = c;
139 			else if (bufc[col] == ' ')
140 				bufc[col++] = c;
141 			else if (bufd[col] == ' ')
142 				bufd[col++] = c;
143 			else
144 			{
145 				int i;
146 
147 				putout(bufa, FALSE);
148 				putchar('\r');
149 				for (i = 0; i < LINELEN; i++)
150 					bufa[i] = ' ';
151 				bufa[col++] = c;
152 			}
153 		}
154 	}
155 }
156 
157 putout(buf, cr)
158 	char buf[];
159 	bool cr;
160 {
161 	register char *p;
162 
163 	/* find the end of the line */
164 	for (p = &buf[LINELEN-1]; p >= buf && *p == ' '; p--)
165 		continue;
166 	*++p = '\0';
167 	if (buf[0] == '\0')
168 		return;
169 	if (cr)
170 		putchar('\r');
171 	for (p = buf; *p != '\0'; p++)
172 		putchar(*p);
173 }
174 
175 setupterm()
176 {
177 	int oldflags;
178 
179 	if (gtty(1, &tbuf) < 0)
180 	{
181 		perror("cpr: stdout");
182 		exit(1);
183 	}
184 	oldflags = tbuf.sg_flags;
185 	tbuf.sg_flags &= ~ECHO;
186 	tbuf.sg_flags |= CBREAK | XTABS;
187 	stty(1, &tbuf);
188 	tbuf.sg_flags = oldflags;
189 	if (SysLinePid > 0)
190 		kill(SysLinePid, SIGSTOP);
191 	fputs("\033Y", stdout);
192 	if (EchoDuringPrint)
193 		fputs("4", stdout);
194 	else
195 		fputs("$", stdout);
196 	if (getack() >= 0)
197 		return;
198 	fprintf(stderr, "Cannot attach printer\n");
199 	resetmodes();
200 	exit(1);
201 }
202 
203 cleanterm()
204 {
205 	/* output trailing formfeed */
206 	if (FormFeedFollowing)
207 		fputs("\r\f", stdout);
208 
209 	/* disconnect printer */
210 	printf("\033Y0");
211 	getack();
212 	fflush(stdout);
213 
214 	/* back to the real world.... */
215 	resetmodes();
216 	exit(0);
217 }
218 
219 getack()
220 {
221 	char buf[1];
222 
223 	fflush(stdout);
224 	if (read(2, buf, 1) <= 0 || buf[0] != '\006')
225 		return (-1);
226 	return (0);
227 }
228 
229 resetmodes()
230 {
231 	stty(1, &tbuf);
232 	if (SysLinePid > 0)
233 		kill(SysLinePid, SIGCONT);
234 }
235