File: g3hack.c

package info (click to toggle)
mgetty 1.2.1-5
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 6,880 kB
  • sloc: ansic: 42,728; sh: 6,487; perl: 6,262; makefile: 1,457; tcl: 756; lisp: 283
file content (207 lines) | stat: -rw-r--r-- 5,941 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
/* 
* From owner-mgetty Wed Jun 28 02:08:30 1995
* Return-Path: <owner-mgetty>
* Received: by greenie.muc.de (/\==/\ Smail3.1.24.1 #24.2)
* 	id <m0sQkgA-0001nCC@greenie.muc.de>; Wed, 28 Jun 95 02:08 MEST
* Return-Path: <l-mgetty-owner@muc.de>
* Received: by greenie.muc.de (/\==/\ Smail3.1.24.1 #24.2)
* 	id <m0sQkg6-0002jPC@greenie.muc.de>; Wed, 28 Jun 95 02:08 MEST
* Received: from greenie.muc.de ([193.174.4.62]) by colin.muc.de with SMTP id <25543-2>; Wed, 28 Jun 1995 02:08:14 +0200
* Received: by greenie.muc.de (/\==/\ Smail3.1.24.1 #24.2)
* 	id <m0sQkXo-0001nCC@greenie.muc.de>; Wed, 28 Jun 95 01:59 MEST
* Received: from GATEWAY by greenie.muc.de with netnews
* 	for mgetty@muc.de (mgetty@muc.de)
* To: mgetty@muc.de
* Date: Sat, 24 Jun 1995 21:26:42 +0200
* From: fdc@cliwe.ping.de (Frank D. Cringle)
* Message-ID: <vt68lv7cb1.fsf_-_@cliwe.ping.de>
* Organization: calls for speculation 
* References: <m0sNnpJ-0001v0C@greenie.muc.de>
* Subject: Save the forests (was: Conversion ascii->g3)
* Status: RO
* 
* gert@greenie.muc.de (Gert Doering) writes:
* >Erlend Schei wrote:
* >> Any recommendations (perhaps som script-gurus who know how to make
* >> gslp skip the white stuff at the end of the last page)?
* >
* >I'd like to see that too. I don't think it's easy, you'll have to hack the
* >dfaxhigh (or faxg3) driver, I think.
* 
* Here is a nasty little hack that will chop the end off a g3 file.  It
* is nasty 'cos it only works for single-page 1d-encoded files with
* msbfirst bit order.  But that is what mgetty uses at present, so what
* the hell.
* 
* It is rather cool in the way that it decides what to chop.  All
* identical lines at the end of the page are candidates and any more
* than 10 (by default) are discarded.  It does not matter whether they
* are white, black or striped.
* 
* I leave it to a competent shell programmer to integrate it into the
* faxspool script.
* 
* ----------------------------------------------------------------
*/
/* g3hack.c - hack identical lines off the end of a fax
 *
 * This program is in the public domain.  If it does not work or
 * causes you any sort of grief, blame the public, not me.
 *
 * fdc@cliwe.ping.de, 1995-06-24
 *
 * $Id: g3hack.c,v 1.2 2006/06/14 10:33:14 gert Exp $
 *
 * $Log: g3hack.c,v $
 * Revision 1.2  2006/06/14 10:33:14  gert
 * add <memory.h> to silence compiler warnings
 * add ibits=0 to silence compiler warning
 *    (the code was correct, but the compiler didn't see this...)
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <memory.h>

extern int getopt();
extern char *optarg;
extern int optind, opterr;

char *usage = "usage: %s <-n count> <-h size> -o <outputfile>\n\n\
Copy a g3-(1d)-fax file from stdin to stdout and delete any\n\
   more than `count' identical trailing lines (default 10).\n\
Optionally skip `size'-byte header.\n\
Optionally named outputfile (else stdout).\n";

#define nxtbit()	((imask>>=1) ? ((ibits&imask)!=0) :		\
			 ((ibits=getchar()) == EOF) ? -1 :		\
			 (((imask=0x80)&ibits)!=0))
#define putbit(b)							\
    do {								\
	if (b)								\
	    obits |= omask;						\
	if ((omask >>= 1) == 0) {					\
	    this->line[this->length>>3] = obits;			\
	    omask = 0x80;						\
	    obits = 0;							\
	}								\
	this->length++;							\
	if (this->length >= BUFSIZ<<3) {				\
	    fputs("g3hack: unreasonably long line\n", stderr);		\
	    exit(1);							\
	}								\
    } while (0)

static void
copy(int nlines)
{
    int ibits = 0, imask = 0;	/* input bits and mask */
    int obits = 0;		/* output bits */
    int omask = 0x80;		/* output mask */
    int zeros = 0;		/* number of consecutive zero bits */
    int thisempty = 1;		/* empty line (so far) */
    int empties = 0;		/* number of consecutive EOLs */
    int identcount = 0;		/* number of consecutive identical lines */
    struct {
	char line[BUFSIZ];
	int length;
    } lines[2], *prev, *this, *temp;

    this = &lines[0];
    prev = &lines[1];
    this->length = prev->length = 0;
    while (!ferror(stdout)) {
	int bit = nxtbit();
	if (bit == -1)
	    break;		/* end of file */
	putbit(bit);
	if (bit == 0) {
	    zeros++;
	    continue;
	}
	if (zeros < 11) {	/* not eol and not empty */
	    zeros = 0;
	    thisempty = 0;
	    for ( ; empties; empties--)
		fwrite("\0\1", 1, 2, stdout);
	    continue;
	}
	/* at end of line */
	zeros = 0;
	omask = 0x80;
	obits = 0;
	if (thisempty) {
	    empties++;
	    if (empties >= 6)
		break;
	    this->length = 0;
	    continue;
	}
	thisempty = 1;
	/* at end of non-empty line */
	identcount++;
	this->length = (this->length+7)&~7;
	this->line[(this->length-1)>>3] = 1; /* byte-align the eol */
	if (this->length == prev->length &&
	    memcmp(this->line, prev->line, this->length>>3) == 0) {
	    this->length = 0;
	    continue;
	}
	/* at end of non-matching line */
	for ( ; identcount; identcount--)
	    fwrite(prev->line, 1, prev->length>>3, stdout);
	temp = prev;
	prev = this;
	this = temp;
	this->length = 0;
    }
    if (identcount > nlines)
	identcount = nlines;
    for ( ; !ferror(stdout) && identcount; identcount--)
	    fwrite(prev->line, 1, prev->length>>3, stdout);
    for ( ; !ferror(stdout) && empties; empties--)
	fwrite("\0\1", 1, 2, stdout);
    if (ferror(stdout)) {
	fputs("write error\n", stderr);
	exit(1);
    }
}

int
main(int argc, char **argv)
{
    int c;
    int header = 0;
    int nlines = 10;

    opterr = 0;
    while ((c = getopt(argc, argv, "h:n:o:")) != EOF)
	switch (c) {
	case 'h':
	    header = atoi(optarg);
	    break;
	case 'n':
	    nlines = atoi(optarg);
	    break;
	case 'o':
	    if (freopen(optarg, "w", stdout) == NULL) {
		perror(optarg);
		exit(1);
	    }
	    break;
	case '?':
	    fprintf(stderr, usage, argv[0]);
	    exit(1);
	}
    while (header--)
	putchar(getchar());
    copy(nlines);
    exit(0);
}

/*
* -- 
* Frank Cringle                      | fdc@cliwe.ping.de
* voice + fax                        | +49 2304 467101
*/