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