--- /dev/null
+<code_set_name>ISO-IR-197
+<comment_char> %
+<escape_char> /
+% source: http://www.itek.norut.no/project/barent/barsek/ip/197t.html
+% author: Petter Reinholdtsen <pere@td.org.uit.no>
+% date: 1998-08-31
+% comment: Proposed nothern sami charset. Superseeded by WS2
+
+% alias none
+
+CHARMAP
+<NU> /x00 <U0000> NULL (NUL)
+<SH> /x01 <U0001> START OF HEADING (SOH)
+<SX> /x02 <U0002> START OF TEXT (STX)
+<EX> /x03 <U0003> END OF TEXT (ETX)
+<ET> /x04 <U0004> END OF TRANSMISSION (EOT)
+<EQ> /x05 <U0005> ENQUIRY (ENQ)
+<AK> /x06 <U0006> ACKNOWLEDGE (ACK)
+<BL> /x07 <U0007> BELL (BEL)
+<BS> /x08 <U0008> BACKSPACE (BS)
+<HT> /x09 <U0009> CHARACTER TABULATION (HT)
+<LF> /x0A <U000A> LINE FEED (LF)
+<VT> /x0B <U000B> LINE TABULATION (VT)
+<FF> /x0C <U000C> FORM FEED (FF)
+<CR> /x0D <U000D> CARRIAGE RETURN (CR)
+<SO> /x0E <U000E> SHIFT OUT (SO)
+<SI> /x0F <U000F> SHIFT IN (SI)
+<DL> /x10 <U0010> DATALINK ESCAPE (DLE)
+<D1> /x11 <U0011> DEVICE CONTROL ONE (DC1)
+<D2> /x12 <U0012> DEVICE CONTROL TWO (DC2)
+<D3> /x13 <U0013> DEVICE CONTROL THREE (DC3)
+<D4> /x14 <U0014> DEVICE CONTROL FOUR (DC4)
+<NK> /x15 <U0015> NEGATIVE ACKNOWLEDGE (NAK)
+<SY> /x16 <U0016> SYNCHRONOUS IDLE (SYN)
+<EB> /x17 <U0017> END OF TRANSMISSION BLOCK (ETB)
+<CN> /x18 <U0018> CANCEL (CAN)
+<EM> /x19 <U0019> END OF MEDIUM (EM)
+<SB> /x1A <U001A> SUBSTITUTE (SUB)
+<EC> /x1B <U001B> ESCAPE (ESC)
+<FS> /x1C <U001C> FILE SEPARATOR (IS4)
+<GS> /x1D <U001D> GROUP SEPARATOR (IS3)
+<RS> /x1E <U001E> RECORD SEPARATOR (IS2)
+<US> /x1F <U001F> UNIT SEPARATOR (IS1)
+<SP> /x20 <U0020> SPACE
+<!> /x21 <U0021> EXCLAMATION MARK
+<"> /x22 <U0022> QUOTATION MARK
+<Nb> /x23 <U0023> NUMBER SIGN
+<DO> /x24 <U0024> DOLLAR SIGN
+<%> /x25 <U0025> PERCENT SIGN
+<&> /x26 <U0026> AMPERSAND
+<'> /x27 <U0027> APOSTROPHE
+<(> /x28 <U0028> LEFT PARENTHESIS
+<)> /x29 <U0029> RIGHT PARENTHESIS
+<*> /x2A <U002A> ASTERISK
+<+> /x2B <U002B> PLUS SIGN
+<,> /x2C <U002C> COMMA
+<-> /x2D <U002D> HYPHEN-MINUS
+<.> /x2E <U002E> FULL STOP
+<//> /x2F <U002F> SOLIDUS
+<0> /x30 <U0030> DIGIT ZERO
+<1> /x31 <U0031> DIGIT ONE
+<2> /x32 <U0032> DIGIT TWO
+<3> /x33 <U0033> DIGIT THREE
+<4> /x34 <U0034> DIGIT FOUR
+<5> /x35 <U0035> DIGIT FIVE
+<6> /x36 <U0036> DIGIT SIX
+<7> /x37 <U0037> DIGIT SEVEN
+<8> /x38 <U0038> DIGIT EIGHT
+<9> /x39 <U0039> DIGIT NINE
+<:> /x3A <U003A> COLON
+<;> /x3B <U003B> SEMICOLON
+<<> /x3C <U003C> LESS-THAN SIGN
+<=> /x3D <U003D> EQUALS SIGN
+</>> /x3E <U003E> GREATER-THAN SIGN
+<?> /x3F <U003F> QUESTION MARK
+<At> /x40 <U0040> COMMERCIAL AT
+<A> /x41 <U0041> LATIN CAPITAL LETTER A
+<B> /x42 <U0042> LATIN CAPITAL LETTER B
+<C> /x43 <U0043> LATIN CAPITAL LETTER C
+<D> /x44 <U0044> LATIN CAPITAL LETTER D
+<E> /x45 <U0045> LATIN CAPITAL LETTER E
+<F> /x46 <U0046> LATIN CAPITAL LETTER F
+<G> /x47 <U0047> LATIN CAPITAL LETTER G
+<H> /x48 <U0048> LATIN CAPITAL LETTER H
+<I> /x49 <U0049> LATIN CAPITAL LETTER I
+<J> /x4A <U004A> LATIN CAPITAL LETTER J
+<K> /x4B <U004B> LATIN CAPITAL LETTER K
+<L> /x4C <U004C> LATIN CAPITAL LETTER L
+<M> /x4D <U004D> LATIN CAPITAL LETTER M
+<N> /x4E <U004E> LATIN CAPITAL LETTER N
+<O> /x4F <U004F> LATIN CAPITAL LETTER O
+<P> /x50 <U0050> LATIN CAPITAL LETTER P
+<Q> /x51 <U0051> LATIN CAPITAL LETTER Q
+<R> /x52 <U0052> LATIN CAPITAL LETTER R
+<S> /x53 <U0053> LATIN CAPITAL LETTER S
+<T> /x54 <U0054> LATIN CAPITAL LETTER T
+<U> /x55 <U0055> LATIN CAPITAL LETTER U
+<V> /x56 <U0056> LATIN CAPITAL LETTER V
+<W> /x57 <U0057> LATIN CAPITAL LETTER W
+<X> /x58 <U0058> LATIN CAPITAL LETTER X
+<Y> /x59 <U0059> LATIN CAPITAL LETTER Y
+<Z> /x5A <U005A> LATIN CAPITAL LETTER Z
+<<(> /x5B <U005B> LEFT SQUARE BRACKET
+<////> /x5C <U005C> REVERSE SOLIDUS
+<)/>> /x5D <U005D> RIGHT SQUARE BRACKET
+<'/>> /x5E <U005E> CIRCUMFLEX ACCENT
+<_> /x5F <U005F> LOW LINE
+<'!> /x60 <U0060> GRAVE ACCENT
+<a> /x61 <U0061> LATIN SMALL LETTER A
+<b> /x62 <U0062> LATIN SMALL LETTER B
+<c> /x63 <U0063> LATIN SMALL LETTER C
+<d> /x64 <U0064> LATIN SMALL LETTER D
+<e> /x65 <U0065> LATIN SMALL LETTER E
+<f> /x66 <U0066> LATIN SMALL LETTER F
+<g> /x67 <U0067> LATIN SMALL LETTER G
+<h> /x68 <U0068> LATIN SMALL LETTER H
+<i> /x69 <U0069> LATIN SMALL LETTER I
+<j> /x6A <U006A> LATIN SMALL LETTER J
+<k> /x6B <U006B> LATIN SMALL LETTER K
+<l> /x6C <U006C> LATIN SMALL LETTER L
+<m> /x6D <U006D> LATIN SMALL LETTER M
+<n> /x6E <U006E> LATIN SMALL LETTER N
+<o> /x6F <U006F> LATIN SMALL LETTER O
+<p> /x70 <U0070> LATIN SMALL LETTER P
+<q> /x71 <U0071> LATIN SMALL LETTER Q
+<r> /x72 <U0072> LATIN SMALL LETTER R
+<s> /x73 <U0073> LATIN SMALL LETTER S
+<t> /x74 <U0074> LATIN SMALL LETTER T
+<u> /x75 <U0075> LATIN SMALL LETTER U
+<v> /x76 <U0076> LATIN SMALL LETTER V
+<w> /x77 <U0077> LATIN SMALL LETTER W
+<x> /x78 <U0078> LATIN SMALL LETTER X
+<y> /x79 <U0079> LATIN SMALL LETTER Y
+<z> /x7A <U007A> LATIN SMALL LETTER Z
+<(!> /x7B <U007B> LEFT CURLY BRACKET
+<!!> /x7C <U007C> VERTICAL LINE
+<!)> /x7D <U007D> RIGHT CURLY BRACKET
+<'?> /x7E <U007E> TILDE
+<DT> /x7F <U007F> DELETE (DEL)
+<.9> /x82 <U201A> SINGLE LOW-9 QUOTATION MARK
+<f2> /x83 <U0192> LATIN SMALL LETTER F WITH HOOK
+<:9> /x84 <U201E> DOUBLE LOW-9 QUOTATION MARK
+<.3> /x85 <U2026> HORIZONTAL ELLIPSIS
+<NO> /x86 <U00AC> NOT SIGN
+<!=> /x87 <U2260> NOT EQUAL TO
+<Pd>> /x88 <U00A3> POUND SIGN
+<%0> /x89 <U2030> PER MILLE SIGN
+<?I> /x8A <U00BF> INVERTED QUESTION MARK
+<=<> /x8B <U2264> LESS-THAN OR EQUAL TO
+<OE> /x8C <U0152> LATIN CAPITAL LIGATURE OE
+<'6> /x91 <U2018> LEFT SINGLE QUOTATION MARK
+<'9> /x92 <U2019> RIGHT SINGLE QUOTATION MARK
+<"6> /x93 <U201C> LEFT DOUBLE QUOTATION MARK
+<"9> /x94 <U201D> RIGHT DOUBLE QUOTATION MARK
+<Sb> /x95 <U2022> BULLET
+<-N> /x96 <U2013> EN DASH
+<-M> /x97 <U2014> EM DASH
+<Rg> /x98 <U00AE> REGISTERED SIGN
+<TM> /x99 <U2122> TRADE MARK SIGN
+<!I> /x9A <U00A1> INVERTED EXCLAMATION MARK
+</>=> /x9B <U2265> GREATER-THAN OR EQUAL TO
+<oe> /x9C <U0153> LATIN SMALL LIGATURE OE
+<Y:> /x9F <U0178> LATIN CAPITAL LETTER Y WITH DIAERESIS
+<NS> /xA0 <U00A0> NO-BREAK SPACE
+<C<> /xA1 <U010C> LATIN CAPITAL LETTER C WITH CARON
+<c<> /xA2 <U010D> LATIN SMALL LETTER C WITH CARON
+<D//> /xA3 <U0110> LATIN CAPITAL LETTER D WITH STROKE
+<d//> /xA4 <U0111> LATIN SMALL LETTER D WITH STROKE
+<G//> /xA5 <U01E4> LATIN CAPITAL LETTER G WITH STROKE
+<g//> /xA6 <U01E5> LATIN SMALL LETTER G WITH STROKE
+<SE> /xA7 <U00A7> SECTION SIGN
+<G<> /xA8 <U01E6> LATIN CAPITAL LETTER G WITH CARON
+<Co> /xA9 <U00A9> COPYRIGHT SIGN
+<g<> /xAA <U01E7> LATIN SMALL LETTER G WITH CARON
+<<<> /xAB <U00AB> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+<K<> /xAC <U01E8> LATIN CAPITAL LETTER K WITH CARON
+<--> /xAD <U00AD> SOFT HYPHEN
+<k<> /xAE <U01E9> LATIN SMALL LETTER K WITH CARON
+<NG> /xAF <U014A> LATIN CAPITAL LETTER ENG (Sami)
+<DG> /xB0 <U00B0> DEGREE SIGN
+<ng> /xB1 <U014B> LATIN SMALL LETTER ENG (Sami)
+<S<> /xB2 <U0160> LATIN CAPITAL LETTER S WITH CARON
+<s<> /xB3 <U0161> LATIN SMALL LETTER S WITH CARON
+<''> /xB4 <U00B4> ACUTE ACCENT
+<T//> /xB5 <U0166> LATIN CAPITAL LETTER T WITH STROKE
+<PI> /xB6 <U00B6> PILCROW SIGN
+<.M> /xB7 <U00B7> MIDDLE DOT
+<t//> /xB8 <U0167> LATIN SMALL LETTER T WITH STROKE
+<Z<> /xB9 <U017D> LATIN CAPITAL LETTER Z WITH CARON
+<z<> /xBA <U017E> LATIN SMALL LETTER Z WITH CARON
+</>/>> /xBB <U00BB> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+<ED> /xBC <U01B7> LATIN CAPITAL LETTER EZH
+<ed> /xBD <U0292> LATIN SMALL LETTER EZH
+<EZ> /xBE <U01EE> LATIN CAPITAL LETTER EZH WITH CARON
+<ez> /xBF <U01EF> LATIN SMALL LETTER EZH WITH CARON
+<A!> /xC0 <U00C0> LATIN CAPITAL LETTER A WITH GRAVE
+<A'> /xC1 <U00C1> LATIN CAPITAL LETTER A WITH ACUTE
+<A/>> /xC2 <U00C2> LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+<A?> /xC3 <U00C3> LATIN CAPITAL LETTER A WITH TILDE
+<A:> /xC4 <U00C4> LATIN CAPITAL LETTER A WITH DIAERESIS
+<AA> /xC5 <U00C5> LATIN CAPITAL LETTER A WITH RING ABOVE
+<AE> /xC6 <U00C6> LATIN CAPITAL LETTER AE
+<C,> /xC7 <U00C7> LATIN CAPITAL LETTER C WITH CEDILLA
+<E!> /xC8 <U00C8> LATIN CAPITAL LETTER E WITH GRAVE
+<E'> /xC9 <U00C9> LATIN CAPITAL LETTER E WITH ACUTE
+<E/>> /xCA <U00CA> LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+<E:> /xCB <U00CB> LATIN CAPITAL LETTER E WITH DIAERESIS
+<I!> /xCC <U00CC> LATIN CAPITAL LETTER I WITH GRAVE
+<I'> /xCD <U00CD> LATIN CAPITAL LETTER I WITH ACUTE
+<I/>> /xCE <U00CE> LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+<I:> /xCF <U00CF> LATIN CAPITAL LETTER I WITH DIAERESIS
+<D-> /xD0 <U00D0> LATIN CAPITAL LETTER ETH (Icelandic)
+<N?> /xD1 <U00D1> LATIN CAPITAL LETTER N WITH TILDE
+<O!> /xD2 <U00D2> LATIN CAPITAL LETTER O WITH GRAVE
+<O'> /xD3 <U00D3> LATIN CAPITAL LETTER O WITH ACUTE
+<O/>> /xD4 <U00D4> LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+<O?> /xD5 <U00D5> LATIN CAPITAL LETTER O WITH TILDE
+<O:> /xD6 <U00D6> LATIN CAPITAL LETTER O WITH DIAERESIS
+<*X> /xD7 <U00D7> MULTIPLICATION SIGN
+<O//> /xD8 <U00D8> LATIN CAPITAL LETTER O WITH STROKE
+<U!> /xD9 <U00D9> LATIN CAPITAL LETTER U WITH GRAVE
+<U'> /xDA <U00DA> LATIN CAPITAL LETTER U WITH ACUTE
+<U/>> /xDB <U00DB> LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+<U:> /xDC <U00DC> LATIN CAPITAL LETTER U WITH DIAERESIS
+<Y'> /xDD <U00DD> LATIN CAPITAL LETTER Y WITH ACUTE
+<TH> /xDE <U00DE> LATIN CAPITAL LETTER THORN (Icelandic)
+<ss> /xDF <U00DF> LATIN SMALL LETTER SHARP S (German)
+<a!> /xE0 <U00E0> LATIN SMALL LETTER A WITH GRAVE
+<a'> /xE1 <U00E1> LATIN SMALL LETTER A WITH ACUTE
+<a/>> /xE2 <U00E2> LATIN SMALL LETTER A WITH CIRCUMFLEX
+<a?> /xE3 <U00E3> LATIN SMALL LETTER A WITH TILDE
+<a:> /xE4 <U00E4> LATIN SMALL LETTER A WITH DIAERESIS
+<aa> /xE5 <U00E5> LATIN SMALL LETTER A WITH RING ABOVE
+<ae> /xE6 <U00E6> LATIN SMALL LETTER AE
+<c,> /xE7 <U00E7> LATIN SMALL LETTER C WITH CEDILLA
+<e!> /xE8 <U00E8> LATIN SMALL LETTER E WITH GRAVE
+<e'> /xE9 <U00E9> LATIN SMALL LETTER E WITH ACUTE
+<e/>> /xEA <U00EA> LATIN SMALL LETTER E WITH CIRCUMFLEX
+<e:> /xEB <U00EB> LATIN SMALL LETTER E WITH DIAERESIS
+<i!> /xEC <U00EC> LATIN SMALL LETTER I WITH GRAVE
+<i'> /xED <U00ED> LATIN SMALL LETTER I WITH ACUTE
+<i/>> /xEE <U00EE> LATIN SMALL LETTER I WITH CIRCUMFLEX
+<i:> /xEF <U00EF> LATIN SMALL LETTER I WITH DIAERESIS
+<d-> /xF0 <U00F0> LATIN SMALL LETTER ETH (Icelandic)
+<n?> /xF1 <U00F1> LATIN SMALL LETTER N WITH TILDE
+<o!> /xF2 <U00F2> LATIN SMALL LETTER O WITH GRAVE
+<o'> /xF3 <U00F3> LATIN SMALL LETTER O WITH ACUTE
+<o/>> /xF4 <U00F4> LATIN SMALL LETTER O WITH CIRCUMFLEX
+<o?> /xF5 <U00F5> LATIN SMALL LETTER O WITH TILDE
+<o:> /xF6 <U00F6> LATIN SMALL LETTER O WITH DIAERESIS
+<-:> /xF7 <U00F7> DIVISION SIGN
+<o//> /xF8 <U00F8> LATIN SMALL LETTER O WITH STROKE
+<u!> /xF9 <U00F9> LATIN SMALL LETTER U WITH GRAVE
+<u'> /xFA <U00FA> LATIN SMALL LETTER U WITH ACUTE
+<u/>> /xFB <U00FB> LATIN SMALL LETTER U WITH CIRCUMFLEX
+<u:> /xFC <U00FC> LATIN SMALL LETTER U WITH DIAERESIS
+<y'> /xFD <U00FD> LATIN SMALL LETTER Y WITH ACUTE
+<th> /xFE <U00FE> LATIN SMALL LETTER THORN (Icelandic)
+<y:> /xFF <U00FF> LATIN SMALL LETTER Y WITH DIAERESIS
+<NUL> /x00 <U0000> NUL
+<SOH> /x01 <U0001> START OF HEADING (SOH)
+<STX> /x02 <U0002> START OF TEXT (STX)
+<ETX> /x03 <U0003> END OF TEXT (ETX)
+<EOT> /x04 <U0004> END OF TRANSMISSION (EOT)
+<ENQ> /x05 <U0005> ENQUIRY (ENQ)
+<ACK> /x06 <U0006> ACKNOWLEDGE (ACK)
+<alert> /x07 <U0007> BELL (BEL)
+<BEL> /x07 <U0007> BELL (BEL)
+<backspace> /x08 <U0008> BACKSPACE (BS)
+<tab> /x09 <U0009> CHARACTER TABULATION (HT)
+<newline> /x0A <U000A> LINE FEED (LF)
+<vertical-tab> /x0B <U000B> LINE TABULATION (VT)
+<form-feed> /x0C <U000C> FORM FEED (FF)
+<carriage-return> /x0D <U000D> CARRIAGE RETURN (CR)
+<DLE> /x10 <U0010> DATALINK ESCAPE (DLE)
+<DC1> /x11 <U0011> DEVICE CONTROL ONE (DC1)
+<DC2> /x12 <U0012> DEVICE CONTROL TWO (DC2)
+<DC3> /x13 <U0013> DEVICE CONTROL THREE (DC3)
+<DC4> /x14 <U0014> DEVICE CONTROL FOUR (DC4)
+<NAK> /x15 <U0015> NEGATIVE ACKNOWLEDGE (NAK)
+<SYN> /x16 <U0016> SYNCHRONOUS IDLE (SYN)
+<ETB> /x17 <U0017> END OF TRANSMISSION BLOCK (ETB)
+<CAN> /x18 <U0018> CANCEL (CAN)
+<SUB> /x1A <U001A> SUBSTITUTE (SUB)
+<ESC> /x1B <U001B> ESCAPE (ESC)
+<IS4> /x1C <U001C> FILE SEPARATOR (IS4)
+<IS3> /x1D <U001D> GROUP SEPARATOR (IS3)
+<intro> /x1D <U001D> GROUP SEPARATOR (IS3)
+<IS2> /x1E <U001E> RECORD SEPARATOR (IS2)
+<IS1> /x1F <U001F> UNIT SEPARATOR (IS1)
+<DEL> /x7F <U007F> DELETE (DEL)
+<space> /x20 <U0020> SPACE
+<exclamation-mark> /x21 <U0021> EXCLAMATION MARK
+<quotation-mark> /x22 <U0022> QUOTATION MARK
+<number-sign> /x23 <U0023> NUMBER SIGN
+<dollar-sign> /x24 <U0024> DOLLAR SIGN
+<percent-sign> /x25 <U0025> PERCENT SIGN
+<ampersand> /x26 <U0026> AMPERSAND
+<apostrophe> /x27 <U0027> APOSTROPHE
+<left-parenthesis> /x28 <U0028> LEFT PARENTHESIS
+<right-parenthesis> /x29 <U0029> RIGHT PARENTHESIS
+<asterisk> /x2A <U002A> ASTERISK
+<plus-sign> /x2B <U002B> PLUS SIGN
+<comma> /x2C <U002C> COMMA
+<hyphen> /x2D <U002D> HYPHEN-MINUS
+<hyphen-minus> /x2D <U002D> HYPHEN-MINUS
+<period> /x2E <U002E> FULL STOP
+<full-stop> /x2E <U002E> FULL STOP
+<slash> /x2F <U002F> SOLIDUS
+<solidus> /x2F <U002F> SOLIDUS
+<zero> /x30 <U0030> DIGIT ZERO
+<one> /x31 <U0031> DIGIT ONE
+<two> /x32 <U0032> DIGIT TWO
+<three> /x33 <U0033> DIGIT THREE
+<four> /x34 <U0034> DIGIT FOUR
+<five> /x35 <U0035> DIGIT FIVE
+<six> /x36 <U0036> DIGIT SIX
+<seven> /x37 <U0037> DIGIT SEVEN
+<eight> /x38 <U0038> DIGIT EIGHT
+<nine> /x39 <U0039> DIGIT NINE
+<colon> /x3A <U003A> COLON
+<semicolon> /x3B <U003B> SEMICOLON
+<less-than-sign> /x3C <U003C> LESS-THAN SIGN
+<equals-sign> /x3D <U003D> EQUALS SIGN
+<greater-than-sign> /x3E <U003E> GREATER-THAN SIGN
+<question-mark> /x3F <U003F> QUESTION MARK
+<commercial-at> /x40 <U0040> COMMERCIAL AT
+<left-square-bracket> /x5B <U005B> LEFT SQUARE BRACKET
+<backslash> /x5C <U005C> REVERSE SOLIDUS
+<reverse-solidus> /x5C <U005C> REVERSE SOLIDUS
+<right-square-bracket> /x5D <U005D> RIGHT SQUARE BRACKET
+<circumflex> /x5E <U005E> CIRCUMFLEX ACCENT
+<circumflex-accent> /x5E <U005E> CIRCUMFLEX ACCENT
+<underscore> /x5F <U005F> LOW LINE
+<low-line> /x5F <U005F> LOW LINE
+<grave-accent> /x60 <U0060> GRAVE ACCENT
+<left-brace> /x7B <U007B> LEFT CURLY BRACKET
+<left-curly-bracket> /x7B <U007B> LEFT CURLY BRACKET
+<vertical-line> /x7C <U007C> VERTICAL LINE
+<right-brace> /x7D <U007D> RIGHT CURLY BRACKET
+<right-curly-bracket> /x7D <U007D> RIGHT CURLY BRACKET
+<tilde> /x7E <U007E> TILDE
+END CHARMAP
--- /dev/null
+<code_set_name> WIN-SAMI-2
+<comment_char> %
+<escape_char> /
+% source: <URL:http://www2.isl.uit.no/trond/ws2t.html> and
+% <URL:http://www.unicode.org/unicode/alloc/Pipeline.html>
+% author: Petter Reinholdtsen <pere@td.org.uit.no>
+% date: 1999-01-20
+% based on info from Trond Trosterud <Trond.Trosterud@hum.uit.no>.
+% This charmap is based on MS CP1252, not ISO 8859/1.
+
+% alias WS2
+CHARMAP
+<NU> /x00 <U0000> NULL (NUL)
+<SH> /x01 <U0001> START OF HEADING (SOH)
+<SX> /x02 <U0002> START OF TEXT (STX)
+<EX> /x03 <U0003> END OF TEXT (ETX)
+<ET> /x04 <U0004> END OF TRANSMISSION (EOT)
+<EQ> /x05 <U0005> ENQUIRY (ENQ)
+<AK> /x06 <U0006> ACKNOWLEDGE (ACK)
+<BL> /x07 <U0007> BELL (BEL)
+<BS> /x08 <U0008> BACKSPACE (BS)
+<HT> /x09 <U0009> CHARACTER TABULATION (HT)
+<LF> /x0A <U000A> LINE FEED (LF)
+<VT> /x0B <U000B> LINE TABULATION (VT)
+<FF> /x0C <U000C> FORM FEED (FF)
+<CR> /x0D <U000D> CARRIAGE RETURN (CR)
+<SO> /x0E <U000E> SHIFT OUT (SO)
+<SI> /x0F <U000F> SHIFT IN (SI)
+<DL> /x10 <U0010> DATALINK ESCAPE (DLE)
+<D1> /x11 <U0011> DEVICE CONTROL ONE (DC1)
+<D2> /x12 <U0012> DEVICE CONTROL TWO (DC2)
+<D3> /x13 <U0013> DEVICE CONTROL THREE (DC3)
+<D4> /x14 <U0014> DEVICE CONTROL FOUR (DC4)
+<NK> /x15 <U0015> NEGATIVE ACKNOWLEDGE (NAK)
+<SY> /x16 <U0016> SYNCHRONOUS IDLE (SYN)
+<EB> /x17 <U0017> END OF TRANSMISSION BLOCK (ETB)
+<CN> /x18 <U0018> CANCEL (CAN)
+<EM> /x19 <U0019> END OF MEDIUM (EM)
+<SB> /x1A <U001A> SUBSTITUTE (SUB)
+<EC> /x1B <U001B> ESCAPE (ESC)
+<FS> /x1C <U001C> FILE SEPARATOR (IS4)
+<GS> /x1D <U001D> GROUP SEPARATOR (IS3)
+<RS> /x1E <U001E> RECORD SEPARATOR (IS2)
+<US> /x1F <U001F> UNIT SEPARATOR (IS1)
+<SP> /x20 <U0020> SPACE
+<!> /x21 <U0021> EXCLAMATION MARK
+<"> /x22 <U0022> QUOTATION MARK
+<Nb> /x23 <U0023> NUMBER SIGN
+<DO> /x24 <U0024> DOLLAR SIGN
+<%> /x25 <U0025> PERCENT SIGN
+<&> /x26 <U0026> AMPERSAND
+<'> /x27 <U0027> APOSTROPHE
+<(> /x28 <U0028> LEFT PARENTHESIS
+<)> /x29 <U0029> RIGHT PARENTHESIS
+<*> /x2A <U002A> ASTERISK
+<+> /x2B <U002B> PLUS SIGN
+<,> /x2C <U002C> COMMA
+<-> /x2D <U002D> HYPHEN-MINUS
+<.> /x2E <U002E> FULL STOP
+<//> /x2F <U002F> SOLIDUS
+<0> /x30 <U0030> DIGIT ZERO
+<1> /x31 <U0031> DIGIT ONE
+<2> /x32 <U0032> DIGIT TWO
+<3> /x33 <U0033> DIGIT THREE
+<4> /x34 <U0034> DIGIT FOUR
+<5> /x35 <U0035> DIGIT FIVE
+<6> /x36 <U0036> DIGIT SIX
+<7> /x37 <U0037> DIGIT SEVEN
+<8> /x38 <U0038> DIGIT EIGHT
+<9> /x39 <U0039> DIGIT NINE
+<:> /x3A <U003A> COLON
+<;> /x3B <U003B> SEMICOLON
+<<> /x3C <U003C> LESS-THAN SIGN
+<=> /x3D <U003D> EQUALS SIGN
+</>> /x3E <U003E> GREATER-THAN SIGN
+<?> /x3F <U003F> QUESTION MARK
+<At> /x40 <U0040> COMMERCIAL AT
+<A> /x41 <U0041> LATIN CAPITAL LETTER A
+<B> /x42 <U0042> LATIN CAPITAL LETTER B
+<C> /x43 <U0043> LATIN CAPITAL LETTER C
+<D> /x44 <U0044> LATIN CAPITAL LETTER D
+<E> /x45 <U0045> LATIN CAPITAL LETTER E
+<F> /x46 <U0046> LATIN CAPITAL LETTER F
+<G> /x47 <U0047> LATIN CAPITAL LETTER G
+<H> /x48 <U0048> LATIN CAPITAL LETTER H
+<I> /x49 <U0049> LATIN CAPITAL LETTER I
+<J> /x4A <U004A> LATIN CAPITAL LETTER J
+<K> /x4B <U004B> LATIN CAPITAL LETTER K
+<L> /x4C <U004C> LATIN CAPITAL LETTER L
+<M> /x4D <U004D> LATIN CAPITAL LETTER M
+<N> /x4E <U004E> LATIN CAPITAL LETTER N
+<O> /x4F <U004F> LATIN CAPITAL LETTER O
+<P> /x50 <U0050> LATIN CAPITAL LETTER P
+<Q> /x51 <U0051> LATIN CAPITAL LETTER Q
+<R> /x52 <U0052> LATIN CAPITAL LETTER R
+<S> /x53 <U0053> LATIN CAPITAL LETTER S
+<T> /x54 <U0054> LATIN CAPITAL LETTER T
+<U> /x55 <U0055> LATIN CAPITAL LETTER U
+<V> /x56 <U0056> LATIN CAPITAL LETTER V
+<W> /x57 <U0057> LATIN CAPITAL LETTER W
+<X> /x58 <U0058> LATIN CAPITAL LETTER X
+<Y> /x59 <U0059> LATIN CAPITAL LETTER Y
+<Z> /x5A <U005A> LATIN CAPITAL LETTER Z
+<<(> /x5B <U005B> LEFT SQUARE BRACKET
+<////> /x5C <U005C> REVERSE SOLIDUS
+<)/>> /x5D <U005D> RIGHT SQUARE BRACKET
+<'/>> /x5E <U005E> CIRCUMFLEX ACCENT
+<_> /x5F <U005F> LOW LINE
+<'!> /x60 <U0060> GRAVE ACCENT
+<a> /x61 <U0061> LATIN SMALL LETTER A
+<b> /x62 <U0062> LATIN SMALL LETTER B
+<c> /x63 <U0063> LATIN SMALL LETTER C
+<d> /x64 <U0064> LATIN SMALL LETTER D
+<e> /x65 <U0065> LATIN SMALL LETTER E
+<f> /x66 <U0066> LATIN SMALL LETTER F
+<g> /x67 <U0067> LATIN SMALL LETTER G
+<h> /x68 <U0068> LATIN SMALL LETTER H
+<i> /x69 <U0069> LATIN SMALL LETTER I
+<j> /x6A <U006A> LATIN SMALL LETTER J
+<k> /x6B <U006B> LATIN SMALL LETTER K
+<l> /x6C <U006C> LATIN SMALL LETTER L
+<m> /x6D <U006D> LATIN SMALL LETTER M
+<n> /x6E <U006E> LATIN SMALL LETTER N
+<o> /x6F <U006F> LATIN SMALL LETTER O
+<p> /x70 <U0070> LATIN SMALL LETTER P
+<q> /x71 <U0071> LATIN SMALL LETTER Q
+<r> /x72 <U0072> LATIN SMALL LETTER R
+<s> /x73 <U0073> LATIN SMALL LETTER S
+<t> /x74 <U0074> LATIN SMALL LETTER T
+<u> /x75 <U0075> LATIN SMALL LETTER U
+<v> /x76 <U0076> LATIN SMALL LETTER V
+<w> /x77 <U0077> LATIN SMALL LETTER W
+<x> /x78 <U0078> LATIN SMALL LETTER X
+<y> /x79 <U0079> LATIN SMALL LETTER Y
+<z> /x7A <U007A> LATIN SMALL LETTER Z
+<(!> /x7B <U007B> LEFT CURLY BRACKET
+<!!> /x7C <U007C> VERTICAL LINE
+<!)> /x7D <U007D> RIGHT CURLY BRACKET
+<'?> /x7E <U007E> TILDE
+<DT> /x7F <U007F> DELETE (DEL)
+<C<> /x82 <U010C> LATIN CAPITAL LETTER C WITH CARON
+<f2> /x83 <U0192> LATIN SMALL LETTER F WITH HOOK
+<c<> /x84 <U010D> LATIN SMALL LETTER C WITH CARON
+<ED> /x85 <U01B7> LATIN CAPITAL LETTER EZH
+<ed> /x86 <U0292> LATIN SMALL LETTER EZH
+<EZ> /x87 <U01EE> LATIN CAPITAL LETTER EZH WITH CARON
+<ez> /x88 <U01EF> LATIN SMALL LETTER EZH WITH CARON
+<D//> /x89 <U0110> LATIN CAPITAL LETTER D WITH STROKE
+<S<> /x8A <U0160> LATIN CAPITAL LETTER S WITH CARON
+<<1> /x8B <U2039> SINGLE LEFT-POINTING ANGLE QUOTATION MARK
+<OE> /x8C <U0152> LATIN CAPITAL LIGATURE OE
+<'6> /x91 <U2018> LEFT SINGLE QUOTATION MARK
+<'9> /x92 <U2019> RIGHT SINGLE QUOTATION MARK
+<"6> /x93 <U201C> LEFT DOUBLE QUOTATION MARK
+<"9> /x94 <U201D> RIGHT DOUBLE QUOTATION MARK
+<Sb> /x95 <U2022> BULLET
+<-N> /x96 <U2013> EN DASH
+<-M> /x97 <U2014> EM DASH
+<d//> /x98 <U0111> LATIN SMALL LETTER D WITH STROKE
+<G<> /x99 <U01E6> LATIN CAPITAL LETTER G WITH CARON
+<s<> /x9A <U0161> LATIN SMALL LETTER S WITH CARON
+</>1> /x9B <U203A> SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
+<oe> /x9C <U0153> LATIN SMALL LIGATURE OE
+<Y:> /x9F <U0178> LATIN CAPITAL LETTER Y WITH DIAERESIS
+<NS> /xA0 <U00A0> NO-BREAK SPACE
+<g<> /xA1 <U01E7> LATIN SMALL LETTER G WITH CARON
+<G//> /xA2 <U01E4> LATIN CAPITAL LETTER G WITH STROKE
+<Pd> /xA3 <U00A3> POUND SIGN
+<Cu> /xA4 <U00A4> CURRENCY SIGN
+<g//> /xA5 <U01E5> LATIN SMALL LETTER G WITH STROKE
+<BB> /xA6 <U00A6> BROKEN BAR
+<SE> /xA7 <U00A7> SECTION SIGN
+<':> /xA8 <U00A8> DIAERESIS
+<Co> /xA9 <U00A9> COPYRIGHT SIGN
+<H<> /xAA <U021E> LATIN CAPITAL LETTER H WITH CARON
+<<<> /xAB <U00AB> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+<NO> /xAC <U00AC> NOT SIGN
+<--> /xAD <U00AD> SOFT HYPHEN
+<Rg> /xAE <U00AE> REGISTERED SIGN
+<h<> /xAF <U021F> LATIN SMALL LETTER H WITH CARON
+<DG> /xB0 <U00B0> DEGREE SIGN
+<+-> /xB1 <U00B1> PLUS-MINUS SIGN
+<K<> /xB2 <U01E8> LATIN CAPITAL LETTER K WITH CARON
+<k<> /xB3 <U01E9> LATIN SMALL LETTER K WITH CARON
+<''> /xB4 <U00B4> ACUTE ACCENT
+<My> /xB5 <U00B5> MICRO SIGN
+<PI> /xB6 <U00B6> PILCROW SIGN
+<.M> /xB7 <U00B7> MIDDLE DOT
+<NG> /xB8 <U014A> LATIN CAPITAL LETTER ENG (Sami)
+<ng> /xB9 <U014B> LATIN SMALL LETTER ENG (Sami)
+<T//> /xBA <U0166> LATIN CAPITAL LETTER T WITH STROKE
+</>/>> /xBB <U00BB> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+<t//> /xBC <U0167> LATIN SMALL LETTER T WITH STROKE
+<12> /xBD <U00BD> VULGAR FRACTION ONE HALF
+<Z<> /xBE <U017D> LATIN CAPITAL LETTER Z WITH CARON
+<z<> /xBF <U017E> LATIN SMALL LETTER Z WITH CARON
+<A!> /xC0 <U00C0> LATIN CAPITAL LETTER A WITH GRAVE
+<A'> /xC1 <U00C1> LATIN CAPITAL LETTER A WITH ACUTE
+<A/>> /xC2 <U00C2> LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+<A?> /xC3 <U00C3> LATIN CAPITAL LETTER A WITH TILDE
+<A:> /xC4 <U00C4> LATIN CAPITAL LETTER A WITH DIAERESIS
+<AA> /xC5 <U00C5> LATIN CAPITAL LETTER A WITH RING ABOVE
+<AE> /xC6 <U00C6> LATIN CAPITAL LETTER AE
+<C,> /xC7 <U00C7> LATIN CAPITAL LETTER C WITH CEDILLA
+<E!> /xC8 <U00C8> LATIN CAPITAL LETTER E WITH GRAVE
+<E'> /xC9 <U00C9> LATIN CAPITAL LETTER E WITH ACUTE
+<E/>> /xCA <U00CA> LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+<E:> /xCB <U00CB> LATIN CAPITAL LETTER E WITH DIAERESIS
+<I!> /xCC <U00CC> LATIN CAPITAL LETTER I WITH GRAVE
+<I'> /xCD <U00CD> LATIN CAPITAL LETTER I WITH ACUTE
+<I/>> /xCE <U00CE> LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+<I:> /xCF <U00CF> LATIN CAPITAL LETTER I WITH DIAERESIS
+<D-> /xD0 <U00D0> LATIN CAPITAL LETTER ETH (Icelandic)
+<N?> /xD1 <U00D1> LATIN CAPITAL LETTER N WITH TILDE
+<O!> /xD2 <U00D2> LATIN CAPITAL LETTER O WITH GRAVE
+<O'> /xD3 <U00D3> LATIN CAPITAL LETTER O WITH ACUTE
+<O/>> /xD4 <U00D4> LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+<O?> /xD5 <U00D5> LATIN CAPITAL LETTER O WITH TILDE
+<O:> /xD6 <U00D6> LATIN CAPITAL LETTER O WITH DIAERESIS
+<*X> /xD7 <U00D7> MULTIPLICATION SIGN
+<O//> /xD8 <U00D8> LATIN CAPITAL LETTER O WITH STROKE
+<U!> /xD9 <U00D9> LATIN CAPITAL LETTER U WITH GRAVE
+<U'> /xDA <U00DA> LATIN CAPITAL LETTER U WITH ACUTE
+<U/>> /xDB <U00DB> LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+<U:> /xDC <U00DC> LATIN CAPITAL LETTER U WITH DIAERESIS
+<Y'> /xDD <U00DD> LATIN CAPITAL LETTER Y WITH ACUTE
+<TH> /xDE <U00DE> LATIN CAPITAL LETTER THORN (Icelandic)
+<ss> /xDF <U00DF> LATIN SMALL LETTER SHARP S (German)
+<a!> /xE0 <U00E0> LATIN SMALL LETTER A WITH GRAVE
+<a'> /xE1 <U00E1> LATIN SMALL LETTER A WITH ACUTE
+<a/>> /xE2 <U00E2> LATIN SMALL LETTER A WITH CIRCUMFLEX
+<a?> /xE3 <U00E3> LATIN SMALL LETTER A WITH TILDE
+<a:> /xE4 <U00E4> LATIN SMALL LETTER A WITH DIAERESIS
+<aa> /xE5 <U00E5> LATIN SMALL LETTER A WITH RING ABOVE
+<ae> /xE6 <U00E6> LATIN SMALL LETTER AE
+<c,> /xE7 <U00E7> LATIN SMALL LETTER C WITH CEDILLA
+<e!> /xE8 <U00E8> LATIN SMALL LETTER E WITH GRAVE
+<e'> /xE9 <U00E9> LATIN SMALL LETTER E WITH ACUTE
+<e/>> /xEA <U00EA> LATIN SMALL LETTER E WITH CIRCUMFLEX
+<e:> /xEB <U00EB> LATIN SMALL LETTER E WITH DIAERESIS
+<i!> /xEC <U00EC> LATIN SMALL LETTER I WITH GRAVE
+<i'> /xED <U00ED> LATIN SMALL LETTER I WITH ACUTE
+<i/>> /xEE <U00EE> LATIN SMALL LETTER I WITH CIRCUMFLEX
+<i:> /xEF <U00EF> LATIN SMALL LETTER I WITH DIAERESIS
+<d-> /xF0 <U00F0> LATIN SMALL LETTER ETH (Icelandic)
+<n?> /xF1 <U00F1> LATIN SMALL LETTER N WITH TILDE
+<o!> /xF2 <U00F2> LATIN SMALL LETTER O WITH GRAVE
+<o'> /xF3 <U00F3> LATIN SMALL LETTER O WITH ACUTE
+<o/>> /xF4 <U00F4> LATIN SMALL LETTER O WITH CIRCUMFLEX
+<o?> /xF5 <U00F5> LATIN SMALL LETTER O WITH TILDE
+<o:> /xF6 <U00F6> LATIN SMALL LETTER O WITH DIAERESIS
+<-:> /xF7 <U00F7> DIVISION SIGN
+<o//> /xF8 <U00F8> LATIN SMALL LETTER O WITH STROKE
+<u!> /xF9 <U00F9> LATIN SMALL LETTER U WITH GRAVE
+<u'> /xFA <U00FA> LATIN SMALL LETTER U WITH ACUTE
+<u/>> /xFB <U00FB> LATIN SMALL LETTER U WITH CIRCUMFLEX
+<u:> /xFC <U00FC> LATIN SMALL LETTER U WITH DIAERESIS
+<y'> /xFD <U00FD> LATIN SMALL LETTER Y WITH ACUTE
+<th> /xFE <U00FE> LATIN SMALL LETTER THORN (Icelandic)
+<y:> /xFF <U00FF> LATIN SMALL LETTER Y WITH DIAERESIS
+<NUL> /x00 <U0000> NUL
+<SOH> /x01 <U0001> START OF HEADING (SOH)
+<STX> /x02 <U0002> START OF TEXT (STX)
+<ETX> /x03 <U0003> END OF TEXT (ETX)
+<EOT> /x04 <U0004> END OF TRANSMISSION (EOT)
+<ENQ> /x05 <U0005> ENQUIRY (ENQ)
+<ACK> /x06 <U0006> ACKNOWLEDGE (ACK)
+<alert> /x07 <U0007> BELL (BEL)
+<BEL> /x07 <U0007> BELL (BEL)
+<backspace> /x08 <U0008> BACKSPACE (BS)
+<tab> /x09 <U0009> CHARACTER TABULATION (HT)
+<newline> /x0A <U000A> LINE FEED (LF)
+<vertical-tab> /x0B <U000B> LINE TABULATION (VT)
+<form-feed> /x0C <U000C> FORM FEED (FF)
+<carriage-return> /x0D <U000D> CARRIAGE RETURN (CR)
+<DLE> /x10 <U0010> DATALINK ESCAPE (DLE)
+<DC1> /x11 <U0011> DEVICE CONTROL ONE (DC1)
+<DC2> /x12 <U0012> DEVICE CONTROL TWO (DC2)
+<DC3> /x13 <U0013> DEVICE CONTROL THREE (DC3)
+<DC4> /x14 <U0014> DEVICE CONTROL FOUR (DC4)
+<NAK> /x15 <U0015> NEGATIVE ACKNOWLEDGE (NAK)
+<SYN> /x16 <U0016> SYNCHRONOUS IDLE (SYN)
+<ETB> /x17 <U0017> END OF TRANSMISSION BLOCK (ETB)
+<CAN> /x18 <U0018> CANCEL (CAN)
+<SUB> /x1A <U001A> SUBSTITUTE (SUB)
+<ESC> /x1B <U001B> ESCAPE (ESC)
+<IS4> /x1C <U001C> FILE SEPARATOR (IS4)
+<IS3> /x1D <U001D> GROUP SEPARATOR (IS3)
+<intro> /x1D <U001D> GROUP SEPARATOR (IS3)
+<IS2> /x1E <U001E> RECORD SEPARATOR (IS2)
+<IS1> /x1F <U001F> UNIT SEPARATOR (IS1)
+<DEL> /x7F <U007F> DELETE (DEL)
+<space> /x20 <U0020> SPACE
+<exclamation-mark> /x21 <U0021> EXCLAMATION MARK
+<quotation-mark> /x22 <U0022> QUOTATION MARK
+<number-sign> /x23 <U0023> NUMBER SIGN
+<dollar-sign> /x24 <U0024> DOLLAR SIGN
+<percent-sign> /x25 <U0025> PERCENT SIGN
+<ampersand> /x26 <U0026> AMPERSAND
+<apostrophe> /x27 <U0027> APOSTROPHE
+<left-parenthesis> /x28 <U0028> LEFT PARENTHESIS
+<right-parenthesis> /x29 <U0029> RIGHT PARENTHESIS
+<asterisk> /x2A <U002A> ASTERISK
+<plus-sign> /x2B <U002B> PLUS SIGN
+<comma> /x2C <U002C> COMMA
+<hyphen> /x2D <U002D> HYPHEN-MINUS
+<hyphen-minus> /x2D <U002D> HYPHEN-MINUS
+<period> /x2E <U002E> FULL STOP
+<full-stop> /x2E <U002E> FULL STOP
+<slash> /x2F <U002F> SOLIDUS
+<solidus> /x2F <U002F> SOLIDUS
+<zero> /x30 <U0030> DIGIT ZERO
+<one> /x31 <U0031> DIGIT ONE
+<two> /x32 <U0032> DIGIT TWO
+<three> /x33 <U0033> DIGIT THREE
+<four> /x34 <U0034> DIGIT FOUR
+<five> /x35 <U0035> DIGIT FIVE
+<six> /x36 <U0036> DIGIT SIX
+<seven> /x37 <U0037> DIGIT SEVEN
+<eight> /x38 <U0038> DIGIT EIGHT
+<nine> /x39 <U0039> DIGIT NINE
+<colon> /x3A <U003A> COLON
+<semicolon> /x3B <U003B> SEMICOLON
+<less-than-sign> /x3C <U003C> LESS-THAN SIGN
+<equals-sign> /x3D <U003D> EQUALS SIGN
+<greater-than-sign> /x3E <U003E> GREATER-THAN SIGN
+<question-mark> /x3F <U003F> QUESTION MARK
+<commercial-at> /x40 <U0040> COMMERCIAL AT
+<left-square-bracket> /x5B <U005B> LEFT SQUARE BRACKET
+<backslash> /x5C <U005C> REVERSE SOLIDUS
+<reverse-solidus> /x5C <U005C> REVERSE SOLIDUS
+<right-square-bracket> /x5D <U005D> RIGHT SQUARE BRACKET
+<circumflex> /x5E <U005E> CIRCUMFLEX ACCENT
+<circumflex-accent> /x5E <U005E> CIRCUMFLEX ACCENT
+<underscore> /x5F <U005F> LOW LINE
+<low-line> /x5F <U005F> LOW LINE
+<grave-accent> /x60 <U0060> GRAVE ACCENT
+<left-brace> /x7B <U007B> LEFT CURLY BRACKET
+<left-curly-bracket> /x7B <U007B> LEFT CURLY BRACKET
+<vertical-line> /x7C <U007C> VERTICAL LINE
+<right-brace> /x7D <U007D> RIGHT CURLY BRACKET
+<right-curly-bracket> /x7D <U007D> RIGHT CURLY BRACKET
+<tilde> /x7E <U007E> TILDE
+END CHARMAP
--- /dev/null
+#!/store/bin/perl
+#
+# Name: aliases2html
+# Author: Petter Reinholdtsen <pere@td.org.uit.no>
+# Date: 1997-05-07
+# Changed: 1998-08-20
+# Version: 1.2
+#
+# Creates an html overview of the aliases file.
+#
+# 1998-08-20 v1.2 Added comment about where this program was found
+# 1997-08-20 v1.1 added NIS-support using module Net::NIS
+# 1997-05-09 v1.0 released
+
+use Getopt::Std;
+
+getopts("f:nv");
+
+if ($opt_n) {
+ print STDERR "Reading aliases from NIS\n" if ($opt_v);
+ eval 'use Net::NIS::Table;';
+ die $@ if ($@);
+ $map = Net::NIS::Table->new("mail.aliases");
+ $aliases = $map->list();
+ for $alias (keys %{$aliases}) {
+ chop($$aliases{$alias}) if ($$aliases{$alias} =~ m/\0$/);
+ if ("\@\0" ne $alias) {
+ @e = split(/\s*,\s*/, $$aliases{$alias});
+ chop($alias) if ($alias =~ m/\0$/);
+ $aliases{$alias} = [@e];
+ }
+ }
+} else {
+ if ($opt_f) {
+ print "Reading aliases from $opt_f\n" if ($opt_v);
+ %aliases = &parseAliases($opt_f);
+ } else {
+ %aliases = &parseAliases;
+ }
+}
+
+
+&expandAliases();
+
+$date = localtime();
+
+print <<EOF;
+<HTML>
+<HEAD><TITLE>Aliases</TITLE></HEAD>
+<!-- Generated by $0 -->
+<BODY>
+<H1>Aliases</H1>
+Updated $date
+<TABLE>
+<TR><TD valign="top"><UL>
+EOF
+
+for $alias (sort keys %aliases) {
+ print "<LI><A HREF=\"\#$alias\">$alias</A>\n";
+}
+print "</UL></TD><TD>\n";
+
+for $alias (sort keys %aliases) {
+ print "<A NAME=\"$alias\"><H2>$alias</H2>\n<UL>\n";
+ for $entry (sort @{$aliases{$alias}}) {
+ $entry = expandEntry($entry);
+ print "<LI>$entry\n";
+ }
+ print "</UL></A>\n";
+}
+print <<EOF;
+</TD></TR></TABLE></BODY></HTML>
+EOF
+
+exit 0;
+##
+# Expand all aliases to final receivers
+sub expandAliases {
+ local($expanded) = 1;
+ while ($expanded) {
+ my($alias);
+ $expanded = 0;
+ for $alias (keys %aliases) {
+ local(@e) = ();
+ for $entry (@{$aliases{$alias}}) {
+ if ($aliases{$entry}) {
+ push(@e, @{$aliases{$entry}});
+ $expanded = 1;
+ } elsif ($entry =~ /^:include:(.*)$/) {
+ push(@e, getIncEntries($1));
+ } else {
+ push(@e, $entry);
+ }
+ }
+ $aliases{$alias} = [@e];
+ }
+ }
+}
+
+##
+# Read and expand aliases from alias-file
+sub parseAliases {
+ if (! @_ ) {
+ local($aliases) = "/etc/aliases";
+ } else {
+ local($aliases) = @_;
+ }
+
+ # Read alias-file
+ local(%a);
+ open(ALIASES, "<$aliases") || die "Unable to open $aliases for reading";
+ while (<ALIASES>) {
+ chomp;
+ next if (/^\#/);
+ next if (/^\s*$/);
+ local($alias, $content) = m/^\s*([^:]+):\s*(.*)$/;
+ local(@content) = split(/\s*,\s*/, $content);
+ local(@entries);
+ undef @entries;
+ while (@content) {
+ local($entry) = pop @content;
+ push(@entries, $entry);
+ }
+ $a{$alias} = [@entries];
+ }
+ close(ALIASES);
+
+ return %a;
+}
+
+##
+# Look up username in passwd
+sub expandEntry {
+ local($entry) = @_;
+ ($name,$passwd,$uid,$gid,
+ $quota,$comment,$gcos,$dir,$shell) = getpwnam($entry);
+ $gcos =~ s/,.*$//;
+ return "$gcos <$entry>";
+}
+
+##
+# Expand alias include files
+sub getIncEntries {
+ local($filename) = @_;
+ local(@entries);
+ if ( !open(INCFILE, "<$filename") ) {
+ warn "Unable to open $filename for reading";
+ push(@entries, "[file $filename]");
+ return @entries;
+ }
+ while (<INCFILE>) {
+ chomp;
+ next if (/^\#/);
+ next if (/^\s*$/);
+ push(@entries, $_);
+ }
+ close(INCFILE);
+ return @entries;
+}
--- /dev/null
+#!/usr/bin/perl -w
+#
+# Author: Petter Reinholdtsen <pere@td.org.uit.no>
+# Date: 2001-08-05
+# Source: http://www.student.uit.no/~pere/linux/
+#
+# Read available translations from .po files, and allow translations
+# already done in one file to be inserted into all the other places
+# where the original text occurs.
+#
+# Usage: auto_translate <po-files>
+#
+# Changes:
+# 2001-08-05 v0.2
+# Fixed bug. Unable to handle multiline 'msgid'.
+# 2001-08-05 v0.3
+# Add 'fuzzy' tag when inserting text.
+# 2001-08-05 v0.4
+# Only add 'fuzzy' tag in the changed files.
+
+#use strict;
+use Getopt::Std;
+
+my ($pofile, %translation, @problem, %msgstrs, %files);
+my $showfile = 1;
+
+#########################################################################
+
+sub add_translation {
+ my ($pofile, $msgid, $msgstr) = @_;
+# print " Translation: $msgid = $msgstr\n";
+ $msgstr = $1;
+ $msgstrs{"$msgid\t$msgstr"}++;
+ push(@{$files{"$msgid\t$msgstr"}}, $pofile);
+ if ( !defined($translation{$msgid}) ) {
+ push(@{$translation{$msgid}}, $msgstr);
+ } else {
+ if ( ! in_array($msgstr, $translation{$msgid}) ) {
+ push(@{$translation{$msgid}}, $msgstr);
+ push(@problem, $msgid) unless grep($msgid, @problem);
+ }
+ }
+ $msgid = "";
+}
+
+sub in_array ($$) {
+ my ($str, $aref) = @_;
+ my $test;
+ for $test (@$aref) {
+ return 1 if ($test eq $str);
+ }
+ return 0;
+}
+
+sub replace_translation {
+ my ($filename, $msgid, $msgstr) = @_;
+ my $count = 0;
+ open(POTMPFILE, ">$filename.new") || die "Unable to open $filename.new";
+
+ open(POFILE, "<$filename") || die "Unable to open $filename";
+ while (<POFILE>) {
+ chomp;
+ my @lines = ();
+ if (m/^msgid\s+\"(.*)\"\s*$/) {
+ my $thisid = $1;
+ my $thisstr = "";
+ push(@lines, $_);
+ while (<POFILE>) {
+ chomp;
+ push(@lines, $_);
+ if (m/^\s*\"(.+)\"\s*$/) {
+ print "Appending \'$thisid\' \n + \'$1\'\n" if ($debug);
+ $thisid .= $1;
+ }
+ if (m/^msgstr\s\"(.*)\"\s*$/) {
+ print "ID: $thisid\n" if ($debug);
+ $thisstr = $1;
+ while (<POFILE>) {
+ chomp;
+ push(@lines, $_);
+ last if (/^\s*$/);
+ if (m/^\s*\"(.+\")\s*$/) {
+ $thisstr .= $1;
+ }
+ }
+ print "Msg: $thisstr\n" if ($debug);
+ last;
+ }
+ }
+ if ("\"$thisid\"" eq $msgid &&
+ "\"$thisstr\"" ne $msgstr) {
+ print POTMPFILE "#, fuzzy\n";
+ print POTMPFILE "msgid $msgid\n";
+ print POTMPFILE "msgstr $msgstr\n";
+ print POTMPFILE "\n";
+ $count++;
+ } else {
+ print POTMPFILE join("\n", @lines), "\n";
+ }
+ } else {
+ print POTMPFILE "$_\n";
+ }
+ }
+ close(POFILE) || die "unable to close $filename";
+ close(POTMPFILE) || die "unable to close $filename.new";
+ rename "$filename.new", $filename;
+
+ if (0 == $count) {
+ print "Did not find anything to replace!\n";
+ }
+}
+
+sub choose_transl {
+ my ($msgid) = @_;
+ print "\n$msgid\n";
+ my $msgstr;
+ my $num = 0;
+ print " $num - skip this translation\n";
+ my @strings = sort { $msgstrs{"$msgid\t$b"} <=> $msgstrs{"$msgid\t$a"}; } @{$translation{$msgid}};
+ my %curfiles;
+ for $msgstr (@strings) {
+ $num++;
+ print " $num $msgstr # (" . $msgstrs{"$msgid\t$msgstr"}. ") " or die;
+ print "[" . join(",", @{$files{"$msgid\t$msgstr"}}) . "]" or die if $showfile;
+ print "\n" or die;
+ my $file;
+ for $file (@{$files{"$msgid\t$msgstr"}}) {
+ $curfiles{$file}++;
+ }
+ }
+ if ($num != 2)
+ {
+ print "** To many choices. **\n";
+ return;
+ }
+
+ print "Choice: ";
+ $choice = <STDIN>;
+
+ return if (0 == $choice);
+ $msgstr = $strings[$choice-1];
+ print "\n Translating $msgid as $msgstr in\n";
+ for $file (keys %curfiles) {
+ print " $file\n";
+ replace_translation($file, $msgid, $msgstr);
+ }
+}
+
+# Remove leading space and '&' before comparing
+sub kde_magic_sort {
+ my $aa = $a;
+ my $bb = $b;
+
+ $aa =~ s/\&|^\s+//;
+ $bb =~ s/\&|^\s+//;
+ return lc($aa) cmp lc($bb);
+}
+
+sub translate {
+ my ($msgid);
+ my ($count, $icount) = (0,0);
+ for $msgid (sort kde_magic_sort keys %translation ) {
+ $count++;
+ if ( 1 < scalar(@{$translation{$msgid}}) ) {
+ $icount++;
+ choose_transl($msgid);
+ }
+ }
+}
+
+sub read_files
+{
+ my @argv = @_;
+
+ for $pofile ( @argv ) {
+ open(POFILE, "<$pofile") || next;
+
+ my ($next, $msgid, $msgstr);
+
+ while (1) {
+ $_ = $next || <POFILE>;
+ last unless $_;
+ $next = "";
+
+ chomp;
+
+ s/^\#.+$//; # Remove comments
+
+ next if (/^\s*$/);
+
+ if (/^msgid (\".+)/) {
+ $msgid = $1;
+ while (<POFILE>) {
+ chomp;
+ unless (/^\"/) {
+ $next = $_;
+ last;
+ }
+ $msgid .= $_;
+ $msgid =~ s/\"\"//;
+ }
+
+ $msgstr = "";
+ next;
+ }
+
+ if (/^msgstr (\".+)/) {
+ $msgstr = $1;
+ while (<POFILE>) {
+ chomp;
+ unless (/^\"/) {
+ $next = $_;
+ last;
+ }
+ $msgstr .= $_;
+ $msgstr =~ s/\"\"//;
+ }
+
+ add_translation($pofile, $msgid, $msgstr);
+
+ $msgid = "";
+ $msgstr = "";
+ }
+
+ }
+ close(POFILE);
+ }
+}
+#########################################################################
+
+getopt('f');
+
+if (defined $opt_f) {
+ $showfile = 1;
+ print "Showing filenames\n";
+}
+
+print "Reading .po files...\n";
+read_files(@ARGV);
+
+print "Ready to autotranslate\n";
+translate();
+
--- /dev/null
+#!/bin/sh
+#
+# Author: Petter Reinholdtsen <pere@td.org.uit.no>
+# Date: 1999-02-02
+#
+# Convert CD music to mp3, fetching title, artist and track names from CDDB
+
+TMPDIR=/var/tmp
+CDDEV=/dev/cdrom
+CDINFO=$TMPDIR/cdinfo-$$
+
+# Fetch CD info
+gcdplay -i -q > $CDINFO
+
+PWD=`pwd`
+
+TITLE=`grep 'CD TITLE:' $CDINFO|cut -d: -f2-`
+TTITLE=`echo $TITLE|tr ' ()' '_'|sed 's/_\/_/\//'`
+
+if test -z "$TITLE"; then
+ echo "Unable to find info on CD from cddb. Not ripping"
+ exit 1
+fi
+
+echo "Converting CD: $TITLE"
+
+mkdirhier $TTITLE
+cd $TTITLE
+
+pid='0'
+for track in `grep '^[0-9]*:' $CDINFO|tr -s ' ()\/' '_'|sed 's/:_/:/'`
+do
+ t=`echo $track|cut -d: -f1`
+ WAVFILE=$TMPDIR/cdinfo-$$-track$t.wav
+ OUT1=$TMPDIR/cdinfo-$$-track$t.out
+ OUT2=$TMPDIR/cdinfo-$$-track$t-enc.out
+
+ echo "Reading track $t ($track)"
+ time nice cdda2wav -D $CDDEV -t $t $WAVFILE > $OUT1 2>&1
+ echo "waiting for encoding (pid=$pid) to end"
+ wait $pid # > /dev/null 2>&1
+ echo "Starting to encode track $t"
+ time nice l3enc $WAVFILE $track.mp3 > $OUT2 2>&1 &
+ pid=$!
+
+ # Give l3enc time to read file before removing it
+ (sleep 10; nice rm -f $WAVFILE $OUT1 $OUT2) &
+done
+rm -f $CDINFO
+
+cd $PWD
--- /dev/null
+#!/usr/bin/perl
+#
+# Author: Espen Skoglund <espensk@stud.cs.uit.no>
+# Date: before 1999-02-08
+#
+# Rip music from CD and convert to MP3
+#
+# Hacked by Petter Reinholdtsen <pere@td.org.uit.no>, 1999-02-08
+
+sub usage {
+ print "USAGE: $0 [-h][-t] <topdir> [<start track> [<endtrack>]]\n";
+}
+
+use File::Path;
+
+$rip_times_only = 0;
+while ( $_ = shift ) {
+ if ( /^-t$/ ) {
+ $rip_times_only = 1;
+ } elsif ( /^-?-h(elp)?$/ ) {
+ $0 =~ s!.*/([^/]+)$!\1!;
+ usage();
+ exit;
+ } else {
+ push( @args, $_ );
+ }
+}
+($topdir, $trbegin, $trend) = @args;
+
+if ( ! $topdir ) {
+ usage();
+ exit;
+}
+
+$dagrab = find_prog_in_path("dagrab");
+$cdparanoia = find_prog_in_path("cdparanoia");
+$cdda2wav = find_prog_in_path("cdda2wav");
+$gcdplay = find_prog_in_path("gcdplay");
+
+$l3enc = find_prog_in_path("l3enc");
+$bladeenc = find_prog_in_path("bladeenc");
+$mp3_8hz = find_prog_in_path("8hz-mp3");
+
+# Choose encoder
+if ( $l3enc ) {
+ $mp3encoder = "$l3enc _infile_ _outfile_";
+} elsif ( $bladeenc ) {
+ $mp3encoder = "$bladeenc _infile_ _outfile_ -br 192000";
+} elsif ( $mp3_8hz ) {
+ $mp3encoder = "$mp3_8hz -b 128 _infile_ _outfile_";
+}
+
+$tmp = $ENV{TMPDIR} || '/tmp';
+
+$[ = 1;
+
+## Get artist and tracknages from CDDB
+if ( $gcdplay ) {
+ # extract online from CDDB
+ open (GCDPLAY, "$gcdplay -q -i|") || die "open($gcdplay -q -i |): $!\n";
+ while (<GCDPLAY>) {
+ chomp;
+ if (m/^CD TITLE:/) {
+ ($artist) = m%^CD TITLE: (.+\S)\s*/[^/]+$%;
+ ($title) = m%/\s*([^/]+)$%;
+ }
+ if (m/\d+: /) {
+ my ($track, $name) = m/^(\d+): (.+)$/;
+ $names[$track] = $name;
+ }
+ }
+ close(GCDPLAY);
+} else {
+ print "Unable to find gcdplay. It is required to fetch title and track\n";
+ print "names from CDDB. Fetch gcdplay from\n";
+ print "<URL:http://www.korax.net/~mglisic/gcdplay/>.\n";
+ exit;
+}
+
+if ($artist) {
+ $artist =~ s%/%&%g;
+ print "Artist: $artist\n";
+ print "Title: $title\n";
+ $destdir = "$topdir/$artist/$title";
+ mkpath($destdir, 0, 0775);
+} else {
+ print "Error: CD is unknown to CDDB. Unable to extract info, and\n";
+ print "thereby unable to rip. Add it to CDDB.\n";
+ exit;
+}
+$numnames = scalar(@names);
+
+## Get tracktimes
+if ( $cdparanoia ) {
+ open( TOC, "$cdparanoia -Q 2>&1|" ) || die "open(cdparanoia -Q |): $!\n";
+ while( <TOC> ) {
+ push( @times, $1 ) if /^\s*\d+\.\s*\d+\s*\[(\d+:\d*)/;
+ }
+ close TOC;
+} elsif ( $dagrab ) {
+ open( TOC, "$dagrab -i 2>&1|" ) || die "open(dagrab -i |): $!\n";
+ while( <TOC> ) {
+ push( @times, $1 ) if /\d\d:(\d\d:\d\d)/;
+ }
+ close TOC;
+} elsif ( $gcdplay ) {
+ open( TOC, "$gcdplay -di 2>&1|" ) || die "open(gcdplay -di |): $!\n";
+ my (@starttimes, $endtime);
+ while( <TOC> ) {
+ chomp;
+ $endtime = $1 * 60 + $2 if /^\d+ Tracks, (\d+) minutes and (\d+) seconds/;
+ push(@starttimes, $1 * 60 + $2) if /minute: \[(\d+)\] second: \[(\d+)\]/;
+ }
+ close TOC;
+
+ my $lasttime;
+ for $time (@starttimes, $endtime) {
+ if ($lasttime) {
+ my $sec = $time - $lasttime;
+ my $time = sprintf("%02d:%02d", int($sec / 60), ($sec%60));
+ push(@times, $time);
+ }
+ $lasttime = $time;
+ }
+}
+$numtracks = scalar(@times);
+
+## Warn if the number of tracknames does not match number of tracks
+if ( $numtracks && !$rip_times_only && $numnames != $numtracks ) {
+ warn ("Warn: The number of names is not equal to the Number of ".
+ "tracks on CD.\n (Number of tracks = $numtracks, ".
+ "number of names = $numnames)\n");
+}
+$trbegin = 1 unless $trbegin;
+$trend = $numtracks if $numtracks && !$trend;
+
+## Store tracktimes.
+$timesfile = "$destdir/.times";
+open( TIMES, ">$timesfile" ) || die "open(>$timesfile): $!\n";
+foreach $time ( @times ) {
+ print TIMES "$time\n";
+}
+close TIMES;
+
+exit if $rip_times_only;
+
+## Start processing the tracks
+my $pid = 0;
+foreach $track ( $trbegin .. $trend ) {
+
+ # Get the track from the CD.
+ if ( $cdda2wav ) {
+ system "$cdda2wav -D /dev/cdrom -x -t $track+$track ".
+ "$tmp/track-$track.wav 2>&-";
+ } elsif ( $dagrab ) {
+ system "$dagrab -f $tmp/track-$track.wav $track 2>/dev/null 1>/dev/null";
+ } elsif ( $cdparanoia ) {
+ system "$cdparanoia $track $tmp/track-$track.wav 2>&-";
+ } else {
+ die "I don't know of any cdrippers.\n";
+ }
+
+ # Wait for the previous encoding to get finished.
+ waitpid( $pid, 0 ) if $pid != 0;
+
+ # Fork off a new process that does the encoding. We may then start
+ # reading another track from the CD.
+ unless ( $pid = fork ) {
+ chdir($destdir);
+ my $time = $times[$track];
+ my $name = $names[$track] || "Track $track";
+ my $mp3enc = $mp3encoder;
+ my $destfile = sprintf( "%02d - %s.mp3", $track, $name );
+ $destfile =~ s/\"/\\\"/g;
+ $destfile =~ s/\\/\\\\/g;
+ $mp3enc =~ s!_infile_!$tmp/track-$track.wav!;
+ $mp3enc =~ s!_outfile_!\"$destfile\"!;
+
+ print sprintf("Encoding: %02d - $name\n", $track);
+
+ # MP3 encode the track
+ system "$mp3enc >/dev/null 2>&1";
+
+ # Remove temporary wav file.
+ unlink "$tmp/track-$track.wav";
+ exit;
+ }
+
+}
+
+# Wait for last encoding to be finished
+waitpid( $pid, 0 ) if $pid;
+
+sub find_prog_in_path {
+ my $prog = shift;
+ for $dir (split(/:/, $ENV{PATH})) {
+ my $fullpath = "$dir/$prog";
+ return $fullpath if ( -x $fullpath );
+ }
+ return; # Not found
+}
+
--- /dev/null
+#!/store/bin/perl5 -w
+#
+# Author: Petter Reinholdtsen <pere@td.org.uit.no>
+# Date: 1998-08-31
+#
+# Check GNU libc charmaps for consistent symbolic naming and Unicode
+# encoding in comments.
+#
+# I run it like this: 'charmaps-check ISO_10646 ISO-IR-197' to
+# check if ISO-IR-197 use the same names as ISO-10646 (Unicode)
+
+use strict;
+use vars qw($filename $error %unicodes %codes
+ $code_set_name $comment_char $escape_char);
+
+$error = 0;
+while ($filename = shift) {
+
+ # *** Default values ***
+ $escape_char = '\\';
+ $comment_char = '#';
+
+ open(CHARMAP, "<$filename") || warn "Unable to open $filename";
+ while (<CHARMAP>) {
+ if (/<code_set_name>\s*(.*)$/) {
+ $code_set_name = $1;
+ next;
+ }
+ if (/<comment_char>\s*(\S+)/) {
+ $comment_char = $1;
+ next;
+ }
+
+ if (/<escape_char>\s*(\S+)/) {
+ $escape_char = $1;
+ next;
+ }
+ parse_charmap() if (/^CHARMAP/);
+ }
+ close CHARMAP;
+}
+exit 1 if ($error);
+
+# Convert hex, octal and decimal string values to numbers
+# Must handle /x0f => 15 /x0f/x0f => 3855
+sub parse_encoding {
+ my $input = shift;
+
+ my $base = 1;
+ my $value = 0;
+ while ( $input ) {
+ $value *= $base;
+
+ if ( $input =~ m/${escape_char}x([0-9a-fA-F]{2})/ ) {
+ my $hex = $1;
+ my $number = oct("0x".$hex);
+ $value += $number;
+ $input =~ s/${escape_char}x$hex//; # Remove this part of the string
+ $base = 16*16;
+ }
+ }
+
+ return $value;
+}
+
+# Receive param with this format, and return them as array
+# <SO> /x0E <U000E> SHIFT OUT (SO)
+# @retval = ('SO', 14, '<U000U> SHIFT OUT');
+sub parse_charmap_line {
+ my $line = shift;
+
+ # Skip comments
+ return if ($comment_char && /^%comment_char/);
+
+ # Skip blank lines
+ return if ($line =~ /^\s*$/);
+
+ my ($code, $encoding, $comment) =
+ $line =~ m/^<(\S+)>\s+(\S+)\s+(.+)$/;
+ $encoding = parse_encoding($encoding);
+ return ($code, $encoding, $comment);
+}
+
+sub parse_charmap {
+ while (<CHARMAP>) {
+ if (/^END CHARMAP$/) {
+ $code_set_name = "[unknown]";
+ return;
+ }
+
+ chomp;
+ my $line = $_;
+
+ my ($code, $encoding, $comment) = parse_charmap_line($line);
+ my ($unicode, $name);
+
+ print "Unable to parse line: $line\n" if ( ! $comment );
+
+ if ( $comment =~ m/<U([0-9a-fA-Fx]{4})>\s+(.*)/ ) {
+ ($unicode, $name) = (oct("0x".$1), $2);
+ } else {
+ $unicode = $encoding;
+ $name = $comment;
+ }
+
+ if ($code) {
+
+ # ************ Check UNICODE value<->name *****************
+ # Don't test U0000, as it is named both 'NULL' and 'NUL'
+ if (0 != $unicode && exists $unicodes{$unicode}) {
+ unless ($unicodes{$unicode} eq $name) {
+ print "$filename\[$code_set_name\]: Same unicode ($unicode) but different name\n \"$name\"\n != \"$unicodes{$unicode}\"\n";
+ $error = 1;
+ }
+ } else {
+ $unicodes{$unicode} = $name;
+ }
+ # *********** Check UNICODE value<->code *****************
+ # XXX Hm, don't seem to work right. Don't handle multiple
+ # codes for the same name
+ if (exists $codes{$code}) {
+ unless ($codes{$code} eq $unicode) {
+ print "$filename\[$code_set_name\]: Same code ($code) but different unicode \"$unicode\" != \"$codes{$code}\"\n";
+ $error = 1;
+ }
+ } else {
+ $codes{$code} = $unicode;
+ }
+ }
+ }
+}
--- /dev/null
+#!/usr/bin/perl -w
+#
+# Author: Petter Reinholdtsen <pere@td.org.uit.no>
+# Date: 2001-08-04
+# Source: http://www.student.uit.no/~pere/linux/
+#
+# Check .po files for consistency. Write two files msg-all and
+# msg-inconsistent.
+#
+# Usage: $0 <po-files>
+
+#use strict;
+use Getopt::Std;
+
+getopt('a');
+
+my ($pofile, %translation, @problem, %msgstrs, %files);
+
+my $showfile = 1;
+
+for $pofile ( @ARGV ) {
+ open(POFILE, "<$pofile") || next;
+
+ my ($next, $msgid, $msgstr);
+
+ while (1) {
+ $_ = $next || <POFILE>;
+ last unless $_;
+ $next = "";
+
+ chomp;
+
+ s/^\#.+$//; # Remove comments
+
+ next if (/^\s*$/);
+
+ if (/^msgid (\".+)/) {
+ $msgid = $1;
+ while (<POFILE>) {
+ chomp;
+ unless (/^\"/) {
+ $next = $_;
+ last;
+ }
+ $msgid .= $_;
+ $msgid =~ s/\"\"//;
+ }
+
+ $msgstr = "";
+ next;
+ }
+
+ if (/^msgstr (\".+)/) {
+ $msgstr = $1;
+ while (<POFILE>) {
+ chomp;
+ unless (/^\"/) {
+ $next = $_;
+ last;
+ }
+ $msgstr .= $_;
+ $msgstr =~ s/\"\"//;
+ }
+
+ add_translation($pofile, $msgid, $msgstr);
+
+ $msgid = "";
+ $msgstr = "";
+ }
+
+ }
+ close(POFILE);
+}
+
+sub add_translation {
+ my ($pofile, $msgid, $msgstr) = @_;
+# print " Translation: $msgid = $msgstr\n";
+ $msgstr = $1;
+ $msgstrs{"$msgid\t$msgstr"}++;
+ $files{"$msgid\t$msgstr"} = $pofile;
+ if ( !defined($translation{$msgid}) ) {
+ push(@{$translation{$msgid}}, $msgstr);
+ } else {
+ if ( ! in_array($msgstr, $translation{$msgid}) ) {
+ push(@{$translation{$msgid}}, $msgstr);
+ push(@problem, $msgid) unless grep($msgid, @problem);
+ }
+ }
+ $msgid = "";
+}
+
+sub in_array ($$) {
+ my ($str, $aref) = @_;
+ my $test;
+ for $test (@$aref) {
+ return 1 if ($test eq $str);
+ }
+ return 0;
+}
+
+sub output_transl {
+ my ($fp, $msgid) = @_;
+ print $fp "\nmsgid $msgid\n";
+ my $msgstr;
+ for $msgstr (sort @{$translation{$msgid}}) {
+ print $fp "msgstr $msgstr # (" . $msgstrs{"$msgid\t$msgstr"}. ") " or die;
+ print $fp "[" . $files{"$msgid\t$msgstr"} . "]" or die if $showfile;
+ print $fp "\n" or die;
+ }
+}
+
+output();
+
+# Remove leading space and '&' before comparing
+sub kde_magic_sort {
+ my $aa = $a;
+ my $bb = $b;
+
+ $aa =~ s/\&|^\s+//;
+ $bb =~ s/\&|^\s+//;
+ return lc($aa) cmp lc($bb);
+}
+
+sub output {
+ my ($msgid);
+ my ($count, $icount) = (0,0);
+ if ($opt_a) {
+ open (ALL, ">msg-all");
+ print "Creating msg-all\n";
+ }
+ open (INCONS, ">msg-inconsistent");
+ print "Creating msg-inconsistent\n";
+ for $msgid (sort kde_magic_sort keys %translation ) {
+ if ($opt_a) {
+ output_transl(ALL, $msgid);
+ }
+ $count++;
+ if ( 1 < scalar(@{$translation{$msgid}}) ) {
+ $icount++;
+ output_transl(INCONS, $msgid);
+ }
+ }
+ print ALL "\n#Total # of messages: $count\n" if ($opt_a);
+ print INCONS "\n#Total inconsistent: $icount of $count (",
+ int(100*$icount/$count), "%)\n";
+
+ close(INCONS);
+ close(ALL) if ($opt_a);
+}
--- /dev/null
+#!/store/bin/perl
+
+##
+# Fetches all crontabs on the hosts specified on the command line
+# and presents them sorted on user, machine and time.
+#
+# @author Petter Reinholdtsen <pere@td.org.uit.no>
+# @params host1 [host2 ...]
+# @made 1996-07-27
+# @version $Id: cron-summary,v 1.1 2003/06/02 13:01:37 pere Exp $
+sub about {}
+
+$crondir = "/var/spool/cron/crontabs";
+$rsh = $ENV{RSH} || 'rsh';
+
+@hosts = @ARGV;
+
+foreach $host (@hosts) {
+ @users = &get_cronusers($host);
+ print "Users at $host: ".join(",", @users)."\n";
+ foreach $user (@users) {
+ &parse_crontab($host, $user);
+ }
+}
+
+&show_cronsummary();
+
+##
+# Fetches the contents of $crondir from $host and returns all users as
+# an array
+#
+# @params $host
+# @return @users
+sub get_cronusers {
+ local($host) = @_;
+ local($res) = `$rsh $host echo $crondir/\\*`;
+ $res =~ s%$crondir/%%g;
+ local(@users) = split(/\s+/, $res);
+ return @users;
+}
+
+##
+# Fetches the crontab-file for $user from $host and stores the info in
+# @cron.
+# @params $host, $user
+# @return "" on failures and "1" on success.
+sub parse_crontab {
+ local($host, $user) = @_;
+ open(CRONTAB, "rsh $host cat $crondir/$user|") ||
+ die "Unable to open crontab on $host for $user";
+ while (<CRONTAB>) {
+ next if (/^\#/);
+ ($min, $hour, $dom, $moy, $daw, $command) =
+ m/^(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(.+)$/;
+ push(@cron,join(":", $user, $host, $hour, $min, $dom, $moy, $daw, $command));
+ }
+ close(CRONTAB);
+ return "1";
+}
+
+##
+# Prints the crontab summary based on the info in @cron
+sub show_cronsummary {
+ local($lastuser, $lasthost);
+ foreach $line (sort @cron) {
+
+ ($user) = m/^(.+):/;
+ ($user, $host, $hour, $min, $dom, $moy, $daw, @command) =
+ split(/:/, $line);
+ if ($user ne $lastuser) {
+ print "\nUser: $user\n";
+ $lasthost = "";
+ }
+ print " Host: $host\n" if ($host ne $lasthost);
+ $lastuser = $user;
+ $lasthost = $host;
+
+ print " $line\n";
+ }
+}
--- /dev/null
+#!/store/bin/perl
+
+##
+# Lager en tekstlig oppsummering over mange perl-skript basert på
+# kommentarer i filene.
+# Kjenner igjen følgende variabler: @project, @module, @status,
+# @author, @version, @made, @params, @param, @return og @see.
+#
+# @author Petter Reinholdtsen <pere@td.org.uit.no>
+# @made 1996-07-17
+# @version $Id: extract-comments,v 1.1 2003/06/02 13:01:37 pere Exp $
+# @project Origo
+# @params [-p <project>] [-m <module>] <files>
+# @return Oppsummering for alle filene
+# @module Utviklingsverktøy
+sub about {}
+
+# require "getopts.pl"; # GNU getopts lib
+
+use Getopt::Std;
+
+$debug = "1";
+
+format HEAD =
+~~ ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
+ $intro
+.
+
+format SUBROUTINE =
+@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
+$subroutine
+.
+format VERSION =
+ Versjon: @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
+ $version
+.
+format PARAMS =
+ Parametre: @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
+ $params
+.
+format PARAM =
+ @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
+ $paramline
+.
+format RETVAL =
+ Returnerer: @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
+ $retval
+.
+format AUTHOR =
+ Forfatter(e):^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
+$author
+~ ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
+$author
+.
+format DESCRIPTION =
+~~ ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
+ $intro
+.
+
+format HEADER =
+========================================================================
+
+Fil: @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
+ $file
+ Prosjekt: @<<<<<<<<<<<<<<<<<<<< Modul: @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
+ $project, $module
+ Require: @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
+ $require
+ Uses: @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
+ $use
+.
+
+# &Getopts("pm");
+getopts('p:m:f');
+
+@files = @ARGV;
+
+if ($opt_p) {
+ $def_project = $opt_p;
+}
+if ($opt_m) {
+ $def_module = $opt_m;
+}
+
+
+undef %info;
+foreach $file (@files) {
+ if (-f $file && !( $file =~ m%CVS/%)) {
+ $exec = &parse_perl_file($file);
+ $exec_status{$file} = $exec;
+ }
+}
+&output_info();
+
+##
+# Skriver ut alle filene sortert alfabetisk på prosjekt, modul og
+# metode.
+sub output_info {
+ foreach $subroutine (sort keys %info) {
+ ($project, $module, $file, $method) = split(/;/, $subroutine);
+ if ($project ne $lastproject || $module ne $lastmodule ||
+ $file ne $lastfile) {
+
+ $lastfile = $file;
+ $lastproject = $project;
+ $lastmodule = $module;
+
+ $use = $use{$file};
+ $use =~ s/;/, /g;
+ $require = $require{$file};
+ $require =~ s/;/, /g;
+ $exec = $exec_status{$file};
+ $file .= " ($exec)" if ($exec);
+ $~ = "HEADER";
+ write;
+ $file = $lastfile;
+
+ if ($info{"$project;$module;$file;about"}) {
+ ($intro, $authors, $version, $params, $param, $retval)
+ =split("\t", delete $info{"$project;$module;$file;about"});
+ $~ = "AUTHOR"; # XXX skriver ikke ut noenting
+ write if ($authors);
+
+ $~ = "VERSION";
+ write if ($version);
+
+ print "\n";
+ $~ = "HEAD";
+ write;
+
+ }
+ print "\n";
+ }
+ next if ( $opt_f || $subroutine =~ m/about$/ );
+ ($intro, $authors, $version, $params, $param, $retval)
+ = split("\t", $info{$subroutine});
+ $subroutine = "$method()";
+ @authorlist = split(";", $authors);
+ @author = ();
+ foreach (@authorlist) {
+ push(@author, m/([^,]+)/);
+ }
+ $author = join(", ", @author);
+
+ $~ = "SUBROUTINE";
+ write;
+
+ $~ = "VERSION";
+ write if ($version);
+
+ $~ = "AUTHOR";
+ write if ($author);
+
+ $~ = "DESCRIPTION";
+ write if ($intro);
+
+ $~ = "PARAMS";
+ write if ($params);
+
+ $~ = "PARAM";
+ foreach $paramline (split(/;/, $param)) {
+ write;
+ }
+
+ $~ = "RETVAL";
+ write if ($retval);
+ print "\n";
+ }
+
+}
+
+##
+# Leser gjennom en perl-fil og leser ut info fra kommentarene om hver
+# enkelt subrutine. Returnerer %info der nøkkel er
+# "prosjekt;modul;subrutinene" og innhold er intro,
+# forfatterliste(;-delt) og versjon.
+# @return "X" if script is executable - "" if not.
+
+sub parse_perl_file {
+ &clear_parse_vars();
+ $project = ($def_project? $def_project: "");
+ $module = ($def_module? $def_module: "");
+ ($file) = @_;
+ open(FILE, "<$file");
+ undef $first_line;
+ undef $subs;
+ while (<FILE>) {
+ $first_line = $_ unless ($first_line);
+ if ( /^##+\s*/ || $running_descrtiption ) {
+ $running_descrtiption = "1";
+ if ( ! /^##*\s*\@[^\s,.:]+\s+/ && /^#/ ) {
+ ($text) = m/^#+\s*([^#\s]+.*)$/;
+ $text =~ s/\t/ /g;
+ $intro .= $text." ";
+ } else {
+ $running_descrtiption = "";
+ }
+ }
+ if (! /^#/ ) {
+ if (/^\s*sub\s+([^\{ ]*)\s*\{*/) {
+ $subroutine = $1;
+ $subs++;
+ if ($intro =~ m/^\s+$/) {
+ undef $intro;
+ }
+ $info{"$project;$module;$file;$subroutine"}
+ = join("\t", $intro, join(";",@authors),
+ $version,$params,$param,$retval);
+ &clear_parse_vars();
+ }
+ if (/^\s*require\s+(.*);.*$/) {
+ $require{$file} = ($require{$file} ? "$require{$file};$1" : $1);
+ }
+ if (/^\s*use\s+(.*);.*$/) {
+ $use{$file} = ($use{$file} ? "$use{$file};$1" : $1);
+ }
+ next;
+ }
+ # Look in all the comments
+ if (/^#\s*\@author\s+(.*)$/) {
+ push(@authors, $1);
+ }
+ if (/^#\s*\@version\s+(.*)$/) {
+ $version = $1;
+ }
+ if (/^#\s*\@params\s+(.*)$/) {
+ $params = $1;
+ }
+ if (/^#\s*\@param\s+(.*)$/) {
+ $param = ($param ? "$param;$1" : "$1");
+ }
+ if (/^#\s*\@return\s*(.*)$/) {
+ $retval = $1;
+ }
+ if (/^#\s*\@module\s+(.*)$/) {
+ $module = $1;
+ }
+ if (/^#\s*\@project\s+(.*)$/) {
+ $project = $1;
+ }
+
+
+ }
+ if (! $subs) {
+ $info{"$project;$module;$file;about"} = "\t";
+
+ }
+ return ($first_line =~ m%#!/.*/bin/perl%) ? "X" : "";
+}
+##
+# Blanker ut alle nødvendige variabler mellom hver subrutine. Kalles
+# fra parse_perl_file()
+# @see parse_perl_file
+sub clear_parse_vars {
+ undef @authors;
+ undef $intro;
+ undef $version;
+ undef $params;
+ undef $param;
+ undef $retval;
+ undef $running_descrtiption;
+}
+
--- /dev/null
+#!/usr/bin/perl
+#
+# ftp-upgrade - fetch redhat package manager updates from the network
+#
+# usage: ftp-upgrade [-n] [-u uname]
+#
+# -u - specify a username to use - will be prompted for a password
+# -n - identify packages that are "new" (e.g. not yet installed)
+#
+# ftp-upgrade queries the set of installed packages on the local machine. It
+# then connects to the redhat repository of your choice via ftp, examines
+# the list of available updates there, and informs you of any packages that
+# have had their patch level increased or version number changed. You can
+# then choose to have all of the indicated packages downloaded, or
+# individually select which packages to download. The transferred RPMs are
+# placed in the current working directory. They can then be installed on
+# your system by using the command rpm -u <file>, where <file> is one of
+# the downloaded RPMs.
+#
+# Note that if there is an update to RPM or GLINT, these should be updated
+# first!
+#
+# $Header: /storage/cvsroot/user/www/homepage/linux/ftp-upgrade,v 1.1 2003/06/02 13:01:37 pere Exp $
+#
+# $Log: ftp-upgrade,v $
+# Revision 1.1 2003/06/02 13:01:37 pere
+# Add all my patches to CVS.
+#
+# Revision 1.10-pr 1998/05/28 10:00:00 pere
+# Lost of changes. Added handling of many directories, etc.
+#
+# Revision 1.10 1995/11/27 11:01:33 ahby
+# Changed default path to be for the 2.1 RPMS directory.
+#
+# Revision 1.9 1995/11/22 09:38:21 ahby
+# Removed some debugging code.
+#
+# Revision 1.8 1995/11/20 19:27:58 ahby
+# Added ability to get packages that are not yet installed.
+#
+# Revision 1.7 1995/11/14 21:53:41 ahby
+# Fixed an erroneously anchored string.
+# Improved package recognition.
+# Fixed a stupid array reference (I really am a better programmer
+# than this!).
+#
+# Revision 1.6 1995/11/14 19:09:35 ahby
+# Added list of mirror sites and username option.
+# Changed handling on connection error.
+#
+# Revision 1.5 1995/11/14 15:59:07 ahby
+# Changed it so if there are no changes it just terminates.
+#
+# Revision 1.4 1995/11/14 15:51:16 ahby
+# Cleaned up some comments.
+#
+# Revision 1.3 1995/11/09 23:15:46 ahby
+# CHanged revision tracking strategy to be smarter and use associative
+# array instead of a flat array and a search.
+#
+# Revision 1.2 1995/11/09 17:27:01 ahby
+# Fixed RCS headers.
+#
+#
+sub get_redhat_version {
+ my($tmp) = `rpm -q redhat-release`;
+ my($ver) = $tmp =~ m/^.+-([\d\.]+)-\d+/;
+ if ($ver) {
+ return $ver;
+ } else {
+ print "Unable to determine RedHat version. Exiting.\n";
+ exit(1);
+ }
+}
+
+sub get_redhat_architecture {
+ my($tmp) = `uname -m`;
+ chomp($tmp);
+ my($arch);
+ if ($tmp =~ m/i?86/) {
+ $arch = 'i386';
+ } else {
+ $arch = $tmp;
+ }
+ return $arch;
+}
+
+$version = get_redhat_version();
+$arch = get_redhat_architecture();
+@rpm_dirs = ("redhat-$version/$arch/RedHat/RPMS",
+ "updates/$version/$arch",
+ "powertools-$version/$arch");
+
+# Popular RedHat mirrors sites
+#$host = "ftp.nvg.unit.no";
+#$path = "/pub/linux/redhat";
+$host = "sunsite.uio.no";
+$path = "/pub/unix/linux/redhat";
+#$host = "ftp.caldera.com";
+#$path = "/pub/mirrors/redhat";
+#$host = "ftp.cc.gatech.edu";
+#$path = "/pub/linux/distributions/redhat";
+#$host = "ftp.pht.com";
+#$path = "/pub/linux/redhat";
+#$host = "ftp.cms.uncwil.edu";
+#$path = "/linux/redhat";
+#$host = "ftp.wilmington.net";
+#$path = "/linux/redhat";
+#$host = "ftp.caldera.com";
+#$path = "/pub/mirrors/redhat";
+#$host = "ftp.lasermoon.co.uk";
+#$path = "/pub/distributions/RedHat";
+#$host = "sunsite.unc.edu";
+#$path = "/pub/Linux/distributions/redhat";
+#$host = "sunsite.doc.ic.ac.uk";
+#$path = "/packages/linux/sunsite.unc-mirror/distributions/redhat";
+#$host = "ftp.cc.gatech.edu";
+#$path = "/pub/linux/distributions/redhat";
+#$host = "uiarchive.cso.uiuc.edu";
+#$path = "/pub/systems/linux/distributions/redhat";
+#$host = "ftp.ibp.fr";
+#$path = "/pub/linux/distributions/redhat";
+#$host = "ftp.gwdg.de";
+#$path = "/pub/linux/install/redhat";
+#$host = "ftp.uoknor.edu";
+#$path = "/linux/redhat";
+#$host = "ftp.msu.ru";
+#$path = "/pub/Linux/RedHat";
+#$host = "linux.ucs.indiana.edu";
+#$path = "/pub/linux/redhat";
+#$host = "ftp.cvut.cz";
+#$path = "/pub/linux/redhat";
+#$host = "ftp.ton.tut.fi";
+#$path = "/pub/Linux/RedHat";
+#$host = "ftp.funet.fi";
+#$path = "/pub/Linux/images/RedHat";
+
+BEGIN {
+ # Find Net::FTP if it is in an nonstandard place
+ push(@INC, "/store/lib/perl5", "/store/lib/perl5/site_perl" );
+
+ # Workaround for a bug in early RedHat 5 perl distributions.
+ eval 'require "ftp.pl"; import ftp;';
+ return unless ( $@ );
+
+ # Make backup include files
+ mkdir "/tmp/perl-fix", 0777;
+ mkdir "/tmp/perl-fix/gnu", 0777;
+ my($tmp) = `echo '1;' > /tmp/perl-fix/gnu/stubs.ph`;
+ $tmp = `echo '1;' > /tmp/perl-fix/stddef.ph`;
+ push(@INC, "/tmp/perl-fix");
+}
+
+# compare versions - needs more work
+# 1.9.1 is newer then 1.9 and 3.19 is newer then 3.2
+# Return true if v2 is newer then v1
+sub version_newer {
+ my ($v1, $v2) = @_;
+ my($r1, $r2);
+ ($v1,$r1) = $v1 =~ m/^(.+)-(\d+).+rpm/;
+ ($v2,$r2) = $v2 =~ m/^(.+)-(\d+).+rpm/;
+ if ($v1 eq $v2) {
+ return ($r1 < $r2);
+ }
+ my @v1 = split(/\./, $v1);
+ my @v2 = split(/\./, $v2);
+ if ($v1[0] < $v2[0] ||
+ ($v1[0] == $v2[0] && $v1[1] < $v2[1]) ||
+ ($v1[0] == $v2[0] && $v1[1] == $v2[1] && $v1[2] lt $v2[2])) {
+# print "Comparing $v1 and $v2 - true\n";
+ return 1;
+ }
+# print "Comparing $v1 and $v2 - false\n";
+ return 0;
+}
+
+use Getopt::Std;
+
+# XXX use Net::FTP;
+require "ftp.pl";
+import ftp;
+
+
+$uname = "anonymous";
+$pword = "upgrade-user@";
+
+&getopts('nu:');
+
+if ($opt_u) {
+ $uname = $opt_u;
+ system "stty -echo";
+ print "Password: ";
+ chop($pword = <STDIN>);
+ print "\n";
+ system "stty echo";
+}
+
+# subroutine to get y/n answer
+
+sub getyn {
+ local($prompt) = @_;
+ local($answer) = "";
+ local($a) = "";
+
+ do {
+ print "$prompt (y/n)? ";
+ $answer = <STDIN>;
+ $a = substr($answer, 0, 1);
+ } while (($a ne "Y") && ($a ne "y") && ($a ne "N") && ($a ne "n"));
+ return (($a eq "Y") || ($a eq "y"));
+}
+
+
+# get the local list of installed packages
+
+print "Getting list of installed packages\n";
+@llist = `rpm -qa`;
+chop(@llist);
+sort(@llist);
+
+# now connect to the remote host
+
+print ("Getting the list of updated packages from $host.\n");
+
+# make the connection and fetch the directory
+
+print "Opening connection to $host\n";
+
+# XXX $ftp = Net::FTP->new($host, Timeout => '30');
+ftp::set_timeout(30);
+$ftp = ftp::open($host,21,0,10);
+
+if ( ! $ftp ) {
+ die("open of $host failed");
+}
+print "Logging in to $host as $uname\n";
+
+# XXX $ftp->login($uname,$pword) || die("login failed");
+ftp::login($uname,$pword) || die("login failed");
+
+for $dir (@rpm_dirs) {
+ fetch_subdir_list($dir);
+}
+
+##
+# Exports: @templist, %rlist
+sub fetch_subdir_list {
+ my($dir) = @_;
+ my($curpath) = $path . "/" . $dir;
+
+ print "Changing to directory $curpath on $host\n";
+
+ # XXX $ftp->cwd($curpath);
+ if ( ! ftp::cwd($curpath) ) {
+ return;
+ }
+
+ print "Fetching directory list\n";
+
+ # XXX my(@longlist) = $ftp->ls();
+ ftp::dir_open("");
+ @longlist = <ftp::NS>;
+ ftp::dir_close();
+
+ push(@templist, grep(/\.rpm/, @longlist));
+ undef @longlist;
+
+ chomp(@templist);
+ sort (@templist);
+
+ my(@temp);
+ for (@templist) {
+ @temp = m/([^ ]*)-([^- ]*-[0-9]*[^ ]*rpm).*/;
+ ($file) = m/(\S+rpm)/;
+ # Only add newer package
+ if ( (! $rlist{$temp[0]} ) ||
+ ($rlist{$temp[0]} && version_newer($rlist{$temp[0]},$temp[1])) ) {
+ $rlist{$temp[0]} = $temp[1];
+ $directory{$file} = $curpath;
+ }
+ }
+}
+
+# XXX $ftp->type("I");
+ftp::type("I");
+
+# XXX $ftp->debug(1);
+#ftp::debug(1);
+
+if ($opt_n) { # if we are looking for new packages
+
+ for (@llist) {
+ @temp = m/([^ ]*)-([^-]*-[0-9]*)/;
+ $ilist{$temp[0]} = $temp[1];
+ }
+
+ $uindex = 0; #initialize index for uninstalled package array
+
+ for (@templist) {
+ $fname = $_;
+ $fname =~ s/.*\s([^ ]*rpm).*/$1/;
+ @pname = ($fname =~ m/^(.*)-([^-]*)-([0-9]*)/);
+ if (! $ilist{$pname[0]}) { # if this not package already installed
+ @ulist[$uindex] = $fname;
+ $uindex++;
+ }
+ }
+ @ulist = sort(@ulist);
+ if (@ulist) {
+ print "Uninstalled packages:\n";
+ for (@ulist) {
+ print " $_\n";
+ }
+ $all = getyn("Fetch all?");
+
+ for (@ulist) {
+ if (! $all) {
+ if (!getyn("Fetch $_")) { next };
+ }
+ getfile($ftp, $_);
+ }
+ } else {
+ print ("No new packages are available on $host\n");
+ }
+
+} else { # check for updated packages
+
+ $nindex = 0; #initialize index for new version array
+ $cindex = 0; #initialize index for changed patch array
+
+ for (@llist) {
+ @lname = m/^(.*)-([^-]*)-([0-9]*$)/;
+ if ($rlist{$lname[0]}) { # if this package has an update
+ @temp = ($rlist{$lname[0]} =~ m/([^-]*)-([0-9]*).*rpm/);
+ if ($lname[1] eq $temp[0]) { # if versions equal
+ if ($lname[2] < $temp[1]) { # if patch level has increased
+ @clist[$cindex] = $lname[0] . '-' . $rlist{$lname[0]};
+ $cindex++;
+ };
+ } else { # if different version
+ if (version_newer($lname[1], $temp[0])) {
+ @nlist[$nindex] = $lname[0] . '-' . $rlist{$lname[0]};
+ $nindex++;
+ }
+ }
+ }
+ }
+ if (@clist || @nlist) {
+ @clist = sort(@clist);
+ @nlist = sort(@nlist);
+ print "New patches:\n\n";
+ for (@clist) {
+ print " $_\n"
+ }
+ print "\nDifferent versions:\n\n";
+ for (@nlist) {
+ print " $_\n"
+ }
+
+ $all = getyn("Fetch all?");
+
+ for (@clist) {
+ if (! $all) {
+ if (!getyn("Fetch $_")) { next };
+ }
+ getfile($ftp, $_);
+ }
+ for (@nlist) {
+ if (! $all) {
+ if (!getyn("Fetch $_")) { next };
+ }
+ getfile($ftp, $_);
+ }
+ print "\nTo upgrade, run 'rpm -Uvh *.rpm' as root.\n"
+ } else {
+ print ("No new updates are available on $host\n");
+ }
+}
+
+
+#$ftp->debug(0);
+# XXX $ftp->quit();
+ftp::close();
+
+sub getfile {
+ my($ftphandle, $filename) = @_;
+ my($dir) = $directory{$filename};
+ print "Fetching $dir/$filename\n";
+ # XXX $ftphandle->cwd($dir);
+ ftp::cwd($dir);
+
+ # XXX $ftphandle->get($filename);
+ ftp::get($filename);
+}
--- /dev/null
+#!/usr/bin/perl -w
+#
+# Author: Petter Reinholdtsen <pere@td.org.uit.no>
+# Date: 2000-12-17
+#
+# Parse output from gprof, and generate graph output for daVinci or xvcg.
+#
+# This is alpha quality code, and indended as proof of consept. The
+# idea is based on the C++ implementation cg by ? (look up name).
+#
+# Todo:
+# - Encode # calls and time used into graph (color, edge width, dashed, etc)
+# - Add daVinci output mode
+# - Detect non-GNU gprof, and correct flags for this case
+# - Clean up code
+# - Use getopt to choose output mode and if unused functions should be
+# included.
+#
+# ChangeLog:
+# 2000-12-30 Petter Reinholdtsen <pere@td.org.uit.no>
+# Changed to skip unused functions.
+# 2001-11-13 Kaupo Palo <kaupo.palo@ebi.ee>
+# Added dot format and spent time
+
+use strict;
+
+my $url = "http://www.student.uit.no/~pere/linux/";
+
+my $debug = 0;
+
+# For GNU gprof
+my $gprofopt = "-c -z";
+
+# Which program to profile
+my $program = shift;
+
+# Only show called functions (flag) [dont work yet]
+my $used_only = 1;
+
+# Map from function name, to list of funcion calling this function
+my %pre;
+
+# Map from function name, to list of function called
+my %post;
+
+# Map from function id to function name
+my %func;
+
+# Map from function id to function name
+my %spent;
+
+# Used during parsing
+my @parents = ();
+my @children = ();
+
+parse_gnu_gprof($program);
+dump_graph_dot();
+
+exit(0);
+
+sub parse_gnu_gprof
+{
+ my ($program) = @_;
+ my $current = "";
+
+ # Flag set when parsing gprof call graph output
+ my $ingraph = 0;
+
+ open(GPROF, "gprof $gprofopt $program |") || die "Unable to run gprof";
+ while (<GPROF>) {
+ chomp;
+
+ $ingraph = 1 if (/Call graph/);
+ $ingraph = 0 if (/This table describes the call tree/);
+ next unless $ingraph;
+
+ if (/^-+$/) { # End of current entry
+ debugmsg(1, "Registering \"$current\"\n") if defined $current;
+
+ if ($current) {
+ $pre{$current} = [@parents] if (@parents);
+ $post{$current}= [@children] if (@children);
+ } else {
+ debugmsg(1, "No current func!\n");
+ }
+
+ $current = "";
+ @children = ();
+ @parents = ();
+ next;
+ }
+
+ if (/^\[\d+\]?\s/) {
+ $current = parse_current_func($_);
+ }
+
+ # Match the parent and child functions. Examples:
+ # 2 get_ll_tempfile <cycle 3> [36]
+ # 0.00 0.00 0/5 __getproperty [891]
+ if (/^\s+[\d.]+\s/) {
+ parse_parent_or_child($current, $_);
+ }
+ }
+ close(GPROF);
+}
+
+sub sort_func_name {
+ return $func{$a} cmp $func{$b}
+}
+
+# Match current function, ie lines like these (notice the GNU
+# gprof bug in the last line):
+# Skip unused functions.
+#
+# [1] 0.0 0.00 0.00 0 <cycle 1 as a whole> [1]
+# [4] 0.0 0.00 0.00 9 incache [4]
+# [10000 0.0 0.00 0.00 9 incache [10000
+# [10] 0.0 0.00 0.00 7 fndentry [10]
+# [11] 0.0 0.00 0.00 7 get_property <cycle 3> [11]
+sub parse_current_func {
+ my $line = shift;
+ if(/^\[(\d+)\]?\s+([\d.]+)\s+([\d.]+)\s+([\d.]+)\s+([\d\+]*)\s+(.+)\s+\[(\d+)\]$/) {
+ # Name the extracted variables
+ my ($id, $ptime, $selftime, $chtime, $called, $name, $index) =
+ ($1, $2, $3, $4, $5, $6, $7);
+
+ # I'm not quite sure if this would ever happen
+ print "Bad index or id: $id != $index\n " if ($id != $index);
+
+ # If this function wasn't called, skip to the next one
+ return undef if ($used_only && !$called);
+
+ if ($name =~ m/^\<.+\>$/) {
+ # cycle, not a function
+ debugmsg(1, "Cycle \"$name\" index $index\n");
+ return undef;
+ }
+ save_func_spent($ptime, $id);
+ return save_func_name($name, $id);
+ } else {
+ debugmsg(0, "Bad formatting of line \"$line\"\n");
+ exit;
+ }
+}
+
+#
+# Match parents and child of the current function.
+# Skip unused functions.
+#
+sub parse_parent_or_child
+{
+ my ($current, $line) = @_;
+ my ($selftime, $chtime, $countinfo, $name, $index) = $line =~
+ m%^\s+([\d.]*)\s+([\d.]*)\s+([\d/\+]+)\s+(.+)\s\[(\d+)\]$%;
+ if (!defined $name) {
+ debugmsg(0, "Unable to parse \"$_\"\n");
+ next;
+ }
+
+ # Check if this function was called at all
+ if ($used_only) {
+ my ($this, $total) = split(/\//, $countinfo);
+ return unless (defined $total && 0 < $this);
+ }
+
+ debugmsg(1, "Called: $countinfo\n");
+
+ $name = save_func_name($name, $index);
+
+ if ($current) {
+ push(@children, $name);
+ } else {
+ push(@parents, $name);
+ }
+}
+
+#
+# Store decoded function name in hash with the function index as key
+#
+sub save_func_name {
+ my ($name, $id) = @_;
+ my $current = $name;
+
+ # Remove cycle information
+ $current =~ s/\s*\<.+\>//;
+
+ $func{$id} = $current;
+ debugmsg(1, "Name: \"$name\" -> \"$current\"\n");
+ return $id;
+}
+
+#
+# Store time spent in function with function index as key
+#
+sub save_func_spent {
+ my ($spent, $id) = @_;
+
+ $spent{$id} = $spent;
+# debugmsg(1, "Name: \"$name\" -> \"$current\"\n");
+ return $id;
+}
+
+#
+# Output current graph database
+#
+sub dump_graph_raw {
+ my $current;
+ for $current (sort sort_func_name keys %func) {
+ my $name = $func{$current};
+ print "Func: \"" . $name . "\" [$current]\n";
+
+ # Print callers
+ if (defined $pre{$current}) {
+ my $f;
+ for $f (sort sort_func_name @{$pre{$current}}) {
+ print " " . $func{$f} . " [$f] -> \"$name\"\n";
+ }
+ }
+
+ # Print called
+ if (defined $post{$current}) {
+ my $f;
+ for $f (sort sort_func_name @{$post{$current}}) {
+ print " \"$name\" -> \"" . $func{$f} . "\" [$f]\n";
+ }
+ }
+ }
+}
+
+sub vcg_edge
+{
+ my ($src, $dst, $thickness, $comment) = @_;
+ my $buffer = " edge: {".
+ " sourcename: \"$src\"".
+ " targetname: \"$dst\"" .
+ " thickness: $thickness }";
+ $buffer .= " /* $comment */\n" if ($comment);
+ return $buffer;
+}
+
+#
+# Output current graph database in vcg format
+#
+sub dump_graph_vcg {
+ my $current;
+
+ my %printed;
+
+ print <<EOF;
+/*
+ * VCG formatted call graph for program "$program" based on gprof output.
+ *
+ * Check <URL:$url> for more information.
+ */
+
+graph: {
+ title: "Profiling $program"
+ orientation: left_to_right
+
+EOF
+
+ # First print all the nodes
+ for $current (sort sort_func_name keys %func) {
+ my $name = $func{$current};
+ print " node: { title: \"$current\" label: \"$name\" borderwidth: 0}\n"
+ }
+
+ print "\n";
+
+ # Then print all the edges
+ for $current (sort sort_func_name keys %func) {
+ my $name = $func{$current};
+
+ if (defined $pre{$current}) {
+ my $content = 0;
+ my $buffer = " /* \"$name\" callers */\n";
+ my $f;
+ for $f (sort sort_func_name @{$pre{$current}}) {
+ if (!exists $printed{"$f:$current"}) {
+ my $prename = $func{$f};
+ my $thickness = 1;
+ $buffer .= vcg_edge($f, $current, $thickness, $prename);
+ $printed{"$f:$current"} = 1;
+ $content++;
+ }
+ }
+ $buffer .= "\n";
+ print $buffer if (0 < $content);
+ }
+
+ if (defined $post{$current}) {
+ my $content = 0;
+ my $buffer = " /* \"$name\" called */\n";
+ my $f;
+ for $f (sort sort_func_name @{$post{$current}}) {
+ if (!exists $printed{"$current:$f"}) {
+ my $postname = $func{$f};
+ my $thickness = 1;
+ $buffer .= vcg_edge($current, $f, $thickness, $postname);
+ $printed{"$current:$f"} = 1;
+ $content++;
+ }
+ }
+ $buffer .= "\n";
+ print $buffer if (0 < $content);
+ }
+ }
+ print <<EOF;
+}
+EOF
+}
+#
+# Output current graph database in daVinci format
+#
+sub dump_graph_daVinci {
+ my $current;
+
+ my %printed = ();
+
+ print "[\n";
+
+ # First print all the nodes
+ for $current (sort sort_func_name keys %func) {
+ my $name = $func{$current};
+ print " l(\"$current\",n(\"$name\",[],[\n";
+ # Print callers
+ if (defined $pre{$current}) {
+ my $f;
+ for $f (sort sort_func_name @{$pre{$current}}) {
+ print "l(\"$f\"->\"$current\",e(\"B\",[],";
+ if ($printed{$f}) {
+ print "r(\"$f\"";
+ }
+ print " edge: { sourcename: \"$f\" targetname: \"$current\"" .
+ " thickness: 1 }\n";
+ }
+ }
+
+ # Print called
+ if (defined $post{$current}) {
+ my $f;
+ for $f (sort sort_func_name @{$post{$current}}) {
+ print " edge: { sourcename: \"$current\" targetname: \"$f\"" .
+ " thickness: 1 }\n";
+ }
+ }
+ }
+ print <<EOF;
+}
+EOF
+}
+#
+# Output current graph database in dot format
+#
+sub dump_graph_dot {
+ my $current;
+
+ my %printed;
+
+ print <<EOF;
+/*
+ * DOT formatted call graph for program "$program" based on gprof output.
+ *
+ * AT\&T
+ */
+
+digraph g {
+ node[shape=box];
+ orientation=landscape;
+ graph[rankdir=LR,
+ size="8.5,11",
+ ratio=compress];
+
+EOF
+
+ # First print all the nodes
+ for $current (sort sort_func_name keys %func) {
+ my $name = "\"" . $func{$current};
+ my $val = "";
+ if( defined($spent{$current}) ){
+ $val = $spent{$current};
+ if($val ne "0.0" ){
+ $name .= "\\n" . $val . "\",style=filled";
+ }
+ else{
+ $name .="\"";
+ }
+
+ }
+ else{
+ $name .="\"";
+ }
+ print " n$current\[label=$name]\n"
+ }
+
+ print "\n";
+
+ # Then print all the edges
+ for $current (sort sort_func_name keys %func) {
+ my $name = $func{$current};
+
+ if (defined $pre{$current}) {
+ my $content = 0;
+ my $buffer="";
+ my $f;
+ for $f (sort sort_func_name @{$pre{$current}}) {
+ if (!exists $printed{"$f:$current"}) {
+ $buffer .= " n$f -> n$current;\n";
+ $printed{"$f:$current"} = 1;
+ $content++;
+ }
+ }
+ print $buffer if (0 < $content);
+ }
+
+ if (defined $post{$current}) {
+ my $content = 0;
+ my $buffer="";
+ my $f;
+ for $f (sort sort_func_name @{$post{$current}}) {
+ if (!exists $printed{"$current:$f"}) {
+ $buffer .= " n$current -> n$f;\n";
+ $printed{"$current:$f"} = 1;
+ $content++;
+ }
+ }
+ print $buffer if (0 < $content);
+ }
+ }
+ print <<EOF;
+
+ node0[label="Profiling $program"];
+}
+EOF
+}
+
+sub debugmsg
+{
+ my ($level, $msg) = @_;
+ print STDERR $msg if ($level <= $debug);
+}
+
+
--- /dev/null
+#!/usr/bin/perl -w
+#
+# Author: Petter Reinholdtsen <pere@td.org.uit.no>
+# Date: 2000-12-17
+#
+# Parse output from gprof, and generate graph output for daVinci or xvcg.
+#
+# This is alpha quality code, and indended as proof of consept. The
+# idea is based on the C++ implementation cg by ? (look up name).
+#
+# Todo:
+# - Encode # calls and time used into graph (color, edge width, dashed, etc)
+# - Add daVinci output mode
+# - Detect non-GNU gprof, and correct flags for this case
+# - Clean up code
+# - Use getopt to choose output mode and if unused functions should be
+# included.
+#
+# ChangeLog:
+# 2000-12-30 Petter Reinholdtsen <pere@td.org.uit.no>
+# Changed to skip unused functions.
+
+use strict;
+
+my $url = "http://www.student.uit.no/~pere/linux/";
+
+my $debug = 0;
+
+# For GNU gprof
+my $gprofopt = "-c -z";
+
+# Which program to profile
+my $program = shift;
+
+# Only show called functions (flag) [dont work yet]
+my $used_only = 1;
+
+# Map from function name, to list of funcion calling this function
+my %pre;
+
+# Map from function name, to list of function called
+my %post;
+
+# Map from function id to function name
+my %func;
+
+# Used during parsing
+my @parents = ();
+my @children = ();
+
+parse_gnu_gprof($program);
+dump_graph_vcg();
+
+exit(0);
+
+sub parse_gnu_gprof
+{
+ my ($program) = @_;
+ my $current = "";
+
+ # Flag set when parsing gprof call graph output
+ my $ingraph = 0;
+
+ open(GPROF, "gprof $gprofopt $program |") || die "Unable to run gprof";
+ while (<GPROF>) {
+ chomp;
+
+ $ingraph = 1 if (/Call graph/);
+ $ingraph = 0 if (/This table describes the call tree/);
+ next unless $ingraph;
+
+ if (/^-+$/) { # End of current entry
+ debugmsg(1, "Registering \"$current\"\n") if defined $current;
+
+ if ($current) {
+ $pre{$current} = [@parents] if (@parents);
+ $post{$current}= [@children] if (@children);
+ } else {
+ debugmsg(1, "No current func!\n");
+ }
+
+ $current = "";
+ @children = ();
+ @parents = ();
+ next;
+ }
+
+ if (/^\[\d+\]?\s/) {
+ $current = parse_current_func($_);
+ }
+
+ # Match the parent and child functions. Examples:
+ # 2 get_ll_tempfile <cycle 3> [36]
+ # 0.00 0.00 0/5 __getproperty [891]
+ if (/^\s+[\d.]+\s/) {
+ parse_parent_or_child($current, $_);
+ }
+ }
+ close(GPROF);
+}
+
+sub sort_func_name {
+ return $func{$a} cmp $func{$b}
+}
+
+# Match current function, ie lines like these (notice the GNU
+# gprof bug in the last line):
+# Skip unused functions.
+#
+# [1] 0.0 0.00 0.00 0 <cycle 1 as a whole> [1]
+# [4] 0.0 0.00 0.00 9 incache [4]
+# [10000 0.0 0.00 0.00 9 incache [10000
+# [10] 0.0 0.00 0.00 7 fndentry [10]
+# [11] 0.0 0.00 0.00 7 get_property <cycle 3> [11]
+sub parse_current_func {
+ my $line = shift;
+ if(/^\[(\d+)\]?\s+([\d.]+)\s+([\d.]+)\s+([\d.]+)\s+([\d\+]*)\s+(.+)\s+\[(\d+)\]$/) {
+ # Name the extracted variables
+ my ($id, $ptime, $selftime, $chtime, $called, $name, $index) =
+ ($1, $2, $3, $4, $5, $6, $7);
+
+ # I'm not quite sure if this would ever happen
+ print "Bad index or id: $id != $index\n " if ($id != $index);
+
+ # If this function wasn't called, skip to the next one
+ return undef if ($used_only && !$called);
+
+ if ($name =~ m/^\<.+\>$/) {
+ # cycle, not a function
+ debugmsg(1, "Cycle \"$name\" index $index\n");
+ return undef;
+ }
+ return save_func_name($name, $id);
+ } else {
+ debugmsg(0, "Bad formatting of line \"$line\"\n");
+ exit;
+ }
+}
+
+#
+# Match parents and child of the current function.
+# Skip unused functions.
+#
+sub parse_parent_or_child
+{
+ my ($current, $line) = @_;
+ my ($selftime, $chtime, $countinfo, $name, $index) = $line =~
+ m%^\s+([\d.]*)\s+([\d.]*)\s+([\d/\+]+)\s+(.+)\s\[(\d+)\]$%;
+ if (!defined $name) {
+ debugmsg(0, "Unable to parse \"$_\"\n");
+ next;
+ }
+
+ # Check if this function was called at all
+ if ($used_only) {
+ my ($this, $total) = split(/\//, $countinfo);
+ return unless (defined $total && 0 < $this);
+ }
+
+ debugmsg(1, "Called: $countinfo\n");
+
+ $name = save_func_name($name, $index);
+
+ if ($current) {
+ push(@children, $name);
+ } else {
+ push(@parents, $name);
+ }
+}
+
+#
+# Store decoded function name in hash with the function index as key
+#
+sub save_func_name {
+ my ($name, $id) = @_;
+ my $current = $name;
+
+ # Remove cycle information
+ $current =~ s/\s*\<.+\>//;
+
+ $func{$id} = $current;
+ debugmsg(1, "Name: \"$name\" -> \"$current\"\n");
+ return $id;
+}
+#
+# Output current graph database
+#
+sub dump_graph_raw {
+ my $current;
+ for $current (sort sort_func_name keys %func) {
+ my $name = $func{$current};
+ print "Func: \"" . $name . "\" [$current]\n";
+
+ # Print callers
+ if (defined $pre{$current}) {
+ my $f;
+ for $f (sort sort_func_name @{$pre{$current}}) {
+ print " " . $func{$f} . " [$f] -> \"$name\"\n";
+ }
+ }
+
+ # Print called
+ if (defined $post{$current}) {
+ my $f;
+ for $f (sort sort_func_name @{$post{$current}}) {
+ print " \"$name\" -> \"" . $func{$f} . "\" [$f]\n";
+ }
+ }
+ }
+}
+
+sub vcg_edge
+{
+ my ($src, $dst, $thickness, $comment) = @_;
+ my $buffer = " edge: {".
+ " sourcename: \"$src\"".
+ " targetname: \"$dst\"" .
+ " thickness: $thickness }";
+ $buffer .= " /* $comment */\n" if ($comment);
+ return $buffer;
+}
+
+#
+# Output current graph database in vcg format
+#
+sub dump_graph_vcg {
+ my $current;
+
+ my %printed;
+
+ print <<EOF;
+/*
+ * VCG formatted call graph for program "$program" based on gprof output.
+ *
+ * Check <URL:$url> for more information.
+ */
+
+graph: {
+ title: "Profiling $program"
+ orientation: left_to_right
+
+EOF
+
+ # First print all the nodes
+ for $current (sort sort_func_name keys %func) {
+ my $name = $func{$current};
+ print " node: { title: \"$current\" label: \"$name\" borderwidth: 0}\n"
+ }
+
+ print "\n";
+
+ # Then print all the edges
+ for $current (sort sort_func_name keys %func) {
+ my $name = $func{$current};
+
+ if (defined $pre{$current}) {
+ my $content = 0;
+ my $buffer = " /* \"$name\" callers */\n";
+ my $f;
+ for $f (sort sort_func_name @{$pre{$current}}) {
+ if (!exists $printed{"$f:$current"}) {
+ my $prename = $func{$f};
+ my $thickness = 1;
+ $buffer .= vcg_edge($f, $current, $thickness, $prename);
+ $printed{"$f:$current"} = 1;
+ $content++;
+ }
+ }
+ $buffer .= "\n";
+ print $buffer if (0 < $content);
+ }
+
+ if (defined $post{$current}) {
+ my $content = 0;
+ my $buffer = " /* \"$name\" called */\n";
+ my $f;
+ for $f (sort sort_func_name @{$post{$current}}) {
+ if (!exists $printed{"$current:$f"}) {
+ my $postname = $func{$f};
+ my $thickness = 1;
+ $buffer .= vcg_edge($current, $f, $thickness, $postname);
+ $printed{"$current:$f"} = 1;
+ $content++;
+ }
+ }
+ $buffer .= "\n";
+ print $buffer if (0 < $content);
+ }
+ }
+ print <<EOF;
+}
+EOF
+}
+#
+# Output current graph database in daVinci format
+#
+sub dump_graph_daVinci {
+ my $current;
+
+ my %printed = ();
+
+ print "[\n";
+
+ # First print all the nodes
+ for $current (sort sort_func_name keys %func) {
+ my $name = $func{$current};
+ print " l(\"$current\",n(\"$name\",[],[\n";
+ # Print callers
+ if (defined $pre{$current}) {
+ my $f;
+ for $f (sort sort_func_name @{$pre{$current}}) {
+ print "l(\"$f\"->\"$current\",e(\"B\",[],";
+ if ($printed{$f}) {
+ print "r(\"$f\"";
+ }
+ print " edge: { sourcename: \"$f\" targetname: \"$current\"" .
+ " thickness: 1 }\n";
+ }
+ }
+
+ # Print called
+ if (defined $post{$current}) {
+ my $f;
+ for $f (sort sort_func_name @{$post{$current}}) {
+ print " edge: { sourcename: \"$current\" targetname: \"$f\"" .
+ " thickness: 1 }\n";
+ }
+ }
+ }
+ print <<EOF;
+}
+EOF
+}
+
+sub debugmsg
+{
+ my ($level, $msg) = @_;
+ print STDERR $msg if ($level <= $debug);
+}
--- /dev/null
+%!PS-Adobe-2.0
+%%Creator: dot version 1.7.4 (Sun Jan 21 22:22:26 GMT 2001)
+%%For: (palo) Kaupo Palo,2.54,+372-2-6560601,+372-6091497
+%%Title: g
+%%Pages: (atend)
+%%BoundingBox: 36 36 393 649
+%%EndComments
+%%BeginProlog
+save
+/DotDict 200 dict def
+DotDict begin
+
+%%BeginResource: procset
+/coord-font-family /Times-Roman def
+/default-font-family /Times-Roman def
+/coordfont coord-font-family findfont 8 scalefont def
+
+/InvScaleFactor 1.0 def
+/set_scale {
+ dup 1 exch div /InvScaleFactor exch def
+ dup scale
+} bind def
+
+% styles
+/solid { } bind def
+/dashed { [9 InvScaleFactor mul dup ] 0 setdash } bind def
+/dotted { [1 InvScaleFactor mul 6 InvScaleFactor mul] 0 setdash } bind def
+/invis {/fill {newpath} def /stroke {newpath} def /show {pop newpath} def} bind def
+/bold { 2 setlinewidth } bind def
+/filled { } bind def
+/unfilled { } bind def
+/rounded { } bind def
+/diagonals { } bind def
+
+% hooks for setting color
+/nodecolor { sethsbcolor } bind def
+/edgecolor { sethsbcolor } bind def
+/graphcolor { sethsbcolor } bind def
+/nopcolor {pop pop pop} bind def
+
+/beginpage { % i j npages
+ /npages exch def
+ /j exch def
+ /i exch def
+ /str 10 string def
+ npages 1 gt {
+ gsave
+ coordfont setfont
+ 0 0 moveto
+ (\() show i str cvs show (,) show j str cvs show (\)) show
+ grestore
+ } if
+} bind def
+
+/set_font {
+ findfont exch
+ scalefont setfont
+} def
+
+% draw aligned label in bounding box aligned to current point
+% alignfactor tells what fraction to place on the left.
+% -.5 is centered.
+/alignedtext { % text labelwidth fontsz alignfactor
+ /alignfactor exch def
+ /fontsz exch def
+ /width exch def
+ /text exch def
+ gsave
+ % even if node or edge is dashed, don't paint text with dashes
+ [] 0 setdash
+ currentpoint newpath moveto
+ text stringwidth pop
+ alignfactor mul fontsz -.3 mul rmoveto
+ text show
+ grestore
+} def
+
+/boxprim { % xcorner ycorner xsize ysize
+ 4 2 roll
+ moveto
+ 2 copy
+ exch 0 rlineto
+ 0 exch rlineto
+ pop neg 0 rlineto
+ closepath
+} bind def
+
+/ellipse_path {
+ /ry exch def
+ /rx exch def
+ /y exch def
+ /x exch def
+ matrix currentmatrix
+ newpath
+ x y translate
+ rx ry scale
+ 0 0 1 0 360 arc
+ setmatrix
+} bind def
+
+/endpage { showpage } bind def
+
+/layercolorseq
+ [ % layer color sequence - darkest to lightest
+ [0 0 0]
+ [.2 .8 .8]
+ [.4 .8 .8]
+ [.6 .8 .8]
+ [.8 .8 .8]
+ ]
+def
+
+/setlayer {/maxlayer exch def /curlayer exch def
+ layercolorseq curlayer get
+ aload pop sethsbcolor
+ /nodecolor {nopcolor} def
+ /edgecolor {nopcolor} def
+ /graphcolor {nopcolor} def
+} bind def
+
+/onlayer { curlayer ne {invis} if } def
+
+/onlayers {
+ /myupper exch def
+ /mylower exch def
+ curlayer mylower lt
+ curlayer myupper gt
+ or
+ {invis} if
+} def
+
+/curlayer 0 def
+
+%%EndProlog
+%%BeginSetup
+14 default-font-family set_font
+1 setmiterlimit
+% /arrowlength 10 def
+% /arrowwidth 5 def
+
+% make sure pdfmark is harmless for PS-interpreters other than Distiller
+/pdfmark where {pop} {userdict /pdfmark /cleartomark load put} ifelse
+% make '<<' and '>>' safe on PS Level 1 devices
+/languagelevel where {pop languagelevel}{1} ifelse
+2 lt {
+ userdict (<<) cvn ([) cvn load put
+ userdict (>>) cvn ([) cvn load put
+} if
+
+%%EndResource
+%%EndSetup
+%%Page: 1 1
+%%PageBoundingBox: 36 36 393 649
+%%PageOrientation: Landscape
+gsave
+35 35 358 614 boxprim clip newpath
+36 36 translate
+gsave 356 0 translate 90 rotate
+0 0 1 beginpage
+grestore
+0.5406 set_scale
+660 0 translate 90 rotate
+[ /CropBox [36 36 393 649] /PAGES pdfmark
+0.000 0.000 0.000 graphcolor
+14.00 /Times-Roman set_font
+
+% n27
+gsave 10 dict begin
+newpath 862 336 moveto
+808 336 lineto
+808 300 lineto
+862 300 lineto
+closepath
+stroke
+gsave 10 dict begin
+835 319 moveto (eigens) 35 14.00 -0.50 alignedtext
+end grestore
+end grestore
+
+% n28
+gsave 10 dict begin
+newpath 862 660 moveto
+808 660 lineto
+808 624 lineto
+862 624 lineto
+closepath
+stroke
+gsave 10 dict begin
+835 643 moveto (f_LL) 28 14.00 -0.50 alignedtext
+end grestore
+end grestore
+
+% n23
+gsave 10 dict begin
+newpath 866 606 moveto
+804 606 lineto
+804 570 lineto
+866 570 lineto
+closepath
+stroke
+gsave 10 dict begin
+835 589 moveto (f_choldc) 48 14.00 -0.50 alignedtext
+end grestore
+end grestore
+
+% n29
+gsave 10 dict begin
+newpath 757 606 moveto
+635 606 lineto
+635 570 lineto
+757 570 lineto
+closepath
+stroke
+gsave 10 dict begin
+696 589 moveto (f_cholesky_inverse) 108 14.00 -0.50 alignedtext
+end grestore
+end grestore
+
+% n29 -> n28
+newpath 743 606 moveto
+761 614 782 621 799 628 curveto
+stroke
+newpath 799 625 moveto
+808 631 lineto
+798 630 lineto
+closepath
+fill
+
+% n29 -> n23
+newpath 758 588 moveto
+770 588 783 588 794 588 curveto
+stroke
+newpath 793 586 moveto
+803 588 lineto
+793 591 lineto
+closepath
+fill
+
+% n24
+gsave 10 dict begin
+newpath 752 552 moveto
+640 552 lineto
+640 516 lineto
+752 516 lineto
+closepath
+stroke
+gsave 10 dict begin
+696 535 moveto (f_cholesky_solve) 97 14.00 -0.50 alignedtext
+end grestore
+end grestore
+
+% n24 -> n23
+newpath 743 552 moveto
+760 559 778 566 794 573 curveto
+stroke
+newpath 794 570 moveto
+803 576 lineto
+793 575 lineto
+closepath
+fill
+
+% n25
+gsave 10 dict begin
+newpath 864 552 moveto
+806 552 lineto
+806 516 lineto
+864 516 lineto
+closepath
+stroke
+gsave 10 dict begin
+835 535 moveto (f_cholsl) 45 14.00 -0.50 alignedtext
+end grestore
+end grestore
+
+% n24 -> n25
+newpath 752 534 moveto
+767 534 783 534 796 534 curveto
+stroke
+newpath 795 532 moveto
+805 534 lineto
+795 537 lineto
+closepath
+fill
+
+% n26
+gsave 10 dict begin
+newpath 866 267 moveto
+804 267 lineto
+804 231 lineto
+866 231 lineto
+closepath
+stroke
+gsave 10 dict begin
+835 250 moveto (f_gauleg) 48 14.00 -0.50 alignedtext
+end grestore
+end grestore
+
+% n3
+gsave 10 dict begin
+newpath 76 171 moveto
+22 171 lineto
+22 135 lineto
+76 135 lineto
+closepath
+stroke
+gsave 10 dict begin
+49 154 moveto (main) 28 14.00 -0.50 alignedtext
+end grestore
+end grestore
+
+% n2
+gsave 10 dict begin
+filled
+0.000 0.000 0.827 nodecolor
+newpath 180 171 moveto
+126 171 lineto
+126 135 lineto
+180 135 lineto
+closepath
+fill
+newpath 180 171 moveto
+126 171 lineto
+126 135 lineto
+180 135 lineto
+closepath
+stroke
+gsave 10 dict begin
+0.000 0.000 0.000 nodecolor
+153 162 moveto (vv1) 21 14.00 -0.50 alignedtext
+153 146 moveto (100.0) 31 14.00 -0.50 alignedtext
+end grestore
+end grestore
+
+% n3 -> n2
+newpath 76 153 moveto
+88 153 103 153 116 153 curveto
+stroke
+newpath 116 151 moveto
+126 153 lineto
+116 156 lineto
+closepath
+fill
+
+% n30
+gsave 10 dict begin
+newpath 430 198 moveto
+374 198 lineto
+374 162 lineto
+430 162 lineto
+closepath
+stroke
+gsave 10 dict begin
+402 181 moveto (savepar) 42 14.00 -0.50 alignedtext
+end grestore
+end grestore
+
+% n12
+gsave 10 dict begin
+newpath 585 98 moveto
+511 98 lineto
+511 62 lineto
+585 62 lineto
+closepath
+stroke
+gsave 10 dict begin
+548 81 moveto (showglyph) 61 14.00 -0.50 alignedtext
+end grestore
+end grestore
+
+% n31
+gsave 10 dict begin
+newpath 432 144 moveto
+372 144 lineto
+372 108 lineto
+432 108 lineto
+closepath
+stroke
+gsave 10 dict begin
+402 127 moveto (showpar) 47 14.00 -0.50 alignedtext
+end grestore
+end grestore
+
+% n31 -> n12
+newpath 433 116 moveto
+452 110 478 101 501 95 curveto
+stroke
+newpath 500 93 moveto
+510 92 lineto
+501 98 lineto
+closepath
+fill
+
+% n32
+gsave 10 dict begin
+newpath 726 390 moveto
+666 390 lineto
+666 354 lineto
+726 354 lineto
+closepath
+stroke
+gsave 10 dict begin
+696 373 moveto (v07_svd) 47 14.00 -0.50 alignedtext
+end grestore
+end grestore
+
+% n32 -> n27
+newpath 727 360 moveto
+748 352 777 340 799 331 curveto
+stroke
+newpath 798 329 moveto
+808 328 lineto
+799 334 lineto
+closepath
+fill
+
+% n33
+gsave 10 dict begin
+newpath 438 90 moveto
+366 90 lineto
+366 54 lineto
+438 54 lineto
+closepath
+stroke
+gsave 10 dict begin
+402 73 moveto (v09_c2lab) 58 14.00 -0.50 alignedtext
+end grestore
+end grestore
+
+% n16
+gsave 10 dict begin
+newpath 733 660 moveto
+659 660 lineto
+659 624 lineto
+733 624 lineto
+closepath
+stroke
+gsave 10 dict begin
+696 643 moveto (v09_calloc) 61 14.00 -0.50 alignedtext
+end grestore
+end grestore
+
+% n19
+gsave 10 dict begin
+newpath 585 541 moveto
+511 541 lineto
+511 505 lineto
+585 505 lineto
+closepath
+stroke
+gsave 10 dict begin
+548 524 moveto (v09_check) 60 14.00 -0.50 alignedtext
+end grestore
+end grestore
+
+% n17
+gsave 10 dict begin
+newpath 1005 444 moveto
+913 444 lineto
+913 408 lineto
+1005 408 lineto
+closepath
+stroke
+gsave 10 dict begin
+959 427 moveto (v09_compAV) 79 14.00 -0.50 alignedtext
+end grestore
+end grestore
+
+% n15
+gsave 10 dict begin
+newpath 1113 444 moveto
+1053 444 lineto
+1053 408 lineto
+1113 408 lineto
+closepath
+stroke
+gsave 10 dict begin
+1083 427 moveto (vp12_gt) 45 14.00 -0.50 alignedtext
+end grestore
+end grestore
+
+% n17 -> n15
+newpath 1006 426 moveto
+1019 426 1032 426 1044 426 curveto
+stroke
+newpath 1043 424 moveto
+1053 426 lineto
+1043 429 lineto
+closepath
+fill
+
+% n6
+gsave 10 dict begin
+filled
+0.000 0.000 0.827 nodecolor
+newpath 737 444 moveto
+655 444 lineto
+655 408 lineto
+737 408 lineto
+closepath
+fill
+newpath 737 444 moveto
+655 444 lineto
+655 408 lineto
+737 408 lineto
+closepath
+stroke
+gsave 10 dict begin
+0.000 0.000 0.000 nodecolor
+696 435 moveto (v09_compR) 68 14.00 -0.50 alignedtext
+696 419 moveto (73.2) 24 14.00 -0.50 alignedtext
+end grestore
+end grestore
+
+% n7
+gsave 10 dict begin
+filled
+0.000 0.000 0.827 nodecolor
+newpath 876 498 moveto
+794 498 lineto
+794 462 lineto
+876 462 lineto
+closepath
+fill
+newpath 876 498 moveto
+794 498 lineto
+794 462 lineto
+876 462 lineto
+closepath
+stroke
+gsave 10 dict begin
+0.000 0.000 0.000 nodecolor
+835 489 moveto (v09_compT) 67 14.00 -0.50 alignedtext
+835 473 moveto (13.0) 24 14.00 -0.50 alignedtext
+end grestore
+end grestore
+
+% n6 -> n7
+newpath 737 442 moveto
+752 448 769 454 785 460 curveto
+stroke
+newpath 786 458 moveto
+794 464 lineto
+784 462 lineto
+closepath
+fill
+
+% n10
+gsave 10 dict begin
+filled
+0.000 0.000 0.827 nodecolor
+newpath 872 390 moveto
+798 390 lineto
+798 354 lineto
+872 354 lineto
+closepath
+fill
+newpath 872 390 moveto
+798 390 lineto
+798 354 lineto
+872 354 lineto
+closepath
+stroke
+gsave 10 dict begin
+0.000 0.000 0.000 nodecolor
+835 381 moveto (v09_fmom) 61 14.00 -0.50 alignedtext
+835 365 moveto (8.7) 17 14.00 -0.50 alignedtext
+end grestore
+end grestore
+
+% n6 -> n10
+newpath 737 410 moveto
+753 404 772 397 788 390 curveto
+stroke
+newpath 787 388 moveto
+797 387 lineto
+788 393 lineto
+closepath
+fill
+
+% n20
+gsave 10 dict begin
+newpath 869 444 moveto
+801 444 lineto
+801 408 lineto
+869 408 lineto
+closepath
+stroke
+gsave 10 dict begin
+835 427 moveto (v09_sync) 53 14.00 -0.50 alignedtext
+end grestore
+end grestore
+
+% n6 -> n20
+newpath 737 426 moveto
+754 426 774 426 792 426 curveto
+stroke
+newpath 791 424 moveto
+801 426 lineto
+791 429 lineto
+closepath
+fill
+
+% n7 -> n17
+newpath 876 462 moveto
+886 457 897 453 908 448 curveto
+stroke
+newpath 907 446 moveto
+917 444 lineto
+909 450 lineto
+closepath
+fill
+
+% n18
+gsave 10 dict begin
+newpath 998 606 moveto
+920 606 lineto
+920 570 lineto
+998 570 lineto
+closepath
+stroke
+gsave 10 dict begin
+959 589 moveto (v09_partest) 65 14.00 -0.50 alignedtext
+end grestore
+end grestore
+
+% n7 -> n18
+newpath 866 498 moveto
+872 502 876 504 876 504 curveto
+892 521 896 547 912 564 curveto
+912 564 912 564 912 564 curveto
+stroke
+newpath 914 562 moveto
+920 570 lineto
+911 566 lineto
+closepath
+fill
+
+% n8
+gsave 10 dict begin
+filled
+0.000 0.000 0.827 nodecolor
+newpath 1000 552 moveto
+918 552 lineto
+918 516 lineto
+1000 516 lineto
+closepath
+fill
+newpath 1000 552 moveto
+918 552 lineto
+918 516 lineto
+1000 516 lineto
+closepath
+stroke
+gsave 10 dict begin
+0.000 0.000 0.000 nodecolor
+959 543 moveto (v10_compG) 69 14.00 -0.50 alignedtext
+959 527 moveto (13.0) 24 14.00 -0.50 alignedtext
+end grestore
+end grestore
+
+% n7 -> n8
+newpath 876 498 moveto
+886 503 897 507 908 512 curveto
+stroke
+newpath 909 510 moveto
+917 516 lineto
+907 514 lineto
+closepath
+fill
+
+% n14
+gsave 10 dict begin
+newpath 1005 498 moveto
+913 498 lineto
+913 462 lineto
+1005 462 lineto
+closepath
+stroke
+gsave 10 dict begin
+959 481 moveto (v10_compVB) 78 14.00 -0.50 alignedtext
+end grestore
+end grestore
+
+% n7 -> n14
+newpath 876 480 moveto
+885 480 893 480 902 480 curveto
+stroke
+newpath 902 478 moveto
+912 480 lineto
+902 483 lineto
+closepath
+fill
+
+% n1
+gsave 10 dict begin
+filled
+0.000 0.000 0.827 nodecolor
+newpath 305 198 moveto
+217 198 lineto
+217 162 lineto
+305 162 lineto
+closepath
+fill
+newpath 305 198 moveto
+217 198 lineto
+217 162 lineto
+305 162 lineto
+closepath
+stroke
+gsave 10 dict begin
+0.000 0.000 0.000 nodecolor
+261 189 moveto (v09_fimda1d) 74 14.00 -0.50 alignedtext
+261 173 moveto (100.0) 31 14.00 -0.50 alignedtext
+end grestore
+end grestore
+
+% n1 -> n30
+newpath 306 180 moveto
+325 180 346 180 364 180 curveto
+stroke
+newpath 363 178 moveto
+373 180 lineto
+363 183 lineto
+closepath
+fill
+
+% n1 -> n31
+newpath 306 163 moveto
+324 156 345 148 362 141 curveto
+stroke
+newpath 361 139 moveto
+371 138 lineto
+362 144 lineto
+closepath
+fill
+
+% n1 -> n33
+newpath 295 162 moveto
+301 158 306 156 306 156 curveto
+323 140 325 112 342 96 curveto
+347 92 353 89 359 86 curveto
+stroke
+newpath 356 85 moveto
+366 83 lineto
+358 89 lineto
+closepath
+fill
+
+% n1 -> n16
+newpath 268 198 moveto
+294 267 392 513 498 599 curveto
+508 606 596 623 651 634 curveto
+stroke
+newpath 648 631 moveto
+658 635 lineto
+648 636 lineto
+closepath
+fill
+
+% n4
+gsave 10 dict begin
+filled
+0.000 0.000 0.827 nodecolor
+newpath 436 344 moveto
+368 344 lineto
+368 308 lineto
+436 308 lineto
+closepath
+fill
+newpath 436 344 moveto
+368 344 lineto
+368 308 lineto
+436 308 lineto
+closepath
+stroke
+gsave 10 dict begin
+0.000 0.000 0.000 nodecolor
+402 335 moveto (v09_fit1d) 54 14.00 -0.50 alignedtext
+402 319 moveto (87.0) 24 14.00 -0.50 alignedtext
+end grestore
+end grestore
+
+% n1 -> n4
+newpath 279 198 moveto
+304 224 351 273 379 302 curveto
+stroke
+newpath 380 299 moveto
+385 308 lineto
+376 303 lineto
+closepath
+fill
+
+% n34
+gsave 10 dict begin
+newpath 438 252 moveto
+366 252 lineto
+366 216 lineto
+438 216 lineto
+closepath
+stroke
+gsave 10 dict begin
+402 235 moveto (v09_lab2c) 58 14.00 -0.50 alignedtext
+end grestore
+end grestore
+
+% n1 -> n34
+newpath 306 197 moveto
+322 203 341 210 357 217 curveto
+stroke
+newpath 357 214 moveto
+366 220 lineto
+356 219 lineto
+closepath
+fill
+
+% n9
+gsave 10 dict begin
+filled
+0.000 0.000 0.827 nodecolor
+newpath 461 36 moveto
+343 36 lineto
+343 0 lineto
+461 0 lineto
+closepath
+fill
+newpath 461 36 moveto
+343 36 lineto
+343 0 lineto
+461 0 lineto
+closepath
+stroke
+gsave 10 dict begin
+0.000 0.000 0.000 nodecolor
+402 27 moveto (v09_readmultidata) 104 14.00 -0.50 alignedtext
+402 11 moveto (13.0) 24 14.00 -0.50 alignedtext
+end grestore
+end grestore
+
+% n1 -> n9
+newpath 295 162 moveto
+301 158 306 156 306 156 curveto
+327 122 320 76 341 43 curveto
+stroke
+newpath 339 41 moveto
+348 36 lineto
+343 45 lineto
+closepath
+fill
+
+% n4 -> n26
+newpath 418 308 moveto
+438 287 471 255 498 250 curveto
+580 236 724 242 794 246 curveto
+stroke
+newpath 793 243 moveto
+803 247 lineto
+793 248 lineto
+closepath
+fill
+
+% n4 -> n16
+newpath 407 344 moveto
+421 388 457 501 498 553 curveto
+515 574 595 613 650 632 curveto
+stroke
+newpath 650 629 moveto
+658 635 lineto
+648 634 lineto
+closepath
+fill
+
+% n4 -> n19
+newpath 411 344 moveto
+429 379 469 455 498 494 curveto
+500 496 502 499 505 501 curveto
+stroke
+newpath 504 497 moveto
+511 505 lineto
+501 502 lineto
+closepath
+fill
+
+% n4 -> n10
+newpath 436 327 moveto
+506 328 667 333 758 342 curveto
+767 343 780 347 792 351 curveto
+stroke
+newpath 790 347 moveto
+798 354 lineto
+788 352 lineto
+closepath
+fill
+
+% n5
+gsave 10 dict begin
+filled
+0.000 0.000 0.827 nodecolor
+newpath 597 449 moveto
+499 449 lineto
+499 413 lineto
+597 413 lineto
+closepath
+fill
+newpath 597 449 moveto
+499 449 lineto
+499 413 lineto
+597 413 lineto
+closepath
+stroke
+gsave 10 dict begin
+0.000 0.000 0.000 nodecolor
+548 440 moveto (v09_marquardt) 85 14.00 -0.50 alignedtext
+548 424 moveto (81.9) 24 14.00 -0.50 alignedtext
+end grestore
+end grestore
+
+% n4 -> n5
+newpath 427 344 moveto
+452 362 490 390 517 409 curveto
+stroke
+newpath 516 405 moveto
+523 413 lineto
+513 410 lineto
+closepath
+fill
+
+% n37
+gsave 10 dict begin
+newpath 591 298 moveto
+505 298 lineto
+505 262 lineto
+591 262 lineto
+closepath
+stroke
+gsave 10 dict begin
+548 281 moveto (v09_tunetest) 71 14.00 -0.50 alignedtext
+end grestore
+end grestore
+
+% n4 -> n37
+newpath 436 315 moveto
+453 310 476 303 496 297 curveto
+stroke
+newpath 495 295 moveto
+505 294 lineto
+496 300 lineto
+closepath
+fill
+
+% n21
+gsave 10 dict begin
+newpath 581 152 moveto
+515 152 lineto
+515 116 lineto
+581 116 lineto
+closepath
+stroke
+gsave 10 dict begin
+548 135 moveto (v09_gray) 52 14.00 -0.50 alignedtext
+end grestore
+end grestore
+
+% n34 -> n16
+newpath 424 252 moveto
+439 265 456 282 462 296 curveto
+484 347 467 414 498 461 curveto
+518 489 576 466 598 493 curveto
+627 525 611 581 634 618 curveto
+634 618 640 620 648 623 curveto
+stroke
+newpath 650 621 moveto
+658 627 lineto
+648 626 lineto
+closepath
+fill
+
+% n34 -> n21
+newpath 438 219 moveto
+451 214 462 210 462 210 curveto
+479 197 483 172 498 158 curveto
+501 156 504 154 508 151 curveto
+stroke
+newpath 504 150 moveto
+514 148 lineto
+506 155 lineto
+closepath
+fill
+
+% n22
+gsave 10 dict begin
+newpath 581 206 moveto
+515 206 lineto
+515 170 lineto
+581 170 lineto
+closepath
+stroke
+gsave 10 dict begin
+548 189 moveto (v09_t2fft) 52 14.00 -0.50 alignedtext
+end grestore
+end grestore
+
+% n34 -> n22
+newpath 438 223 moveto
+458 216 484 208 506 201 curveto
+stroke
+newpath 505 199 moveto
+515 198 lineto
+506 204 lineto
+closepath
+fill
+
+% n5 -> n29
+newpath 586 449 moveto
+591 452 595 455 598 460 curveto
+618 490 612 533 633 563 curveto
+stroke
+newpath 635 562 moveto
+641 570 lineto
+632 565 lineto
+closepath
+fill
+
+% n5 -> n24
+newpath 579 449 moveto
+589 455 598 460 598 460 curveto
+614 473 618 497 634 510 curveto
+634 510 635 511 635 511 curveto
+stroke
+newpath 636 509 moveto
+644 516 lineto
+634 513 lineto
+closepath
+fill
+
+% n5 -> n32
+newpath 593 413 moveto
+614 405 637 396 657 388 curveto
+stroke
+newpath 655 386 moveto
+665 384 lineto
+657 391 lineto
+closepath
+fill
+
+% n5 -> n16
+newpath 579 449 moveto
+589 455 598 460 598 460 curveto
+621 509 609 570 634 618 curveto
+637 623 644 628 651 631 curveto
+stroke
+newpath 650 628 moveto
+658 634 lineto
+648 632 lineto
+closepath
+fill
+
+% n5 -> n6
+newpath 598 429 moveto
+613 429 630 428 645 428 curveto
+stroke
+newpath 645 426 moveto
+655 427 lineto
+645 430 lineto
+closepath
+fill
+
+% n35
+gsave 10 dict begin
+newpath 739 498 moveto
+653 498 lineto
+653 462 lineto
+739 462 lineto
+closepath
+stroke
+gsave 10 dict begin
+696 481 moveto (v09_parcopy) 72 14.00 -0.50 alignedtext
+end grestore
+end grestore
+
+% n5 -> n35
+newpath 598 447 moveto
+613 452 628 458 643 463 curveto
+stroke
+newpath 643 460 moveto
+652 466 lineto
+642 465 lineto
+closepath
+fill
+
+% n13
+gsave 10 dict begin
+newpath 1001 390 moveto
+917 390 lineto
+917 354 lineto
+1001 354 lineto
+closepath
+stroke
+gsave 10 dict begin
+959 373 moveto (v09_parsync) 71 14.00 -0.50 alignedtext
+end grestore
+end grestore
+
+% n36
+gsave 10 dict begin
+newpath 737 298 moveto
+655 298 lineto
+655 262 lineto
+737 262 lineto
+closepath
+stroke
+gsave 10 dict begin
+696 281 moveto (v09_qnodes) 67 14.00 -0.50 alignedtext
+end grestore
+end grestore
+
+% n36 -> n26
+newpath 737 271 moveto
+755 267 776 262 794 258 curveto
+stroke
+newpath 793 256 moveto
+803 256 lineto
+794 261 lineto
+closepath
+fill
+
+% n20 -> n13
+newpath 869 411 moveto
+881 406 895 400 908 394 curveto
+stroke
+newpath 907 392 moveto
+917 390 lineto
+909 396 lineto
+closepath
+fill
+
+% n37 -> n36
+newpath 591 280 moveto
+608 280 628 280 645 280 curveto
+stroke
+newpath 645 278 moveto
+655 280 lineto
+645 283 lineto
+closepath
+fill
+
+% n11
+gsave 10 dict begin
+filled
+0.000 0.000 0.827 nodecolor
+newpath 1124 552 moveto
+1042 552 lineto
+1042 516 lineto
+1124 516 lineto
+closepath
+fill
+newpath 1124 552 moveto
+1042 552 lineto
+1042 516 lineto
+1124 516 lineto
+closepath
+stroke
+gsave 10 dict begin
+0.000 0.000 0.000 nodecolor
+1083 543 moveto (v10_compZ) 67 14.00 -0.50 alignedtext
+1083 527 moveto (4.3) 17 14.00 -0.50 alignedtext
+end grestore
+end grestore
+
+% n8 -> n11
+newpath 1001 534 moveto
+1011 534 1022 534 1032 534 curveto
+stroke
+newpath 1032 532 moveto
+1042 534 lineto
+1032 537 lineto
+closepath
+fill
+
+% n38
+gsave 10 dict begin
+newpath 293 144 moveto
+229 144 lineto
+229 108 lineto
+293 108 lineto
+closepath
+stroke
+gsave 10 dict begin
+261 127 moveto (vinit2lab) 49 14.00 -0.50 alignedtext
+end grestore
+end grestore
+
+% n2 -> n1
+newpath 180 160 moveto
+188 162 197 164 206 167 curveto
+stroke
+newpath 207 165 moveto
+216 169 lineto
+206 169 lineto
+closepath
+fill
+
+% n2 -> n38
+newpath 180 146 moveto
+192 143 206 140 219 136 curveto
+stroke
+newpath 219 134 moveto
+229 134 lineto
+220 138 lineto
+closepath
+fill
+
+% node0
+gsave 10 dict begin
+newpath 89 513 moveto
+9 513 lineto
+9 477 lineto
+89 477 lineto
+closepath
+stroke
+gsave 10 dict begin
+49 496 moveto (Profiling v1) 67 14.00 -0.50 alignedtext
+end grestore
+end grestore
+endpage
+grestore
+%%PageTrailer
+%%EndPage: 1
+%%Trailer
+%%Pages: 1
+end
+restore
+%%EOF
--- /dev/null
+#!/store/bin/perl
+#
+# Search and replace params in HTML tags. Change all lines to end with \r\n
+#
+# Author: Petter Reinholdtsen <pere@td.org.uit.no>
+# Date: 1997-05-27
+# Changed:1997-05-27
+
+#$debug = 1;
+
+require "find.pl";
+use Getopt::Std;
+
+sub usage {
+ print "$0 [-c <configfile>|'<search-replace command>'] <paths>\n";
+ print " -c Change default config-file\n\n";
+ print "Command format: <TAG>.<PARAM> {<from>-><to>|-}\n";
+ print " If <from> is '*', the param will be inserted where necessary.\n";
+ print " If command is '-', the param is removed.\n\n";
+}
+
+if (! getopts('c:') || ! @ARGV) {
+ usage();
+ exit 1;
+}
+
+if ($opt_c) {
+ open(CFILE, "<$opt_c") || die "Unable to open $opt_c for reading";
+ while (<CFILE>) {
+ next if (/^\#/);
+ push(@commands,msdosChompLine($_));
+ }
+ close(CFILE);
+} else {
+ @commands = (shift(@ARGV));
+}
+
+umask 002;
+
+&find(@ARGV);
+
+sub wanted {
+ return if ( ! /\.s?html?$/i || ! -r "$dir/$_" );
+ $filename = "$dir/$_";
+ print "Prosessing $filename\n";
+ $oldtime = (stat("$filename"))[10]; # save change-time to compare before saveing
+ if (! open(FILE, "<$filename") ) {
+ warn "Unable to open $filename for reading. Nothing changed.";
+ return;
+ }
+ foreach $line (<FILE>) {
+ push(@html, $line);
+ $line = msdosChompLine($line);
+ foreach $command (@commands) {
+ local($tag, $param, $cmd) = $command =~ m/^(\w+)\.(\w+) (.+)$/;
+ if ( $line =~ /\<$tag[^\>]*\>/i ) {
+ print "L: \"$line\"\nC: $tag $param $cmd\n" if ($debug);
+ if ($cmd eq "-") { # Remove the param
+ $line =~ s/(\<$tag[^\>]*) $param\s*=\s*\"?[^\" ]+\"?([ >])/\1\2/i;
+ } elsif ($cmd =~ /\-\>/) { # change param
+ ($from, $to) = $cmd =~ m/^(.+)-\>(.+)$/;
+ print "$tag.$param $from -> $to\n" if ($debug);
+
+ if ( $line =~
+ m/^(.*\<$tag[^\>]* )($param\s*=\s*\"?)([^\" >]+)(\"?.*)$/i ) {
+ print "Param hit: \"$3\"\n" if ($debug);
+ # param exist - change it
+ if ($from eq '*' || $from eq $3) {
+ $line = "$1\U$2"."$to$4";
+ print "Replaced\n" if ($debug);
+ }
+ } elsif ($from eq '*') {
+ # new param in tag - insert it
+ $line =~ m/^(.*\<$tag[^\>]+)(\>.*)$/i;
+ $line = "$1 \U$param=\""."$to\"$2";
+ print "Inserted\n" if ($debug);
+ } # else nothing is done
+ }
+ # Pack and remove redundand space inside tags
+ $line =~ s/(\<[^\>]+) \s+([^\>]*>)/\1 \2/;
+ $line =~ s/\s+\>/\>/;
+ print "L2: \"$line\"\n" if ($debug);
+ }
+ }
+ push(@newhtml, "$line\r\n");
+ }
+ close(FILE);
+
+ # Save backup and replace
+ if ($oldtime == (stat("$filename"))[10]) { # Not changed while we prossessed
+ print @newhtml if ($debug);
+ local($backupname) = "$filename.backup";##-$$";
+ if (open(BACKUP, ">$backupname") ) {
+ if (print BACKUP @html) { # backup saved - replace original
+ close(BACKUP);
+ if ( open(FILE, ">$filename") ) {
+ if (print FILE @newhtml) { # Original replaced - all OK
+ close(FILE);
+ } else {
+ close(FILE);
+ warn "Unable to write to $filename. Probably damage - check backup $backupname."
+ }
+ } else {
+ warn "Unable to open $filename for writeing. Possible damage! - check backup $backupname";
+ }
+ } else {
+ close(BACKUP);
+ unlink $backupname;
+ warn "Unable to save backup for $filename. Nothing changed.";
+ }
+ } else {
+ warn "Unable to open backupfile $filename for writeing. Nothing changed.";
+ }
+ }
+}
+
+sub msdosChompLine {
+ local($line) = @_;
+ local($tmp) = $/;
+ $/ = "\n";
+ chomp($line);
+ $/ = "\r";
+ chomp($line);
+ $/ = $tmp;
+ return $line;
+}
--- /dev/null
+Only in src-1.0-sgi4irix6: .gdb_history
+diff -ru src-1.0/codegen.c src-1.0-sgi4irix6/codegen.c
+--- src-1.0/codegen.c Tue May 28 09:21:20 1996
++++ src-1.0-sgi4irix6/codegen.c Thu Apr 3 20:51:21 1997
+@@ -7,7 +7,11 @@
+
+ #include<string.h>
+ #include<stdio.h>
++#ifndef unix
+ #include<dos.h>
++#else
++#include <stdlib.h>
++#endif
+ #include"codegen.h"
+ #include"defs.h"
+ #include"fileio.h"
+Only in src-1.0-sgi4irix6: codegen.o
+diff -ru src-1.0/defs.h src-1.0-sgi4irix6/defs.h
+--- src-1.0/defs.h Tue May 28 09:44:10 1996
++++ src-1.0-sgi4irix6/defs.h Thu Apr 3 21:03:22 1997
+@@ -8,6 +8,8 @@
+ #ifndef _defs_h_
+ #define _defs_h_
+
++#define SIZEDEF_FILE "/store/lib/html2rtf/sizes.def"
++
+ /*Symbole fuer eine Auswahl von Elementsymbolen aus einem HTML-Text*/
+ enum symbol{ HTML_SYM, /*Anfangs Symbole*/
+ HEAD_SYM,
+Only in src-1.0-sgi4irix6: defs.o
+diff -ru src-1.0/error.c src-1.0-sgi4irix6/error.c
+--- src-1.0/error.c Tue Apr 16 12:31:28 1996
++++ src-1.0-sgi4irix6/error.c Thu Apr 3 21:12:18 1997
+@@ -5,6 +5,7 @@
+ Funktion : Funktionen zur Fehler- und Warnungsbehandlung
+ */
+ #include<stdlib.h>
++#include <stdio.h>
+ #include"error.h"
+ #include"fileio.h"
+
+Only in src-1.0-sgi4irix6: error.o
+diff -ru src-1.0/fileio.c src-1.0-sgi4irix6/fileio.c
+--- src-1.0/fileio.c Thu Apr 18 17:09:22 1996
++++ src-1.0-sgi4irix6/fileio.c Thu Apr 3 20:47:36 1997
+@@ -52,7 +52,7 @@
+ }
+ }
+
+-char lies(void)
++int lies(void)
+ /*
+ Rueckgabewert: char-Wert des naechsten Zeichens.
+ Funktion: Aus der Quelldatei FpI wird ein Zeichen gelesen und die
+@@ -60,7 +60,7 @@
+ Vorbedingungen: Es muss ueber den Pointer FpI auf den Quelltext
+ zugegriffen werden koennen.
+ */
+-{ char c=getc(FpI);
++{ int c=getc(FpI);
+ Spalte++;
+ if(c=='\n'){
+ Zeile++;
+diff -ru src-1.0/fileio.h src-1.0-sgi4irix6/fileio.h
+--- src-1.0/fileio.h Thu Apr 18 10:34:56 1996
++++ src-1.0-sgi4irix6/fileio.h Thu Apr 3 20:47:44 1997
+@@ -10,7 +10,7 @@
+
+ void openInput (char *);
+ void closeInput (void);
+-char lies (void);
++int lies (void);
+ void actPos (unsigned *, unsigned *);
+ void openOutput (char *);
+ void closeOutput(void);
+Only in src-1.0-sgi4irix6: fileio.o
+diff -ru src-1.0/ftext.c src-1.0-sgi4irix6/ftext.c
+--- src-1.0/ftext.c Tue Apr 23 09:36:40 1996
++++ src-1.0-sgi4irix6/ftext.c Thu Apr 3 20:53:08 1997
+@@ -8,6 +8,9 @@
+
+ #include<stdio.h>
+ #include<stdlib.h>
++#ifdef unix
++#include <string.h>
++#endif
+ #include"ftext.h"
+ #include"defs.h"
+
+Only in src-1.0-sgi4irix6: ftext.o
+diff -ru src-1.0/links.c src-1.0-sgi4irix6/links.c
+--- src-1.0/links.c Tue Apr 16 12:31:28 1996
++++ src-1.0-sgi4irix6/links.c Thu Apr 3 21:09:23 1997
+@@ -6,7 +6,12 @@
+ */
+
+ #include<string.h>
++#ifndef unix
+ #include<io.h>
++#else
++#include <ctype.h>
++#include <unistd.h>
++#endif
+ #include"links.h"
+
+ extern char path[256];
+Only in src-1.0-sgi4irix6: links.o
+diff -ru src-1.0/main.c src-1.0-sgi4irix6/main.c
+--- src-1.0/main.c Thu May 30 11:09:00 1996
++++ src-1.0-sgi4irix6/main.c Thu Apr 3 21:11:44 1997
+@@ -5,7 +5,11 @@
+ Funktion : Hauptprogramm
+ */
+
++#ifndef unix
+ #include<dos.h>
++#else
++#include <unistd.h>
++#endif
+ #include<stdlib.h>
+ #include<string.h>
+ #include<stdio.h>
+@@ -37,10 +41,14 @@
+ struct element elementDaten;
+ enum symbol symbol;
+ unsigned int warnings, errors;
++#ifndef unix
+ struct time zeit1, zeit2;
++#endif
+ int i, printDefaults;
+
++#ifndef unix
+ gettime(&zeit1);
++#endif
+ elementDaten.parameterPtr=NULL;
+ puts("HTML-to-RTF Compiler 0.9, Robin Gressmann 1996");
+
+@@ -56,7 +64,7 @@
+ split(nameI, path, name);
+ creat_HPJ_Name(nameHPJ, name);
+ creat_RTF_Name(nameRTF, name);
+- strcpy(nameDEF, "sizes.def");
++ strcpy(nameDEF, SIZEDEF_FILE);
+ strcpy(nameWindow, "Manual");
+ strcpy(HeadLabel, "top_of_file_label");
+ printDefaults=0;
+@@ -105,9 +113,13 @@
+ fileError("found a write-protected HPJ-file");
+ }
+ value_of_WarningsErrors(&warnings, &errors);
++#ifndef unix
+ gettime(&zeit2);
++#endif
+
++#ifndef unix
+ printf("\ntime in use : %.2f sec", diffTime(zeit1, zeit2));
++#endif
+ printf("\nWarnings : %u", warnings);
+ printf("\nErrors : %u", errors);
+ printf("\nDEF-File : %s", nameDEF);
+@@ -116,6 +128,7 @@
+ printf("\nProjekt-File: %s", nameHPJ);
+ printf("\nPath : %s", path);
+ printf("\nName : %s\n\n", name);
++ return 0;
+ }
+
+ void check(char *nameI)
+@@ -205,12 +218,14 @@
+ void insert_in_HPJ_file(char *HPJ, char *RTF)
+ { FILE *fp;
+ char zeile[50], zeichen[2];
++ int tmp = 0;
+ int in=0;
+ zeichen[1]=zeile[0]='\0';
+ if((fp=fopen(HPJ, "r+"))==NULL){
+ fileError("can not create projekt file");
+ }
+- while((zeichen[0]=getc(fp))!=EOF){
++ while((tmp = getc(fp))!=EOF){
++ zeichen[0] = (char)tmp;
+ if(zeichen[0]=='\n'){
+ if(!stricmp(zeile,RTF)){
+ in=1;
+Only in src-1.0-sgi4irix6: main.o
+diff -ru src-1.0/makefile src-1.0-sgi4irix6/makefile
+--- src-1.0/makefile Thu May 30 11:09:36 1996
++++ src-1.0-sgi4irix6/makefile Thu Apr 3 21:29:42 1997
+@@ -1,42 +1,43 @@
+-para=-O2 -fomit-frame-pointer -funroll-all-loops
++CC=gcc
++CFLAGS=-Wall -O2 -fomit-frame-pointer -funroll-all-loops
+
+ html2rtf.exe : main.o scanner.o error.o codegen.o parser.o sizes.o utils.o links.o fileio.o defs.o ftext.o
+- gcc *.o -lm
++ $(CC) *.o -lm
+ mkexe.bat html2rtf
+ copy html2rtf.exe c:\a\bin
+
+ main.o : main.c main.h utils.h parser.h defs.h sizes.h fileio.h
+- gcc $(para) -c main.c
++ $(CC) $(CFLAGS) -c main.c
+
+ scanner.o : scanner.c scanner.h defs.h error.h fileio.h ftext.h
+- gcc $(para) -c scanner.c
++ $(CC) $(CFLAGS) -c scanner.c
+
+ defs.o : defs.c defs.h error.h
+- gcc $(para) -c defs.c
++ $(CC) $(CFLAGS) -c defs.c
+
+ fileio.o : fileio.c fileio.h defs.h error.h
+- gcc $(para) -c fileio.c
++ $(CC) $(CFLAGS) -c fileio.c
+
+ parser.o : parser.c parser.h defs.h error.h scanner.h codegen.h ftext.h
+- gcc $(para) -c parser.c
++ $(CC) $(CFLAGS) -c parser.c
+
+ codegen.o : codegen.c codegen.h defs.h links.h fileio.h error.h ftext.h
+- gcc $(para) -c codegen.c
++ $(CC) $(CFLAGS) -c codegen.c
+
+ sizes.o : sizes.c sizes.h error.h utils.h
+- gcc $(para) -c sizes.c
++ $(CC) $(CFLAGS) -c sizes.c
+
+ error.o : error.c error.h
+- gcc $(para) -c error.c
++ $(CC) $(CFLAGS) -c error.c
+
+ utils.o : utils.c utils.h error.h
+- gcc $(para) -c utils.c
++ $(CC) $(CFLAGS) -c utils.c
+
+ links.o : links.c links.h
+- gcc $(para) -c links.c
++ $(CC) $(CFLAGS) -c links.c
+
+ ftext.o : ftext.c ftext.h defs.h
+- gcc $(para) -c ftext.c
++ $(CC) $(CFLAGS) -c ftext.c
+
+ clear :
+ del *.o
+diff -ru src-1.0/parser.c src-1.0-sgi4irix6/parser.c
+--- src-1.0/parser.c Tue Apr 30 10:30:24 1996
++++ src-1.0-sgi4irix6/parser.c Thu Apr 3 21:12:48 1997
+@@ -6,8 +6,10 @@
+ HTML-Befehle
+ */
+ #include<stdio.h>
++#include <stdlib.h>
+ #include<setjmp.h>
+ #include"parser.h"
++#include "fileio.h"
+ #include"defs.h"
+ #include"scanner.h"
+ #include"codegen.h"
+Only in src-1.0-sgi4irix6: parser.o
+diff -ru src-1.0/scanner.c src-1.0-sgi4irix6/scanner.c
+--- src-1.0/scanner.c Thu Apr 18 16:09:58 1996
++++ src-1.0-sgi4irix6/scanner.c Thu Apr 3 21:06:35 1997
+@@ -8,7 +8,11 @@
+ #include<stdio.h>
+ #include<string.h>
+ #include<stdlib.h>
++#ifndef unix
+ #include<dos.h>
++#else
++#include <ctype.h>
++#endif
+ #include"defs.h"
+ #include"scanner.h"
+ #include"error.h"
+@@ -28,7 +32,7 @@
+ Anfangssymbol '--'.
+ Nachbedingingen: FpI zeigt genau hinter das Kommentarendesymbol --'.
+ */
+-{ char c;
++{ int c;
+ while ((c=lies())!=EOF){
+ if(c=='-'){
+ if(lies()=='-'){
+@@ -48,7 +52,7 @@
+ Anfangssymbol '<!'.
+ Nachbedingingen: FpI zeigt genau hinter das Definitionssymbol '>'.
+ */
+-{ char c;
++{ int c;
+ while ((c=lies())!=EOF){
+ if(c=='>'){
+ return;
+@@ -64,7 +68,7 @@
+ Datei dann wieder vor dieses Zeichen.
+ Vorbedingungen: FpI muss auf eine Datei mit Lesezugriff zeigen.
+ */
+-{ char c;
++{ int c;
+ long pos;
+ do{
+ pos=ftell(FpI);
+@@ -298,8 +302,8 @@
+ Funktion: Scanner des Quellcodes (endlicher Automat)
+ */
+ { static unsigned status=1;
+- char nextc, temp,
+- elementText[ELEMENT_TYP_MAX],
++ int nextc, temp;
++ char elementText[ELEMENT_TYP_MAX],
+ attributNameText[ATTRIBUT_NAME_MAX],
+ attributWertText[ATTRIBUT_WERT_MAX];
+ int textFlag=0, entityFlag=0, symbolFlag=0, gleichFlag=0;
+Only in src-1.0-sgi4irix6: scanner.o
+diff -ru src-1.0/sizes.c src-1.0-sgi4irix6/sizes.c
+--- src-1.0/sizes.c Thu Apr 25 13:03:46 1996
++++ src-1.0-sgi4irix6/sizes.c Thu Apr 3 20:52:17 1997
+@@ -6,7 +6,9 @@
+ */
+ #include<stdio.h>
+ #include<string.h>
++#ifndef unix
+ #include<dos.h>
++#endif
+ #include"sizes.h"
+ #include"error.h"
+ #include"utils.h"
+@@ -246,7 +248,7 @@
+ }
+
+ int newLine(char *line)
+-{ char c;
++{ int c;
+ int i=0;
+ while((c=getc(fp))!='\n'&&c!=EOF&&i<MAX_LINE){
+ line[i++]=c;
+Only in src-1.0-sgi4irix6: sizes.o
+diff -ru src-1.0/utils.c src-1.0-sgi4irix6/utils.c
+--- src-1.0/utils.c Tue Apr 16 12:31:28 1996
++++ src-1.0-sgi4irix6/utils.c Thu Apr 3 21:26:08 1997
+@@ -6,7 +6,11 @@
+ */
+ #include<math.h>
+ #include<string.h>
++#ifndef unix
+ #include<dos.h>
++#else
++#include <ctype.h>
++#endif
+ #include"utils.h"
+ #include"error.h"
+
+@@ -54,12 +58,15 @@
+ return 0;
+ }
+
++#ifndef unix
+ double diffTime(struct time z1, struct time z2)
+-{ return fabs(3600*(z2.ti_hour-z1.ti_hour)+
++{
++ return fabs(3600*(z2.ti_hour-z1.ti_hour)+
+ 60*(z2.ti_min-z1.ti_min)+
+ (z2.ti_sec-z1.ti_sec)+
+ (double)(z2.ti_hund-z1.ti_hund)/100);
+ }
++#endif
+
+ void appendString(char *string, char zeichen, unsigned max)
+ /*
+@@ -78,4 +85,18 @@
+ }else{
+ fatalError("String buffer overflow!");
+ }
++}
++
++void strlwr(char *str)
++{
++ if (NULL == str)
++ return;
++ while (*str != '\0') {
++ *str=tolower(*str);
++ str++;
++ }
++}
++int stricmp(char *s1, char *s2)
++{
++ return strcasecmp(s1,s2);
+ }
+diff -ru src-1.0/utils.h src-1.0-sgi4irix6/utils.h
+--- src-1.0/utils.h Tue Apr 16 12:31:28 1996
++++ src-1.0-sgi4irix6/utils.h Thu Apr 3 20:45:27 1997
+@@ -11,7 +11,14 @@
+
+ void my_itoa(int, char *);
+ int whichValue(char *, char *, struct attribut *);
++#ifndef unix
+ double diffTime(struct time, struct time);
++#endif
+ void appendString(char *, char, unsigned);
++
++#ifdef unix
++int stricmp(char *, char *);
++void strlwr(char *);
++#endif
+
+ #endif
+Only in src-1.0-sgi4irix6: utils.o
--- /dev/null
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+ <head>
+ <title>Linux and Unix stuff from Petter Reinholdtsen</title>
+ </head>
+
+ <body>
+ <h1>Linux and Unix stuff from Petter Reinholdtsen</h1>
+
+ Here is some of my collection of stuff written for Unix and linux.
+
+ <dl>
+
+ <DT><A HREF="gprof-callgraph/gprof-callgraph.pl">gprof-callgraph.pl</A>
+ - 2001-12-12</DT>
+ <DD>Create a VCG or a dot call graph file from the output generated
+ by gprof. (example <a href="gprof-callgraph/graph-dot.ps">graph</a>
+ from dot)</dd>
+
+ <DT><A HREF="make-cvs-pwhash.pl">make-cvs-pwhash.pl</A> - 2000-06-29</DT>
+ <DD>Simple unix password hash generator to generate CVS :pserver: access list entries.</DD>
+
+ <DT><A HREF="meteor_fgrab_widget_0.8-pere.diff">meteor_fgrab_widget_0.8-pere.diff</A> - 1999-12-14</DT>
+ <DD>Patch to get Matrox Meteor Tcl/Tk framegrabber widget 0.8 compiling on RedHat 6.1.</DD>
+ <DT><A HREF="check_po_consistency">check_po_consistency</A> - 2001-08-05</DT>
+ <dd>Check gettext translation files (.po files) for inconsistencies.</DD>
+ <DT><A HREF="auto_translate">auto_translate</A> - 2001-08-05</DT>
+ <dd>Autotranslate gettext translation files (.po files) based on
+ existing translations.</DD>
+
+ <DT><A HREF="http://www.pvv.org/~arnej/store/storedoc.html">Store</A> utilities</DT>
+
+ <DD><dl>
+ <DT><A HREF="store/storeconfig-20001009.tar.gz">storeconfig-20001009.tar.gz</A> - 2000-10-09</DT>
+ <DD>Make it easier to maintain ~store/etc/config.</DD>
+ <DT><A HREF="store/store-extra-20000928.tar.gz">store-extra-20000928.tar.gz</A> - 2000-09-28</DT>
+ <DD>My collection of store scripts.</DD>
+ <DT><A HREF="store/buildall.txt">Automatisk kompilering av Store-programmer på alle plattformer</A> 1999-07-28
+ <DD>Norsk instruksjon på bruk av scriptet build-all.</DD>
+ </dl></DD>
+ <DT><A HREF="http://www.math.duke.edu/~yu/wreq/">wreq</A> patches relative to 2.7</DT>
+ <DD><dl>
+ <DT><A HREF="wreq/no-sig-no-mime-2.diff">no-sig-no-mime-2.diff</A> 1999-05-19</DT>
+ <DD>Add option to remove sig from incoming mails. Only accept MIME mail of type text/plain or non-MIME mail. Unpack ISO-8859-1 MIME-encoded subject in incoming mails.</DD>
+ <DT><A HREF="wreq/list-all-config.diff">list-all-config.diff</A> 1999-05-16</DT>
+ <DD>Bugfix: Add missing field (announcement) to config listing.</DD>
+
+ <DT><A HREF="wreq/list-stat-mail.diff">list-stat-mail.diff</A> 1999-05-16</DT>
+ <DD>Bugfix: Correct text statistics email count.</DD>
+
+ <DT><A HREF="wreq/handle-no-GD.diff">handle-no-GD.diff</A> 1999-05-16</DT>
+ <DD>OBS: Do not work... Make sure everything in statistics package except graph generation
+works even when GD.pm is missing.</DD>
+
+ <DT><A HREF="wreq/url-fix.diff">url-fix.diff</A> 1999-05-16</DT>
+ <DD>Correct URL to home page to include trailing slash, and
+ include link to home page on every wreq page.</DD>
+
+ <DT><A HREF="wreq/list-top-newrequest.diff">list-top-newrequest.diff</A> 1999-05-15</DT>
+ <DD>Change confusing label 'Top' to 'New request'.</DD>
+ <DT><A HREF="wreq/newreq-linkform.diff">newreq-linkform.diff</A> 1999-05-15</DT>
+ <DD>Add link back to web form from page presented after accepting a request.</DD>
+ <DT><A HREF="wreq/no-scriptdir.diff">no-scriptdir.diff</A> 1999-05-15</DT>
+ <DD>Remove the need for config variable $scriptdir</DD>
+ <DT><A HREF="wreq/no-sendmail.diff">no-sendmail.diff</A> 1999-05-15</DT>
+ <DD>If sendmail is missing, use module Net::SMTP to send mail</DD>
+ </dl></DD>
+ <DT><A HREF="linux-nfs-wp8-nolock.diff">linux-nfs-wp8-nolock.diff</A> 1999-04-20
+ <dd>Ignore all tries to lock over NFS. This gets WP8 running. A better solution is the 'nolock' mount option.</DD>
+ <DT><A HREF="http://www.mostang.com/sane/">SANE</A> patches not yet included in distribution (and other stuff)</DT>
+ <dd><dl>
+
+ <DT><A HREF="sane/sane-devel-20000802.tar.gz">Unstable
+ development snapshot</A> - 2000-08-02 (old
+ <A HREF="sane/sane-devel-20000713.tar.gz">2000-07-13</A>,
+ <A HREF="sane/sane-devel-20000426.tar.gz">2000-04-26</A>,
+ <A HREF="sane/sane-devel-20000227.tar.gz">2000-02-27</A>,
+ <A HREF="sane/sane-devel-20000221.tar.gz">2000-02-21</A>,
+ <A HREF="sane/sane-devel-20000213.tar.gz">2000-02-13</A>,
+ <A HREF="sane/sane-devel-20000206.tar.gz">2000-02-06</A>,
+ <A HREF="sane/sane-devel-20000130.tar.gz">2000-01-30</A>,
+ <A HREF="sane/sane-devel-20000123.tar.gz">2000-01-23</A>,
+ <A HREF="sane/sane-devel-20000110.tar.gz">2000-01-10</A>,
+ <A HREF="sane/sane-devel-19991212.tar.gz">1999-12-12</A>,
+ <A HREF="sane/sane-devel-19991119.tar.gz">1999-11-19</A>,
+ <A HREF="sane/sane-devel-19990912.tar.gz">1999-09-12</A>)</DT>
+
+ <DT><A HREF="sane/sane-1.0.1-devel-win32.tar.gz">Win32 scanimage (v1.0.1 + patches)</A> - 1999-08-14</DT>
+ <DT><A HREF="sane/cvs-server.html">CVS server information</A> - 1999-07-25</DT>
+ <DT><A HREF="sane/19990428-sane-dll-cleanup.diff">dll-cleanup.diff</A> - 1999-04-28</DT>
+ <DD>Cleanup and bugfix in dll backend</DD>
+ <DT><A HREF="sane/19990428-sane-init-return.diff">sane-init-return.diff</A> - 1999-04-28</DT>
+ <DD>Change spec to require sane_init() to return SANE_STATUS_GOOD before backend is usable.</DD>
+ <DT><A HREF="sane/19990428-sane-install-hpux.diff">install-hpux.diff</A> - 1999-04-28</DT>
+ <DD>Make correct symlinks on HP/UX, and install libsane.la to allow binary rebuild during install.</DD>
+ <DT><A HREF="sane/sane-win32.diff">sane-win32.diff</A> - 1999-04-09
+ <DD>Win32 patches to dll and net backend, relative to v1.01pre4.</DD>
+ </dl>
+ </DT>
+ <DT><A HREF="html-search-replace">html-search-replace</a> - 1999-02-19
+ <DD>Search and replace params in HTML tags.</dd>
+ <DT><A HREF="cd2mp3">cd2mp3</a> - 1999-02-02
+ <dd>Perl script to rip music from CD into MP3. This script do the
+ right thing with file names, store times, etc to include
+ the files in my CGI mp3 system.
+
+ <DT><A HREF="cd-to-mp3.sh">cd-to-mp3.sh</a> - 1999-02-02
+ <dd>Use cdda2wav, gcdplay and l3enc to convert CDs to mp3.
+
+ <DT><A HREF="http://www.gnu.org/">glibc</A>
+ <dd><dl>
+ <DT><A HREF="SAMI-WS2">SAMI-WS2</A> - 1999-01-20
+ <DD>SAMI charmap WS2
+
+ <DT><A HREF="ISO-IR-197">ISO-IR-197</A> - 1999-01-20
+ <DD>SAMI charmap ISO-IR-197
+
+ <DT><A HREF="charmaps-check">charmaps-check</a> - 1999-01-20
+ <dd>Perl script to check if charsets uses the same symbolic name for
+ identical Unicode characters.
+
+ </dl>
+ </dd>
+
+ <DT><A HREF="http://www.kde.org/">KDE</A>
+ <dd><dl>
+ <DT><A HREF="kde/logout-hanger.tar.gz">logout-hanger.tar.gz</A> - 1999-06-04</DT>
+ <DD>Demonstrate kwm hanging logout bug.</DD>
+ <DT><A HREF="kde/make-kikbd-map.pl">make-kikbd-map.pl</A> - 1999-05-01</DT>
+ <DD>Use xmodmap to extract kikbd keycode map from X server</DD>
+ <DT><A HREF="kde/klpq-printcap-missing.diff">klpq-printcap-missing.diff</A> - 1999-04-25
+ <DD>Better error message from klpq if /etc/printcap is missing or unparsable.
+
+ <DT><A HREF="kde/pc102.kimap">pc102.kimap</A> - 1999-01-12
+ <DD>Keycode definition for pc102 US keyboard
+
+ <DT><A HREF="kde/hp9000hil-107.kimap">hp9000hil-107.kimap</A> - 1999-01-12
+ <DD>Keycode definition for Hewlett-Packard HP9000 ITF HIL (US)
+
+ <DT><A HREF="kde/no.kimap">no.kimap</a> - 1999-01-03
+ <DD>Norwegian keymap for KDE International keyboard manager
+ </dl>
+
+ <DT><A HREF="cron-summary">cron-summary</a> - 1998-11-02
+ <DD>Make a summary of all crontab entries on some machines. Use it
+ like this: <TT>RSH=ssh cron-summary host1 host2 host3</TT>
+
+ <DT><A HREF="extract-comments">extract-comments</a> - 1998-11-02
+ <DD>Extract JavaDoc like comments from perl source to form
+ API documentation.
+
+ <DT><A HREF="pg-show-db-access">pg-show-db-access</a> - 1998-09-28
+ <DD>Generates PostgreSQL SQL statements to recreate current access list
+ on database.
+ <dt><a href="html2rtf-1.0-unix.diff">HTML2RTF patch for Unix</a> - 1998-03-03</dt>
+
+ <dd>Small patch for
+ <a href="http://www.gkrueger.com/other/studproj/html2rtf/">HTML2RTF</a>
+ v1.0 for Unix. This is tested on SGI Irix 6.3</dd>
+
+ <dt><a href="ftp-upgrade">ftp-upgrade</a> - 1998-10-10</dt>
+
+ <dd>If you want to find and fetch the upgrades for your
+ <a href="http://www.redhat.com/">RedHat</a> installation, run this
+ program. Now works with plain RedHat 5.0 again. If you want to
+ upgrade 5.0 to 5.1, fetch and install the RPM package
+ "redhat-release-5.1 manually, and then run ftp-upgrade.</dd>
+
+ <dt><a href="aliases2html">aliases2html</a> - 1998-08-20</dt>
+
+ <dd>Take your sendmail aliases and make a nice web presentation.
+ Nest all aliases to find out who really receves the mail.</dd>
+
+ <dt><a href="http://ee-staff.ethz.ch/~oetiker/webtools/mrtg/mrtg.html">MRTG</a> data generators</dt>
+ <dd><dl>
+ <dt><a href="mrtg/smb-machines-used.sh">smb-machines-used.sh</a> - 2001-10-11</dt>
+ <dd>Count hosts logged into samba server.</dd>
+
+ <dt><a href="mrtg/ruptime.sh">ruptime.sh</a> - 2001-09-16</dt>
+ <dd>Count hosts up/down as reported by ruptime.</dd>
+
+ <dt><a href="mrtg/linux-swap.sh">linux-swap.sh</a> - 1999-01-05</dt>
+ <dd>Show free swap and used shared memory on Linux systems</dd>
+
+ <dt><a href="mrtg/unix-load.sh">unix-load.sh</a> - 1999-01-05</dt>
+ <dd>Show load on 1 and 5 minute average</dd>
+
+ <dt><a href="mrtg/quake2-users.sh">quake2-users.sh</a> - 1998-02-09</dt>
+ <dd>Use qstat to fetch user count from a Quake II server</dd>
+
+ <dt><a href="mrtg/xpilot-userlist.sh">xpilot-userlist.sh</a> - 1998-02-11</dt>
+ <dd>Fetch user count from XPilot server or metaserver</dd>
+
+ <DT><A HREF="mrtg/mailstats">mailstats</A> - 1998-09-14
+ <DD>Replacement for MRTG contrib. Get sendmail stats using mailstats(1)
+ </dl>
+ </dd>
+
+ <dt><a href="http://www.winehq.com/">Wine</a> patches not (yet) accepted by Alexandre</dt>
+ <dd><dl>
+ <dt><a href="wine-auto-author.diff">wine-auto-author.diff</A> - 1998-09-27
+ <dd>AUTHORS Makefile.in tools/extractauthors.pl include/authors.h:
+ <br>Now generates include/authors.h from AUTHORS using perl script
+ authorsextract.c. No need to keep info in two different places.</dd>
+
+ <dt><a href="wine-ccwarn.diff">wine-ccwarn.diff</A> - 1998-10-25
+ <dd>configure.in acinclude.m4:
+ <br>Add '-Wstrict-prototypes -Wcomments -pedantic' and '-ansi' when
+ --enable-ansi is used, to CFLAGS when using GCC. The code currently
+ fails to compile when -ansi is used.</dd>
+
+ <dt><a href="wine-cdlabel.diff">wine-cdlabel.diff</A> - 1998-10-26
+ <dd>files/drive.c:
+ <br>Changed DRIVE_GetLabel to extract ISO 9660 label from CDROMs. It
+ requires read access to /dev/cdrom and 'Device=/dev/cdrom' and
+ 'Type=cdrom' to be set in the [Drive X] section of .winerc.</dd>
+
+ </dl>
+ </dd>
+ </dl>
+
+
+
+ <hr>
+ <address><a href="mailto:pere@hungry.com">Petter Reinholdtsen</a></address>
+<!-- Created: Thu Feb 12 16:52:36 MET 1998 -->
+<!-- hhmts start -->
+Last modified: Sat May 15 13:31:59 METDST 1999
+<!-- hhmts end -->
+ </body>
+</html>
--- /dev/null
+# KDE Config File
+#
+# Author: Petter Reinholdtsen <pere@td.org.uit.no>
+#
+# Place in kikbd/maps/codes/
+
+[International Keyboard]
+Label=Codes for Hewlett-Packard HP9000 ITF HIL (US)
+
+[KeyboardMap]
+keycode0=10,Meta_R
+keycode1=11,Meta_L
+keycode2=12,Shift_R
+keycode3=13,Shift_L
+keycode4=14,Control_L
+keycode5=15,Break,hpReset
+keycode6=16,KP_4
+keycode7=17,KP_8
+keycode8=18,KP_5
+keycode9=19,KP_9
+keycode10=20,KP_6
+keycode11=21,KP_7
+keycode12=22,KP_Separator
+keycode13=23,KP_Enter
+keycode14=24,KP_1
+keycode15=25,KP_Divide
+keycode16=26,KP_2
+keycode17=27,KP_Add
+keycode18=28,KP_3
+keycode19=29,KP_Multiply
+keycode20=30,KP_0
+keycode21=31,KP_Subtract
+keycode22=32,B,NoSymbol,hpblock
+keycode23=33,V,NoSymbol,section
+keycode24=34,C,NoSymbol,ccedilla,Ccedilla
+keycode25=35,X,NoSymbol,scaron,Scaron
+keycode26=36,Z,NoSymbol,paragraph
+keycode27=39,Escape,Delete
+keycode28=41,F10,KP_F2
+keycode29=43,F11,KP_F3
+keycode30=44,KP_Decimal
+keycode31=45,F9,KP_F1
+keycode32=46,KP_Tab,hpKP_BackTab
+keycode33=47,F12,KP_F4
+keycode34=48,H,NoSymbol,yen
+keycode35=49,G,NoSymbol,currency
+keycode36=50,F,NoSymbol,hpguilder
+keycode37=51,D,NoSymbol,eth,ETH
+keycode38=52,S,NoSymbol,ssharp
+keycode39=53,A,NoSymbol,aring,Aring
+keycode40=54,Mode_switch,NoSymbol,NoSymbol,Mode_switch
+keycode41=55,Caps_Lock
+keycode42=56,U,NoSymbol,usldead_diaeresis
+keycode43=57,Y,NoSymbol,usldead_asciicircum
+keycode44=58,T,NoSymbol,usldead_grave
+keycode45=59,R,NoSymbol,usldead_acute
+keycode46=60,E,NoSymbol,ae,AE
+keycode47=61,W,NoSymbol,asciitilde
+keycode48=62,Q,NoSymbol,periodcentered
+keycode49=63,Tab,hpBackTab
+keycode50=64,7,ampersand,backslash
+keycode51=65,6,asciicircum,asciicircum
+keycode52=66,5,percent,onehalf
+keycode53=67,4,dollar,onequarter,threequarters
+keycode54=68,3,numbersign,numbersign
+keycode55=69,2,at,at
+keycode56=70,1,exclam,exclamdown
+keycode57=71,grave,asciitilde,guillemotleft,guillemotright
+keycode58=80,Menu
+keycode59=81,F4
+keycode60=82,F3
+keycode61=83,F2
+keycode62=84,F1
+keycode63=86,Cancel
+keycode64=87,Execute,Print
+keycode65=88,hpSystem,hpUser
+keycode66=89,F5
+keycode67=90,F6
+keycode68=91,F7
+keycode69=92,F8
+keycode70=94,hpClearLine
+keycode71=95,Clear
+keycode72=96,8,asterisk,bracketleft,braceleft
+keycode73=97,9,parenleft,bracketright,braceright
+keycode74=98,0,parenright,questiondown
+keycode75=99,minus,underscore,hplongminus,macron
+keycode76=100,equal,plus,plusminus
+keycode77=101,BackSpace
+keycode78=102,hpInsertLine
+keycode79=103,hpDeleteLine
+keycode80=104,I,NoSymbol,hpmute_asciitilde
+keycode81=105,O,NoSymbol,oslash,Ooblique
+keycode82=106,P,NoSymbol,thorn,THORN
+keycode83=107,bracketleft,braceleft,degree
+keycode84=108,bracketright,braceright,bar,brokenbar
+keycode85=109,backslash,bar,mu
+keycode86=110,hpInsertChar
+keycode87=111,hpDeleteChar
+keycode88=112,J,NoSymbol,dollar
+keycode89=113,K,NoSymbol,cent
+keycode90=114,L,NoSymbol,sterling
+keycode91=115,semicolon,colon,hplira
+keycode92=116,apostrophe,quotedbl,grave,apostrophe
+keycode93=117,Return
+keycode94=118,Home
+keycode95=119,Prior
+keycode96=120,M,NoSymbol,masculine
+keycode97=121,comma,less,less
+keycode98=122,period,greater,greater
+keycode99=123,slash,question,underscore
+keycode100=125,Select
+keycode101=127,Next
+keycode102=128,N,NoSymbol,ordfeminine
+keycode103=129,space
+keycode104=132,Left
+keycode105=133,Down
+keycode106=134,Up
+keycode107=135,Right
--- /dev/null
+diff -ru src-1.1.1pre1/klpq/main.cpp src-1.1.1pre1-386linuxlibc6/klpq/main.cpp
+--- src-1.1.1pre1/klpq/main.cpp Sun Jan 10 18:47:19 1999
++++ src-1.1.1pre1-386linuxlibc6/klpq/main.cpp Sun Apr 25 18:16:45 1999
+@@ -33,6 +33,7 @@
+ #include <qfile.h>
+ #include <qtstream.h>
+ #include <qstrlist.h>
++#include <qmessagebox.h>
+
+ #include <kapp.h>
+ #include <drag.h>
+@@ -175,13 +176,18 @@
+ }
+ if( no_printcap )
+ {
+- debug(klocale->translate("Sorry, can't open your printcap file."));
++ QMessageBox::critical( 0, "klpq",
++ QString(klocale->translate("Sorry, can't open your printcap file."))
++ + "\n\n" + klocale->translate("klpq will no exit."));
+ exit(1);
+ }
+ if( empty_printcap )
+ {
+- debug(klocale->translate("Sorry, unable to parse your printcap."));
+- debug(klocale->translate("Please email your printcap to Christoph.Neerfeld@home.ivm.de"));
++ QMessageBox::critical( 0, "klpq",
++ QString(klocale->translate("Sorry, unable to parse your printcap."))
++ + "\n"
++ + klocale->translate("Please email your printcap to Christoph.Neerfeld@home.ivm.de")
++ + "\n\n" + klocale->translate("klpq will no exit."));
+ exit(1);
+ }
+
--- /dev/null
+#!/usr/bin/perl -w
+#
+# Author: Petter Reinholdtsen <pere@td.org.uit.no>
+# Date: 1998-12-15
+#
+# Make KDE International keyboard keycode listing. Requires perl 5
+
+open(XMODMAP, "xmodmap -pk|");
+
+print <<HEAD;
+# KDE Config File
+#
+# Author: Your Name <and\@email.address>
+#
+#
+# Place in kikbd/maps/codes/
+[International Keyboard]
+Label=Codes for ??? keyboard
+
+[KeyboardMap]
+HEAD
+
+my $count = 0;
+while (<XMODMAP>) {
+ chomp;
+
+ if (/^\s+(\d+)\s+(.+)$/) {
+ my $keycode = $1;
+ my @f = split(/[\s\)\(]+/, $2);
+ if (@f) {
+ print "keycode$count=$keycode,";
+ $count++;
+ my @syms;
+ for $sym (@f) {
+ next if ($sym =~ /^0x/);
+ push(@syms, $sym);
+ }
+ print join(',', @syms),"\n";
+
+ }
+ }
+}
--- /dev/null
+# KDE International Keyboard Config File
+#
+# Created 1998-12-15. Please send corrections to both me and the
+# kikbd maintainer.
+
+[International Keyboard]
+Authors=Petter Reinholdtsen <pere@td.org.uit.no>,
+
+Comment=Normal layout
+Comment[no]=Normal utlegg
+
+Language=Norwegian
+Language[no]=Norsk
+
+Charset=ISO-8859-1
+Label=No
+Locale=no
+
+[KeyboardMap]
+CapsSymbols=q,w,e,r,t,y,u,i,o,p,a,s,d,f,g,h,j,k,l,z,x,c,v,b,n,m,ae,oslash,aring
+
+keysym0=grave,bar,section
+keysym1=2,2,quotedbl,at
+keysym2=3,3,numbersign,sterling
+keysym3=4,4,currency,dollar
+keysym4=6,6,ampersand,
+keysym5=7,7,slash,braceleft
+keysym6=8,8,parenleft,bracketleft
+keysym7=9,9,parenright,bracketright
+keysym8=0,0,equal,braceright
+keysym9=minus,plus,question
+keysym10=equal,backslash,dead_grave,dead_acute
+keysym11=bracketleft,aring,Aring
+keysym12=bracketright,dead_diaeresis,dead_circumflex,dead_tilde
+keysym13=semicolon,oslash,Oslash
+keysym14=apostrophe,ae,AE
+keysym15=backslash,apostrophe,asterisk
+keysym16=less,less,greater
+keysym17=comma,comma,semicolon
+keysym18=period,period,colon
+keysym19=slash,minus,underscore
--- /dev/null
+# KDE Config File
+#
+# Copy of pc101.kimap with the addition of scancode 94, less / greater
+# [Petter Reinholdtsen <pere@td.org.uit.no>, 1999-01-12]
+#
+# Place in kikbd/maps/codes/
+
+[International Keyboard]
+Label=Codes for pc102 US keyboard
+
+[KeyboardMap]
+keycode1=9,Escape,,
+keycode2=10,1,exclam,
+keycode3=11,2,at,
+keycode4=12,3,numbersign,
+keycode5=13,4,dollar,
+keycode6=14,5,percent,
+keycode7=15,6,asciicircum,
+keycode8=16,7,ampersand,
+keycode9=17,8,asterisk,
+keycode10=18,9,parenleft,
+keycode11=19,0,parenright,
+keycode12=20,minus,underscore,
+keycode13=21,equal,plus,
+keycode14=22,BackSpace,,
+keycode15=23,Tab,ISO_Left_Tab,
+keycode16=24,q,Q,
+keycode17=25,w,W,
+keycode18=26,e,E,
+keycode19=27,r,R,
+keycode20=28,t,T,
+keycode21=29,y,Y,
+keycode22=30,u,U,
+keycode23=31,i,I,
+keycode24=32,o,O,
+keycode25=33,p,P,
+keycode26=34,bracketleft,braceleft,
+keycode27=35,bracketright,braceright,
+keycode28=36,Return,,
+keycode29=37,Control_L,,
+keycode30=38,a,A,
+keycode31=39,s,S,
+keycode32=40,d,D,
+keycode33=41,f,F,
+keycode34=42,g,G,
+keycode35=43,h,H,
+keycode36=44,j,J,
+keycode37=45,k,K,
+keycode38=46,l,L,
+keycode39=47,semicolon,colon,
+keycode40=48,apostrophe,quotedbl,
+keycode41=49,grave,asciitilde,
+keycode42=50,Shift_L,,
+keycode43=51,backslash,bar,
+keycode44=52,z,Z,
+keycode45=53,x,X,
+keycode46=54,c,C,
+keycode47=55,v,V,
+keycode48=56,b,B,
+keycode49=57,n,N,
+keycode50=58,m,M,
+keycode51=59,comma,less,
+keycode52=60,period,greater,
+keycode53=61,slash,question,
+keycode54=62,Shift_R,,
+keycode55=63,KP_Multiply,,
+keycode56=64,Alt_L,Meta_L,
+keycode57=65,space,,
+keycode58=66,Caps_Lock,,
+keycode59=67,F1,,
+keycode60=68,F2,,
+keycode61=69,F3,,
+keycode62=70,F4,,
+keycode63=71,F5,,
+keycode64=72,F6,,
+keycode65=73,F7,,
+keycode66=74,F8,,
+keycode67=75,F9,,
+keycode68=76,F10,,
+keycode69=77,Num_Lock,Pointer_EnableKeys,
+keycode70=78,Scroll_Lock,,
+keycode71=79,KP_Home,KP_7,
+keycode72=80,KP_Up,KP_8,
+keycode73=81,KP_Prior,KP_9,
+keycode74=82,KP_Subtract,,
+keycode75=83,KP_Left,KP_4,
+keycode76=84,KP_Begin,KP_5,
+keycode77=85,KP_Right,KP_6,
+keycode78=86,KP_Add,,
+keycode79=87,KP_End,KP_1,
+keycode80=88,KP_Down,KP_2,
+keycode81=89,KP_Next,KP_3,
+keycode82=90,KP_Insert,KP_0,
+keycode83=91,KP_Delete,KP_Decimal,
+# Hm, not sure if this is the extra key on 102 keyboards, but I beleave it is
+keycode86=94,less,greater,
+keycode87=95,F11,,
+keycode88=96,F12,,
+keycode89=97,Home,,
+keycode90=98,Up,,
+keycode91=99,Prior,,
+keycode92=100,Left,,
+keycode94=102,Right,,
+keycode95=103,End,,
+keycode96=104,Down,,
+keycode97=105,Next,,
+keycode98=106,Insert,,
+keycode99=107,Delete,,
+keycode100=108,KP_Enter,,
+keycode101=109,Control_R,,
+keycode102=110,Pause,Break,
+keycode103=111,Print,Execute,
+keycode104=112,KP_Divide,,
+keycode105=113,Alt_R,Meta_R,
+
--- /dev/null
+--- linux-2.2.5/fs/lockd/clntproc.c-prepere Wed Apr 21 23:11:24 1999
++++ linux-2.2.5/fs/lockd/clntproc.c Thu Apr 22 14:29:09 1999
+@@ -322,6 +322,10 @@
+ {
+ int status;
+
++ /* There is never a conflicting lock - try to get WP8 running [pere 1999-04-21] */
++ fl->fl_type = F_UNLCK;
++ return 0;
++
+ if ((status = nlmclnt_call(req, NLMPROC_TEST)) < 0)
+ return status;
+
+@@ -368,6 +372,9 @@
+ struct nlm_host *host = req->a_host;
+ struct nlm_res *resp = &req->a_res;
+ int status;
++
++ /* All locking succeds to get WP8 running [pere 1999-04-22] */
++ return 0;
+
+ if (!host->h_monitored && nsm_monitor(host) < 0) {
+ printk(KERN_NOTICE "lockd: failed to monitor %s\n",
--- /dev/null
+#!/usr/bin/perl
+#
+# Author: Petter Reinholdtsen <pere@td.org.uit.no>
+# Date: 2000-06-29
+#
+# Simple quick and dirty CVS pserver password hash generator. Based
+# on source from Andreas Rick.
+
+if ($#ARGV<1) {
+ print "\nUSAGE: $0 <username> <password>\n\n";
+ exit;
+}
+
+sub scramble {
+ my ($password, $enc) = @_;
+ return crypt($password,$enc);
+}
+my $username = $ARGV[0];
+my $password = $ARGV[1];
+my $try = scramble($password, scramble($password, $username));
+
+print "$username:$try:cvs\n";
--- /dev/null
+Here is a small patch to get meteor_fgrab_widget_0.8 framegrabber widget
+working with Tcl/Tk 8.0 on Linux RedHat 6.1.
+
+With this, I have it working. The colors are a bit strange, but I
+guess that is a local problem. :-)
+
+diff -ru meteor_fgrab_widget_0.8/Makefile meteor_fgrab_widget_0.8-pere/Makefile
+--- meteor_fgrab_widget_0.8/Makefile Mon Feb 10 22:54:51 1997
++++ meteor_fgrab_widget_0.8-pere/Makefile Tue Dec 14 14:27:05 1999
+@@ -9,7 +9,7 @@
+ fgrab_wish: fgrab_tkAppInit.o fgrab_meteor.o
+ cc -o fgrab_wish-$(VERSION) fgrab_tkAppInit.o $(FGRAB_METEOR).o\
+ -L/usr/X11R6/lib\
+- -ltk4.1 -ltcl7.5 -lXext -lX11 -lm -ldl
++ -ltk8.0 -ltcl8.0 -lXext -lX11 -lm -ldl
+ fgrab_tkAppInit.o: fgrab_tkAppInit.c; cc -c -g fgrab_tkAppInit.c
+ fgrab_meteor.o: $(FGRAB_METEOR).c;
+ cc -D$(FORMAT) -D$(DEVICE) -D$(BOARD) -c -g $(FGRAB_METEOR).c
+diff -ru meteor_fgrab_widget_0.8/fgrab_meteor-0.8.c meteor_fgrab_widget_0.8-pere/fgrab_meteor-0.8.c
+--- meteor_fgrab_widget_0.8/fgrab_meteor-0.8.c Mon Feb 10 23:22:16 1997
++++ meteor_fgrab_widget_0.8-pere/fgrab_meteor-0.8.c Tue Dec 14 14:43:25 1999
+@@ -55,18 +55,8 @@
+ static struct meteor_geomet geo;
+ static struct meteor_frame_offset off;
+
+-
+-
+-static struct sigaction sigact =
+-((struct sigaction){ sa_handler: FGrabGotFrame,
+- sa_mask: (sigset_t)0,
+- sa_flags: SA_RESTART });
+-
+-static struct sigaction sigalrm =
+-((struct sigaction){ sa_handler: FGrabCountFrame,
+- sa_mask: (sigset_t)SIGUSR2,
+- sa_flags: SA_RESTART });
+-
++static struct sigaction sigact;
++static struct sigaction sigalrm;
+
+ static void FGrabCountFrame( int signum ) {
+
+@@ -953,6 +943,12 @@
+ if (!(FGrabReg & FPSCOUNT)) {
+ FGrabReg |= FPSCOUNT;
+ /* hier muß noch der alte Wert von Sigaction gespeichert werden !! */
++
++ sigalrm.sa_handler = FGrabCountFrame;
++ sigalrm.sa_flags = SA_RESTART;
++ sigemptyset(&sigalrm.sa_mask);
++ sigaddset(&sigalrm.sa_mask, SIGUSR2);
++
+ if (sigaction (SIGALRM, &sigalrm, NULL)) {
+ Tcl_AppendResult (interp, "alrmaction failed", (char *) NULL);
+ return TCL_ERROR;
+@@ -1012,6 +1008,9 @@
+ geo.frames = NOFRAMES;
+ geo.oformat = fgrabPtr->video.oformat | fgrabPtr->fieldmode;
+
++ sigact.sa_handler = FGrabGotFrame;
++ sigact.sa_flags = SA_RESTART;
++ sigemptyset(&sigact.sa_mask);
+ if (sigaction (SIGUSR2, &sigact, NULL)) {
+ Tcl_AppendResult (interp, "sigaction failed", (char *) NULL);
+ return TCL_ERROR;
+Only in meteor_fgrab_widget_0.8-pere: fgrab_meteor-0.8.c~
+diff -ru meteor_fgrab_widget_0.8/fgrab_meteor-0.8.h meteor_fgrab_widget_0.8-pere/fgrab_meteor-0.8.h
+--- meteor_fgrab_widget_0.8/fgrab_meteor-0.8.h Mon Feb 10 22:53:23 1997
++++ meteor_fgrab_widget_0.8-pere/fgrab_meteor-0.8.h Tue Dec 14 13:59:54 1999
+@@ -28,6 +28,7 @@
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <unistd.h>
++#include <signal.h>
+
+ #include <sys/types.h>
+ #include <sys/mman.h>
+@@ -37,7 +38,10 @@
+ #include <sys/resource.h>
+ #include <sys/shm.h>
+
++/* Does not compile on newer glibc */
++#if 0
+ #include <linux/mm.h>
++#endif
+
+ #include <X11/Intrinsic.h>
+ #include <X11/StringDefs.h>
+Only in meteor_fgrab_widget_0.8-pere: fgrab_meteor-0.8.o
+Only in meteor_fgrab_widget_0.8-pere: fgrab_tkAppInit.o
+Binary files meteor_fgrab_widget_0.8/fgrab_wish-0.8 and meteor_fgrab_widget_0.8-pere/fgrab_wish-0.8 differ
+Only in meteor_fgrab_widget_0.8-pere: meteor_fgrab_widget_0.8.lsm
--- /dev/null
+#!/bin/sh
+#
+# Author: Petter Reinholdtsen <pere@td.org.uit.no>
+#
+# Feed swap free and mem shared to MRTG
+
+if [ ! -r /proc/meminfo ]; then
+ echo "Non Linux system? Missing /proc/meminfo"
+ exit 1;
+fi
+
+SWAPFREE=`cat /proc/meminfo|grep "^SwapFree:"|awk '{print $2}'`
+MEMSHARED=`cat /proc/meminfo|grep "^MemShared:"|awk '{print $2}'`
+UP=`uptime|cut -d, -f 1,2`
+
+echo $SWAPFREE
+echo $MEMSHARED
+echo $UP
+echo localhost
\ No newline at end of file
--- /dev/null
+#!/store/bin/perl
+#
+# Author: Petter Reinholdtsen <pere@td.org.uit.no>
+# Date: 1997-07-09
+# The original was written by Rachel Polanskis <rachel@juno.virago.org.au>
+#
+# Fetches output from mailstats(1) either via TCP or via exec and
+# feeds changes on smtp to mrtg.
+#
+# Irix 6.x seems to lack mailstats
+#
+# Usage mailstats [host]
+# if host is missing, localhost is used
+
+use strict;
+use Socket;
+
+my($datafile, $source, $sourceport, @mailstatspaths,
+ $oldfrm, $oldto,
+ $newfrm, $newto, $uptime);
+
+# Adjust this to your own mailserver. Uses local `mailstats` if set
+# to 'localhost'
+$source = $ARGV[0] || "localhost";
+$sourceport = "7256";
+
+$datafile = "/tmp/mailstat-$source.old";
+@mailstatspaths = ( "/usr/sbin/mailstats", "/usr/bin/mailstats" );
+
+($oldfrm, $oldto) = getOldStats($datafile);
+
+($newfrm, $newto, $uptime) = getStats($source, $sourceport);
+
+putOldStats($datafile, $newfrm, $newto) || warn "$0: Unable to save stats to $datafile";
+
+print $newfrm-$oldfrm,"\n",$newto-$oldto,"\n","$uptime\n$source\n" if ($oldfrm);
+
+##
+# Returns first line of file given as param splittet on space
+sub getOldStats {
+ my($filename) = @_;
+ open(OLD, $filename) || warn "$0: Unable to open $filename for reading";
+ my($line) = <OLD>;
+ close(OLD);
+ return split(/ /, $line);
+}
+
+sub findFirstExecutable {
+ my($filename);
+ foreach $filename (@_) {
+ return $filename if ( -x $filename && ! -d $filename );
+ }
+}
+
+sub getStats {
+ my($source, $sourceport) = @_;
+ my(@output, $port, $proto, $iaddr, $paddr);
+ if ( $source eq "localhost" ) {
+ my($progpath) = findFirstExecutable(@mailstatspaths);
+ @output = `$progpath`;
+ chomp(@output);
+ } else {
+ $port = $sourceport;
+ $port = getservbyname ($sourceport, 'tcp') if ($sourceport =~ /\D/);
+ die "$0: Bad port \"$sourceport\"" unless ($port);
+ $proto = getprotobyname ('tcp') || die "$0: Bad prototype tcp";
+
+ $iaddr = inet_aton($source) or die "$0: no host \"$source\"";
+ $paddr = sockaddr_in($port, $iaddr);
+
+ socket (SOCK, PF_INET, SOCK_STREAM, $proto) or die "$0: socket error $!";
+ connect (SOCK, $paddr) or die "$0: connect error $!";
+
+ while (<SOCK>) {
+ push(@output,$_);
+ }
+ close(SOCK) || warn "$0: socket close error $!";
+ }
+ my($curfrm, $curto, $uptime);
+ foreach (@output) {
+ # Our sendmail reports smtp as uucp (stupid admin... :-)
+ ($curfrm, $curto) = (split(/ +/))[2,4] if (/uucp|e?smtp/);
+ ($uptime) = m/Statistics from (.*)/ if (/Stati/);
+ }
+ return ($curfrm, $curto, $uptime);
+}
+
+sub putOldStats {
+ my($filename, $frm, $to) = @_;
+ open(STAT, ">$filename") || return "";
+ print STAT "$frm $to\n";
+ close(STAT);
+ return "1";
+}
--- /dev/null
+#!/bin/sh
+#
+# Author: Petter Reinholdtsen <pere@td.org.uit.no>
+#
+# Extract usage stats from Quake II servers using qstat
+
+QSTAT=/store/bin/qstat
+
+H=$1
+P=$2
+
+HOST=$H:$P
+TMP=/var/tmp/qstat-$$
+
+if [ ! -x $QSTAT ]; then
+ echo "$QSTAT missing or unexecutable."
+ exit 1
+fi
+
+$QSTAT -qws $HOST |tail -1 > $TMP
+
+users=`awk '{ print $2 }' < $TMP|cut -d/ -f1`
+
+rm -f $TMP
+
+echo $users
+echo 0
+echo unknown
+echo $HOST
--- /dev/null
+#!/bin/sh
+#
+# Author: Petter Reinholdtsen <pere@hungry.com>
+# Date: 2001-09-16
+#
+# Report number of hosts up/down as gathered by rwhod.
+
+ruptime | grep 'up ' | wc -l
+ruptime | grep 'down ' | wc -l
+uptime | cut -d, -f1-2
+hostname
--- /dev/null
+#!/bin/sh
+#
+# Author: Petter Reinholdtsen <pere@td.org.uit.no>
+# Date: 1999-04-26
+#
+# MRTG datagenerator to get number of WinNT machines connected to
+# local samba server.
+
+PATH=/usr/local/samba/bin:$PATH
+export PATH
+
+ALLHOSTREGEX="$1"
+#ALLHOSTREGEX="ember|nightfall|dewshine"
+
+LINUXUSERS=`rwho| egrep "$ALLHOSTREGEX" | grep '::0 ' | awk '{print $2}' |
+ sort -u | wc -l`
+WINNTUSERS=`/usr/local/samba/bin/smbstatus 2>/dev/null | egrep
+"$ALLHOSTREGEX" |
+ grep -v Profile | grep -v IPC | awk '{print $3}' | sort -u | wc -l`
+
+echo $WINNTUSERS
+echo $LINUXUSERS
+date
+hostname
--- /dev/null
+#!/bin/sh
+#
+# Expected output from uptime:
+# 8:50pm up 26 days, 6:46, 24 users, load average: 0.13, 0.14, 0.13
+
+UPTIME=`uptime`
+LOAD=`echo $UPTIME|rev|cut -d: -f1|rev`
+
+AVG1=`echo $LOAD |awk '{print $1}'|cut -d, -f1`
+VALUE1=`echo "$AVG1 * 100"|bc|cut -d. -f1`
+
+AVG5=`echo $LOAD|awk '{print $2}'|cut -d, -f1`
+VALUE5=`echo "$AVG5 * 100"|bc|cut -d. -f1`
+
+UP=`echo $UPTIME|cut -d, -f 1,2`
+
+echo $VALUE1
+echo $VALUE5
+echo $UP
+echo localhost
\ No newline at end of file
--- /dev/null
+#!/bin/sh
+#
+# Author: Petter Reinholdtsen <pere@td.org.uit.no>
+#
+# Fetch user count from xpilot server
+
+SERVER=$1
+PATH=/store/bin:/bin:/usr/bin:$PATH
+export PATH
+
+TMP=/var/tmp/xpilot-users.$$
+
+if false; then
+ (echo s; echo q) | xpilot -display NO_X $SERVER 2>/dev/null > $TMP
+ cat $TMP
+ users=`cat $TMP | grep '\.\.\. '|grep -v robot@xpilot.org|wc -l`
+ rm -f $TMP
+else
+ netcat -w 5 meta.xpilot.org 4401 |grep $SERVER > $TMP 2>/dev/null
+ if test -s $TMP; then
+ users=`cut -d: -f4 < $TMP`
+ uptime=`cut -d: -f13 < $TMP`
+ hours=`echo "$uptime / (60*60*24)"|bc`
+ else
+ users=0
+ hours=unknown
+ fi
+ rm -f $TMP
+fi
+
+echo $users
+echo 0
+echo "$hours days"
+echo $SERVER
--- /dev/null
+Index: ChangeLog
+===================================================================
+RCS file: /home/cvspublic/kaffe/ChangeLog,v
+retrieving revision 1.588
+diff -u -w -u -r1.588 ChangeLog
+--- ChangeLog 1999/04/22 16:47:42 1.588
++++ ChangeLog 1999/04/26 12:22:22
+@@ -1,3 +1,9 @@
++1999-04-25 Petter Reinholdtsen <pere@td.org.uit.no
++
++ * libraries/clib/net/InetAddressImpl.c: JDK returns hostname as
++ info in UnknownHostException, not "Unknown host". Fixing this
++ with kaffe.
++
+ Thu Apr 22 09:38:32 PDT 1999 Robert Zawiasa <rhz@bibl.u-szeged.hu>
+
+ * libraries/javalib/kaffe/net/www/protocol/http/HttpURLConnection.java:
+Index: libraries/clib/net/InetAddressImpl.c
+===================================================================
+RCS file: /home/cvspublic/kaffe/libraries/clib/net/InetAddressImpl.c,v
+retrieving revision 1.8
+diff -u -w -u -r1.8 InetAddressImpl.c
+--- InetAddressImpl.c 1999/02/13 09:22:01 1.8
++++ InetAddressImpl.c 1999/04/26 12:22:23
+@@ -64,7 +64,7 @@
+
+ rc = KGETHOSTBYNAME(name, &ent);
+ if (rc) {
+- SignalError("java.net.UnknownHostException", SYS_HERROR(rc));
++ SignalError("java.net.UnknownHostException", name);
+ }
+ return (ntohl(*(jint*)ent->h_addr_list[0]));
+ }
+@@ -86,7 +86,7 @@
+
+ rc = KGETHOSTBYNAME(name, &ent);
+ if (rc) {
+- SignalError("java.net.UnknownHostException", SYS_HERROR(rc));
++ SignalError("java.net.UnknownHostException", name);
+ }
+
+ for (alength = 0; ent->h_addr_list[alength]; alength++)
+@@ -115,7 +115,14 @@
+ addr = htonl(addr);
+ rc = KGETHOSTBYADDR((char*)&addr, sizeof(jint), AF_INET, &ent);
+ if (rc) {
+- SignalError("java.net.UnknownHostException", SYS_HERROR(rc));
++ char errstr[16];
++ sprintf(errstr, "%3o.%3o.%3o.%3o",
++ /* XXX Make sure it is the right endiannes */
++ (addr >> 24) & 0xff,
++ (addr >> 16) & 0xff,
++ (addr >> 8) & 0xff,
++ (addr) & 0xff);
++ SignalError("java.net.UnknownHostException", errstr);
+ }
+
+ return (stringC2Java((char*)ent->h_name));
--- /dev/null
+#!/store/bin/perl -w
+#
+# Author: Petter Reinholdtsen <pere@td.org.uit.no>
+# Date: 1998-09-28
+#
+# Make list of 'grant' commands based on current db permissions.
+#
+# Use './pg-show-db-access.pl |sort +5 +3' to get a nice list
+
+sub usage {
+ print "$0 [dbname [dbhost]]\n";
+}
+
+use vars qw($dbhost $db $cmd);
+
+($db, $dbhost) = ("", "");
+$db = $ARGV[0] if ( defined $ARGV[0] );
+$dbhost = "-h $ARGV[1]" if ( defined $ARGV[1] );
+
+$cmd = "psql -t -c \\\\z $dbhost $db";
+
+open(CMD, "$cmd |") || die "Unable to execute \"$cmd\"";
+
+while (<CMD>) {
+ chomp;
+ my ($table, $perm) = m/\s+\|\s+(\w+)\s+\|\s+\{(.+)\}\s+\|/;
+ if ( defined $table ) {
+ my @perms = split(/,/, $perm);
+ for $perm (@perms) {
+ my ($username, $access) = $perm =~ m/(\w*)=(\w+)/;
+ $username = "public" unless ($username);
+ if (defined $access) {
+ my %ACL;
+ $ACL{SELECT} = 1 if ($access =~ m/r/);
+ $ACL{INSERT} = 1 if ($access =~ m/a/);
+ if ($access =~ m/w/) {
+ $ACL{DELETE} = 1;
+ $ACL{UPDATE} = 1;
+ $ACL{INSERT} = 1;
+ }
+ # XXX Not sure what 'R' means, skipping it
+ # $ACL{PLACE_RULES} = 1 if ($access =~ m/R/);
+
+ for $c (sort keys %ACL) {
+ print "GRANT $c ON $table TO $username;\n";
+
+ }
+ }
+ }
+ }
+}
+
+close(CMD);
--- /dev/null
+diff -ur sane-1.0.1/ChangeLog sane-1.0.1-pere/ChangeLog
+--- sane-1.0.1/ChangeLog Mon Apr 19 18:21:33 1999
++++ sane-1.0.1-pere/ChangeLog Wed Apr 28 00:52:19 1999
+@@ -1,3 +1,11 @@
++1999-04-28 Petter Reinholdtsen <pere@td.org.uit.no>
++
++ * backend/dll.c: Cleanup. Use calloc() instead of
++ malloc/memset(0). Only check the correct environment path
++ variables. Make ifdef'ed code smaller and clearer. Include
++ bugfix reported by Ingo Wilken: use dlerror() instead of
++ strerror(errno).
++
+ 1999-04-19 David Mosberger-Tang <David.Mosberger@acm.org>
+
+ * Version 1.0.1 released.
+diff -ur sane-1.0.1/backend/dll.c sane-1.0.1-pere/backend/dll.c
+--- sane-1.0.1/backend/dll.c Sun Feb 28 00:51:37 1999
++++ sane-1.0.1-pere/backend/dll.c Wed Apr 28 01:01:58 1999
+@@ -68,12 +68,22 @@
+ # ifndef RTLD_LAZY
+ # define RTLD_LAZY 1
+ # endif
++# if defined(_AIX)
++# define DLL_PATH_ENV "LIBPATH"
++# else
++# define DLL_PATH_ENV "LD_LIBRARY_PATH"
++# endif
++# define DLL_PATH_SEPARATOR ":"
++# define DLL_SLASH "/"
++# define DLL_NAME "libsane-%s.so." STRINGIFY(V_MAJOR)
+ # define HAVE_DLL
+-#endif
+-
++#elif defined (HAVE_SHL_LOAD) && defined(HAVE_DL_H)
+ /* HP/UX DLL support */
+-#if defined (HAVE_SHL_LOAD) && defined(HAVE_DL_H)
+ # include <dl.h>
++# define DLL_PATH_ENV "SHLIB_PATH"
++# define DLL_PATH_SEPARATOR ":"
++# define DLL_SLASH "/"
++# define DLL_NAME "libsane-%s.sl." STRINGIFY(V_MAJOR)
+ # define HAVE_DLL
+ #endif
+
+@@ -211,11 +221,10 @@
+ return SANE_STATUS_GOOD;
+ }
+
+- be = malloc (sizeof (*be));
++ be = calloc (1, sizeof (*be));
+ if (!be)
+ return SANE_STATUS_NO_MEM;
+
+- memset (be, 0, sizeof (*be));
+ be->name = strdup (name);
+ if (!be->name)
+ return SANE_STATUS_NO_MEM;
+@@ -230,24 +239,12 @@
+ load (struct backend *be)
+ {
+ #ifdef HAVE_DLL
+- int mode = 0;
++ int funcnamesize = 0;
+ char *funcname, *src, *dir, *path = 0;
+ char libname[PATH_MAX];
+ int i;
+ FILE *fp = 0;
+
+-#if defined(HAVE_DLOPEN)
+-# define PREFIX "libsane-"
+-# define POSTFIX ".so.%u"
+- mode = getenv ("LD_BIND_NOW") ? RTLD_NOW : RTLD_LAZY;
+-#elif defined(HAVE_SHL_LOAD)
+-# define PREFIX "libsane-"
+-# define POSTFIX ".sl.%u"
+- mode = BIND_DEFERRED;
+-#else
+-# error "Tried to compile unsupported DLL."
+-#endif /* HAVE_DLOPEN */
+-
+ DBG(1, "loading backend %s\n", be->name);
+
+ /* initialize all ops to "unsupported" so we can "use" the backend
+@@ -260,28 +257,23 @@
+ dir = STRINGIFY(LIBDIR);
+ while (dir)
+ {
+- snprintf (libname, sizeof (libname), "%s/"PREFIX"%s"POSTFIX,
+- dir, be->name, V_MAJOR);
++ /* Make string like "<libdir>/sane-<backend>.so.<version>" */
++ snprintf (libname, sizeof (libname), "%s" DLL_SLASH DLL_NAME,
++ dir, be->name);
+ fp = fopen (libname, "r");
+ if (fp)
+ break;
+
+ if (!path)
+ {
+- path = getenv ("LD_LIBRARY_PATH");
+- if (!path)
+- {
+- path = getenv ("SHLIB_PATH"); /* for HP-UX */
+- if (!path)
+- path = getenv ("LIBPATH"); /* for AIX */
+- }
++ path = getenv (DLL_PATH_ENV);
+ if (!path)
+ break;
+
+ path = strdup (path);
+ src = path;
+ }
+- dir = strsep (&src, ":");
++ dir = strsep (&src, DLL_PATH_SEPARATOR);
+ }
+ if (path)
+ free (path);
+@@ -294,57 +286,52 @@
+ DBG(2, "dlopen()ing `%s'\n", libname);
+
+ #ifdef HAVE_DLOPEN
+- be->handle = dlopen (libname, mode);
++ be->handle = dlopen (libname, getenv ("LD_BIND_NOW") ? RTLD_NOW : RTLD_LAZY);
+ #elif defined(HAVE_SHL_LOAD)
+- be->handle = (shl_t)shl_load (libname, mode, 0L);
++ be->handle = (shl_t)shl_load (libname, BIND_DEFERRED, 0L);
+ #else
+ # error "Tried to compile unsupported DLL."
+ #endif /* HAVE_DLOPEN */
+ if (!be->handle)
+ {
++#ifdef HAVE_DLOPEN
++ DBG(2, "dlopen() failed (%s)\n", dlerror());
++#else
+ DBG(2, "dlopen() failed (%s)\n", strerror (errno));
++#endif
+ return SANE_STATUS_INVAL;
+ }
+
+ /* all is dandy---lookup and fill in backend ops: */
+- funcname = alloca (strlen (be->name) + 64);
++ funcnamesize = strlen (be->name) + 64;
++ funcname = alloca (funcnamesize);
+ for (i = 0; i < NUM_OPS; ++i)
+ {
+ void *(*op) ();
++ void *(*op_) ();
+
+- sprintf (funcname, "_sane_%s_%s", be->name, op_name[i]);
++ snprintf (funcname, funcnamesize, "_sane_%s_%s", be->name, op_name[i]);
+
+ /* First try looking up the symbol without a leading underscore. */
++ /* Then try again, with an underscore prepended. */
+ #ifdef HAVE_DLOPEN
+ op = (void *(*)()) dlsym (be->handle, funcname + 1);
++ op_ = (void *(*)()) dlsym (be->handle, funcname);
+ #elif defined(HAVE_SHL_LOAD)
+ shl_findsym ((shl_t*)&(be->handle), funcname + 1, TYPE_UNDEFINED, &op);
++ shl_findsym (be->handle, funcname, TYPE_UNDEFINED, &op_);
+ #else
+ # error "Tried to compile unsupported DLL."
+ #endif /* HAVE_DLOPEN */
+- if (op)
+- be->op[i] = op;
++
++ if (NULL != op || NULL != op_)
++ be->op[i] = (NULL != op) ? op : op_;
+ else
+- {
+- /* Try again, with an underscore prepended. */
+-#ifdef HAVE_DLOPEN
+- op = (void *(*)()) dlsym (be->handle, funcname);
+-#elif defined(HAVE_SHL_LOAD)
+- shl_findsym (be->handle, funcname, TYPE_UNDEFINED, &op);
+-#else
+-# error "Tried to compile unsupported DLL."
+-#endif /* HAVE_DLOPEN */
+- if (op)
+- be->op[i] = op;
+- }
+- if (NULL == op)
+ DBG(2, "unable to find %s\n", funcname);
+ }
+
+ return SANE_STATUS_GOOD;
+
+-# undef PREFIX
+-# undef POSTFIX
+ #else /* HAVE_DLL */
+ DBG(1, "load: ignoring attempt to load `%s'; compiled without dl support\n",
+ be->name);
+@@ -441,15 +428,16 @@
+ (*be->op[OP_EXIT]) ();
+ #ifdef HAVE_DLL
+
+-#ifdef HAVE_DLOPEN
+ if (be->handle)
+- dlclose (be->handle);
++ {
++#ifdef HAVE_DLOPEN
++ dlclose (be->handle);
+ #elif defined(HAVE_SHL_LOAD)
+- if (be->handle)
+- shl_unload(be->handle);
++ shl_unload(be->handle);
+ #else
+ # error "Tried to compile unsupported DLL."
+ #endif /* HAVE_DLOPEN */
++ }
+
+ #endif /* HAVE_DLL */
+ }
+@@ -607,11 +595,10 @@
+ if (status != SANE_STATUS_GOOD)
+ return status;
+
+- s = malloc (sizeof (*s));
++ s = calloc (1, sizeof (*s));
+ if (!s)
+ return SANE_STATUS_NO_MEM;
+
+- memset (s, 0, sizeof (*s));
+ s->be = be;
+ s->handle = handle;
+ *meta_handle = s;
--- /dev/null
+diff -ur sane-1.0.1/ChangeLog sane-1.0.1-pere/ChangeLog
+--- sane-1.0.1/ChangeLog Mon Apr 19 18:21:33 1999
++++ sane-1.0.1-pere/ChangeLog Wed Apr 28 00:43:22 1999
+@@ -1,3 +1,10 @@
++1999-04-28 Petter Reinholdtsen <pere@td.org.uit.no>
++
++ * doc/sane.tex frontend/scanimage.c frontend/xcam.c
++ frontend/xscanimage.c: Specified valid return values for
++ sane_init(), and made sure all our frontends checks for the
++ correct return value before using other methods in the backend.
++
+ 1999-04-19 David Mosberger-Tang <David.Mosberger@acm.org>
+
+ * Version 1.0.1 released.
+diff -ur sane-1.0.1/doc/sane.tex sane-1.0.1-pere/doc/sane.tex
+--- sane-1.0.1/doc/sane.tex Sat Apr 3 23:16:07 1999
++++ sane-1.0.1-pere/doc/sane.tex Wed Apr 28 00:17:31 1999
+@@ -1052,9 +1052,11 @@
+
+ This function must be called before any other SANE function can be
+ called. The behavior of a SANE backend is undefined if this function
+-is not called first. The version code of the backend is returned in
+-the value pointed to by \code{version\_code}. If that pointer is
+-\code{NULL}, no version code is returned.
++is not called first. The behavior of a backend is also undefined if
++this function returns anything other then \code{SANE\_STATUS\_GOOD}.
++The version code of the backend is returned in the value pointed to by
++\code{version\_code}. If that pointer is \code{NULL}, no version code
++is returned.
+ Argument \code{authorize} is either a pointer to a function that is
+ invoked when the backend requires authentication for a specific
+ resource or \code{NULL} if the frontend does not support
+@@ -1064,6 +1066,16 @@
+ SANE_Status sane_init (SANE_Int * version_code,
+ SANE_Authorization_Callback authorize);
+ \end{verbatim}
++\end{quote}
++
++This function may fail with one of the following status codes.
++\begin{quote}
++\begin{description}
++\item[\code{SANE\_STATUS\_UNSUPPORTED}:] The backend is not supported on
++ this machines current configuration.
++\item[\code{SANE\_STATUS\_NO\_MEM}:] An insufficent amount of memory
++ is available to complete. Try later when more memory is available.
++\end{description}
+ \end{quote}
+
+ The authorization function may be called by a backend in response to
+diff -ur sane-1.0.1/frontend/scanimage.c sane-1.0.1-pere/frontend/scanimage.c
+--- sane-1.0.1/frontend/scanimage.c Fri Mar 5 07:13:49 1999
++++ sane-1.0.1-pere/frontend/scanimage.c Wed Apr 28 00:28:44 1999
+@@ -73,6 +73,7 @@
+ static SANE_Handle device;
+ static int verbose;
+ static int test;
++static int list;
+ static int help;
+ static const char * prog_name;
+ static SANE_Option_Descriptor window_option[2];
+@@ -1041,6 +1042,29 @@
+ free (image.data);
+ }
+
++void
++list_devices(void)
++{
++ const SANE_Device ** device_list;
++ SANE_Status status;
++ int i;
++
++ status = sane_get_devices (&device_list, SANE_FALSE);
++ if (status != SANE_STATUS_GOOD)
++ {
++ fprintf (stderr, "%s: sane_get_devices() failed: %s\n",
++ prog_name, sane_strstatus (status));
++ return;
++ }
++
++ for (i = 0; device_list[i]; ++i)
++ {
++ printf ("device `%s' is a %s %s %s\n",
++ device_list[i]->name, device_list[i]->vendor,
++ device_list[i]->model, device_list[i]->type);
++ }
++}
++
+ int
+ main (int argc, char **argv)
+ {
+@@ -1060,8 +1084,6 @@
+ else
+ prog_name = argv[0];
+
+- sane_init (0, 0);
+-
+ /* make a first pass through the options with error printing and argument
+ permutation disabled: */
+ opterr = 0;
+@@ -1079,27 +1101,7 @@
+ case 'h': help = 1; break;
+ case 'v': ++verbose; break;
+ case 'T': test= 1; break;
+- case 'L':
+- {
+- int i;
+-
+- status = sane_get_devices (&device_list, SANE_FALSE);
+- if (status != SANE_STATUS_GOOD)
+- {
+- fprintf (stderr, "%s: sane_get_devices() failed: %s\n",
+- prog_name, sane_strstatus (status));
+- exit (1);
+- }
+-
+- for (i = 0; device_list[i]; ++i)
+- {
+- printf ("device `%s' is a %s %s %s\n",
+- device_list[i]->name, device_list[i]->vendor,
+- device_list[i]->model, device_list[i]->type);
+- }
+- exit (0);
+- }
+-
++ case 'L': list = 1; break;
+ case 'V':
+ printf ("scanimage (%s) %s\n", PACKAGE, VERSION);
+ exit (0);
+@@ -1122,6 +1124,18 @@
+ -v, --verbose give even more status messages\n\
+ -V, --version print version information\n",
+ prog_name);
++
++ if (SANE_STATUS_GOOD != sane_init (NULL, NULL))
++ {
++ fprintf(stderr,"sane_init() failed. Unable to do anything. Exiting\n");
++ return(1);
++ }
++
++ if (list)
++ {
++ list_devices();
++ return(0);
++ }
+
+ if (!devname)
+ {
+diff -ur sane-1.0.1/frontend/xcam.c sane-1.0.1-pere/frontend/xcam.c
+--- sane-1.0.1/frontend/xcam.c Sat Apr 4 06:39:20 1998
++++ sane-1.0.1-pere/frontend/xcam.c Tue Apr 27 23:54:56 1999
+@@ -894,7 +894,11 @@
+ /* turn on by default as we don't support graphical geometry selection */
+ preferences.advanced = 1;
+
+- sane_init (NULL, 0);
++ if (SANE_STATUS_GOOD != sane_init (NULL, NULL))
++ {
++ fprintf(stderr,"sane_init() failed. Unable to do anything. Exiting\n");
++ return(1);
++ }
+
+ gdk_set_show_events (0);
+ gtk_init (&argc, &argv);
+diff -ur sane-1.0.1/frontend/xscanimage.c sane-1.0.1-pere/frontend/xscanimage.c
+--- sane-1.0.1/frontend/xscanimage.c Sat Apr 3 06:07:57 1999
++++ sane-1.0.1-pere/frontend/xscanimage.c Tue Apr 27 23:56:42 1999
+@@ -257,7 +257,12 @@
+ nargs, nreturn_vals,
+ args, return_vals);
+
+- sane_init (0, 0);
++ if (SANE_STATUS_GOOD != sane_init (NULL, NULL))
++ {
++ fprintf(stderr,"sane_init() failed. Unable to do anything. Exiting\n");
++ return(1);
++ }
++
+ sane_get_devices (&devlist, SANE_FALSE);
+
+ for (i = 0; devlist[i]; ++i)
--- /dev/null
+diff -ur sane-1.0.1/ChangeLog sane-1.0.1-pere/ChangeLog
+--- sane-1.0.1/ChangeLog Mon Apr 19 18:21:33 1999
++++ sane-1.0.1-pere/ChangeLog Wed Apr 28 01:26:32 1999
+@@ -1,3 +1,9 @@
++1999-04-28 Petter Reinholdtsen <pere@td.org.uit.no>
++
++ * backend/Makefile.in (install): Correct target to work on
++ platforms where dll endings isn't .so. Extract endings from
++ libsane-dll.la.
++
+ 1999-04-19 David Mosberger-Tang <David.Mosberger@acm.org>
+
+ * Version 1.0.1 released.
+diff -ur sane-1.0.1/backend/Makefile.in sane-1.0.1-pere/backend/Makefile.in
+--- sane-1.0.1/backend/Makefile.in Sun Apr 4 01:00:44 1999
++++ sane-1.0.1-pere/backend/Makefile.in Wed Apr 28 01:23:20 1999
+@@ -94,21 +94,26 @@
+ || exit 1; \
+ done
+ @$(LIBTOOL) $(MINST) --finish $(libsanedir)
+- @list="$(ALL_BACKENDS)"; cd $(libsanedir) && for be in $$list; do \
+- file=libsane-$${be}.so.$(V_MAJOR); \
++ @# Assume the dll name without any versions is last
++ @dllend=`grep library_names= libsane-dll.la |rev|cut -d" " -f1|rev|sed 's/libsane-dll.//'|cut -d\' -f1`; \
++ list="$(ALL_BACKENDS)"; cd $(libsanedir) && for be in $$list; do \
++ file=libsane-$${be}.$$dllend.$(V_MAJOR); \
+ lib=`grep dlname= libsane-$${be}.la | cut -f2 -d"'"`; \
+ if test ! -f $${file} -a -n "$${lib}"; then \
+ $(LN_S) $${lib} $${file}; \
+ fi; \
+ done
+- rm -f $(libdir)/libsane.a $(libdir)/libsane.so \
+- $(libdir)/libsane.so.$(V_MAJOR)*
+- $(LN_S) sane/libsane-dll.a $(libdir)/libsane.a
+- $(LN_S) sane/libsane-dll.so $(libdir)/libsane.so
+- @cd $(libsanedir) && for n in libsane-dll.so.$(V_MAJOR)*; do \
++ @# Assume the dll name without any versions is last
++ @dllend=`grep library_names= libsane-dll.la |rev|cut -f1 -d" "|rev|sed 's/libsane-dll.//'|cut -f1 -d\'`; \
++ rm -f $(libdir)/libsane.a $(libdir)/libsane.$$dllend \
++ $(libdir)/libsane.$$dllend.$(V_MAJOR)*; \
++ $(LN_S) sane/libsane-dll.a $(libdir)/libsane.a; \
++ $(LN_S) sane/libsane-dll.$$dllend $(libdir)/libsane.$$dllend ; \
++ cd $(libsanedir) && for n in libsane-dll.$$dllend.$(V_MAJOR)*; do \
+ nn=`echo $$n | sed 's,^libsane-dll,libsane,'`; \
+ (cd ..; $(LN_S) sane/$$n $$nn); \
+ done || exit 1
++ $(INSTALL_PROGRAM) libsane.la $(libdir)/libsane.la
+ @list="$(CONFIGS)"; for cfg in $$list; do \
+ if test ! -r $(srcdir)/$${cfg}; then continue; fi; \
+ if test -f $(configdir)/$${cfg}; then \
--- /dev/null
+diff --new-file -ur sane-1.0.1/ChangeLog sane-1.0.1-pere/ChangeLog
+--- sane-1.0.1/ChangeLog Mon Apr 19 18:21:33 1999
++++ sane-1.0.1-pere/ChangeLog Wed Apr 28 00:42:00 1999
+@@ -1,3 +1,8 @@
++1999-04-28 Petter Reinholdtsen <pere@td.org.uit.no>
++
++ * Makefile.in (lsm) sane.lsm: New target to generate Linux
++ Software Map (LSM) entry from template.
++
+ 1999-04-19 David Mosberger-Tang <David.Mosberger@acm.org>
+
+ * Version 1.0.1 released.
+diff --new-file -ur sane-1.0.1/Makefile.in sane-1.0.1-pere/Makefile.in
+--- sane-1.0.1/Makefile.in Fri May 8 08:48:16 1998
++++ sane-1.0.1-pere/Makefile.in Wed Apr 28 00:38:27 1999
+@@ -5,6 +5,9 @@
+ top_srcdir = @top_srcdir@
+ top_builddir = .
+
++PACKAGE = @PACKAGE@
++VERSION = @VERSION@
++
+ prefix = @prefix@
+ exec_prefix = @exec_prefix@
+ bindir = @bindir@
+@@ -36,6 +39,15 @@
+
+ all: all-recursive
+
++$(PACKAGE)-$(VERSION).lsm: $(PACKAGE)-$(VERSION).tar.gz $(PACKAGE).lsm
++ ( cat $(PACKAGE).lsm | \
++ sed -e "s|_DATE_|`date +%d%b%y`|g" \
++ -e "s|_VERSION_|$(VERSION)|g" \
++ -e "s|_T_S_|`find $(PACKAGE)-$(VERSION).tar.gz -printf \"%3k\"`|g"\
++ -e "s|_L_S_|`find $(PACKAGE).lsm -printf "%3k"`|g" > \
++ $(PACKAGE)-$(VERSION).lsm \
++ )
++lsm: $(PACKAGE)-$(VERSION).lsm
+
+ install: install-recursive
+ $(MKDIR) $(includedir)/sane
+diff --new-file -ur sane-1.0.1/sane.lsm sane-1.0.1-pere/sane.lsm
+--- sane-1.0.1/sane.lsm Thu Jan 1 01:00:00 1970
++++ sane-1.0.1-pere/sane.lsm Wed Apr 28 00:40:26 1999
+@@ -0,0 +1,27 @@
++Begin3
++Title: SANE
++Version: _VERSION_
++Entered-date: _DATE_
++Description: SANE (Scanner Access Now Easy) is a universal scanner
++ interface and comes complete with documentation and several
++ frontends and backends.
++Keywords: camera, scanner, Abaton, Apple, Agfa, Artec, Canon, Epson,
++ HP, Kodak DC25 & DC210, Microtek, Mustek, Nikon CoolScan,
++ Polaroid Digital Microscope Camera, PINT, Connectix QuickCam,
++ Ricoh, Siemens, Tamarack, UMAX, network server & client,
++ Java API & client
++Author: David.Mosberger@acm.org (David Mosberger-Tang)
++ (see AUTHORS for complete list)
++Maintained-by: David.Mosberger@acm.org (David Mosberger-Tang)
++Primary-site: ftp.mostang.com /pub/sane
++ _T_S_ kB sane-_VERSION_.tar.gz
++ _L_S_ kB sane-_VERSION_.lsm
++Alternate-site: tsx-11.mit.edu /pub/linux/packages/sane
++ sunsite.unc.edu /pub/Linux/apps/graphics/capture
++ gd.tuwien.ac.at /hci/sane/
++Platforms: AIX, Digital Unix, HP Apollo Domain/OS, FreeBSD, HP-UX, IRIX,
++ Linux (Alpha, m68k, SPARC, x86), NetBSD, OpenStep (x86),
++ SCO OpenServer 5.x (x86), OS/2, Solaris (SPARC, x86), SunOS
++Copying-policy: GPL (programs), relaxed GPL (libraries), and public domain
++ (SANE standard)
++End
--- /dev/null
+Index: ChangeLog
+===================================================================
+RCS file: /cvsroot/external/sane/ChangeLog,v
+retrieving revision 1.1.1.1.2.115
+diff -u -r1.1.1.1.2.115 ChangeLog
+--- ChangeLog 2000/03/18 03:14:11 1.1.1.1.2.115
++++ ChangeLog 2000/03/18 03:19:11
+@@ -1,5 +1,10 @@
+ 2000-03-18 Petter Reinholdtsen <pere@td.org.uit.no>
+
++ * include/sane/sanei_debug.h sanei/sanei_init_debug.c: Send debug
++ messages to syslog if stderr is a socket.
++
++2000-03-18 Petter Reinholdtsen <pere@td.org.uit.no>
++
+ * backend/Makefile.in tools/libtool-get-dll-ext: New script to
+ detect shared library endings without using 'rev' which is missing
+ on some platforms.
+Index: include/sane/sanei_debug.h
+===================================================================
+RCS file: /cvsroot/external/sane/include/sane/sanei_debug.h,v
+retrieving revision 1.1.1.1.2.1
+diff -u -r1.1.1.1.2.1 sanei_debug.h
+--- sanei_debug.h 2000/01/25 15:37:55 1.1.1.1.2.1
++++ sanei_debug.h 2000/03/18 03:19:12
+@@ -1,3 +1,6 @@
++#ifndef _SANEI_DEBUG_H
++#define _SANEI_DEBUG_H
++
+ #include <sane/sanei.h>
+
+ #define ENTRY(name) PASTE(PASTE(PASTE(sane_,BACKEND_NAME),_),name)
+@@ -8,9 +11,7 @@
+ # define HAVE_VARARG_MACROS
+ #endif
+
+-#ifndef HAVE_VARARG_MACROS
+- extern void sanei_debug (int level, const char *msg, ...);
+-#endif
++extern void sanei_debug (int level, const char *msg, ...);
+
+ #ifdef NDEBUG
+ # define DBG_INIT(backend, var)
+@@ -26,28 +27,31 @@
+ #define DBG_LEVEL PASTE(sanei_debug_,BACKEND_NAME)
+
+ #if defined(BACKEND_NAME) && !defined(STUBS)
+-int PASTE(sanei_debug_,BACKEND_NAME);
++int DBG_LEVEL;
+ #endif
+
+ # define DBG_INIT() \
+- sanei_init_debug (STRINGIFY(BACKEND_NAME), \
+- &PASTE(sanei_debug_,BACKEND_NAME))
++ sanei_init_debug (STRINGIFY(BACKEND_NAME), &DBG_LEVEL)
+
+ /* The cpp that comes with GNU C 2.5 seems to have troubles understanding
+ vararg macros. */
+ #ifdef HAVE_VARARG_MACROS
++extern void sanei_debug_max (int level, int max_level, const char *msg, ...);
++
+ # define DBG(level, msg, args...) \
+ do { \
+- if (DBG_LEVEL >= (level)){ \
+- fprintf (stderr, "[" STRINGIFY(BACKEND_NAME) "] " msg, ##args); \
+- fflush(stderr); \
+- } \
++ sanei_debug_max ( level, DBG_LEVEL, \
++ "[" STRINGIFY(BACKEND_NAME) "] " msg, ##args); \
+ } while (0)
+
+ extern void sanei_init_debug (const char * backend, int * debug_level_var);
+ #else
+ # define DBG sanei_debug
+-#endif
++#endif /* HAVE_VARARG_MACROS */
+
+ # define IF_DBG(x) x
+-#endif
++#endif */ NDEBUG */
++
++#else
++# warning "sane/sanei_debug.h included more then once!"
++#endif /* _SANEI_DEBUG_H */
+Index: sanei/sanei_init_debug.c
+===================================================================
+RCS file: /cvsroot/external/sane/sanei/sanei_init_debug.c,v
+retrieving revision 1.1.1.1
+diff -u -r1.1.1.1 sanei_init_debug.c
+--- sanei_init_debug.c 1999/08/09 18:05:59 1.1.1.1
++++ sanei_init_debug.c 2000/03/18 03:19:12
+@@ -43,24 +43,33 @@
+ #include <ctype.h>
+ #include <stdio.h>
+ #include <stdlib.h>
++#ifdef HAVE_UNISTD_H
++#include <unistd.h>
++#endif
++#include <stdarg.h>
++#include <sys/syslog.h>
++#ifdef HAVE_SYS_SOCKET_H
++#include <sys/socket.h>
++#endif
++#include <sys/stat.h>
+
+ #ifdef __EMX__
+ # define INCL_DOS
+ # include <os2.h>
+ #endif
+
++#define BACKEND_NAME sanei_debug
+ #include <sane/sanei_debug.h>
+
+-#ifndef HAVE_VARARG_MACROS
+- static int max_level = 0;
+-#endif
++static int global_max_level = 0;
++
+
+ void
+ sanei_init_debug (const char * backend, int * var)
+ {
+ char ch, buf[256] = "SANE_DEBUG_";
+ const char * val;
+- int i;
++ unsigned int i;
+
+ *var = 0;
+
+@@ -84,30 +93,38 @@
+
+ *var = atoi (val);
+
+-#ifndef HAVE_VARARG_MACROS
+- if (*var > max_level)
+- max_level = *var;
+-#endif
++ if (*var > global_max_level)
++ global_max_level = *var;
+
+- fprintf (stderr, "[sanei_init_debug]: Setting debug level of %s to %d.\n",
+- backend, *var);
++ DBG (0, "Setting debug level of %s to %d.\n", backend, *var);
+ }
+
+-#ifndef HAVE_VARARG_MACROS
+-
+-#include <stdarg.h>
++static void
++debug_msg (int level, int max_level, const char *fmt, va_list ap)
++{
++ if (max_level >= level)
++ {
++ if ( 1 == isfdtype(fileno(stderr), S_IFSOCK) )
++ vsyslog(LOG_DEBUG, fmt, ap);
++ else
++ vfprintf (stderr, fmt, ap);
++ }
++}
+
+ void
+ sanei_debug (int level, const char *fmt, ...)
+ {
+ va_list ap;
+-
+- if (max_level >= level)
+- {
+- va_start (ap, fmt);
+- vfprintf (stderr, fmt, ap);
+- va_end (ap);
+- }
++ va_start (ap, fmt);
++ debug_msg (level, global_max_level, fmt, ap);
++ va_end (ap);
+ }
+
+-#endif /* !HAVE_VARARG_MACROS */
++void
++sanei_debug_max (int level, int max_level, const char *fmt, ...)
++{
++ va_list ap;
++ va_start (ap, fmt);
++ debug_msg (level, max_level, fmt, ap);
++ va_end (ap);
++}
--- /dev/null
+diff -ru /store/store/joseph/sane/src-pre1.01r3/ChangeLog src-pre1.01r3-allarchs/ChangeLog
+--- /store/store/joseph/sane/src-pre1.01r3/ChangeLog Fri Mar 5 07:20:00 1999
++++ src-pre1.01r3-allarchs/ChangeLog Sat Mar 13 15:37:48 1999
+@@ -1,3 +1,14 @@
++1999-03-10 Petter Reinholdtsen <pere@td.org.uit.no>
++
++ * backend/snapscan.c (add_device init_options inquiry
++ sane_snapscan_get_parameters sane_snapscan_start
++ sane_snapscan_set_io_mode sane_snapscan_read) backend/snapscan.h
++ backend/snapscan.desc: Rewrote scanner detection code to loop over
++ array of supported SCSI names. Added AGFA SnapScan 1236 support.
++ It seems to be compatible with SnapScan 600.
++ Make sure to not add the same device more then once to the device
++ list. Bugfix in sane_snapscan_read() triggered on EOF.
++
+ 1999-03-04 David Mosberger-Tang <David.Mosberger@acm.org>
+
+ * backend/canon.c (adjust_hilo_points): Print values of type
+diff -ru /store/store/joseph/sane/src-pre1.01r3/backend/snapscan.c src-pre1.01r3-allarchs/backend/snapscan.c
+--- /store/store/joseph/sane/src-pre1.01r3/backend/snapscan.c Sun Feb 28 21:34:05 1999
++++ src-pre1.01r3-allarchs/backend/snapscan.c Fri Mar 12 20:17:16 1999
+@@ -111,6 +111,8 @@
+
+ /*----- internal scanner operations -----*/
+
++#define DEFAULT_DEVICE "/dev/scanner" /* Check this if config is missing */
++
+ /* hardware configuration byte masks */
+
+ #define HCFG_ADC 0x80 /* AD converter 1 ==> 10bit, 0 ==> 8bit */
+@@ -161,7 +163,6 @@
+ #define DEFAULT_BRX (x_range.max)
+ #define DEFAULT_BRY (y_range.max)
+
+-
+ #ifdef INOPERATIVE
+ static const SANE_Range percent_range =
+ {
+@@ -339,6 +340,7 @@
+ {
+ case SNAPSCAN310:
+ case SNAPSCAN600:
++ case SNAPSCAN1236:
+ case VUEGO310S: /* WG changed */
+ po[OPT_MODE].constraint.string_list = names_310;
+ break;
+@@ -370,6 +372,7 @@
+ {
+ case SNAPSCAN310:
+ case SNAPSCAN600:
++ case SNAPSCAN1236:
+ case VUEGO310S: /* WG changed */
+ po[OPT_PREVIEW_MODE].constraint.string_list = names_310;
+ break;
+@@ -995,6 +998,7 @@
+ {
+ case SNAPSCAN310:
+ case SNAPSCAN600:
++ case SNAPSCAN1236:
+ case VUEGO310S: /* WG changed */
+ rgb_buf_set_diff (pss,
+ pss->buf[INQUIRY_G2R_DIFF],
+@@ -1530,6 +1534,15 @@
+ static SnapScan_Device *first_device = NULL; /* device list head */
+ static int n_devices = 0; /* the device count */
+
++static SANE_Bool
++device_already_in_list(SnapScan_Device *current, SANE_String_Const name)
++{
++ for ( ;NULL != current; current = current->pnext )
++ if (0 == strcmp(name, current->dev.name))
++ return SANE_TRUE;
++ return SANE_FALSE;
++}
++
+ static SANE_Status
+ add_device (SANE_String_Const name)
+ {
+@@ -1537,10 +1550,16 @@
+ static const char me[] = "add_device";
+ SANE_Status status;
+ SnapScan_Device *pd;
+- SnapScan_Model model_num;
++ SnapScan_Model model_num = UNKNOWN;
+ char vendor[8], model[17];
++ int i, vendor_ok = 0;
+
+- DBG (DL_CALL_TRACE, "%s\n", me);
++ DBG (DL_CALL_TRACE, "%s(%s)\n", me, name);
++
++ /* Avoid adding the same device more then once */
++ if (device_already_in_list(first_device, name)) {
++ return SANE_STATUS_GOOD;
++ }
+
+ vendor[0] = model[0] = '\0';
+
+@@ -1561,38 +1580,38 @@
+ return status;
+ }
+
+- if ((strncasecmp (vendor, SNAPSCAN_VENDOR, strlen (SNAPSCAN_VENDOR)) == 0)
+- ||
+- (strncasecmp (vendor, VUEGO_VENDOR, strlen (VUEGO_VENDOR)) == 0)) /* WG changed */
+- {
+- /* original SnapScan */
+- if (strncasecmp (model, SNAPSCAN_MODEL310,
+- strlen (SNAPSCAN_MODEL310)) == 0)
+- model_num = SNAPSCAN310;
+- else if (strncasecmp (model, SNAPSCAN_MODEL600,
+- strlen (SNAPSCAN_MODEL600)) == 0)
+- model_num = SNAPSCAN600;
+- else if (strncasecmp (model, SNAPSCAN_MODEL300,
+- strlen (SNAPSCAN_MODEL300)) == 0)
+- model_num = SNAPSCAN300;
+- else if (strncasecmp (model, VUEGO_MODEL310S, /* WG changed */
+- strlen (VUEGO_MODEL310S)) == 0)
+- model_num = VUEGO310S;
+- else
++ /* check if this is one of our supported vendors */
++ for (i = 0; i < known_vendors; i++)
++ if (0 == strncasecmp (vendor, vendors[i], strlen(vendors[i])))
++ {
++ vendor_ok = 1;
++ break;
++ }
++ if (!vendor_ok)
++ {
++ DBG (DL_MINOR_ERROR, "%s: \"%s %s\" is not an %s\n",
++ me, vendor, model,
++ "AGFA SnapScan model 300, 310, 600 and 1236"
++ " or VUEGO model 310S"); /* WG changed */
++ sanei_scsi_close (fd);
++ return SANE_STATUS_INVAL;
++ }
++
++ /* Known vendor. Check if it is one of our supported models */
++ for (i = 0; i < known_scanners; i++)
++ {
++ if (0 == strncasecmp (model, scanners[i].scsi_name,
++ strlen(scanners[i].scsi_name)))
+ {
+- DBG (DL_INFO, "%s: sorry, model %s is not supported.\n"
+- "Currently supported models are the SnapScan 300 and 310.\n",
+- me, model);
+- sanei_scsi_close (fd);
+- return SANE_STATUS_INVAL;
++ model_num = scanners[i].id;
++ break;
+ }
+ }
+- else
++ if (UNKNOWN == model_num)
+ {
+- DBG (DL_MINOR_ERROR, "%s: \"%s %s\" is not an %s %s\n",
+- me, vendor, model,
+- SNAPSCAN_VENDOR,
+- "AGFA SnapScan model 300, 310, and 600 or VUEGO model 310S"); /* WG changed */
++ DBG (DL_INFO, "%s: sorry, model %s is not supported.\n"
++ "Currently supported models are the SnapScan 300 and 310.\n",
++ me, model);
+ sanei_scsi_close (fd);
+ return SANE_STATUS_INVAL;
+ }
+@@ -1706,10 +1725,10 @@
+ if (!fp)
+ {
+ DBG (DL_INFO,
+- "%s: configuration file not found, defaulting to /dev/scanner.\n",
+- me);
++ "%s: configuration file not found, defaulting to %s.\n",
++ me, DEFAULT_DEVICE);
+ /* default to /dev/scanner instead of insisting on config file */
+- status = add_device ("/dev/scanner");
++ status = add_device (DEFAULT_DEVICE);
+ if (status != SANE_STATUS_GOOD)
+ {
+ DBG (DL_MINOR_ERROR, "%s: failed to add device \"%s\"\n",
+@@ -2673,6 +2692,7 @@
+ {
+ case SNAPSCAN310:
+ case SNAPSCAN600:
++ case SNAPSCAN1236:
+ case VUEGO310S: /* WG changed */
+ if (!pss->preview)
+ {
+@@ -2699,6 +2719,7 @@
+ {
+ case SNAPSCAN310:
+ case SNAPSCAN600:
++ case SNAPSCAN1236:
+ case VUEGO310S: /* WG changed */
+ pss->lines += line_offset;
+ p->lines -= line_offset;
+@@ -3114,6 +3135,7 @@
+ {
+ case SNAPSCAN310:
+ case SNAPSCAN600:
++ case SNAPSCAN1236:
+ case VUEGO310S: /* WG changed */
+ if (SANE_STATUS_GOOD != rgb_buf_init (pss))
+ return SANE_STATUS_NO_MEM;
+@@ -3134,6 +3156,7 @@
+ {
+ case SNAPSCAN310:
+ case SNAPSCAN600:
++ case SNAPSCAN1236:
+ case VUEGO310S: /* WG changed */
+ rgb_buf_clean (pss);
+ break;
+@@ -3153,6 +3176,7 @@
+ {
+ case SNAPSCAN310:
+ case SNAPSCAN600:
++ case SNAPSCAN1236:
+ case VUEGO310S: /* WG changed */
+ transfer_data_diff (other_buf, pss);
+ break;
+@@ -3186,6 +3210,7 @@
+ {
+ case SNAPSCAN310:
+ case SNAPSCAN600:
++ case SNAPSCAN1236:
+ case VUEGO310S: /* WG changed */
+ rgb_buf_clean (pss);
+ break;
+@@ -3231,13 +3256,14 @@
+ pss->bytes_per_line / pss->ms_per_line);
+
+ /* allocate and initialize rgb ring buffer if the device is
+- a snapscan 310 or 600 model, in colour mode */
++ a snapscan 310, 600 or 1236 model, in colour mode */
+ if (colour)
+ {
+ switch (pss->pdev->model)
+ {
+ case SNAPSCAN310:
+ case SNAPSCAN600:
++ case SNAPSCAN1236:
+ case VUEGO310S: /* WG changed */
+ rgb_buf_init (pss);
+ break;
+@@ -3279,6 +3305,8 @@
+ DBG (DL_CALL_TRACE, "%s (%p, %p, %ld, %p)\n",
+ me, (void *) h, (void *) buf, (long) maxlen, (void *) plen);
+
++ *plen = 0;
++
+ if (!pss->expected_data_len)
+ {
+ if (pss->child > 0)
+@@ -3292,8 +3320,6 @@
+ return SANE_STATUS_EOF;
+ }
+
+- *plen = 0;
+-
+ if (pss->preview)
+ mode = pss->preview_mode;
+
+@@ -3413,6 +3444,7 @@
+ {
+ case SNAPSCAN310:
+ case SNAPSCAN600:
++ case SNAPSCAN1236:
+ case VUEGO310S: /* WG changed */
+ transferred_bytes = transfer_data_diff (buf, pss);
+ break;
+@@ -3486,6 +3518,7 @@
+ {
+ case SNAPSCAN310:
+ case SNAPSCAN600:
++ case SNAPSCAN1236:
+ case VUEGO310S: /* WG changed */
+ rgb_buf_clean (pss);
+ break;
+diff -ru /store/store/joseph/sane/src-pre1.01r3/backend/snapscan.desc src-pre1.01r3-allarchs/backend/snapscan.desc
+--- /store/store/joseph/sane/src-pre1.01r3/backend/snapscan.desc Mon Sep 7 09:28:57 1998
++++ src-pre1.01r3-allarchs/backend/snapscan.desc Wed Mar 10 21:14:10 1999
+@@ -28,6 +28,8 @@
+ :comment "Ditto"
+ :model "SnapScan 600"
+ :comment "Ditto"
++:model "SnapScan 1236"
++:comment "Ditto"
+ :mfg "Vuego"
+ :model "310S"
+ :comment "Close SnapScan 310 compatible."
+diff -ru /store/store/joseph/sane/src-pre1.01r3/backend/snapscan.h src-pre1.01r3-allarchs/backend/snapscan.h
+--- /store/store/joseph/sane/src-pre1.01r3/backend/snapscan.h Sun Feb 28 00:59:10 1999
++++ src-pre1.01r3-allarchs/backend/snapscan.h Wed Mar 10 22:19:16 1999
+@@ -54,22 +54,41 @@
+ /* snapscan device field values */
+
+ #define SNAPSCAN_NAME "/dev/sga"
+-#define SNAPSCAN_VENDOR "AGFA"
+-#define VUEGO_VENDOR "COLOR"
+-#define SNAPSCAN_MODEL300 "SnapScan"
+-#define SNAPSCAN_MODEL310 "SNAPSCAN 310"
+-#define VUEGO_MODEL310S "FlatbedScanner_4"
+-#define SNAPSCAN_MODEL600 "SNAPSCAN 600"
+ #define SNAPSCAN_TYPE "flatbed scanner"
+ /*#define INOPERATIVE*/
+
+ typedef enum
+ {
++ UNKNOWN,
+ SNAPSCAN300, /* the original SnapScan or SnapScan 300 */
+ SNAPSCAN310, /* the SnapScan 310 */
+ SNAPSCAN600, /* the SnapScan 600 */
++ SNAPSCAN1236, /* the SnapScan 1236 */
+ VUEGO310S /* Vuego-Version of SnapScan 310 WG changed */
+ } SnapScan_Model;
++
++struct SnapScan_Model_desc
++{
++ char *scsi_name;
++ SnapScan_Model id;
++};
++
++static struct SnapScan_Model_desc scanners[] =
++{
++ { "FlatbedScanner_4", VUEGO310S },
++ { "SNAPSCAN 1236", SNAPSCAN1236 },
++ { "SNAPSCAN 310", SNAPSCAN310 },
++ { "SNAPSCAN 600", SNAPSCAN600 },
++ { "SnapScan", SNAPSCAN300 },
++};
++#define known_scanners (sizeof(scanners)/sizeof(struct SnapScan_Model_desc))
++
++static char *vendors[] =
++{
++ "AGFA",
++ "COLOR",
++};
++#define known_vendors (sizeof(vendors)/sizeof(char*))
+
+ typedef enum
+ {
--- /dev/null
+diff -ru sane-pre1.01-4/ChangeLog sane-pre1.01-4-pere/ChangeLog
+--- sane-pre1.01-4/ChangeLog Sun Apr 4 01:17:20 1999
++++ sane-pre1.01-4-pere/ChangeLog Sun Apr 4 19:01:26 1999
+@@ -1,3 +1,17 @@
++1999-04-04 Petter Reinholdtsen <pere@td.org.uit.no>
++ * backend/snapscan.c (sane_snapscan_*): Changed API entries from
++ sane_snapscan_* to sane_*.
++
++1999-03-10 Petter Reinholdtsen <pere@td.org.uit.no>
++ * backend/snapscan.c (add_device init_options inquiry
++ sane_snapscan_get_parameters sane_snapscan_start
++ sane_snapscan_set_io_mode sane_snapscan_read) backend/snapscan.h
++ backend/snapscan.desc: Rewrote scanner detection code to loop over
++ array of supported SCSI names. Added AGFA SnapScan 1236s support.
++ It seems to be compatible with SnapScan 600.
++ Make sure to not add the same device more then once to the device
++ list. Bugfix in sane_snapscan_read() triggered on EOF.
++
+ 1999-04-03 David Mosberger-Tang <David.Mosberger@acm.org>
+
+ * include/sane/sanei_debug.h: Define sanei_debug_BACKEND_NAME only
+diff -ru sane-pre1.01-4/backend/snapscan.c sane-pre1.01-4-pere/backend/snapscan.c
+--- sane-pre1.01-4/backend/snapscan.c Sun Feb 28 21:34:05 1999
++++ sane-pre1.01-4-pere/backend/snapscan.c Sun Apr 4 18:58:05 1999
+@@ -111,6 +111,8 @@
+
+ /*----- internal scanner operations -----*/
+
++#define DEFAULT_DEVICE "/dev/scanner" /* Check this if config is missing */
++
+ /* hardware configuration byte masks */
+
+ #define HCFG_ADC 0x80 /* AD converter 1 ==> 10bit, 0 ==> 8bit */
+@@ -161,7 +163,6 @@
+ #define DEFAULT_BRX (x_range.max)
+ #define DEFAULT_BRY (y_range.max)
+
+-
+ #ifdef INOPERATIVE
+ static const SANE_Range percent_range =
+ {
+@@ -339,6 +340,7 @@
+ {
+ case SNAPSCAN310:
+ case SNAPSCAN600:
++ case SNAPSCAN1236S:
+ case VUEGO310S: /* WG changed */
+ po[OPT_MODE].constraint.string_list = names_310;
+ break;
+@@ -370,6 +372,7 @@
+ {
+ case SNAPSCAN310:
+ case SNAPSCAN600:
++ case SNAPSCAN1236S:
+ case VUEGO310S: /* WG changed */
+ po[OPT_PREVIEW_MODE].constraint.string_list = names_310;
+ break;
+@@ -995,6 +998,7 @@
+ {
+ case SNAPSCAN310:
+ case SNAPSCAN600:
++ case SNAPSCAN1236S:
+ case VUEGO310S: /* WG changed */
+ rgb_buf_set_diff (pss,
+ pss->buf[INQUIRY_G2R_DIFF],
+@@ -1530,6 +1534,15 @@
+ static SnapScan_Device *first_device = NULL; /* device list head */
+ static int n_devices = 0; /* the device count */
+
++static SANE_Bool
++device_already_in_list(SnapScan_Device *current, SANE_String_Const name)
++{
++ for ( ;NULL != current; current = current->pnext )
++ if (0 == strcmp(name, current->dev.name))
++ return SANE_TRUE;
++ return SANE_FALSE;
++}
++
+ static SANE_Status
+ add_device (SANE_String_Const name)
+ {
+@@ -1537,10 +1550,16 @@
+ static const char me[] = "add_device";
+ SANE_Status status;
+ SnapScan_Device *pd;
+- SnapScan_Model model_num;
++ SnapScan_Model model_num = UNKNOWN;
+ char vendor[8], model[17];
++ int i, vendor_ok = 0;
+
+- DBG (DL_CALL_TRACE, "%s\n", me);
++ DBG (DL_CALL_TRACE, "%s(%s)\n", me, name);
++
++ /* Avoid adding the same device more then once */
++ if (device_already_in_list(first_device, name)) {
++ return SANE_STATUS_GOOD;
++ }
+
+ vendor[0] = model[0] = '\0';
+
+@@ -1561,38 +1580,39 @@
+ return status;
+ }
+
+- if ((strncasecmp (vendor, SNAPSCAN_VENDOR, strlen (SNAPSCAN_VENDOR)) == 0)
+- ||
+- (strncasecmp (vendor, VUEGO_VENDOR, strlen (VUEGO_VENDOR)) == 0)) /* WG changed */
+- {
+- /* original SnapScan */
+- if (strncasecmp (model, SNAPSCAN_MODEL310,
+- strlen (SNAPSCAN_MODEL310)) == 0)
+- model_num = SNAPSCAN310;
+- else if (strncasecmp (model, SNAPSCAN_MODEL600,
+- strlen (SNAPSCAN_MODEL600)) == 0)
+- model_num = SNAPSCAN600;
+- else if (strncasecmp (model, SNAPSCAN_MODEL300,
+- strlen (SNAPSCAN_MODEL300)) == 0)
+- model_num = SNAPSCAN300;
+- else if (strncasecmp (model, VUEGO_MODEL310S, /* WG changed */
+- strlen (VUEGO_MODEL310S)) == 0)
+- model_num = VUEGO310S;
+- else
++ /* check if this is one of our supported vendors */
++ for (i = 0; i < known_vendors; i++)
++ if (0 == strncasecmp (vendor, vendors[i], strlen(vendors[i])))
++ {
++ vendor_ok = 1;
++ break;
++ }
++ if (!vendor_ok)
++ {
++ DBG (DL_MINOR_ERROR, "%s: \"%s %s\" is not an %s\n",
++ me, vendor, model,
++ "AGFA SnapScan model 300, 310, 600 and 1236s"
++ " or VUEGO model 310S"); /* WG changed */
++ sanei_scsi_close (fd);
++ return SANE_STATUS_INVAL;
++ }
++
++ /* Known vendor. Check if it is one of our supported models */
++ for (i = 0; i < known_scanners; i++)
++ {
++ if (0 == strncasecmp (model, scanners[i].scsi_name,
++ strlen(scanners[i].scsi_name)))
+ {
+- DBG (DL_INFO, "%s: sorry, model %s is not supported.\n"
+- "Currently supported models are the SnapScan 300 and 310.\n",
+- me, model);
+- sanei_scsi_close (fd);
+- return SANE_STATUS_INVAL;
++ model_num = scanners[i].id;
++ break;
+ }
+ }
+- else
++ if (UNKNOWN == model_num)
+ {
+- DBG (DL_MINOR_ERROR, "%s: \"%s %s\" is not an %s %s\n",
+- me, vendor, model,
+- SNAPSCAN_VENDOR,
+- "AGFA SnapScan model 300, 310, and 600 or VUEGO model 310S"); /* WG changed */
++ DBG (DL_INFO, "%s: sorry, model %s is not supported.\n"
++ "Currently supported models are AGFA SnapScan model 300, 310, 600\n"
++ "and 1236s and VUEGO model 310S"\n",
++ me, model);
+ sanei_scsi_close (fd);
+ return SANE_STATUS_INVAL;
+ }
+@@ -1666,7 +1686,7 @@
+
+
+ SANE_Status
+-sane_snapscan_init (SANE_Int * version_code,
++sane_init (SANE_Int * version_code,
+ SANE_Auth_Callback authorize)
+ {
+ static const char me[] = "sane_snapscan_init";
+@@ -1706,10 +1726,10 @@
+ if (!fp)
+ {
+ DBG (DL_INFO,
+- "%s: configuration file not found, defaulting to /dev/scanner.\n",
+- me);
++ "%s: configuration file not found, defaulting to %s.\n",
++ me, DEFAULT_DEVICE);
+ /* default to /dev/scanner instead of insisting on config file */
+- status = add_device ("/dev/scanner");
++ status = add_device (DEFAULT_DEVICE);
+ if (status != SANE_STATUS_GOOD)
+ {
+ DBG (DL_MINOR_ERROR, "%s: failed to add device \"%s\"\n",
+@@ -1752,7 +1772,7 @@
+ }
+
+ void
+-sane_snapscan_exit (void)
++sane_exit (void)
+ {
+ DBG (DL_CALL_TRACE, "sane_snapscan_exit\n");
+
+@@ -1761,7 +1781,7 @@
+ }
+
+ SANE_Status
+-sane_snapscan_get_devices (const SANE_Device *** device_list,
++sane_get_devices (const SANE_Device *** device_list,
+ SANE_Bool local_only)
+ {
+ static const char *me = "sane_snapscan_get_devices";
+@@ -1793,7 +1813,7 @@
+ #define TMP_FILE "snapscan-tmp"
+
+ SANE_Status
+-sane_snapscan_open (SANE_String_Const name, SANE_Handle * h)
++sane_open (SANE_String_Const name, SANE_Handle * h)
+ {
+ static const char *me = "sane_snapscan_open";
+ SnapScan_Device *psd;
+@@ -1905,7 +1925,7 @@
+ }
+
+ void
+-sane_snapscan_close (SANE_Handle h)
++sane_close (SANE_Handle h)
+ {
+ SnapScan_Scanner *pss = (SnapScan_Scanner *) h;
+ DBG (DL_CALL_TRACE, "sane_snapscan_close (%p)\n", (void *) h);
+@@ -1925,7 +1945,7 @@
+ }
+
+ const SANE_Option_Descriptor *
+-sane_snapscan_get_option_descriptor (SANE_Handle h, SANE_Int n)
++sane_get_option_descriptor (SANE_Handle h, SANE_Int n)
+ {
+ DBG (DL_CALL_TRACE, "sane_snapscan_get_option_descriptor (%p, %ld)\n",
+ (void *) h, (long) n);
+@@ -1938,7 +1958,7 @@
+ }
+
+ SANE_Status
+-sane_snapscan_control_option (SANE_Handle h, SANE_Int n,
++sane_control_option (SANE_Handle h, SANE_Int n,
+ SANE_Action a, void *v,
+ SANE_Int * i)
+ {
+@@ -2621,7 +2641,7 @@
+ }
+
+ SANE_Status
+-sane_snapscan_get_parameters (SANE_Handle h,
++sane_get_parameters (SANE_Handle h,
+ SANE_Parameters * p)
+ {
+ static const char *me = "sane_snapscan_get_parameters";
+@@ -2673,6 +2693,7 @@
+ {
+ case SNAPSCAN310:
+ case SNAPSCAN600:
++ case SNAPSCAN1236S:
+ case VUEGO310S: /* WG changed */
+ if (!pss->preview)
+ {
+@@ -2699,6 +2720,7 @@
+ {
+ case SNAPSCAN310:
+ case SNAPSCAN600:
++ case SNAPSCAN1236S:
+ case VUEGO310S: /* WG changed */
+ pss->lines += line_offset;
+ p->lines -= line_offset;
+@@ -2960,7 +2982,7 @@
+ }
+
+ SANE_Status
+-sane_snapscan_start (SANE_Handle h)
++sane_start (SANE_Handle h)
+ {
+ static const char *me = "sane_snapscan_start";
+ SANE_Status status;
+@@ -3114,6 +3136,7 @@
+ {
+ case SNAPSCAN310:
+ case SNAPSCAN600:
++ case SNAPSCAN1236S:
+ case VUEGO310S: /* WG changed */
+ if (SANE_STATUS_GOOD != rgb_buf_init (pss))
+ return SANE_STATUS_NO_MEM;
+@@ -3134,6 +3157,7 @@
+ {
+ case SNAPSCAN310:
+ case SNAPSCAN600:
++ case SNAPSCAN1236S:
+ case VUEGO310S: /* WG changed */
+ rgb_buf_clean (pss);
+ break;
+@@ -3153,6 +3177,7 @@
+ {
+ case SNAPSCAN310:
+ case SNAPSCAN600:
++ case SNAPSCAN1236S:
+ case VUEGO310S: /* WG changed */
+ transfer_data_diff (other_buf, pss);
+ break;
+@@ -3186,6 +3211,7 @@
+ {
+ case SNAPSCAN310:
+ case SNAPSCAN600:
++ case SNAPSCAN1236S:
+ case VUEGO310S: /* WG changed */
+ rgb_buf_clean (pss);
+ break;
+@@ -3231,13 +3257,14 @@
+ pss->bytes_per_line / pss->ms_per_line);
+
+ /* allocate and initialize rgb ring buffer if the device is
+- a snapscan 310 or 600 model, in colour mode */
++ a snapscan 310, 600 or 1236s model, in colour mode */
+ if (colour)
+ {
+ switch (pss->pdev->model)
+ {
+ case SNAPSCAN310:
+ case SNAPSCAN600:
++ case SNAPSCAN1236S:
+ case VUEGO310S: /* WG changed */
+ rgb_buf_init (pss);
+ break;
+@@ -3268,7 +3295,7 @@
+
+
+ SANE_Status
+-sane_snapscan_read (SANE_Handle h, SANE_Byte * buf,
++sane_read (SANE_Handle h, SANE_Byte * buf,
+ SANE_Int maxlen, SANE_Int * plen)
+ {
+ static const char *me = "sane_snapscan_read";
+@@ -3279,6 +3306,8 @@
+ DBG (DL_CALL_TRACE, "%s (%p, %p, %ld, %p)\n",
+ me, (void *) h, (void *) buf, (long) maxlen, (void *) plen);
+
++ *plen = 0;
++
+ if (!pss->expected_data_len)
+ {
+ if (pss->child > 0)
+@@ -3292,8 +3321,6 @@
+ return SANE_STATUS_EOF;
+ }
+
+- *plen = 0;
+-
+ if (pss->preview)
+ mode = pss->preview_mode;
+
+@@ -3413,6 +3440,7 @@
+ {
+ case SNAPSCAN310:
+ case SNAPSCAN600:
++ case SNAPSCAN1236S:
+ case VUEGO310S: /* WG changed */
+ transferred_bytes = transfer_data_diff (buf, pss);
+ break;
+@@ -3466,7 +3494,7 @@
+ }
+
+ void
+-sane_snapscan_cancel (SANE_Handle h)
++sane_cancel (SANE_Handle h)
+ {
+ char *me = "sane_snapscan_cancel";
+ SnapScan_Scanner *pss = (SnapScan_Scanner *) h;
+@@ -3486,6 +3514,7 @@
+ {
+ case SNAPSCAN310:
+ case SNAPSCAN600:
++ case SNAPSCAN1236S:
+ case VUEGO310S: /* WG changed */
+ rgb_buf_clean (pss);
+ break;
+@@ -3506,7 +3535,7 @@
+ }
+
+ SANE_Status
+-sane_snapscan_set_io_mode (SANE_Handle h, SANE_Bool m)
++sane_set_io_mode (SANE_Handle h, SANE_Bool m)
+ {
+ static char me[] = "sane_snapscan_set_io_mode";
+ SnapScan_Scanner *pss = (SnapScan_Scanner *) h;
+@@ -3541,7 +3570,7 @@
+ }
+
+ SANE_Status
+-sane_snapscan_get_select_fd (SANE_Handle h, SANE_Int * fd)
++sane_get_select_fd (SANE_Handle h, SANE_Int * fd)
+ {
+ static char me[] = "sane_snapscan_get_select_fd";
+ SnapScan_Scanner *pss = (SnapScan_Scanner *) h;
+diff -ru sane-pre1.01-4/backend/snapscan.desc sane-pre1.01-4-pere/backend/snapscan.desc
+--- sane-pre1.01-4/backend/snapscan.desc Mon Sep 7 09:28:57 1998
++++ sane-pre1.01-4-pere/backend/snapscan.desc Sun Apr 4 18:44:11 1999
+@@ -28,6 +28,8 @@
+ :comment "Ditto"
+ :model "SnapScan 600"
+ :comment "Ditto"
++:model "SnapScan 1236s"
++:comment "Ditto"
+ :mfg "Vuego"
+ :model "310S"
+ :comment "Close SnapScan 310 compatible."
+diff -ru sane-pre1.01-4/backend/snapscan.h sane-pre1.01-4-pere/backend/snapscan.h
+--- sane-pre1.01-4/backend/snapscan.h Sun Feb 28 00:59:10 1999
++++ sane-pre1.01-4-pere/backend/snapscan.h Sun Apr 4 18:45:44 1999
+@@ -54,22 +54,41 @@
+ /* snapscan device field values */
+
+ #define SNAPSCAN_NAME "/dev/sga"
+-#define SNAPSCAN_VENDOR "AGFA"
+-#define VUEGO_VENDOR "COLOR"
+-#define SNAPSCAN_MODEL300 "SnapScan"
+-#define SNAPSCAN_MODEL310 "SNAPSCAN 310"
+-#define VUEGO_MODEL310S "FlatbedScanner_4"
+-#define SNAPSCAN_MODEL600 "SNAPSCAN 600"
+ #define SNAPSCAN_TYPE "flatbed scanner"
+ /*#define INOPERATIVE*/
+
+ typedef enum
+ {
++ UNKNOWN,
+ SNAPSCAN300, /* the original SnapScan or SnapScan 300 */
+ SNAPSCAN310, /* the SnapScan 310 */
+ SNAPSCAN600, /* the SnapScan 600 */
++ SNAPSCAN1236S, /* the SnapScan 1236s */
+ VUEGO310S /* Vuego-Version of SnapScan 310 WG changed */
+ } SnapScan_Model;
++
++struct SnapScan_Model_desc
++{
++ char *scsi_name;
++ SnapScan_Model id;
++};
++
++static struct SnapScan_Model_desc scanners[] =
++{
++ { "FlatbedScanner_4", VUEGO310S },
++ { "SNAPSCAN 1236s", SNAPSCAN1236S },
++ { "SNAPSCAN 310", SNAPSCAN310 },
++ { "SNAPSCAN 600", SNAPSCAN600 },
++ { "SnapScan", SNAPSCAN300 },
++};
++#define known_scanners (sizeof(scanners)/sizeof(struct SnapScan_Model_desc))
++
++static char *vendors[] =
++{
++ "AGFA",
++ "COLOR",
++};
++#define known_vendors (sizeof(vendors)/sizeof(char*))
+
+ typedef enum
+ {
--- /dev/null
+diff -ru sane-pre1.01-4/ChangeLog sane-pre1.01-4-pere/ChangeLog
+--- sane-pre1.01-4/ChangeLog Sun Apr 4 01:17:20 1999
++++ sane-pre1.01-4-pere/ChangeLog Sun Apr 4 22:54:36 1999
+@@ -1,3 +1,17 @@
++1999-04-04 Petter Reinholdtsen <pere@td.org.uit.no>
++ * backend/snapscan.c (sane_snapscan_*): Changed API entries from
++ sane_snapscan_* to sane_*.
++
++1999-03-10 Petter Reinholdtsen <pere@td.org.uit.no>
++ * backend/snapscan.c (add_device init_options inquiry
++ sane_snapscan_get_parameters sane_snapscan_start
++ sane_snapscan_set_io_mode sane_snapscan_read) backend/snapscan.h
++ backend/snapscan.desc: Rewrote scanner detection code to loop over
++ array of supported SCSI names. Added AGFA SnapScan 1236s support.
++ It seems to be compatible with SnapScan 600.
++ Make sure to not add the same device more then once to the device
++ list. Bugfix in sane_snapscan_read() triggered on EOF.
++
+ 1999-04-03 David Mosberger-Tang <David.Mosberger@acm.org>
+
+ * include/sane/sanei_debug.h: Define sanei_debug_BACKEND_NAME only
+diff -ru sane-pre1.01-4/backend/snapscan.c sane-pre1.01-4-pere/backend/snapscan.c
+--- sane-pre1.01-4/backend/snapscan.c Sun Feb 28 21:34:05 1999
++++ sane-pre1.01-4-pere/backend/snapscan.c Sun Apr 4 22:52:20 1999
+@@ -111,6 +111,8 @@
+
+ /*----- internal scanner operations -----*/
+
++#define DEFAULT_DEVICE "/dev/scanner" /* Check this if config is missing */
++
+ /* hardware configuration byte masks */
+
+ #define HCFG_ADC 0x80 /* AD converter 1 ==> 10bit, 0 ==> 8bit */
+@@ -161,7 +163,6 @@
+ #define DEFAULT_BRX (x_range.max)
+ #define DEFAULT_BRY (y_range.max)
+
+-
+ #ifdef INOPERATIVE
+ static const SANE_Range percent_range =
+ {
+@@ -339,6 +340,7 @@
+ {
+ case SNAPSCAN310:
+ case SNAPSCAN600:
++ case SNAPSCAN1236S:
+ case VUEGO310S: /* WG changed */
+ po[OPT_MODE].constraint.string_list = names_310;
+ break;
+@@ -370,6 +372,7 @@
+ {
+ case SNAPSCAN310:
+ case SNAPSCAN600:
++ case SNAPSCAN1236S:
+ case VUEGO310S: /* WG changed */
+ po[OPT_PREVIEW_MODE].constraint.string_list = names_310;
+ break;
+@@ -995,6 +998,7 @@
+ {
+ case SNAPSCAN310:
+ case SNAPSCAN600:
++ case SNAPSCAN1236S:
+ case VUEGO310S: /* WG changed */
+ rgb_buf_set_diff (pss,
+ pss->buf[INQUIRY_G2R_DIFF],
+@@ -1530,6 +1534,15 @@
+ static SnapScan_Device *first_device = NULL; /* device list head */
+ static int n_devices = 0; /* the device count */
+
++static SANE_Bool
++device_already_in_list(SnapScan_Device *current, SANE_String_Const name)
++{
++ for ( ;NULL != current; current = current->pnext )
++ if (0 == strcmp(name, current->dev.name))
++ return SANE_TRUE;
++ return SANE_FALSE;
++}
++
+ static SANE_Status
+ add_device (SANE_String_Const name)
+ {
+@@ -1537,10 +1550,16 @@
+ static const char me[] = "add_device";
+ SANE_Status status;
+ SnapScan_Device *pd;
+- SnapScan_Model model_num;
++ SnapScan_Model model_num = UNKNOWN;
+ char vendor[8], model[17];
++ int i, vendor_ok = 0;
+
+- DBG (DL_CALL_TRACE, "%s\n", me);
++ DBG (DL_CALL_TRACE, "%s(%s)\n", me, name);
++
++ /* Avoid adding the same device more then once */
++ if (device_already_in_list(first_device, name)) {
++ return SANE_STATUS_GOOD;
++ }
+
+ vendor[0] = model[0] = '\0';
+
+@@ -1561,38 +1580,39 @@
+ return status;
+ }
+
+- if ((strncasecmp (vendor, SNAPSCAN_VENDOR, strlen (SNAPSCAN_VENDOR)) == 0)
+- ||
+- (strncasecmp (vendor, VUEGO_VENDOR, strlen (VUEGO_VENDOR)) == 0)) /* WG changed */
+- {
+- /* original SnapScan */
+- if (strncasecmp (model, SNAPSCAN_MODEL310,
+- strlen (SNAPSCAN_MODEL310)) == 0)
+- model_num = SNAPSCAN310;
+- else if (strncasecmp (model, SNAPSCAN_MODEL600,
+- strlen (SNAPSCAN_MODEL600)) == 0)
+- model_num = SNAPSCAN600;
+- else if (strncasecmp (model, SNAPSCAN_MODEL300,
+- strlen (SNAPSCAN_MODEL300)) == 0)
+- model_num = SNAPSCAN300;
+- else if (strncasecmp (model, VUEGO_MODEL310S, /* WG changed */
+- strlen (VUEGO_MODEL310S)) == 0)
+- model_num = VUEGO310S;
+- else
++ /* check if this is one of our supported vendors */
++ for (i = 0; i < known_vendors; i++)
++ if (0 == strncasecmp (vendor, vendors[i], strlen(vendors[i])))
++ {
++ vendor_ok = 1;
++ break;
++ }
++ if (!vendor_ok)
++ {
++ DBG (DL_MINOR_ERROR, "%s: \"%s %s\" is not an %s\n",
++ me, vendor, model,
++ "AGFA SnapScan model 300, 310, 600 and 1236s"
++ " or VUEGO model 310S"); /* WG changed */
++ sanei_scsi_close (fd);
++ return SANE_STATUS_INVAL;
++ }
++
++ /* Known vendor. Check if it is one of our supported models */
++ for (i = 0; i < known_scanners; i++)
++ {
++ if (0 == strncasecmp (model, scanners[i].scsi_name,
++ strlen(scanners[i].scsi_name)))
+ {
+- DBG (DL_INFO, "%s: sorry, model %s is not supported.\n"
+- "Currently supported models are the SnapScan 300 and 310.\n",
+- me, model);
+- sanei_scsi_close (fd);
+- return SANE_STATUS_INVAL;
++ model_num = scanners[i].id;
++ break;
+ }
+ }
+- else
++ if (UNKNOWN == model_num)
+ {
+- DBG (DL_MINOR_ERROR, "%s: \"%s %s\" is not an %s %s\n",
+- me, vendor, model,
+- SNAPSCAN_VENDOR,
+- "AGFA SnapScan model 300, 310, and 600 or VUEGO model 310S"); /* WG changed */
++ DBG (DL_INFO, "%s: sorry, model %s is not supported.\n"
++ "Currently supported models are AGFA SnapScan model 300, 310, 600\n"
++ "and 1236s and VUEGO model 310S\n",
++ me, model);
+ sanei_scsi_close (fd);
+ return SANE_STATUS_INVAL;
+ }
+@@ -1666,7 +1686,7 @@
+
+
+ SANE_Status
+-sane_snapscan_init (SANE_Int * version_code,
++sane_init (SANE_Int * version_code,
+ SANE_Auth_Callback authorize)
+ {
+ static const char me[] = "sane_snapscan_init";
+@@ -1706,10 +1726,10 @@
+ if (!fp)
+ {
+ DBG (DL_INFO,
+- "%s: configuration file not found, defaulting to /dev/scanner.\n",
+- me);
++ "%s: configuration file not found, defaulting to %s.\n",
++ me, DEFAULT_DEVICE);
+ /* default to /dev/scanner instead of insisting on config file */
+- status = add_device ("/dev/scanner");
++ status = add_device (DEFAULT_DEVICE);
+ if (status != SANE_STATUS_GOOD)
+ {
+ DBG (DL_MINOR_ERROR, "%s: failed to add device \"%s\"\n",
+@@ -1752,7 +1772,7 @@
+ }
+
+ void
+-sane_snapscan_exit (void)
++sane_exit (void)
+ {
+ DBG (DL_CALL_TRACE, "sane_snapscan_exit\n");
+
+@@ -1761,7 +1781,7 @@
+ }
+
+ SANE_Status
+-sane_snapscan_get_devices (const SANE_Device *** device_list,
++sane_get_devices (const SANE_Device *** device_list,
+ SANE_Bool local_only)
+ {
+ static const char *me = "sane_snapscan_get_devices";
+@@ -1793,7 +1813,7 @@
+ #define TMP_FILE "snapscan-tmp"
+
+ SANE_Status
+-sane_snapscan_open (SANE_String_Const name, SANE_Handle * h)
++sane_open (SANE_String_Const name, SANE_Handle * h)
+ {
+ static const char *me = "sane_snapscan_open";
+ SnapScan_Device *psd;
+@@ -1905,7 +1925,7 @@
+ }
+
+ void
+-sane_snapscan_close (SANE_Handle h)
++sane_close (SANE_Handle h)
+ {
+ SnapScan_Scanner *pss = (SnapScan_Scanner *) h;
+ DBG (DL_CALL_TRACE, "sane_snapscan_close (%p)\n", (void *) h);
+@@ -1925,7 +1945,7 @@
+ }
+
+ const SANE_Option_Descriptor *
+-sane_snapscan_get_option_descriptor (SANE_Handle h, SANE_Int n)
++sane_get_option_descriptor (SANE_Handle h, SANE_Int n)
+ {
+ DBG (DL_CALL_TRACE, "sane_snapscan_get_option_descriptor (%p, %ld)\n",
+ (void *) h, (long) n);
+@@ -1938,7 +1958,7 @@
+ }
+
+ SANE_Status
+-sane_snapscan_control_option (SANE_Handle h, SANE_Int n,
++sane_control_option (SANE_Handle h, SANE_Int n,
+ SANE_Action a, void *v,
+ SANE_Int * i)
+ {
+@@ -2621,7 +2641,7 @@
+ }
+
+ SANE_Status
+-sane_snapscan_get_parameters (SANE_Handle h,
++sane_get_parameters (SANE_Handle h,
+ SANE_Parameters * p)
+ {
+ static const char *me = "sane_snapscan_get_parameters";
+@@ -2673,6 +2693,7 @@
+ {
+ case SNAPSCAN310:
+ case SNAPSCAN600:
++ case SNAPSCAN1236S:
+ case VUEGO310S: /* WG changed */
+ if (!pss->preview)
+ {
+@@ -2699,6 +2720,7 @@
+ {
+ case SNAPSCAN310:
+ case SNAPSCAN600:
++ case SNAPSCAN1236S:
+ case VUEGO310S: /* WG changed */
+ pss->lines += line_offset;
+ p->lines -= line_offset;
+@@ -2960,7 +2982,7 @@
+ }
+
+ SANE_Status
+-sane_snapscan_start (SANE_Handle h)
++sane_start (SANE_Handle h)
+ {
+ static const char *me = "sane_snapscan_start";
+ SANE_Status status;
+@@ -3114,6 +3136,7 @@
+ {
+ case SNAPSCAN310:
+ case SNAPSCAN600:
++ case SNAPSCAN1236S:
+ case VUEGO310S: /* WG changed */
+ if (SANE_STATUS_GOOD != rgb_buf_init (pss))
+ return SANE_STATUS_NO_MEM;
+@@ -3134,6 +3157,7 @@
+ {
+ case SNAPSCAN310:
+ case SNAPSCAN600:
++ case SNAPSCAN1236S:
+ case VUEGO310S: /* WG changed */
+ rgb_buf_clean (pss);
+ break;
+@@ -3153,6 +3177,7 @@
+ {
+ case SNAPSCAN310:
+ case SNAPSCAN600:
++ case SNAPSCAN1236S:
+ case VUEGO310S: /* WG changed */
+ transfer_data_diff (other_buf, pss);
+ break;
+@@ -3186,6 +3211,7 @@
+ {
+ case SNAPSCAN310:
+ case SNAPSCAN600:
++ case SNAPSCAN1236S:
+ case VUEGO310S: /* WG changed */
+ rgb_buf_clean (pss);
+ break;
+@@ -3231,13 +3257,14 @@
+ pss->bytes_per_line / pss->ms_per_line);
+
+ /* allocate and initialize rgb ring buffer if the device is
+- a snapscan 310 or 600 model, in colour mode */
++ a snapscan 310, 600 or 1236s model, in colour mode */
+ if (colour)
+ {
+ switch (pss->pdev->model)
+ {
+ case SNAPSCAN310:
+ case SNAPSCAN600:
++ case SNAPSCAN1236S:
+ case VUEGO310S: /* WG changed */
+ rgb_buf_init (pss);
+ break;
+@@ -3268,7 +3295,7 @@
+
+
+ SANE_Status
+-sane_snapscan_read (SANE_Handle h, SANE_Byte * buf,
++sane_read (SANE_Handle h, SANE_Byte * buf,
+ SANE_Int maxlen, SANE_Int * plen)
+ {
+ static const char *me = "sane_snapscan_read";
+@@ -3279,6 +3306,8 @@
+ DBG (DL_CALL_TRACE, "%s (%p, %p, %ld, %p)\n",
+ me, (void *) h, (void *) buf, (long) maxlen, (void *) plen);
+
++ *plen = 0;
++
+ if (!pss->expected_data_len)
+ {
+ if (pss->child > 0)
+@@ -3292,8 +3321,6 @@
+ return SANE_STATUS_EOF;
+ }
+
+- *plen = 0;
+-
+ if (pss->preview)
+ mode = pss->preview_mode;
+
+@@ -3413,6 +3440,7 @@
+ {
+ case SNAPSCAN310:
+ case SNAPSCAN600:
++ case SNAPSCAN1236S:
+ case VUEGO310S: /* WG changed */
+ transferred_bytes = transfer_data_diff (buf, pss);
+ break;
+@@ -3466,7 +3494,7 @@
+ }
+
+ void
+-sane_snapscan_cancel (SANE_Handle h)
++sane_cancel (SANE_Handle h)
+ {
+ char *me = "sane_snapscan_cancel";
+ SnapScan_Scanner *pss = (SnapScan_Scanner *) h;
+@@ -3486,6 +3514,7 @@
+ {
+ case SNAPSCAN310:
+ case SNAPSCAN600:
++ case SNAPSCAN1236S:
+ case VUEGO310S: /* WG changed */
+ rgb_buf_clean (pss);
+ break;
+@@ -3506,7 +3535,7 @@
+ }
+
+ SANE_Status
+-sane_snapscan_set_io_mode (SANE_Handle h, SANE_Bool m)
++sane_set_io_mode (SANE_Handle h, SANE_Bool m)
+ {
+ static char me[] = "sane_snapscan_set_io_mode";
+ SnapScan_Scanner *pss = (SnapScan_Scanner *) h;
+@@ -3541,7 +3570,7 @@
+ }
+
+ SANE_Status
+-sane_snapscan_get_select_fd (SANE_Handle h, SANE_Int * fd)
++sane_get_select_fd (SANE_Handle h, SANE_Int * fd)
+ {
+ static char me[] = "sane_snapscan_get_select_fd";
+ SnapScan_Scanner *pss = (SnapScan_Scanner *) h;
+diff -ru sane-pre1.01-4/backend/snapscan.desc sane-pre1.01-4-pere/backend/snapscan.desc
+--- sane-pre1.01-4/backend/snapscan.desc Mon Sep 7 09:28:57 1998
++++ sane-pre1.01-4-pere/backend/snapscan.desc Sun Apr 4 18:44:11 1999
+@@ -28,6 +28,8 @@
+ :comment "Ditto"
+ :model "SnapScan 600"
+ :comment "Ditto"
++:model "SnapScan 1236s"
++:comment "Ditto"
+ :mfg "Vuego"
+ :model "310S"
+ :comment "Close SnapScan 310 compatible."
+diff -ru sane-pre1.01-4/backend/snapscan.h sane-pre1.01-4-pere/backend/snapscan.h
+--- sane-pre1.01-4/backend/snapscan.h Sun Feb 28 00:59:10 1999
++++ sane-pre1.01-4-pere/backend/snapscan.h Sun Apr 4 18:45:44 1999
+@@ -54,22 +54,41 @@
+ /* snapscan device field values */
+
+ #define SNAPSCAN_NAME "/dev/sga"
+-#define SNAPSCAN_VENDOR "AGFA"
+-#define VUEGO_VENDOR "COLOR"
+-#define SNAPSCAN_MODEL300 "SnapScan"
+-#define SNAPSCAN_MODEL310 "SNAPSCAN 310"
+-#define VUEGO_MODEL310S "FlatbedScanner_4"
+-#define SNAPSCAN_MODEL600 "SNAPSCAN 600"
+ #define SNAPSCAN_TYPE "flatbed scanner"
+ /*#define INOPERATIVE*/
+
+ typedef enum
+ {
++ UNKNOWN,
+ SNAPSCAN300, /* the original SnapScan or SnapScan 300 */
+ SNAPSCAN310, /* the SnapScan 310 */
+ SNAPSCAN600, /* the SnapScan 600 */
++ SNAPSCAN1236S, /* the SnapScan 1236s */
+ VUEGO310S /* Vuego-Version of SnapScan 310 WG changed */
+ } SnapScan_Model;
++
++struct SnapScan_Model_desc
++{
++ char *scsi_name;
++ SnapScan_Model id;
++};
++
++static struct SnapScan_Model_desc scanners[] =
++{
++ { "FlatbedScanner_4", VUEGO310S },
++ { "SNAPSCAN 1236s", SNAPSCAN1236S },
++ { "SNAPSCAN 310", SNAPSCAN310 },
++ { "SNAPSCAN 600", SNAPSCAN600 },
++ { "SnapScan", SNAPSCAN300 },
++};
++#define known_scanners (sizeof(scanners)/sizeof(struct SnapScan_Model_desc))
++
++static char *vendors[] =
++{
++ "AGFA",
++ "COLOR",
++};
++#define known_vendors (sizeof(vendors)/sizeof(char*))
+
+ typedef enum
+ {
--- /dev/null
+diff -ru sane-pre1.01-4/ChangeLog sane-pre1.01-4-pere/ChangeLog
+--- sane-pre1.01-4/ChangeLog Tue Apr 6 19:27:56 1999
++++ sane-pre1.01-4-pere/ChangeLog Tue Apr 6 20:00:21 1999
+@@ -1,3 +1,25 @@
++1999-04-06 Petter Reinholdtsen <pere@td.org.uit.no>
++ * backend/snapscan.c (sane_exit sane_get_devices): Removed memory
++ leak.
++ (sane_open): Give more sensible error message when unable to open
++ temp file. Open temp file in /var/tmp, not in current directory.
++ (mini_inquiry add_device): Make sure to only match listed models.
++ Earlier, substrings would also match.
++
++1999-04-04 Petter Reinholdtsen <pere@td.org.uit.no>
++ * backend/snapscan.c (sane_snapscan_*): Changed API entries from
++ sane_snapscan_* to sane_*.
++
++1999-03-10 Petter Reinholdtsen <pere@td.org.uit.no>
++ * backend/snapscan.c (add_device init_options inquiry
++ sane_snapscan_get_parameters sane_snapscan_start
++ sane_snapscan_set_io_mode sane_snapscan_read) backend/snapscan.h
++ backend/snapscan.desc: Rewrote scanner detection code to loop over
++ array of supported SCSI names. Added AGFA SnapScan 1236s support.
++ It seems to be compatible with SnapScan 600.
++ Make sure to not add the same device more then once to the device
++ list. Bugfix in sane_snapscan_read() triggered on EOF.
++
+ 1999-04-03 David Mosberger-Tang <David.Mosberger@acm.org>
+
+ * include/sane/sanei_debug.h: Define sanei_debug_BACKEND_NAME only
+diff -ru sane-pre1.01-4/backend/snapscan.desc sane-pre1.01-4-pere/backend/snapscan.desc
+--- sane-pre1.01-4/backend/snapscan.desc Tue Apr 6 19:27:45 1999
++++ sane-pre1.01-4-pere/backend/snapscan.desc Sun Apr 4 18:44:11 1999
+@@ -28,6 +28,8 @@
+ :comment "Ditto"
+ :model "SnapScan 600"
+ :comment "Ditto"
++:model "SnapScan 1236s"
++:comment "Ditto"
+ :mfg "Vuego"
+ :model "310S"
+ :comment "Close SnapScan 310 compatible."
+diff -ru sane-pre1.01-4/backend/snapscan.h sane-pre1.01-4-pere/backend/snapscan.h
+--- sane-pre1.01-4/backend/snapscan.h Tue Apr 6 19:27:41 1999
++++ sane-pre1.01-4-pere/backend/snapscan.h Tue Apr 6 20:18:03 1999
+@@ -53,23 +53,45 @@
+
+ /* snapscan device field values */
+
+-#define SNAPSCAN_NAME "/dev/sga"
+-#define SNAPSCAN_VENDOR "AGFA"
+-#define VUEGO_VENDOR "COLOR"
+-#define SNAPSCAN_MODEL300 "SnapScan"
+-#define SNAPSCAN_MODEL310 "SNAPSCAN 310"
+-#define VUEGO_MODEL310S "FlatbedScanner_4"
+-#define SNAPSCAN_MODEL600 "SNAPSCAN 600"
++#define DEFAULT_DEVICE "/dev/scanner" /* Check this if config is missing */
+ #define SNAPSCAN_TYPE "flatbed scanner"
+ /*#define INOPERATIVE*/
++#define TMP_FILE_PREFIX "/var/tmp/snapscan"
+
+ typedef enum
+ {
++ UNKNOWN,
+ SNAPSCAN300, /* the original SnapScan or SnapScan 300 */
+ SNAPSCAN310, /* the SnapScan 310 */
+ SNAPSCAN600, /* the SnapScan 600 */
++ SNAPSCAN1236S, /* the SnapScan 1236s */
+ VUEGO310S /* Vuego-Version of SnapScan 310 WG changed */
+ } SnapScan_Model;
++
++struct SnapScan_Model_desc
++{
++ char *scsi_name;
++ SnapScan_Model id;
++};
++
++static struct SnapScan_Model_desc scanners[] =
++{
++ /* SCSI model name -> enum value */
++ { "FlatbedScanner_4", VUEGO310S },
++ { "SNAPSCAN 1236", SNAPSCAN1236S },
++ { "SNAPSCAN 310", SNAPSCAN310 },
++ { "SNAPSCAN 600", SNAPSCAN600 },
++ { "SnapScan", SNAPSCAN300 },
++};
++#define known_scanners (sizeof(scanners)/sizeof(scanners[0]))
++
++static char *vendors[] =
++{
++ /* SCSI Vendor name */
++ "AGFA",
++ "COLOR",
++};
++#define known_vendors (sizeof(vendors)/sizeof(vendors[0]))
+
+ typedef enum
+ {
+diff -ru sane-pre1.01-4/backend/snapscan.c sane-pre1.01-4-pere/backend/snapscan.c
+--- sane-pre1.01-4/backend/snapscan.c Tue Apr 6 19:27:40 1999
++++ sane-pre1.01-4-pere/backend/snapscan.c Tue Apr 6 20:23:07 1999
+@@ -161,7 +161,6 @@
+ #define DEFAULT_BRX (x_range.max)
+ #define DEFAULT_BRY (y_range.max)
+
+-
+ #ifdef INOPERATIVE
+ static const SANE_Range percent_range =
+ {
+@@ -339,6 +338,7 @@
+ {
+ case SNAPSCAN310:
+ case SNAPSCAN600:
++ case SNAPSCAN1236S:
+ case VUEGO310S: /* WG changed */
+ po[OPT_MODE].constraint.string_list = names_310;
+ break;
+@@ -370,6 +370,7 @@
+ {
+ case SNAPSCAN310:
+ case SNAPSCAN600:
++ case SNAPSCAN1236S:
+ case VUEGO310S: /* WG changed */
+ po[OPT_PREVIEW_MODE].constraint.string_list = names_310;
+ break;
+@@ -888,6 +889,19 @@
+ pc[3] = (0x000000ff & x);
+ }
+
++/* Convert 'STRING ' to 'STRING' by adding 0 after last non-space */
++static void
++remove_trailing_space(char *s)
++{
++ int position;
++
++ if (NULL == s)
++ return;
++
++ for (position = strlen(s); position > 0 && ' ' == s[position-1];
++ position--);
++ s[position] = 0;
++}
+
+ #define INQUIRY_LEN 6
+ #define INQUIRY_RET_LEN 120
+@@ -936,6 +950,9 @@
+ memcpy (model, data + 16, 16);
+ model[16] = 0;
+
++ remove_trailing_space(vendor);
++ remove_trailing_space(model);
++
+ return SANE_STATUS_GOOD;
+ }
+
+@@ -995,6 +1012,7 @@
+ {
+ case SNAPSCAN310:
+ case SNAPSCAN600:
++ case SNAPSCAN1236S:
+ case VUEGO310S: /* WG changed */
+ rgb_buf_set_diff (pss,
+ pss->buf[INQUIRY_G2R_DIFF],
+@@ -1523,13 +1541,23 @@
+ /*----- global data structures and access utilities -----*/
+
+
+-/* for now, we support only one possible device, a SnapScan on /dev/sga */
+-
+ /* available device list */
+
+ static SnapScan_Device *first_device = NULL; /* device list head */
+ static int n_devices = 0; /* the device count */
+
++/* list returned from sane_get_devices() */
++static const SANE_Device **get_devices_list = NULL;
++
++static SANE_Bool
++device_already_in_list(SnapScan_Device *current, SANE_String_Const name)
++{
++ for ( ;NULL != current; current = current->pnext )
++ if (0 == strcmp(name, current->dev.name))
++ return SANE_TRUE;
++ return SANE_FALSE;
++}
++
+ static SANE_Status
+ add_device (SANE_String_Const name)
+ {
+@@ -1537,10 +1565,16 @@
+ static const char me[] = "add_device";
+ SANE_Status status;
+ SnapScan_Device *pd;
+- SnapScan_Model model_num;
++ SnapScan_Model model_num = UNKNOWN;
++ int i, supported_vendor = 0;
+ char vendor[8], model[17];
+
+- DBG (DL_CALL_TRACE, "%s\n", me);
++ DBG (DL_CALL_TRACE, "%s(%s)\n", me, name);
++
++ /* Avoid adding the same device more then once */
++ if (device_already_in_list(first_device, name)) {
++ return SANE_STATUS_GOOD;
++ }
+
+ vendor[0] = model[0] = '\0';
+
+@@ -1561,38 +1595,41 @@
+ return status;
+ }
+
+- if ((strncasecmp (vendor, SNAPSCAN_VENDOR, strlen (SNAPSCAN_VENDOR)) == 0)
+- ||
+- (strncasecmp (vendor, VUEGO_VENDOR, strlen (VUEGO_VENDOR)) == 0)) /* WG changed */
+- {
+- /* original SnapScan */
+- if (strncasecmp (model, SNAPSCAN_MODEL310,
+- strlen (SNAPSCAN_MODEL310)) == 0)
+- model_num = SNAPSCAN310;
+- else if (strncasecmp (model, SNAPSCAN_MODEL600,
+- strlen (SNAPSCAN_MODEL600)) == 0)
+- model_num = SNAPSCAN600;
+- else if (strncasecmp (model, SNAPSCAN_MODEL300,
+- strlen (SNAPSCAN_MODEL300)) == 0)
+- model_num = SNAPSCAN300;
+- else if (strncasecmp (model, VUEGO_MODEL310S, /* WG changed */
+- strlen (VUEGO_MODEL310S)) == 0)
+- model_num = VUEGO310S;
+- else
++ DBG (DL_VERBOSE, "%s: Is vendor \"%s\" model \"%s\" a supported scanner?\n",
++ me, vendor, model);
++
++ /* check if this is one of our supported vendors */
++ for (i = 0; i < known_vendors; i++)
++ if (0 == strcasecmp (vendor, vendors[i]))
++ {
++ supported_vendor = 1;
++ break;
++ }
++ if (!supported_vendor)
++ {
++ DBG (DL_MINOR_ERROR, "%s: \"%s %s\" is not an %s\n",
++ me, vendor, model,
++ "AGFA SnapScan model 300, 310, 600 and 1236s"
++ " or VUEGO model 310S"); /* WG changed */
++ sanei_scsi_close (fd);
++ return SANE_STATUS_INVAL;
++ }
++
++ /* Known vendor. Check if it is one of our supported models */
++ for (i = 0; i < known_scanners; i++)
++ {
++ if (0 == strcasecmp (model, scanners[i].scsi_name))
+ {
+- DBG (DL_INFO, "%s: sorry, model %s is not supported.\n"
+- "Currently supported models are the SnapScan 300 and 310.\n",
+- me, model);
+- sanei_scsi_close (fd);
+- return SANE_STATUS_INVAL;
++ model_num = scanners[i].id;
++ break;
+ }
+ }
+- else
++ if (UNKNOWN == model_num)
+ {
+- DBG (DL_MINOR_ERROR, "%s: \"%s %s\" is not an %s %s\n",
+- me, vendor, model,
+- SNAPSCAN_VENDOR,
+- "AGFA SnapScan model 300, 310, and 600 or VUEGO model 310S"); /* WG changed */
++ DBG (DL_INFO, "%s: sorry, model %s is not supported.\n"
++ "Currently supported models are AGFA SnapScan model 300, 310, 600\n"
++ "and 1236s and VUEGO model 310S\n",
++ me, model);
+ sanei_scsi_close (fd);
+ return SANE_STATUS_INVAL;
+ }
+@@ -1666,7 +1703,7 @@
+
+
+ SANE_Status
+-sane_snapscan_init (SANE_Int * version_code,
++sane_init (SANE_Int * version_code,
+ SANE_Auth_Callback authorize)
+ {
+ static const char me[] = "sane_snapscan_init";
+@@ -1705,11 +1742,11 @@
+ fp = sanei_config_open (SNAPSCAN_CONFIG_FILE);
+ if (!fp)
+ {
++ /* default to DEFAULT_DEVICE instead of insisting on config file */
+ DBG (DL_INFO,
+- "%s: configuration file not found, defaulting to /dev/scanner.\n",
+- me);
+- /* default to /dev/scanner instead of insisting on config file */
+- status = add_device ("/dev/scanner");
++ "%s: configuration file not found, defaulting to %s.\n",
++ me, DEFAULT_DEVICE);
++ status = add_device (DEFAULT_DEVICE);
+ if (status != SANE_STATUS_GOOD)
+ {
+ DBG (DL_MINOR_ERROR, "%s: failed to add device \"%s\"\n",
+@@ -1752,22 +1789,30 @@
+ }
+
+ void
+-sane_snapscan_exit (void)
++sane_exit (void)
+ {
+ DBG (DL_CALL_TRACE, "sane_snapscan_exit\n");
+
++ if (NULL != get_devices_list)
++ free(get_devices_list);
++ get_devices_list = NULL;
++
+ /* just for safety, reset things to known values */
+ auth = NULL;
+ }
+
+ SANE_Status
+-sane_snapscan_get_devices (const SANE_Device *** device_list,
++sane_get_devices (const SANE_Device *** device_list,
+ SANE_Bool local_only)
+ {
+ static const char *me = "sane_snapscan_get_devices";
+ DBG (DL_CALL_TRACE, "%s (%p, %ld)\n", me, (void *) device_list,
+ (long) local_only);
+
++ /* Waste the last list returned from this function */
++ if (NULL != get_devices_list)
++ free(get_devices_list);
++
+ *device_list = (const SANE_Device **)
+ malloc ((n_devices + 1) * sizeof (SANE_Device *));
+
+@@ -1787,13 +1832,13 @@
+ return SANE_STATUS_NO_MEM;
+ }
+
++ get_devices_list = *device_list;
++
+ return SANE_STATUS_GOOD;
+ }
+
+-#define TMP_FILE "snapscan-tmp"
+-
+ SANE_Status
+-sane_snapscan_open (SANE_String_Const name, SANE_Handle * h)
++sane_open (SANE_String_Const name, SANE_Handle * h)
+ {
+ static const char *me = "sane_snapscan_open";
+ SnapScan_Device *psd;
+@@ -1842,11 +1887,13 @@
+ /* temp file name and the temp file */
+ {
+ char tname[128];
+- sprintf (tname, TMP_FILE "-%p", (void *) pss);
++ snprintf (tname, sizeof(tname), TMP_FILE_PREFIX "-%p", (void *) pss);
+ if ((pss->tfd = open (tname, O_CREAT | O_RDWR | O_TRUNC, 0600)) == -1)
+ {
+- DBG (DL_MAJOR_ERROR, "%s: can't open temp file %s\n", me, tname);
+- perror ("File error: ");
++ char str[200];
++ snprintf(str, sizeof(str), "Can't open temp file %s", tname);
++ DBG (DL_MAJOR_ERROR, "%s: %s\n", me, str);
++ perror (str);
+ free (*h);
+ return SANE_STATUS_ACCESS_DENIED;
+ }
+@@ -1905,7 +1952,7 @@
+ }
+
+ void
+-sane_snapscan_close (SANE_Handle h)
++sane_close (SANE_Handle h)
+ {
+ SnapScan_Scanner *pss = (SnapScan_Scanner *) h;
+ DBG (DL_CALL_TRACE, "sane_snapscan_close (%p)\n", (void *) h);
+@@ -1925,7 +1972,7 @@
+ }
+
+ const SANE_Option_Descriptor *
+-sane_snapscan_get_option_descriptor (SANE_Handle h, SANE_Int n)
++sane_get_option_descriptor (SANE_Handle h, SANE_Int n)
+ {
+ DBG (DL_CALL_TRACE, "sane_snapscan_get_option_descriptor (%p, %ld)\n",
+ (void *) h, (long) n);
+@@ -1938,7 +1985,7 @@
+ }
+
+ SANE_Status
+-sane_snapscan_control_option (SANE_Handle h, SANE_Int n,
++sane_control_option (SANE_Handle h, SANE_Int n,
+ SANE_Action a, void *v,
+ SANE_Int * i)
+ {
+@@ -2621,7 +2668,7 @@
+ }
+
+ SANE_Status
+-sane_snapscan_get_parameters (SANE_Handle h,
++sane_get_parameters (SANE_Handle h,
+ SANE_Parameters * p)
+ {
+ static const char *me = "sane_snapscan_get_parameters";
+@@ -2673,6 +2720,7 @@
+ {
+ case SNAPSCAN310:
+ case SNAPSCAN600:
++ case SNAPSCAN1236S:
+ case VUEGO310S: /* WG changed */
+ if (!pss->preview)
+ {
+@@ -2699,6 +2747,7 @@
+ {
+ case SNAPSCAN310:
+ case SNAPSCAN600:
++ case SNAPSCAN1236S:
+ case VUEGO310S: /* WG changed */
+ pss->lines += line_offset;
+ p->lines -= line_offset;
+@@ -2960,7 +3009,7 @@
+ }
+
+ SANE_Status
+-sane_snapscan_start (SANE_Handle h)
++sane_start (SANE_Handle h)
+ {
+ static const char *me = "sane_snapscan_start";
+ SANE_Status status;
+@@ -3114,6 +3163,7 @@
+ {
+ case SNAPSCAN310:
+ case SNAPSCAN600:
++ case SNAPSCAN1236S:
+ case VUEGO310S: /* WG changed */
+ if (SANE_STATUS_GOOD != rgb_buf_init (pss))
+ return SANE_STATUS_NO_MEM;
+@@ -3134,6 +3184,7 @@
+ {
+ case SNAPSCAN310:
+ case SNAPSCAN600:
++ case SNAPSCAN1236S:
+ case VUEGO310S: /* WG changed */
+ rgb_buf_clean (pss);
+ break;
+@@ -3153,6 +3204,7 @@
+ {
+ case SNAPSCAN310:
+ case SNAPSCAN600:
++ case SNAPSCAN1236S:
+ case VUEGO310S: /* WG changed */
+ transfer_data_diff (other_buf, pss);
+ break;
+@@ -3186,6 +3238,7 @@
+ {
+ case SNAPSCAN310:
+ case SNAPSCAN600:
++ case SNAPSCAN1236S:
+ case VUEGO310S: /* WG changed */
+ rgb_buf_clean (pss);
+ break;
+@@ -3231,13 +3284,14 @@
+ pss->bytes_per_line / pss->ms_per_line);
+
+ /* allocate and initialize rgb ring buffer if the device is
+- a snapscan 310 or 600 model, in colour mode */
++ a snapscan 310, 600 or 1236s model, in colour mode */
+ if (colour)
+ {
+ switch (pss->pdev->model)
+ {
+ case SNAPSCAN310:
+ case SNAPSCAN600:
++ case SNAPSCAN1236S:
+ case VUEGO310S: /* WG changed */
+ rgb_buf_init (pss);
+ break;
+@@ -3268,7 +3322,7 @@
+
+
+ SANE_Status
+-sane_snapscan_read (SANE_Handle h, SANE_Byte * buf,
++sane_read (SANE_Handle h, SANE_Byte * buf,
+ SANE_Int maxlen, SANE_Int * plen)
+ {
+ static const char *me = "sane_snapscan_read";
+@@ -3279,6 +3333,8 @@
+ DBG (DL_CALL_TRACE, "%s (%p, %p, %ld, %p)\n",
+ me, (void *) h, (void *) buf, (long) maxlen, (void *) plen);
+
++ *plen = 0;
++
+ if (!pss->expected_data_len)
+ {
+ if (pss->child > 0)
+@@ -3292,8 +3348,6 @@
+ return SANE_STATUS_EOF;
+ }
+
+- *plen = 0;
+-
+ if (pss->preview)
+ mode = pss->preview_mode;
+
+@@ -3302,13 +3356,15 @@
+ maxlen /= 8;
+
+ /* reset maxlen to a scan line boundary */
++ /* XXX Why is this here? The non-blocking client should have no
++ buffer limits */
+ maxlen = (maxlen / pss->bytes_per_line) * pss->bytes_per_line;
+
+ /* expected data per read is the minimum of the scanner effective
+ buffer length , the frontend effective buffer length, and the
+ total remaining data in the scan */
+- pss->expected_read_bytes = MIN (pss->buf_sz, pss->expected_data_len);
+- pss->expected_read_bytes = MIN (maxlen, pss->expected_read_bytes);
++ pss->expected_read_bytes =
++ MIN (MIN (pss->buf_sz, maxlen), pss->expected_data_len);
+
+ /* since a cancellation happens asynchronously, it seems in practice
+ that we need to check for cancellation both before and after IO
+@@ -3413,6 +3469,7 @@
+ {
+ case SNAPSCAN310:
+ case SNAPSCAN600:
++ case SNAPSCAN1236S:
+ case VUEGO310S: /* WG changed */
+ transferred_bytes = transfer_data_diff (buf, pss);
+ break;
+@@ -3466,7 +3523,7 @@
+ }
+
+ void
+-sane_snapscan_cancel (SANE_Handle h)
++sane_cancel (SANE_Handle h)
+ {
+ char *me = "sane_snapscan_cancel";
+ SnapScan_Scanner *pss = (SnapScan_Scanner *) h;
+@@ -3486,6 +3543,7 @@
+ {
+ case SNAPSCAN310:
+ case SNAPSCAN600:
++ case SNAPSCAN1236S:
+ case VUEGO310S: /* WG changed */
+ rgb_buf_clean (pss);
+ break;
+@@ -3506,7 +3564,7 @@
+ }
+
+ SANE_Status
+-sane_snapscan_set_io_mode (SANE_Handle h, SANE_Bool m)
++sane_set_io_mode (SANE_Handle h, SANE_Bool m)
+ {
+ static char me[] = "sane_snapscan_set_io_mode";
+ SnapScan_Scanner *pss = (SnapScan_Scanner *) h;
+@@ -3541,7 +3599,7 @@
+ }
+
+ SANE_Status
+-sane_snapscan_get_select_fd (SANE_Handle h, SANE_Int * fd)
++sane_get_select_fd (SANE_Handle h, SANE_Int * fd)
+ {
+ static char me[] = "sane_snapscan_get_select_fd";
+ SnapScan_Scanner *pss = (SnapScan_Scanner *) h;
--- /dev/null
+diff -ru /store/store/joseph/sane/src-pre1.01r3/ChangeLog src-pre1.01r3-allarchs/ChangeLog
+--- /store/store/joseph/sane/src-pre1.01r3/ChangeLog Fri Mar 5 07:20:00 1999
++++ src-pre1.01r3-allarchs/ChangeLog Wed Mar 10 22:12:55 1999
+@@ -1,3 +1,12 @@
++1999-03-10 Petter Reinholdtsen <pere@td.org.uit.no>
++
++ * backend/snapscan.c (add_device init_options inquiry
++ sane_snapscan_get_parameters sane_snapscan_start
++ sane_snapscan_set_io_mode) backend/snapscan.h
++ backend/snapscan.desc: Rewrote scanner detection code to loop over
++ array of supported SCSI names. Added AGFA SnapScan 1236 support.
++ It seems to be compatible with SnapScan 600.
++
+ 1999-03-04 David Mosberger-Tang <David.Mosberger@acm.org>
+
+ * backend/canon.c (adjust_hilo_points): Print values of type
+diff -ru /store/store/joseph/sane/src-pre1.01r3/backend/snapscan.c src-pre1.01r3-allarchs/backend/snapscan.c
+--- /store/store/joseph/sane/src-pre1.01r3/backend/snapscan.c Sun Feb 28 21:34:05 1999
++++ src-pre1.01r3-allarchs/backend/snapscan.c Wed Mar 10 22:17:56 1999
+@@ -276,7 +276,9 @@
+ break;
+
+ case SNAPSCAN600:
+- DBG (DL_MINOR_INFO, "600 dpi mode untested on SnapScan 600\nPlease report bugs\n");
++ case SNAPSCAN1236:
++ DBG (DL_MINOR_INFO, "600 dpi mode untested on SnapScan 600 and 1236\n"
++ "Please report bugs\n");
+ default:
+ po[OPT_SCANRES].constraint.word_list = resolutions_300;
+ break;
+@@ -339,6 +341,7 @@
+ {
+ case SNAPSCAN310:
+ case SNAPSCAN600:
++ case SNAPSCAN1236:
+ case VUEGO310S: /* WG changed */
+ po[OPT_MODE].constraint.string_list = names_310;
+ break;
+@@ -370,6 +373,7 @@
+ {
+ case SNAPSCAN310:
+ case SNAPSCAN600:
++ case SNAPSCAN1236:
+ case VUEGO310S: /* WG changed */
+ po[OPT_PREVIEW_MODE].constraint.string_list = names_310;
+ break;
+@@ -995,6 +999,7 @@
+ {
+ case SNAPSCAN310:
+ case SNAPSCAN600:
++ case SNAPSCAN1236:
+ case VUEGO310S: /* WG changed */
+ rgb_buf_set_diff (pss,
+ pss->buf[INQUIRY_G2R_DIFF],
+@@ -1537,8 +1542,9 @@
+ static const char me[] = "add_device";
+ SANE_Status status;
+ SnapScan_Device *pd;
+- SnapScan_Model model_num;
++ SnapScan_Model model_num = UNKNOWN;
+ char vendor[8], model[17];
++ int i, vendor_ok = 0;
+
+ DBG (DL_CALL_TRACE, "%s\n", me);
+
+@@ -1561,38 +1567,38 @@
+ return status;
+ }
+
+- if ((strncasecmp (vendor, SNAPSCAN_VENDOR, strlen (SNAPSCAN_VENDOR)) == 0)
+- ||
+- (strncasecmp (vendor, VUEGO_VENDOR, strlen (VUEGO_VENDOR)) == 0)) /* WG changed */
+- {
+- /* original SnapScan */
+- if (strncasecmp (model, SNAPSCAN_MODEL310,
+- strlen (SNAPSCAN_MODEL310)) == 0)
+- model_num = SNAPSCAN310;
+- else if (strncasecmp (model, SNAPSCAN_MODEL600,
+- strlen (SNAPSCAN_MODEL600)) == 0)
+- model_num = SNAPSCAN600;
+- else if (strncasecmp (model, SNAPSCAN_MODEL300,
+- strlen (SNAPSCAN_MODEL300)) == 0)
+- model_num = SNAPSCAN300;
+- else if (strncasecmp (model, VUEGO_MODEL310S, /* WG changed */
+- strlen (VUEGO_MODEL310S)) == 0)
+- model_num = VUEGO310S;
+- else
++ /* check if this is one of our supported vendors */
++ for (i = 0; i < known_vendors; i++)
++ if (0 == strncasecmp (vendor, vendors[i], strlen(vendors[i])))
++ {
++ vendor_ok = 1;
++ break;
++ }
++ if (!vendor_ok)
++ {
++ DBG (DL_MINOR_ERROR, "%s: \"%s %s\" is not an %s\n",
++ me, vendor, model,
++ "AGFA SnapScan model 300, 310, 600 and 1236"
++ " or VUEGO model 310S"); /* WG changed */
++ sanei_scsi_close (fd);
++ return SANE_STATUS_INVAL;
++ }
++
++ /* Known vendor. Check if it is one of our supported models */
++ for (i = 0; i < known_scanners; i++)
++ {
++ if (0 == strncasecmp (model, scanners[i].scsi_name,
++ strlen(scanners[i].scsi_name)))
+ {
+- DBG (DL_INFO, "%s: sorry, model %s is not supported.\n"
+- "Currently supported models are the SnapScan 300 and 310.\n",
+- me, model);
+- sanei_scsi_close (fd);
+- return SANE_STATUS_INVAL;
++ model_num = scanners[i].id;
++ break;
+ }
+ }
+- else
++ if (UNKNOWN == model_num)
+ {
+- DBG (DL_MINOR_ERROR, "%s: \"%s %s\" is not an %s %s\n",
+- me, vendor, model,
+- SNAPSCAN_VENDOR,
+- "AGFA SnapScan model 300, 310, and 600 or VUEGO model 310S"); /* WG changed */
++ DBG (DL_INFO, "%s: sorry, model %s is not supported.\n"
++ "Currently supported models are the SnapScan 300 and 310.\n",
++ me, model);
+ sanei_scsi_close (fd);
+ return SANE_STATUS_INVAL;
+ }
+@@ -2673,6 +2679,7 @@
+ {
+ case SNAPSCAN310:
+ case SNAPSCAN600:
++ case SNAPSCAN1236:
+ case VUEGO310S: /* WG changed */
+ if (!pss->preview)
+ {
+@@ -2699,6 +2706,7 @@
+ {
+ case SNAPSCAN310:
+ case SNAPSCAN600:
++ case SNAPSCAN1236:
+ case VUEGO310S: /* WG changed */
+ pss->lines += line_offset;
+ p->lines -= line_offset;
+@@ -3114,6 +3122,7 @@
+ {
+ case SNAPSCAN310:
+ case SNAPSCAN600:
++ case SNAPSCAN1236:
+ case VUEGO310S: /* WG changed */
+ if (SANE_STATUS_GOOD != rgb_buf_init (pss))
+ return SANE_STATUS_NO_MEM;
+@@ -3134,6 +3143,7 @@
+ {
+ case SNAPSCAN310:
+ case SNAPSCAN600:
++ case SNAPSCAN1236:
+ case VUEGO310S: /* WG changed */
+ rgb_buf_clean (pss);
+ break;
+@@ -3153,6 +3163,7 @@
+ {
+ case SNAPSCAN310:
+ case SNAPSCAN600:
++ case SNAPSCAN1236:
+ case VUEGO310S: /* WG changed */
+ transfer_data_diff (other_buf, pss);
+ break;
+@@ -3186,6 +3197,7 @@
+ {
+ case SNAPSCAN310:
+ case SNAPSCAN600:
++ case SNAPSCAN1236:
+ case VUEGO310S: /* WG changed */
+ rgb_buf_clean (pss);
+ break;
+@@ -3231,13 +3243,14 @@
+ pss->bytes_per_line / pss->ms_per_line);
+
+ /* allocate and initialize rgb ring buffer if the device is
+- a snapscan 310 or 600 model, in colour mode */
++ a snapscan 310, 600 or 1236 model, in colour mode */
+ if (colour)
+ {
+ switch (pss->pdev->model)
+ {
+ case SNAPSCAN310:
+ case SNAPSCAN600:
++ case SNAPSCAN1236:
+ case VUEGO310S: /* WG changed */
+ rgb_buf_init (pss);
+ break;
+@@ -3413,6 +3426,7 @@
+ {
+ case SNAPSCAN310:
+ case SNAPSCAN600:
++ case SNAPSCAN1236:
+ case VUEGO310S: /* WG changed */
+ transferred_bytes = transfer_data_diff (buf, pss);
+ break;
+@@ -3486,6 +3500,7 @@
+ {
+ case SNAPSCAN310:
+ case SNAPSCAN600:
++ case SNAPSCAN1236:
+ case VUEGO310S: /* WG changed */
+ rgb_buf_clean (pss);
+ break;
+diff -ru /store/store/joseph/sane/src-pre1.01r3/backend/snapscan.desc src-pre1.01r3-allarchs/backend/snapscan.desc
+--- /store/store/joseph/sane/src-pre1.01r3/backend/snapscan.desc Mon Sep 7 09:28:57 1998
++++ src-pre1.01r3-allarchs/backend/snapscan.desc Wed Mar 10 21:14:10 1999
+@@ -28,6 +28,8 @@
+ :comment "Ditto"
+ :model "SnapScan 600"
+ :comment "Ditto"
++:model "SnapScan 1236"
++:comment "Ditto"
+ :mfg "Vuego"
+ :model "310S"
+ :comment "Close SnapScan 310 compatible."
+diff -ru /store/store/joseph/sane/src-pre1.01r3/backend/snapscan.h src-pre1.01r3-allarchs/backend/snapscan.h
+--- /store/store/joseph/sane/src-pre1.01r3/backend/snapscan.h Sun Feb 28 00:59:10 1999
++++ src-pre1.01r3-allarchs/backend/snapscan.h Wed Mar 10 22:19:16 1999
+@@ -54,22 +54,41 @@
+ /* snapscan device field values */
+
+ #define SNAPSCAN_NAME "/dev/sga"
+-#define SNAPSCAN_VENDOR "AGFA"
+-#define VUEGO_VENDOR "COLOR"
+-#define SNAPSCAN_MODEL300 "SnapScan"
+-#define SNAPSCAN_MODEL310 "SNAPSCAN 310"
+-#define VUEGO_MODEL310S "FlatbedScanner_4"
+-#define SNAPSCAN_MODEL600 "SNAPSCAN 600"
+ #define SNAPSCAN_TYPE "flatbed scanner"
+ /*#define INOPERATIVE*/
+
+ typedef enum
+ {
++ UNKNOWN,
+ SNAPSCAN300, /* the original SnapScan or SnapScan 300 */
+ SNAPSCAN310, /* the SnapScan 310 */
+ SNAPSCAN600, /* the SnapScan 600 */
++ SNAPSCAN1236, /* the SnapScan 1236 */
+ VUEGO310S /* Vuego-Version of SnapScan 310 WG changed */
+ } SnapScan_Model;
++
++struct SnapScan_Model_desc
++{
++ char *scsi_name;
++ SnapScan_Model id;
++};
++
++static struct SnapScan_Model_desc scanners[] =
++{
++ { "FlatbedScanner_4", VUEGO310S },
++ { "SNAPSCAN 1236", SNAPSCAN1236 },
++ { "SNAPSCAN 310", SNAPSCAN310 },
++ { "SNAPSCAN 600", SNAPSCAN600 },
++ { "SnapScan", SNAPSCAN300 },
++};
++#define known_scanners (sizeof(scanners)/sizeof(struct SnapScan_Model_desc))
++
++static char *vendors[] =
++{
++ "AGFA",
++ "COLOR",
++};
++#define known_vendors (sizeof(vendors)/sizeof(char*))
+
+ typedef enum
+ {
--- /dev/null
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+ <head>
+ <title>SANE project CVS servers</title>
+ </head>
+
+ <body>
+ <h1>SANE project CVS servers</h1>
+
+ The <A HREF="http://www.mostang.com/sane/">SANE project</A> has two CVS servers, one for developers, and one
+ read only for anonymous access. Both use pserver connections.
+
+ <P>They are hosted by <A HREF="http://www.hungry.com/">The Hungry
+ Programmers</A>
+
+ <h2>Accessing the development server</h2>
+
+ Only peoples allowed by the current SANE maintainer get access to
+ this server. To check out the current development source, issue the
+ following commands:
+
+ <BLOCKQUOTE>
+ cvs -d :pserver:<username>@cvs.hungry.com:/cvsroot login
+ <BR>cvs -d :pserver:<username>@cvs.hungry.com:/cvsroot co sane
+ </BLOCKQUOTE>
+
+ More info on CVS is available from
+ <A HREF="http://www.loria.fr/~molli/cvs/cvs-tut/cvs_tutorial_toc.html">The
+ CVS tutorial</A>
+
+ <h2>Accessing the anonymous server</h2>
+
+ To get read-only access to the latest development version, issue
+ the following commands:
+
+ <BLOCKQUOTE>
+ cvs -d :pserver:anoncvs@anoncvs.hungry.com:/cvsroot login
+ <BR>[password "anoncvs"]
+ <BR>cvs -d :pserver:anoncvs@anoncvs.hungry.com:/cvsroot co sane
+ </BLOCKQUOTE>
+
+ The anonymous CVS version is updated every hour, on the hour.
+
+<P>Before 2000-08-13, development where being done in the DEVEL_1_9
+branch. Now we are developing in the main branch instead.
+
+<H2>How to get write access to the CVS server</H2>
+
+If you are an active SANE backend maintainer, you can get write access
+to the CVS server. You will need to supply my a username and a unix passwd
+hash to feed into the CVS access list. A simple program to do this is
+available from my <A HREF="../">linux and unix stuff</A> page.
+
+<H2>Information to developers with CVS write access</H2>
+
+When doing changes (commits) to the CVS repository, make sure you
+remember to include a <TT>ChangeLog</TT> entry. The format is simple,
+with the date the change was commited to CVS, the name and email
+address of the one doing the commit, the list of files changed
+(ignoring <TT>ChangeLog</TT>), and a description of the change.
+Example:
+
+<PRE>2000-03-06 Petter Reinholdtsen <pere@td.org.uit.no>
+
+ * configure.in configure: New version is 1.0.2.
+</PRE>
+
+<P>When committing patches from other people, I usually add 'Patch
+from <name>.' to record where the change came from.
+
+To make it easier to keep track of my own changes, I maintain a local
+<TT>ChangeLog.local</TT> where I list my local changes before I move
+the entry into the common <TT>ChangeLog</TT> and commit the change.
+
+<P>Do not change other backends then your own. If you find bugs in other
+backends, send a patch to the current backend maintainer or to the
+mailing list, and wait for the maintainer to commit the change.
+
+<P>Global changes require consensus where David has the last word before
+updating the CVS repository.
+
+<P>If you want to keep track of the changes to the CVS repository,
+subscribe to the mailing list sane-commit@list.uit.no by sending an
+email to
+<A HREF="mailto:sane-commit-request@list.uit.no">sane-commit-request@list.uit.no</A>
+with body 'subscribe'.
+
+ <hr>
+ <address><a href="mailto:pere@hungry.com">Petter Reinholdtsen</a></address>
+<!-- Created: Sun Jul 25 19:52:40 CEST 1999 -->
+<!-- hhmts start -->
+Last modified: March 2000
+<!-- hhmts end -->
+ </body>
+</html>
--- /dev/null
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+ <head>
+ <title>SANE project CVS servers</title>
+ </head>
+
+ <body>
+ <h1>SANE project CVS servers</h1>
+
+ The <A HREF="http://www.mostang.com/sane/">SANE project</A> has two CVS servers, one for developers, and one
+ read only for anonymous access. Both use pserver connections.
+
+ <P>They are hosted by <A HREF="http://www.hungry.com/">The Hungry
+ Programmers</A>
+
+ <h2>Accessing the development server</h2>
+
+ Only peoples allowed by the current SANE maintainer get access to
+ this server. To check out the current development source, issue the
+ following commands:
+
+ <BLOCKQUOTE>
+ cvs -d :pserver:<username>@cvs.hungry.com:/cvsroot login
+ <BR>cvs -d :pserver:<username>@cvs.hungry.com:/cvsroot co -r DEVEL_1_9 sane
+ </BLOCKQUOTE>
+
+ More info on CVS is available from
+ <A HREF="http://www.loria.fr/~molli/cvs/cvs-tut/cvs_tutorial_toc.html">The
+ CVS tutorial</A>
+
+ <h2>Accessing the anonymous server</h2>
+
+ To get read-only access to the latest development version, issue
+ the following commands:
+
+ <BLOCKQUOTE>
+ cvs -d :pserver:anoncvs@anoncvs.hungry.com:/cvsroot login
+ <BR>[password "anoncvs"]
+ <BR>cvs -d :pserver:anoncvs@anoncvs.hungry.com:/cvsroot co -r DEVEL_1_9 sane
+ </BLOCKQUOTE>
+
+ The anonymous CVS version is updated every hour, on the hour.
+
+<H2>Information to developers with CVS write access</H2>
+
+When doing changes (commits) to the CVS repository, make sure you
+remember to include a <TT>ChangeLog</TT> entry. The format is simple,
+with the date the change was commited to CVS, the name and email
+address of the one doing the commit, the list of files changed
+(ignoring <TT>ChangeLog</TT>), and a description of the change.
+Example:
+
+<PRE>2000-03-06 Petter Reinholdtsen <pere@td.org.uit.no>
+
+ * configure.in configure: New version is 1.0.2.
+</PRE>
+
+<P>When committing patches from other people, I usually add 'Patch
+from <name>.' to record where the change came from.
+
+To make it easier to keep track of my own changes, I maintain a local
+<TT>ChangeLog.local</TT> where I list my local changes before I move
+the entry into the common <TT>ChangeLog</TT> and commit the change.
+
+<P>Do not change other backends then your own. If you find bugs in other
+backends, send a patch to the current backend maintainer or to the
+mailing list, and wait for the maintainer to commit the change.
+
+<P>Global changes require consensus where David has the last word before
+updating the CVS repository.
+
+<P>If you want to keep track of the changes to the CVS repository,
+subscribe to the mailing list sane-commit@list.uit.no by sending an
+email to
+<A HREF="mailto:sane-commit-request@list.uit.no?subject=subscribe">sane-commit-request@list.uit.no</A>
+with subject 'subscribe'.
+
+ <hr>
+ <address><a href="mailto:pere@hungry.com">Petter Reinholdtsen</a></address>
+<!-- Created: Sun Jul 25 19:52:40 CEST 1999 -->
+<!-- hhmts start -->
+Last modified: Sun Jul 25 20:06:13 CEST 1999
+<!-- hhmts end -->
+ </body>
+</html>
--- /dev/null
+Begin3
+Title: SANE
+Version: 1.0.2
+Entered-date: 06Mar00
+Description: SANE (Scanner Access Now Easy) is a universal scanner
+ interface and comes complete with documentation and several
+ frontends and backends.
+Keywords: camera, scanner, Abaton, Apple, Agfa, Artec, Canon, Epson,
+ HP, Kodak DC25 & DC210, Microtek, Mustek, Nikon CoolScan,
+ Polaroid Digital Microscope Camera, PINT, Connectix QuickCam,
+ Ricoh, Siemens, Tamarack, UMAX, network server & client,
+ Java API & client
+Author: David.Mosberger@acm.org (David Mosberger-Tang)
+ (see AUTHORS for complete list)
+Maintained-by: David.Mosberger@acm.org (David Mosberger-Tang)
+Primary-site: ftp.mostang.com /pub/sane
+ 1169 kB sane-1.0.2.tar.gz
+ 2 kB sane-1.0.2.lsm
+Alternate-site: tsx-11.mit.edu /pub/linux/packages/sane
+ sunsite.unc.edu /pub/Linux/apps/graphics/capture
+ gd.tuwien.ac.at /hci/sane/
+Platforms: AIX, Digital Unix, HP Apollo Domain/OS, FreeBSD, HP-UX, IRIX,
+ Linux (Alpha, m68k, SPARC, x86), NetBSD, OpenStep (x86),
+ SCO OpenServer 5.x (x86), OS/2, Solaris (SPARC, x86), SunOS
+Copying-policy: GPL (programs), relaxed GPL (libraries), and public domain
+ (SANE standard)
+End
--- /dev/null
+Index: ChangeLog
+===================================================================
+RCS file: /cvsroot/external/sane/ChangeLog,v
+retrieving revision 1.1.1.1.2.115
+diff -u -r1.1.1.1.2.115 ChangeLog
+--- ChangeLog 2000/03/18 03:14:11 1.1.1.1.2.115
++++ ChangeLog 2000/03/18 03:19:11
+@@ -1,5 +1,10 @@
+ 2000-03-18 Petter Reinholdtsen <pere@td.org.uit.no>
+
++ * include/sane/sanei_debug.h sanei/sanei_init_debug.c: Send debug
++ messages to syslog if stderr is a socket.
++
++2000-03-18 Petter Reinholdtsen <pere@td.org.uit.no>
++
+ * backend/Makefile.in tools/libtool-get-dll-ext: New script to
+ detect shared library endings without using 'rev' which is missing
+ on some platforms.
+Index: include/sane/sanei_debug.h
+===================================================================
+RCS file: /cvsroot/external/sane/include/sane/sanei_debug.h,v
+retrieving revision 1.1.1.1.2.1
+diff -u -r1.1.1.1.2.1 sanei_debug.h
+--- sanei_debug.h 2000/01/25 15:37:55 1.1.1.1.2.1
++++ sanei_debug.h 2000/03/18 03:19:12
+@@ -1,3 +1,6 @@
++#ifndef _SANEI_DEBUG_H
++#define _SANEI_DEBUG_H
++
+ #include <sane/sanei.h>
+
+ #define ENTRY(name) PASTE(PASTE(PASTE(sane_,BACKEND_NAME),_),name)
+@@ -8,9 +11,7 @@
+ # define HAVE_VARARG_MACROS
+ #endif
+
+-#ifndef HAVE_VARARG_MACROS
+- extern void sanei_debug (int level, const char *msg, ...);
+-#endif
++extern void sanei_debug (int level, const char *msg, ...);
+
+ #ifdef NDEBUG
+ # define DBG_INIT(backend, var)
+@@ -26,28 +27,31 @@
+ #define DBG_LEVEL PASTE(sanei_debug_,BACKEND_NAME)
+
+ #if defined(BACKEND_NAME) && !defined(STUBS)
+-int PASTE(sanei_debug_,BACKEND_NAME);
++int DBG_LEVEL;
+ #endif
+
+ # define DBG_INIT() \
+- sanei_init_debug (STRINGIFY(BACKEND_NAME), \
+- &PASTE(sanei_debug_,BACKEND_NAME))
++ sanei_init_debug (STRINGIFY(BACKEND_NAME), &DBG_LEVEL)
+
+ /* The cpp that comes with GNU C 2.5 seems to have troubles understanding
+ vararg macros. */
+ #ifdef HAVE_VARARG_MACROS
++extern void sanei_debug_max (int level, int max_level, const char *msg, ...);
++
+ # define DBG(level, msg, args...) \
+ do { \
+- if (DBG_LEVEL >= (level)){ \
+- fprintf (stderr, "[" STRINGIFY(BACKEND_NAME) "] " msg, ##args); \
+- fflush(stderr); \
+- } \
++ sanei_debug_max ( level, DBG_LEVEL, \
++ "[" STRINGIFY(BACKEND_NAME) "] " msg, ##args); \
+ } while (0)
+
+ extern void sanei_init_debug (const char * backend, int * debug_level_var);
+ #else
+ # define DBG sanei_debug
+-#endif
++#endif /* HAVE_VARARG_MACROS */
+
+ # define IF_DBG(x) x
+-#endif
++#endif */ NDEBUG */
++
++#else
++# warning "sane/sanei_debug.h included more then once!"
++#endif /* _SANEI_DEBUG_H */
+Index: sanei/sanei_init_debug.c
+===================================================================
+RCS file: /cvsroot/external/sane/sanei/sanei_init_debug.c,v
+retrieving revision 1.1.1.1
+diff -u -r1.1.1.1 sanei_init_debug.c
+--- sanei_init_debug.c 1999/08/09 18:05:59 1.1.1.1
++++ sanei_init_debug.c 2000/03/18 03:19:12
+@@ -43,24 +43,33 @@
+ #include <ctype.h>
+ #include <stdio.h>
+ #include <stdlib.h>
++#ifdef HAVE_UNISTD_H
++#include <unistd.h>
++#endif
++#include <stdarg.h>
++#include <sys/syslog.h>
++#ifdef HAVE_SYS_SOCKET_H
++#include <sys/socket.h>
++#endif
++#include <sys/stat.h>
+
+ #ifdef __EMX__
+ # define INCL_DOS
+ # include <os2.h>
+ #endif
+
++#define BACKEND_NAME sanei_debug
+ #include <sane/sanei_debug.h>
+
+-#ifndef HAVE_VARARG_MACROS
+- static int max_level = 0;
+-#endif
++static int global_max_level = 0;
++
+
+ void
+ sanei_init_debug (const char * backend, int * var)
+ {
+ char ch, buf[256] = "SANE_DEBUG_";
+ const char * val;
+- int i;
++ unsigned int i;
+
+ *var = 0;
+
+@@ -84,30 +93,38 @@
+
+ *var = atoi (val);
+
+-#ifndef HAVE_VARARG_MACROS
+- if (*var > max_level)
+- max_level = *var;
+-#endif
++ if (*var > global_max_level)
++ global_max_level = *var;
+
+- fprintf (stderr, "[sanei_init_debug]: Setting debug level of %s to %d.\n",
+- backend, *var);
++ DBG (0, "Setting debug level of %s to %d.\n", backend, *var);
+ }
+
+-#ifndef HAVE_VARARG_MACROS
+-
+-#include <stdarg.h>
++static void
++debug_msg (int level, int max_level, const char *fmt, va_list ap)
++{
++ if (max_level >= level)
++ {
++ if ( 1 == isfdtype(fileno(stderr), S_IFSOCK) )
++ vsyslog(LOG_DEBUG, fmt, ap);
++ else
++ vfprintf (stderr, fmt, ap);
++ }
++}
+
+ void
+ sanei_debug (int level, const char *fmt, ...)
+ {
+ va_list ap;
+-
+- if (max_level >= level)
+- {
+- va_start (ap, fmt);
+- vfprintf (stderr, fmt, ap);
+- va_end (ap);
+- }
++ va_start (ap, fmt);
++ debug_msg (level, global_max_level, fmt, ap);
++ va_end (ap);
+ }
+
+-#endif /* !HAVE_VARARG_MACROS */
++void
++sanei_debug_max (int level, int max_level, const char *fmt, ...)
++{
++ va_list ap;
++ va_start (ap, fmt);
++ debug_msg (level, max_level, fmt, ap);
++ va_end (ap);
++}
--- /dev/null
+
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html> <head>
+<title>SANE: Backends (Drivers)</title>
+</head>
+
+<body bgcolor=FFFFFF>
+<div align=center>
+<img src="sane.png" alt="SANE">
+<h1>Backends (Drivers)</h1>
+</div>
+<hr>
+<p>The following table summarizes the backends/drivers distributed with
+SANE, and the hardware or software they support.
+
+<p>This is only a summary!
+Please consult the manpages and the author-supplied webpages for more
+detailed (and usually important) information concerning each backend.
+
+<p>If you have new information or corrections, please send e-mail
+to <a href="mailto:sane-devel@mostang.com">sane-devel@mostang.com</a>.
+
+<p>(For an explanation of the table, see the <a href="#legend">legend</a>.)
+
+<p>
+
+<div align=center>
+<table border=1>
+ <tr bgcolor=E0E0FF>
+ <th align=center rowspan=2>Backend</th>
+ <th align=center rowspan=2>Version</th>
+ <th align=center rowspan=2>Status</th>
+ <th align=center colspan=3>Supported Devices</th>
+ <th align=center rowspan=2>Manual Page</th>
+</tr>
+<tr bgcolor=E0E0FF>
+ <th align=center>Manufacturer</th>
+ <th align=center>Model</th>
+ <th align=center>Comment</th>
+</tr>
+
+
+<tr>
+ <td align=left rowspan=2><a href="http://aix2.uottawa.ca/~s1204672/sane/">abaton</a></td>
+ <td align=center rowspan=2>0.1</td>
+ <td align=center rowspan=2><font color=bb0000>alpha</font></td>
+<td align=center rowspan=2><a href="http://www.everex.com/">Abaton</a></td>
+<td>Scan 300/GS</td>
+<td>All known modes and functions supported</td>
+<td align=center rowspan=2><a href="http://www.mostang.com/sane/man/sane-abaton.5.html">sane-abaton</a></td>
+<tr><td>Scan 300/S</td>
+<td>Untested, use with caution</td>
+</tr>
+
+<tr>
+ <td align=left rowspan=6>agfafocus</td>
+ <td align=center rowspan=6>0.2</td>
+ <td align=center rowspan=6><font color=bb0000>alpha</font></td>
+<td align=center rowspan=5><a href="http://www.agfa.com/">AGFA</a></td>
+<td>Focus GS Scanner</td>
+<td>6 bit gray</td>
+<td align=center rowspan=6><a href="http://www.mostang.com/sane/man/sane-agfafocus.5.html">sane-agfafocus</a></td>
+<tr><td>Focus Lineart Scanner</td>
+<td>Lineart only? Untested.</td>
+</tr>
+<tr><td>Focus II</td>
+<td>gray only</td>
+</tr>
+<tr><td>Focus Color</td>
+<td> </td>
+</tr>
+<tr><td>Focus Color Plus</td>
+<td>3-pass</td>
+</tr>
+<tr><td align=center rowspan=1>Siemens</td>
+<td>S9036</td>
+<td>gray only</td>
+</tr>
+
+<tr>
+ <td align=left rowspan=3>apple</td>
+ <td align=center rowspan=3>0.31</td>
+ <td align=center rowspan=3><font color=bb0000>alpha</font></td>
+<td align=center rowspan=3><a href="ftp://ftpdev.info.apple.com/devworld/">Apple</a></td>
+<td>Apple Scanner</td>
+<td>4bit, 16 shades of gray</td>
+<td align=center rowspan=3><a href="http://www.mostang.com/sane/man/sane-apple.5.html">sane-apple</a></td>
+<tr><td>OneScanner</td>
+<td>8bit, 256 shades of gray. The backend needs work especially in the quantization code but it may work.</td>
+</tr>
+<tr><td>ColorOneScanner</td>
+<td>truecolor (needs much work) but it scans in non color modes.</td>
+</tr>
+
+<tr>
+ <td align=left rowspan=8><a href="http://www4.infi.net/~cpinkham/sane/sane-artec-doc.html">artec</a></td>
+ <td align=center rowspan=8>0.5.13</td>
+ <td align=center rowspan=8><font color=008000>stable</font></td>
+<td align=center rowspan=6><a href="http://www.artecusa.com/">Artec/Ultima</a></td>
+<td>AT3</td>
+<td>all modes working</td>
+<td align=center rowspan=8>?</td>
+<tr><td>A6000C</td>
+<td>all modes working</td>
+</tr>
+<tr><td>A6000C PLUS</td>
+<td>f/w <= v1.92 alpha, f/w >= v1.93 OK</td>
+</tr>
+<tr><td>AT6</td>
+<td>testing in progress</td>
+</tr>
+<tr><td>AT12</td>
+<td>all modes working</td>
+</tr>
+<tr><td>AM12S</td>
+<td>all modes working</td>
+</tr>
+<tr><td align=center rowspan=1><a href="http://www.blackwidow.co.uk/">BlackWidow</a></td>
+<td>BW4800SP</td>
+<td>rebadged Artec AT3</td>
+</tr>
+<tr><td align=center rowspan=1><a href="http://www.plustek.com/">Plustek</a></td>
+<td>OpticPro 19200S</td>
+<td>rebadged Artec AM12S</td>
+</tr>
+
+<tr>
+ <td align=left rowspan=1><a href="http://www.rene.rebe.myokay.net/avision/index.html">avision</a></td>
+ <td align=center rowspan=1>0.2</td>
+ <td align=center rowspan=1><font color=806000>beta</font></td>
+<td align=center rowspan=1><a href="http://www.avision.com/">Avision</a></td>
+<td>AV 630 CS</td>
+<td>1 pass, 1200*600 DPI</td>
+<td align=center rowspan=1>?</td>
+
+<tr>
+ <td align=left rowspan=3><a href="http://www.rzg.mpg.de/~mpd/sane/">canon</a></td>
+ <td align=center rowspan=3>0.1</td>
+ <td align=center rowspan=3><font color=bb0000>alpha</font></td>
+<td align=center rowspan=3><a href="http://www.canon.com/">Canon</a></td>
+<td>CanoScan 300</td>
+<td>1 pass; flatbed scanner</td>
+<td align=center rowspan=3>?</td>
+<tr><td>CanoScan 600</td>
+<td>1 pass; flatbed scanner</td>
+</tr>
+<tr><td>CanoScan 2700F</td>
+<td>1 pass; film scanner</td>
+</tr>
+
+<tr>
+ <td align=left rowspan=2><a href="http://www.sema.be/coolscan/">coolscan</a></td>
+ <td align=center rowspan=2>0.3</td>
+ <td align=center rowspan=2><font color=806000>beta</font></td>
+<td align=center rowspan=2><a href="http://www.nikon.com/">Nikon</a></td>
+<td>LS-20</td>
+<td>The LS-20 has been replaced by the LS-30</td>
+<td align=center rowspan=2>?</td>
+<tr><td>LS-1000</td>
+<td>Doesn't support gamma correction</td>
+</tr>
+
+<tr>
+ <td align=left rowspan=1>dc210</td>
+ <td align=center rowspan=1>0.0</td>
+ <td align=center rowspan=1><font color=bb0000>alpha</font></td>
+<td align=center rowspan=1><a href="http://www.kodak.com/US/en/digital/cameras/DCSGateway.shtml">Kodak</a></td>
+<td>DC210</td>
+<td> </td>
+<td align=center rowspan=1><a href="http://www.mostang.com/sane/man/sane-dc210.5.html">sane-dc210</a></td>
+
+<tr>
+ <td align=left rowspan=2><a href="http://peter.fales.com/DC-25.html">dc25</a></td>
+ <td align=center rowspan=2>1.2</td>
+ <td align=center rowspan=2><font color=806000>beta</font></td>
+<td align=center rowspan=2><a href="http://www.kodak.com/US/en/digital/cameras/dc25/">Kodak</a></td>
+<td>DC25</td>
+<td> </td>
+<td align=center rowspan=2><a href="http://www.mostang.com/sane/man/sane-dc25.5.html">sane-dc25</a></td>
+<tr><td>DC20</td>
+<td>DC-20 untested by author but reported to work</td>
+</tr>
+
+<tr>
+ <td align=left rowspan=1>dll</td>
+ <td align=center rowspan=1>0.73</td>
+ <td align=center rowspan=1><font color=806000>beta</font></td>
+<td align=center colspan=2>Dynamic loading of shared-library backends.</td>
+<td> </td>
+<td align=center rowspan=1><a href="http://www.mostang.com/sane/man/sane-dll.5.html">sane-dll</a></td>
+
+<tr>
+ <td align=left rowspan=1>dmc</td>
+ <td align=center rowspan=1>1.0</td>
+ <td align=center rowspan=1><font color=008000>stable</font></td>
+<td align=center rowspan=1><a href="http://www.polaroid.com/">Polaroid</a></td>
+<td><a href="http://digitalimage.polaroid.com/products/digital_cameras/dmc/">DMC</a></td>
+<td> </td>
+<td align=center rowspan=1><a href="http://www.mostang.com/sane/man/sane-dmc.5.html">sane-dmc</a></td>
+
+<tr>
+ <td align=left rowspan=10><a href="http://www.khk.net/">epson</a></td>
+ <td align=center rowspan=10>0.1.15</td>
+ <td align=center rowspan=10><font color=bb0000>alpha</font></td>
+<td align=center rowspan=10><a href="http://www.epson.com/">Epson</a></td>
+<td>GT-5000</td>
+<td>parallel interface</td>
+<td align=center rowspan=10><a href="http://www.mostang.com/sane/man/sane-epson.5.html">sane-epson</a></td>
+<tr><td>GT-6000</td>
+<td>parallel interface</td>
+</tr>
+<tr><td>Actionscanner II</td>
+<td>parallel interface</td>
+</tr>
+<tr><td>GT-7000</td>
+<td> </td>
+</tr>
+<tr><td>Perfection 636S</td>
+<td> </td>
+</tr>
+<tr><td>Perfection 636U</td>
+<td>USB Interface</td>
+</tr>
+<tr><td>Perfection 1200S</td>
+<td> </td>
+</tr>
+<tr><td>Perfection 1200U</td>
+<td>USB Interface</td>
+</tr>
+<tr><td>Expression 636</td>
+<td> </td>
+</tr>
+<tr><td>FilmScan 200</td>
+<td>A better backend for the FilmScan 200 can be found at <A HREF="http://www.vjet.demon.co.uk/scanner/">http://www.vjet.demon.cu.uk/scanner/</A></td>
+</tr>
+
+<tr>
+ <td align=left rowspan=18><a href="http://www.kirchgessner.net/">hp</a></td>
+ <td align=center rowspan=18>0.86</td>
+ <td align=center rowspan=18><font color=806000>beta</font></td>
+<td align=center rowspan=18><a href="http://www.hp.com/">HP</a></td>
+<td>HP ScanJet Plus</td>
+<td> </td>
+<td align=center rowspan=18><a href="http://www.mostang.com/sane/man/sane-hp.5.html">sane-hp</a></td>
+<tr><td>HP ScanJet IIc</td>
+<td> </td>
+</tr>
+<tr><td>HP ScanJet IIp</td>
+<td> </td>
+</tr>
+<tr><td>HP ScanJet IIcx</td>
+<td> </td>
+</tr>
+<tr><td>HP ScanJet 3c</td>
+<td> </td>
+</tr>
+<tr><td>HP ScanJet 3p</td>
+<td> </td>
+</tr>
+<tr><td>HP ScanJet 4c</td>
+<td> </td>
+</tr>
+<tr><td>HP ScanJet 4p</td>
+<td> </td>
+</tr>
+<tr><td>HP ScanJet 4100C</td>
+<td> </td>
+</tr>
+<tr><td>HP ScanJet 5p</td>
+<td> </td>
+</tr>
+<tr><td>HP ScanJet 5100C</td>
+<td> </td>
+</tr>
+<tr><td>HP ScanJet 5200C</td>
+<td> </td>
+</tr>
+<tr><td>HP ScanJet 6100C</td>
+<td> </td>
+</tr>
+<tr><td>HP ScanJet 6200C</td>
+<td> </td>
+</tr>
+<tr><td>HP ScanJet 6250C</td>
+<td> </td>
+</tr>
+<tr><td>HP ScanJet 6300C</td>
+<td> </td>
+</tr>
+<tr><td>HP ScanJet 6350C</td>
+<td> </td>
+</tr>
+<tr><td>HP PhotoSmart PhotoScanner</td>
+<td>USB on HP ScanJet 4100C/5200C/6200C/6300C require USB driver. See http://www.jump.net/~dnelson/linux/usb (under development)</td>
+</tr>
+
+<tr>
+ <td align=left rowspan=0><a href="ftp://www.cs.ubishops.ca/pub/lhii/">lhii</a></td>
+ <td align=center rowspan=0>(0.1)</td>
+ <td align=center rowspan=0><font color=bb0000>alpha</font></td>
+ <td align=center colspan=3>?</td>
+<td align=center rowspan=0>?</td>
+
+<tr>
+ <td align=left rowspan=1><a href="http://www.aa.net/~bentson/sane.html">m3096g</a></td>
+ <td align=center rowspan=1>1.11</td>
+ <td align=center rowspan=1><font color=806000>beta</font></td>
+<td align=center rowspan=1><a href="http://www.fujitsu.com/scanners.html">Fujitsu</a></td>
+<td>M3096G</td>
+<td> </td>
+<td align=center rowspan=1><a href="http://www.mostang.com/sane/man/sane-fujitsu.5.html">sane-fujitsu</a></td>
+
+<tr>
+ <td align=left rowspan=19><a href="http://www.mir.com/mtek/">microtek</a></td>
+ <td align=center rowspan=19>0.12.0</td>
+ <td align=center rowspan=19><font color=806000>beta</font></td>
+<td align=center rowspan=14><a href="http://www.microtek.com/">Microtek</a></td>
+<td>Scanmaker E6</td>
+<td> </td>
+<td align=center rowspan=19><a href="http://www.mostang.com/sane/man/sane-microtek.5.html">sane-microtek</a></td>
+<tr><td>Scanmaker E3</td>
+<td> </td>
+</tr>
+<tr><td>Scanmaker E2</td>
+<td>3-pass</td>
+</tr>
+<tr><td>Scanmaker 35t+</td>
+<td>slide-scanner</td>
+</tr>
+<tr><td>Scanmaker 45t</td>
+<td>slide-scanner</td>
+</tr>
+<tr><td>Scanmaker 35</td>
+<td>slide-scanner</td>
+</tr>
+<tr><td>Scanmaker III</td>
+<td> </td>
+</tr>
+<tr><td>Scanmaker IISP</td>
+<td> </td>
+</tr>
+<tr><td>Scanmaker IIHR</td>
+<td>3-pass</td>
+</tr>
+<tr><td>Scanmaker IIG</td>
+<td>gray only</td>
+</tr>
+<tr><td>Scanmaker II</td>
+<td>3-pass</td>
+</tr>
+<tr><td>Scanmaker 600Z(S)</td>
+<td>untested (color?)</td>
+</tr>
+<tr><td>Scanmaker 600G(S)</td>
+<td>gray only (see manpage)</td>
+</tr>
+<tr><td>Color PageWiz</td>
+<td>sheet-fed (preliminary)</td>
+</tr>
+<tr><td align=center rowspan=5><a href="http://www.agfa.com/">Agfa</a></td>
+<td>Arcus II</td>
+<td>Arcus *II*, not Arcus!</td>
+</tr>
+<tr><td>StudioScan</td>
+<td> </td>
+</tr>
+<tr><td>StudioScan II</td>
+<td> </td>
+</tr>
+<tr><td>StudioScan IIsi</td>
+<td> </td>
+</tr>
+<tr><td>DuoScan</td>
+<td>preliminary</td>
+</tr>
+
+<tr>
+ <td align=left rowspan=13>microtek2</td>
+ <td align=center rowspan=13>pre0.8.161099</td>
+ <td align=center rowspan=13><font color=bb0000>alpha</font></td>
+<td align=center rowspan=12><a href="http://www.microtek.com/">Microtek</a></td>
+<td>parallel models unsupported</td>
+<td> </td>
+<td align=center rowspan=13><a href="http://www.mostang.com/sane/man/sane-microtek2.5.html">sane-microtek2</a></td>
+<tr><td>ScanMaker V300</td>
+<td> </td>
+</tr>
+<tr><td>ScanMaker V310</td>
+<td> </td>
+</tr>
+<tr><td>ScanMaker V600</td>
+<td> </td>
+</tr>
+<tr><td>ScanMaker E3plus</td>
+<td> </td>
+</tr>
+<tr><td>ScanMaker X6</td>
+<td> </td>
+</tr>
+<tr><td>ScanMaker X6EL</td>
+<td> </td>
+</tr>
+<tr><td>ScanMaker 330</td>
+<td> </td>
+</tr>
+<tr><td>ScanMaker 630</td>
+<td> </td>
+</tr>
+<tr><td>ScanMaker 636</td>
+<td> </td>
+</tr>
+<tr><td>ScanMaker 9600XL</td>
+<td>only flatbed mode ?</td>
+</tr>
+<tr><td>Phantom 636</td>
+<td> </td>
+</tr>
+<tr><td align=center rowspan=1><a href="http://www.vobis.de/">Vobis</a></td>
+<td>HighScan</td>
+<td>only E3plus based models</td>
+</tr>
+
+<tr>
+ <td align=left rowspan=12>mustek</td>
+ <td align=center rowspan=12>0.73</td>
+ <td align=center rowspan=12><font color=806000>beta</font></td>
+<td align=center rowspan=12><a href="http://www.mustek.com/">Mustek</a></td>
+<td>MFC-600S</td>
+<td>1 pass; (f/w >= 1.01; scsi id MFC-06000CZ)</td>
+<td align=center rowspan=12><a href="http://www.mostang.com/sane/man/sane-mustek.5.html">sane-mustek</a></td>
+<tr><td>MFC-600CD</td>
+<td>1 pass; (f/w >= 2.03; scsi id MFC-06000CZ)</td>
+</tr>
+<tr><td>MFS-6000CX</td>
+<td>3 pass; (f/w >= 2.71; scsi id MSF-06000CX)</td>
+</tr>
+<tr><td>MSF-6000SP</td>
+<td>1 pass; (f/w >= 3.12; scsi id MSF-06000SP)</td>
+</tr>
+<tr><td>MFS-8000SP</td>
+<td>1 pass; (f/w >= 2.05; scsi id MSF-08000SP) lineart drops lines?</td>
+</tr>
+<tr><td>MFC-800S</td>
+<td>1 pass; (f/w == 1.06; scsi id MFC-08000CZ) color fails?</td>
+</tr>
+<tr><td>MFS-1200SP</td>
+<td>1 pass; (f/w == 1.00; scsi id MSF-12000SP)</td>
+</tr>
+<tr><td>MFS-1200SP</td>
+<td>1 pass; (f/w == 1.07; scsi id MFS-12000SP)</td>
+</tr>
+<tr><td>MFS-1200SP</td>
+<td>1 pass; (f/w == 1.02; scsi id MFS-12000SP) color fails?</td>
+</tr>
+<tr><td>MFS-12000CX</td>
+<td>3 pass; (f/w == 2.71; scsi id MFS-12000CX)</td>
+</tr>
+<tr><td>SE-6000SP</td>
+<td>1 pass; (f/w == ? ; scsi id C03 S10IDW)</td>
+</tr>
+<tr><td>SE-12000SP</td>
+<td>1 pass; (f/w == 1.01; scsi id C06 S12IDW)</td>
+</tr>
+
+<tr>
+ <td align=left rowspan=1><a href="http://www.i2k.com/~jeffd/a4s2/">musteka4s2</a></td>
+ <td align=center rowspan=1>(0.3)</td>
+ <td align=center rowspan=1><font color=806000>beta</font></td>
+<td align=center rowspan=1><a href="http://www.mustek.com/">Mustek</a></td>
+<td>MFS-600IIIP</td>
+<td>Mustek 600 III EP Plus</td>
+<td align=center rowspan=1><a href="http://www.mostang.com/sane/man/sane-musteka4s2.5.html">sane-musteka4s2</a></td>
+
+<tr>
+ <td align=left rowspan=2><a href="mailto:fukuda@avm.nhe.nec.co.jp">nec</a></td>
+ <td align=center rowspan=2>(0.10)</td>
+ <td align=center rowspan=2><font color=000080>NEW!</font></td>
+<td align=center rowspan=2><a href="http://www.nec.co.jp/">NEC</a></td>
+<td>PC-IN500/4C</td>
+<td>PC-IN500/4C was sold only in JAPAN</td>
+<td align=center rowspan=2>?</td>
+<tr><td>PC-IN600,700,800 series</td>
+<td>PC-IN600,700,800 series is not supprted</td>
+</tr>
+
+<tr>
+ <td align=left rowspan=1>net</td>
+ <td align=center rowspan=1>0.73</td>
+ <td align=center rowspan=1><font color=806000>beta</font></td>
+<td align=center colspan=2>Network access to saned servers</td>
+<td> </td>
+<td align=center rowspan=1><a href="http://www.mostang.com/sane/man/sane-net.5.html">sane-net</a></td>
+
+<tr>
+ <td align=left rowspan=1>pint</td>
+ <td align=center rowspan=1>?</td>
+ <td align=center rowspan=1><font color=bb0000>alpha</font></td>
+<td align=center colspan=2>Scanners with the machine-independent PINT interface</td>
+<td> </td>
+<td align=center rowspan=1><a href="http://www.mostang.com/sane/man/sane-pint.5.html">sane-pint</a></td>
+
+<tr>
+ <td align=left rowspan=3><a href="http://www.efn.org/~rick/plustek/">plustek</a></td>
+ <td align=center rowspan=3>(0.27)</td>
+ <td align=center rowspan=3><font color=806000>beta</font></td>
+<td align=center rowspan=3><a href="http://www.plustek.com/">Plustek</a></td>
+<td>Plustek 4830</td>
+<td>OK</td>
+<td align=center rowspan=3>?</td>
+<tr><td>Plustek 9630</td>
+<td>Doesn't work</td>
+</tr>
+<tr><td>Plustek OpticPro 600</td>
+<td>Doesn't work</td>
+</tr>
+
+<tr>
+ <td align=left rowspan=1>pnm</td>
+ <td align=center rowspan=1>?</td>
+ <td align=center rowspan=1><font color=806000>beta</font></td>
+<td align=center colspan=2>Reads PNM files</td>
+<td>Used for debugging frontends</td>
+<td align=center rowspan=1><a href="http://www.mostang.com/sane/man/sane-pnm.5.html">sane-pnm</a></td>
+
+<tr>
+ <td align=left rowspan=2>qcam</td>
+ <td align=center rowspan=2>?</td>
+ <td align=center rowspan=2><font color=bb0000>alpha</font></td>
+<td align=center rowspan=2><a href="http://www.connectix.com/">Connectix</a></td>
+<td>Color QuickCam</td>
+<td>Require root privileges.</td>
+<td align=center rowspan=2><a href="http://www.mostang.com/sane/man/sane-qcam.5.html">sane-qcam</a></td>
+<tr><td>Greyscale QuickCam</td>
+<td>Require root privileges. Partly working.</td>
+</tr>
+
+<tr>
+ <td align=left rowspan=2>ricoh</td>
+ <td align=center rowspan=2>?</td>
+ <td align=center rowspan=2><font color=bb0000>alpha</font></td>
+<td align=center rowspan=2><a href="http://www.ricoh.com/">Ricoh</a></td>
+<td>Ricoh IS50</td>
+<td>?</td>
+<td align=center rowspan=2>?</td>
+<tr><td>Ricoh IS60</td>
+<td>?</td>
+</tr>
+
+<tr>
+ <td align=left rowspan=1>s9036</td>
+ <td align=center rowspan=1>?</td>
+ <td align=center rowspan=1><font color=bb0000>alpha</font></td>
+<td align=center rowspan=1><a href="http://www.siemens.com/">Siemens</a></td>
+<td>9036 Flatbed scanner</td>
+<td> </td>
+<td align=center rowspan=1>?</td>
+
+<tr>
+ <td align=left rowspan=2><a href="http://www.cs.uni-magdeburg.de/~aherms/sane-sagitta.html">sagitta</a></td>
+ <td align=center rowspan=2>(0.4)</td>
+ <td align=center rowspan=2><font color=bb0000>alpha</font></td>
+<td align=center rowspan=2><a href="http://www.qtronix.com">Qtronix</a></td>
+<td>Sagitta Gray</td>
+<td>no monocrome-mode at the moment</td>
+<td align=center rowspan=2>?</td>
+<tr><td>Sagitta Color</td>
+<td>not supported at the moment</td>
+</tr>
+
+<tr>
+ <td align=left rowspan=3><a href="http://www.satzbau-gmbh.de/staff/abel/sane-sharp.html">sharp</a></td>
+ <td align=center rowspan=3>0.30</td>
+ <td align=center rowspan=3><font color=806000>beta</font></td>
+<td align=center rowspan=3><a href="http://sharp-world.com/">SHARP</a></td>
+<td>JX-610</td>
+<td></td>
+<td align=center rowspan=3>?</td>
+<tr><td>JX-250</td>
+<td></td>
+</tr>
+<tr><td>JX-330</td>
+<td>backend is not yet tested with a JX 330!</td>
+</tr>
+
+<tr>
+ <td align=left rowspan=8><a href="http://www.cs.ualberta.ca/~charter/SnapScan/snapscan.html">SnapScan</a></td>
+ <td align=center rowspan=8>0.7</td>
+ <td align=center rowspan=8><font color=bb0000>alpha</font></td>
+<td align=center rowspan=4><a href="http://www.agfa.com/">AGFA</a></td>
+<td>SnapScan 300</td>
+<td>Only 8 bits/sample at present.</td>
+<td align=center rowspan=8>?</td>
+<tr><td>SnapScan 310</td>
+<td>Ditto</td>
+</tr>
+<tr><td>SnapScan 600</td>
+<td>Ditto</td>
+</tr>
+<tr><td>SnapScan 1236s</td>
+<td>Ditto. Have no specific programming info yet.</td>
+</tr>
+<tr><td align=center rowspan=1>Vuego</td>
+<td>310s</td>
+<td>Close SnapScan 310 compatible.</td>
+</tr>
+<tr><td align=center rowspan=2>Acer</td>
+<td>310s</td>
+<td>Same thing as the Vuego 310s.</td>
+</tr>
+<tr><td>Prisa 620s</td>
+<td>Seems to be a close SnapScan 310/600 compatible.</td>
+</tr>
+<tr><td align=center rowspan=1>Guillemot International</td>
+<td>Maxi Scan A4 Deluxe (SCSI)</td>
+<td>May be a repackaged Vuego 310s or SnapScan 310s.</td>
+</tr>
+
+<tr>
+ <td align=left rowspan=1><a href="http://www.aa.net/~bentson/sane.html">sp15c</a></td>
+ <td align=center rowspan=1>1.12</td>
+ <td align=center rowspan=1><font color=806000>beta</font></td>
+<td align=center rowspan=1><a href="http://www.fujitsu.com/scanners.html">Fujitsu Computer Products of America</a></td>
+<td>SP15C</td>
+<td> </td>
+<td align=center rowspan=1><a href="http://www.mostang.com/sane/man/sane-fujitsu.5.html">sane-fujitsu</a></td>
+
+<tr>
+ <td align=left rowspan=1><a href="http://www.informatik.uni-oldenburg.de/~ingo/sane/">st400</a></td>
+ <td align=center rowspan=1>(1.4)</td>
+ <td align=center rowspan=1><font color=bb0000>alpha</font></td>
+<td align=center rowspan=1><a href="http://www.siemens.de/">Siemens</a></td>
+<td>ST400</td>
+<td>6 bit gray</td>
+<td align=center rowspan=1><a href="http://www.mostang.com/sane/man/sane-st400.5.html">sane-st400</a></td>
+
+<tr>
+ <td align=left rowspan=3>tamarack</td>
+ <td align=center rowspan=3>0.5</td>
+ <td align=center rowspan=3><font color=806000>beta</font></td>
+<td align=center rowspan=3><a href="http://www.tamarack.net/">Tamarack</a></td>
+<td>Artiscan 6000C</td>
+<td>3 pass, 300 DPI</td>
+<td align=center rowspan=3>?</td>
+<tr><td>Artiscan 8000C</td>
+<td>3 pass, 400 DPI</td>
+</tr>
+<tr><td>Artiscan 12000C</td>
+<td>3 pass, 600 DPI</td>
+</tr>
+
+<tr>
+ <td align=left rowspan=48><a href="http://www.wolfsburg.de/~rauch/sane/sane-umax.html">umax</a></td>
+ <td align=center rowspan=48>1.0-18</td>
+ <td align=center rowspan=48><font color=008000>stable</font></td>
+<td align=center rowspan=35><a href="http://support.umax.co.uk/">UMAX</a></td>
+<td>parallel scanners</td>
+<td>Not supported!!!</td>
+<td align=center rowspan=48><a href="http://www.mostang.com/sane/man/sane-umax.5.html">sane-umax</a></td>
+<tr><td>USB scanners</td>
+<td>Not supported!!!</td>
+</tr>
+<tr><td>Vista S6</td>
+<td>OK</td>
+</tr>
+<tr><td>Vista S6E</td>
+<td>OK</td>
+</tr>
+<tr><td>UMAX S-6E</td>
+<td>OK</td>
+</tr>
+<tr><td>UMAX S-6EG</td>
+<td>OK</td>
+</tr>
+<tr><td>Vista-S8</td>
+<td>OK</td>
+</tr>
+<tr><td>Supervista S-12</td>
+<td>OK</td>
+</tr>
+<tr><td>UMAX S-12</td>
+<td>OK</td>
+</tr>
+<tr><td>UMAX S-12G</td>
+<td>OK</td>
+</tr>
+<tr><td>Astra 600S</td>
+<td>OK</td>
+</tr>
+<tr><td>Astra 610S</td>
+<td>OK</td>
+</tr>
+<tr><td>Astra 1200S</td>
+<td>OK</td>
+</tr>
+<tr><td>Astra 1220S</td>
+<td>OK</td>
+</tr>
+<tr><td>Astra 2200W</td>
+<td>OK</td>
+</tr>
+<tr><td>Astra 2400S</td>
+<td>OK</td>
+</tr>
+<tr><td>Mirage D-16L</td>
+<td>OK</td>
+</tr>
+<tr><td>Mirage II</td>
+<td>Not tested</td>
+</tr>
+<tr><td>Mirage IIse</td>
+<td>Not tested</td>
+</tr>
+<tr><td>PSD</td>
+<td>OK</td>
+</tr>
+<tr><td>PowerLook</td>
+<td>Not tested</td>
+</tr>
+<tr><td>PL-II</td>
+<td>Not tested</td>
+</tr>
+<tr><td>PowerLook III</td>
+<td>Not tested</td>
+</tr>
+<tr><td>PowerLook 2000</td>
+<td>Not tested</td>
+</tr>
+<tr><td>PowerLook 3000</td>
+<td>Not tested</td>
+</tr>
+<tr><td>Gemini D-16</td>
+<td>OK</td>
+</tr>
+<tr><td>UMAX VT600</td>
+<td>not tested</td>
+</tr>
+<tr><td>Vista-T630</td>
+<td>OK for some firmwareversions, on others only lineart OK</td>
+</tr>
+<tr><td>UC 630</td>
+<td>Version 1.6(?) or 2.8(?) OK, others only lineart OK</td>
+</tr>
+<tr><td>UG 630</td>
+<td>OK</td>
+</tr>
+<tr><td>UG 80</td>
+<td>OK</td>
+</tr>
+<tr><td>UC 840</td>
+<td>Version 1.6 OK, others only lineart OK</td>
+</tr>
+<tr><td>UC 1200S</td>
+<td>unknown - please try</td>
+</tr>
+<tr><td>UC 1200SE</td>
+<td>unknown - please try</td>
+</tr>
+<tr><td>UC 1260</td>
+<td>Version 1.6 OK, others unknown</td>
+</tr>
+<tr><td align=center rowspan=9><a href="http://www.heidelberg-cps.com/">Linotype Hell</a></td>
+<td>Jade</td>
+<td>OK, SCSI-ID=LinoHell Office</td>
+</tr>
+<tr><td>Jade2</td>
+<td>OK, SCSI-ID=LinoHell Office2</td>
+</tr>
+<tr><td>Saphir</td>
+<td>Not tested</td>
+</tr>
+<tr><td>Saphir2</td>
+<td>OK, SCSI-ID=LinoHell SAPHIR2</td>
+</tr>
+<tr><td>Saphir Ultra</td>
+<td>Not tested</td>
+</tr>
+<tr><td>Saphir Ultra II</td>
+<td>Not tested</td>
+</tr>
+<tr><td>Saphir HiRes</td>
+<td>Not tested</td>
+</tr>
+<tr><td>Opal</td>
+<td>Not tested</td>
+</tr>
+<tr><td>Opal Ultra</td>
+<td>Not tested</td>
+</tr>
+<tr><td align=center rowspan=1><a href="http://www.vobis.de/">Vobis/Highscreen</a></td>
+<td>Scanboostar Premium</td>
+<td>OK, SCSI-ID=LinoHell Office2</td>
+</tr>
+<tr><td align=center rowspan=1>Escom</td>
+<td>Image Scanner 256</td>
+<td>OK, SCSI-ID=UMAX UG 80</td>
+</tr>
+<tr><td align=center rowspan=1><a href="http://www.nikon.com/">Nikon</a></td>
+<td>AX-210</td>
+<td>OK</td>
+</tr>
+<tr><td align=center rowspan=1><a href="http://www.genius.kye.de/">Genius</a></td>
+<td>ColorPage-HR5 (Pro)</td>
+<td>OK, SCSI-ID=KYE ColorPage-HR5</td>
+</tr>
+
+<tr>
+ <td align=left rowspan=1><a href="http://www.franken.de/users/solid/">v4l</a></td>
+ <td align=center rowspan=1>(0.1)</td>
+ <td align=center rowspan=1><font color=bb0000>alpha</font></td>
+<td align=center colspan=2>Interface to v4l API</td>
+<td> </td>
+<td align=center rowspan=1>?</td>
+
+<tr>
+ <td align=left rowspan=1><a href="http://video.inodes.org/sane-v4l2/">v4l2</a></td>
+ <td align=center rowspan=1>(19991125)</td>
+ <td align=center rowspan=1><font color=bb0000>alpha</font></td>
+<td align=center colspan=2>Interface to v4l 2 API</td>
+<td> </td>
+<td align=center rowspan=1>?</td>
+
+
+</table>
+</div>
+
+<font size=-1>
+<h3><a name="legend">Legend:</a></h3>
+<blockquote>
+<dl>
+ <dt><b>Backend:</b></dt>
+ <dd>Name of the backend, with a link to more extensive and detailed
+ information, if it exists.</dd>
+
+ <dt><b>Version:</b></dt>
+ <dd>Version of backend/driver distributed in the lastest SANE release.
+ Newer versions may be available from their home sites.</dd>
+
+ <dt><b>Status:</b></dt>
+ <dd>A vague indication of robustness and reliability.
+ <ul><li><font color="000080">NEW!</font> means brand-new to the current release of SANE.
+<li><font color="bb0000">alpha</font> means it must do something, but is not very well
+ tested, probably has bugs, and may even crash your
+ system, etc., etc.
+<li><font color="806000">beta</font> means it works pretty well, and looks stable and
+ functional, but not bullet-proof.
+<li><font color="008000">stable</font> means someone is pulling your leg.
+
+ </ul>
+ </dd>
+
+ <dt><b>Supported Devices:</b></dt>
+ <dd>Which hardware the backend supports.</dd>
+
+ <dt><b>Manual Page:</b></dt>
+ <dd>A link to the man-page on-line, if it exists.</dd>
+</dl>
+
+</blockquote>
+</font>
+
+<hr>
+<a href="http://www.mostang.com/sane/">[Back]</a>
+<address>
+<a href="mailto:sane-devel@mostang.com">sane-devel@mostang.com</a> / SANE Development mailing list
+</address>
+<font size=-1>
+This page was lasted updated on Mon Feb 21 08:57:23 2000
+</font>
+</body> </html>
--- /dev/null
+
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html> <head>
+<title>SANE: Backends (Drivers)</title>
+</head>
+
+<body bgcolor=FFFFFF>
+<div align=center>
+<img src="sane.png" alt="SANE">
+<h1>Backends (Drivers)</h1>
+</div>
+<hr>
+<p>The following table summarizes the backends/drivers distributed with
+SANE, and the hardware or software they support.
+
+<p>This is only a summary!
+Please consult the manpages and the author-supplied webpages for more
+detailed (and usually important) information concerning each backend.
+
+<p>If you have new information or corrections, please send e-mail
+to <a href="mailto:sane-devel@mostang.com">sane-devel@mostang.com</a>.
+
+<p>(For an explanation of the table, see the <a href="#legend">legend</a>.)
+
+<p>
+
+<div align=center>
+<table border=1>
+ <tr bgcolor=E0E0FF>
+ <th align=center rowspan=2>Backend</th>
+ <th align=center rowspan=2>Version</th>
+ <th align=center rowspan=2>Status</th>
+ <th align=center colspan=3>Supported Devices</th>
+ <th align=center rowspan=2>Manual Page</th>
+</tr>
+<tr bgcolor=E0E0FF>
+ <th align=center>Manufacturer</th>
+ <th align=center>Model</th>
+ <th align=center>Comment</th>
+</tr>
+
+
+<tr>
+ <td align=left rowspan=2><a href="http://aix2.uottawa.ca/~s1204672/sane/">abaton</a></td>
+ <td align=center rowspan=2>0.1</td>
+ <td align=center rowspan=2><font color=bb0000>alpha</font></td>
+<td align=center rowspan=2><a href="http://www.everex.com/">Abaton</a></td>
+<td>Scan 300/GS</td>
+<td>All known modes and functions supported</td>
+<td align=center rowspan=2><a href="http://www.mostang.com/sane/man/sane-abaton.5.html">sane-abaton</a></td>
+<tr><td>Scan 300/S</td>
+<td>Untested, use with caution</td>
+</tr>
+
+<tr>
+ <td align=left rowspan=6>agfafocus</td>
+ <td align=center rowspan=6>0.2</td>
+ <td align=center rowspan=6><font color=bb0000>alpha</font></td>
+<td align=center rowspan=5><a href="http://www.agfa.com/">AGFA</a></td>
+<td>Focus GS Scanner</td>
+<td>6 bit gray</td>
+<td align=center rowspan=6><a href="http://www.mostang.com/sane/man/sane-agfafocus.5.html">sane-agfafocus</a></td>
+<tr><td>Focus Lineart Scanner</td>
+<td>Lineart only? Untested.</td>
+</tr>
+<tr><td>Focus II</td>
+<td>gray only</td>
+</tr>
+<tr><td>Focus Color</td>
+<td> </td>
+</tr>
+<tr><td>Focus Color Plus</td>
+<td>3-pass</td>
+</tr>
+<tr><td align=center rowspan=1>Siemens</td>
+<td>S9036</td>
+<td>gray only</td>
+</tr>
+
+<tr>
+ <td align=left rowspan=3>apple</td>
+ <td align=center rowspan=3>0.31</td>
+ <td align=center rowspan=3><font color=bb0000>alpha</font></td>
+<td align=center rowspan=3><a href="ftp://ftpdev.info.apple.com/devworld/">Apple</a></td>
+<td>Apple Scanner</td>
+<td>4bit, 16 shades of gray</td>
+<td align=center rowspan=3><a href="http://www.mostang.com/sane/man/sane-apple.5.html">sane-apple</a></td>
+<tr><td>OneScanner</td>
+<td>8bit, 256 shades of gray. The backend needs work especially in the quantization code but it may work.</td>
+</tr>
+<tr><td>ColorOneScanner</td>
+<td>truecolor (needs much work) but it scans in non color modes.</td>
+</tr>
+
+<tr>
+ <td align=left rowspan=10><a href="http://www4.infi.net/~cpinkham/sane/sane-artec-doc.html">artec</a></td>
+ <td align=center rowspan=10>0.5.13</td>
+ <td align=center rowspan=10><font color=008000>stable</font></td>
+<td align=center rowspan=8><a href="http://www.artecusa.com/">Artec/Ultima</a></td>
+<td>AT3</td>
+<td>all modes working</td>
+<td align=center rowspan=10><a href="http://www.mostang.com/sane/man/sane-artec.5.html">sane-artec</a></td>
+<tr><td>A6000C</td>
+<td>all modes working</td>
+</tr>
+<tr><td>A6000C PLUS</td>
+<td>f/w <= v1.92 alpha, f/w >= v1.93 OK</td>
+</tr>
+<tr><td>AT6</td>
+<td>Unknown - please try</td>
+</tr>
+<tr><td>AT12</td>
+<td>all modes working</td>
+</tr>
+<tr><td>AM12S</td>
+<td>all modes working</td>
+</tr>
+<tr><td>parallel models</td>
+<td>Unsupported, see <a href='http://as6edriver.sourceforge.net/'>http://as6edriver.sourceforge.net</a></td>
+</tr>
+<tr><td>USB models</td>
+<td>Unsupported.</td>
+</tr>
+<tr><td align=center rowspan=1><a href="http://www.blackwidow.co.uk/">BlackWidow</a></td>
+<td>BW4800SP</td>
+<td>rebadged Artec AT3</td>
+</tr>
+<tr><td align=center rowspan=1><a href="http://www.plustek.com/">Plustek</a></td>
+<td>OpticPro 19200S</td>
+<td>rebadged Artec AM12S</td>
+</tr>
+
+<tr>
+ <td align=left rowspan=1><a href="http://www.rene.rebe.myokay.net/avision/index.html">avision</a></td>
+ <td align=center rowspan=1>0.2</td>
+ <td align=center rowspan=1><font color=806000>beta</font></td>
+<td align=center rowspan=1><a href="http://www.avision.com/">Avision</a></td>
+<td>AV 630 CS</td>
+<td>1 pass, 1200*600 DPI</td>
+<td align=center rowspan=1>?</td>
+
+<tr>
+ <td align=left rowspan=3><a href="http://www.rzg.mpg.de/~mpd/sane/">canon</a></td>
+ <td align=center rowspan=3>0.1</td>
+ <td align=center rowspan=3><font color=bb0000>alpha</font></td>
+<td align=center rowspan=3><a href="http://www.canon.com/">Canon</a></td>
+<td>CanoScan 300</td>
+<td>1 pass; flatbed scanner</td>
+<td align=center rowspan=3>?</td>
+<tr><td>CanoScan 600</td>
+<td>1 pass; flatbed scanner</td>
+</tr>
+<tr><td>CanoScan 2700F</td>
+<td>1 pass; film scanner</td>
+</tr>
+
+<tr>
+ <td align=left rowspan=2><a href="http://www.sema.be/coolscan/">coolscan</a></td>
+ <td align=center rowspan=2>0.3</td>
+ <td align=center rowspan=2><font color=806000>beta</font></td>
+<td align=center rowspan=2><a href="http://www.nikon.com/">Nikon</a></td>
+<td>LS-20</td>
+<td>The LS-20 has been replaced by the LS-30</td>
+<td align=center rowspan=2>?</td>
+<tr><td>LS-1000</td>
+<td>Doesn't support gamma correction</td>
+</tr>
+
+<tr>
+ <td align=left rowspan=1>dc210</td>
+ <td align=center rowspan=1>0.0</td>
+ <td align=center rowspan=1><font color=bb0000>alpha</font></td>
+<td align=center rowspan=1><a href="http://www.kodak.com/US/en/digital/cameras/DCSGateway.shtml">Kodak</a></td>
+<td>DC210</td>
+<td> </td>
+<td align=center rowspan=1><a href="http://www.mostang.com/sane/man/sane-dc210.5.html">sane-dc210</a></td>
+
+<tr>
+ <td align=left rowspan=2><a href="http://peter.fales.com/DC-25.html">dc25</a></td>
+ <td align=center rowspan=2>1.2</td>
+ <td align=center rowspan=2><font color=806000>beta</font></td>
+<td align=center rowspan=2><a href="http://www.kodak.com/US/en/digital/cameras/dc25/">Kodak</a></td>
+<td>DC25</td>
+<td> </td>
+<td align=center rowspan=2><a href="http://www.mostang.com/sane/man/sane-dc25.5.html">sane-dc25</a></td>
+<tr><td>DC20</td>
+<td>DC-20 untested by author but reported to work</td>
+</tr>
+
+<tr>
+ <td align=left rowspan=1>dll</td>
+ <td align=center rowspan=1>0.73</td>
+ <td align=center rowspan=1><font color=806000>beta</font></td>
+<td align=center colspan=2>Dynamic loading of shared-library backends.</td>
+<td> </td>
+<td align=center rowspan=1><a href="http://www.mostang.com/sane/man/sane-dll.5.html">sane-dll</a></td>
+
+<tr>
+ <td align=left rowspan=1>dmc</td>
+ <td align=center rowspan=1>1.0</td>
+ <td align=center rowspan=1><font color=008000>stable</font></td>
+<td align=center rowspan=1><a href="http://www.polaroid.com/">Polaroid</a></td>
+<td><a href="http://digitalimage.polaroid.com/products/digital_cameras/dmc/">DMC</a></td>
+<td> </td>
+<td align=center rowspan=1><a href="http://www.mostang.com/sane/man/sane-dmc.5.html">sane-dmc</a></td>
+
+<tr>
+ <td align=left rowspan=10><a href="http://www.khk.net/">epson</a></td>
+ <td align=center rowspan=10>0.1.15</td>
+ <td align=center rowspan=10><font color=bb0000>alpha</font></td>
+<td align=center rowspan=10><a href="http://www.epson.com/">Epson</a></td>
+<td>GT-5000</td>
+<td>parallel interface</td>
+<td align=center rowspan=10><a href="http://www.mostang.com/sane/man/sane-epson.5.html">sane-epson</a></td>
+<tr><td>GT-6000</td>
+<td>parallel interface</td>
+</tr>
+<tr><td>Actionscanner II</td>
+<td>parallel interface</td>
+</tr>
+<tr><td>GT-7000</td>
+<td> </td>
+</tr>
+<tr><td>Perfection 636S</td>
+<td> </td>
+</tr>
+<tr><td>Perfection 636U</td>
+<td>USB Interface</td>
+</tr>
+<tr><td>Perfection 1200S</td>
+<td> </td>
+</tr>
+<tr><td>Perfection 1200U</td>
+<td>USB Interface</td>
+</tr>
+<tr><td>Expression 636</td>
+<td> </td>
+</tr>
+<tr><td>FilmScan 200</td>
+<td>A better backend for the FilmScan 200 can be found at <A HREF="http://www.vjet.demon.co.uk/scanner/">http://www.vjet.demon.cu.uk/scanner/</A></td>
+</tr>
+
+<tr>
+ <td align=left rowspan=18><a href="http://www.kirchgessner.net/">hp</a></td>
+ <td align=center rowspan=18>0.86</td>
+ <td align=center rowspan=18><font color=806000>beta</font></td>
+<td align=center rowspan=18><a href="http://www.hp.com/">HP</a></td>
+<td>HP ScanJet Plus</td>
+<td> </td>
+<td align=center rowspan=18><a href="http://www.mostang.com/sane/man/sane-hp.5.html">sane-hp</a></td>
+<tr><td>HP ScanJet IIc</td>
+<td> </td>
+</tr>
+<tr><td>HP ScanJet IIp</td>
+<td> </td>
+</tr>
+<tr><td>HP ScanJet IIcx</td>
+<td> </td>
+</tr>
+<tr><td>HP ScanJet 3c</td>
+<td> </td>
+</tr>
+<tr><td>HP ScanJet 3p</td>
+<td> </td>
+</tr>
+<tr><td>HP ScanJet 4c</td>
+<td> </td>
+</tr>
+<tr><td>HP ScanJet 4p</td>
+<td> </td>
+</tr>
+<tr><td>HP ScanJet 4100C</td>
+<td> </td>
+</tr>
+<tr><td>HP ScanJet 5p</td>
+<td> </td>
+</tr>
+<tr><td>HP ScanJet 5100C</td>
+<td> </td>
+</tr>
+<tr><td>HP ScanJet 5200C</td>
+<td> </td>
+</tr>
+<tr><td>HP ScanJet 6100C</td>
+<td> </td>
+</tr>
+<tr><td>HP ScanJet 6200C</td>
+<td> </td>
+</tr>
+<tr><td>HP ScanJet 6250C</td>
+<td> </td>
+</tr>
+<tr><td>HP ScanJet 6300C</td>
+<td> </td>
+</tr>
+<tr><td>HP ScanJet 6350C</td>
+<td> </td>
+</tr>
+<tr><td>HP PhotoSmart PhotoScanner</td>
+<td>USB on HP ScanJet 4100C/5200C/6200C/6300C require USB driver. See http://www.jump.net/~dnelson/linux/usb (under development)</td>
+</tr>
+
+<tr>
+ <td align=left rowspan=1><a href="ftp://www.cs.ubishops.ca/pub/lhii/">lhii</a></td>
+ <td align=center rowspan=1>(0.1)</td>
+ <td align=center rowspan=1><font color=bb0000>alpha</font></td>
+<td align=center colspan=2><a href="http://www.willamowius.de/scanner.html">Linux Drivers for Handheld Scanners</a></td>
+<td> </td>
+<td align=center rowspan=1>?</td>
+
+<tr>
+ <td align=left rowspan=1><a href="http://www.aa.net/~bentson/sane.html">m3096g</a></td>
+ <td align=center rowspan=1>1.11</td>
+ <td align=center rowspan=1><font color=806000>beta</font></td>
+<td align=center rowspan=1><a href="http://www.fujitsu.com/scanners.html">Fujitsu</a></td>
+<td>M3096G</td>
+<td> </td>
+<td align=center rowspan=1><a href="http://www.mostang.com/sane/man/sane-fujitsu.5.html">sane-fujitsu</a></td>
+
+<tr>
+ <td align=left rowspan=19><a href="http://www.mir.com/mtek/">microtek</a></td>
+ <td align=center rowspan=19>0.12.0</td>
+ <td align=center rowspan=19><font color=806000>beta</font></td>
+<td align=center rowspan=14><a href="http://www.microtek.com/">Microtek</a></td>
+<td>Scanmaker E6</td>
+<td> </td>
+<td align=center rowspan=19><a href="http://www.mostang.com/sane/man/sane-microtek.5.html">sane-microtek</a></td>
+<tr><td>Scanmaker E3</td>
+<td> </td>
+</tr>
+<tr><td>Scanmaker E2</td>
+<td>3-pass</td>
+</tr>
+<tr><td>Scanmaker 35t+</td>
+<td>slide-scanner</td>
+</tr>
+<tr><td>Scanmaker 45t</td>
+<td>slide-scanner</td>
+</tr>
+<tr><td>Scanmaker 35</td>
+<td>slide-scanner</td>
+</tr>
+<tr><td>Scanmaker III</td>
+<td> </td>
+</tr>
+<tr><td>Scanmaker IISP</td>
+<td> </td>
+</tr>
+<tr><td>Scanmaker IIHR</td>
+<td>3-pass</td>
+</tr>
+<tr><td>Scanmaker IIG</td>
+<td>gray only</td>
+</tr>
+<tr><td>Scanmaker II</td>
+<td>3-pass</td>
+</tr>
+<tr><td>Scanmaker 600Z(S)</td>
+<td>untested (color?)</td>
+</tr>
+<tr><td>Scanmaker 600G(S)</td>
+<td>gray only (see manpage)</td>
+</tr>
+<tr><td>Color PageWiz</td>
+<td>sheet-fed (preliminary)</td>
+</tr>
+<tr><td align=center rowspan=5><a href="http://www.agfa.com/">Agfa</a></td>
+<td>Arcus II</td>
+<td>Arcus *II*, not Arcus!</td>
+</tr>
+<tr><td>StudioScan</td>
+<td> </td>
+</tr>
+<tr><td>StudioScan II</td>
+<td> </td>
+</tr>
+<tr><td>StudioScan IIsi</td>
+<td> </td>
+</tr>
+<tr><td>DuoScan</td>
+<td>preliminary</td>
+</tr>
+
+<tr>
+ <td align=left rowspan=13>microtek2</td>
+ <td align=center rowspan=13>pre0.8.161099</td>
+ <td align=center rowspan=13><font color=bb0000>alpha</font></td>
+<td align=center rowspan=12><a href="http://www.microtek.com/">Microtek</a></td>
+<td>parallel models unsupported</td>
+<td> </td>
+<td align=center rowspan=13><a href="http://www.mostang.com/sane/man/sane-microtek2.5.html">sane-microtek2</a></td>
+<tr><td>ScanMaker V300</td>
+<td> </td>
+</tr>
+<tr><td>ScanMaker V310</td>
+<td> </td>
+</tr>
+<tr><td>ScanMaker V600</td>
+<td> </td>
+</tr>
+<tr><td>ScanMaker E3plus</td>
+<td> </td>
+</tr>
+<tr><td>ScanMaker X6</td>
+<td> </td>
+</tr>
+<tr><td>ScanMaker X6EL</td>
+<td> </td>
+</tr>
+<tr><td>ScanMaker 330</td>
+<td> </td>
+</tr>
+<tr><td>ScanMaker 630</td>
+<td> </td>
+</tr>
+<tr><td>ScanMaker 636</td>
+<td> </td>
+</tr>
+<tr><td>ScanMaker 9600XL</td>
+<td>only flatbed mode ?</td>
+</tr>
+<tr><td>Phantom 636</td>
+<td> </td>
+</tr>
+<tr><td align=center rowspan=1><a href="http://www.vobis.de/">Vobis</a></td>
+<td>HighScan</td>
+<td>only E3plus based models</td>
+</tr>
+
+<tr>
+ <td align=left rowspan=12>mustek</td>
+ <td align=center rowspan=12>0.73</td>
+ <td align=center rowspan=12><font color=806000>beta</font></td>
+<td align=center rowspan=12><a href="http://www.mustek.com/">Mustek</a></td>
+<td>MFC-600S</td>
+<td>1 pass; (f/w >= 1.01; scsi id MFC-06000CZ)</td>
+<td align=center rowspan=12><a href="http://www.mostang.com/sane/man/sane-mustek.5.html">sane-mustek</a></td>
+<tr><td>MFC-600CD</td>
+<td>1 pass; (f/w >= 2.03; scsi id MFC-06000CZ)</td>
+</tr>
+<tr><td>MFS-6000CX</td>
+<td>3 pass; (f/w >= 2.71; scsi id MSF-06000CX)</td>
+</tr>
+<tr><td>MSF-6000SP</td>
+<td>1 pass; (f/w >= 3.12; scsi id MSF-06000SP)</td>
+</tr>
+<tr><td>MFS-8000SP</td>
+<td>1 pass; (f/w >= 2.05; scsi id MSF-08000SP) lineart drops lines?</td>
+</tr>
+<tr><td>MFC-800S</td>
+<td>1 pass; (f/w == 1.06; scsi id MFC-08000CZ) color fails?</td>
+</tr>
+<tr><td>MFS-1200SP</td>
+<td>1 pass; (f/w == 1.00; scsi id MSF-12000SP)</td>
+</tr>
+<tr><td>MFS-1200SP</td>
+<td>1 pass; (f/w == 1.07; scsi id MFS-12000SP)</td>
+</tr>
+<tr><td>MFS-1200SP</td>
+<td>1 pass; (f/w == 1.02; scsi id MFS-12000SP) color fails?</td>
+</tr>
+<tr><td>MFS-12000CX</td>
+<td>3 pass; (f/w == 2.71; scsi id MFS-12000CX)</td>
+</tr>
+<tr><td>SE-6000SP</td>
+<td>1 pass; (f/w == ? ; scsi id C03 S10IDW)</td>
+</tr>
+<tr><td>SE-12000SP</td>
+<td>1 pass; (f/w == 1.01; scsi id C06 S12IDW)</td>
+</tr>
+
+<tr>
+ <td align=left rowspan=1><a href="http://www.i2k.com/~jeffd/a4s2/">musteka4s2</a></td>
+ <td align=center rowspan=1>(0.3)</td>
+ <td align=center rowspan=1><font color=806000>beta</font></td>
+<td align=center rowspan=1><a href="http://www.mustek.com/">Mustek</a></td>
+<td>MFS-600IIIP</td>
+<td>Mustek 600 III EP Plus</td>
+<td align=center rowspan=1><a href="http://www.mostang.com/sane/man/sane-musteka4s2.5.html">sane-musteka4s2</a></td>
+
+<tr>
+ <td align=left rowspan=2><a href="mailto:fukuda@avm.nhe.nec.co.jp">nec</a></td>
+ <td align=center rowspan=2>(0.10)</td>
+ <td align=center rowspan=2><font color=000080>NEW!</font></td>
+<td align=center rowspan=2><a href="http://www.nec.co.jp/">NEC</a></td>
+<td>PC-IN500/4C</td>
+<td>PC-IN500/4C was sold only in JAPAN</td>
+<td align=center rowspan=2>?</td>
+<tr><td>PC-IN600,700,800 series</td>
+<td>PC-IN600,700,800 series is not supprted</td>
+</tr>
+
+<tr>
+ <td align=left rowspan=1>net</td>
+ <td align=center rowspan=1>0.73</td>
+ <td align=center rowspan=1><font color=806000>beta</font></td>
+<td align=center colspan=2>Network access to saned servers</td>
+<td> </td>
+<td align=center rowspan=1><a href="http://www.mostang.com/sane/man/sane-net.5.html">sane-net</a></td>
+
+<tr>
+ <td align=left rowspan=1>pint</td>
+ <td align=center rowspan=1>?</td>
+ <td align=center rowspan=1><font color=bb0000>alpha</font></td>
+<td align=center colspan=2>Scanners with the machine-independent PINT interface</td>
+<td> </td>
+<td align=center rowspan=1><a href="http://www.mostang.com/sane/man/sane-pint.5.html">sane-pint</a></td>
+
+<tr>
+ <td align=left rowspan=3><a href="http://www.efn.org/~rick/plustek/">plustek</a></td>
+ <td align=center rowspan=3>(0.27)</td>
+ <td align=center rowspan=3><font color=806000>beta</font></td>
+<td align=center rowspan=3><a href="http://www.plustek.com/">Plustek</a></td>
+<td>Plustek 4830</td>
+<td>OK</td>
+<td align=center rowspan=3>?</td>
+<tr><td>Plustek 9630</td>
+<td>Doesn't work</td>
+</tr>
+<tr><td>Plustek OpticPro 600</td>
+<td>Doesn't work</td>
+</tr>
+
+<tr>
+ <td align=left rowspan=1>pnm</td>
+ <td align=center rowspan=1>?</td>
+ <td align=center rowspan=1><font color=806000>beta</font></td>
+<td align=center colspan=2>Reads PNM files</td>
+<td>Used for debugging frontends</td>
+<td align=center rowspan=1><a href="http://www.mostang.com/sane/man/sane-pnm.5.html">sane-pnm</a></td>
+
+<tr>
+ <td align=left rowspan=2>qcam</td>
+ <td align=center rowspan=2>?</td>
+ <td align=center rowspan=2><font color=bb0000>alpha</font></td>
+<td align=center rowspan=2><a href="http://www.connectix.com/">Connectix</a></td>
+<td>Color QuickCam</td>
+<td>Require root privileges.</td>
+<td align=center rowspan=2><a href="http://www.mostang.com/sane/man/sane-qcam.5.html">sane-qcam</a></td>
+<tr><td>Greyscale QuickCam</td>
+<td>Require root privileges. Partly working.</td>
+</tr>
+
+<tr>
+ <td align=left rowspan=2>ricoh</td>
+ <td align=center rowspan=2>?</td>
+ <td align=center rowspan=2><font color=bb0000>alpha</font></td>
+<td align=center rowspan=2><a href="http://www.ricoh.com/">Ricoh</a></td>
+<td>Ricoh IS50</td>
+<td>?</td>
+<td align=center rowspan=2>?</td>
+<tr><td>Ricoh IS60</td>
+<td>?</td>
+</tr>
+
+<tr>
+ <td align=left rowspan=1>s9036</td>
+ <td align=center rowspan=1>?</td>
+ <td align=center rowspan=1><font color=bb0000>alpha</font></td>
+<td align=center rowspan=1><a href="http://www.siemens.com/">Siemens</a></td>
+<td>9036 Flatbed scanner</td>
+<td> </td>
+<td align=center rowspan=1>?</td>
+
+<tr>
+ <td align=left rowspan=2><a href="http://www.cs.uni-magdeburg.de/~aherms/sane-sagitta.html">sagitta</a></td>
+ <td align=center rowspan=2>(0.4)</td>
+ <td align=center rowspan=2><font color=bb0000>alpha</font></td>
+<td align=center rowspan=2><a href="http://www.qtronix.com">Qtronix</a></td>
+<td>Sagitta Gray</td>
+<td>no monocrome-mode at the moment</td>
+<td align=center rowspan=2>?</td>
+<tr><td>Sagitta Color</td>
+<td>not supported at the moment</td>
+</tr>
+
+<tr>
+ <td align=left rowspan=3><a href="http://www.satzbau-gmbh.de/staff/abel/sane-sharp.html">sharp</a></td>
+ <td align=center rowspan=3>0.30</td>
+ <td align=center rowspan=3><font color=806000>beta</font></td>
+<td align=center rowspan=3><a href="http://sharp-world.com/">SHARP</a></td>
+<td>JX-610</td>
+<td></td>
+<td align=center rowspan=3>?</td>
+<tr><td>JX-250</td>
+<td></td>
+</tr>
+<tr><td>JX-330</td>
+<td>backend is not yet tested with a JX 330!</td>
+</tr>
+
+<tr>
+ <td align=left rowspan=8><a href="http://www.cs.ualberta.ca/~charter/SnapScan/snapscan.html">SnapScan</a></td>
+ <td align=center rowspan=8>0.7</td>
+ <td align=center rowspan=8><font color=bb0000>alpha</font></td>
+<td align=center rowspan=4><a href="http://www.agfa.com/">AGFA</a></td>
+<td>SnapScan 300</td>
+<td>Only 8 bits/sample at present.</td>
+<td align=center rowspan=8>?</td>
+<tr><td>SnapScan 310</td>
+<td>Ditto</td>
+</tr>
+<tr><td>SnapScan 600</td>
+<td>Ditto</td>
+</tr>
+<tr><td>SnapScan 1236s</td>
+<td>Ditto. Have no specific programming info yet.</td>
+</tr>
+<tr><td align=center rowspan=1>Vuego</td>
+<td>310s</td>
+<td>Close SnapScan 310 compatible.</td>
+</tr>
+<tr><td align=center rowspan=2>Acer</td>
+<td>310s</td>
+<td>Same thing as the Vuego 310s.</td>
+</tr>
+<tr><td>Prisa 620s</td>
+<td>Seems to be a close SnapScan 310/600 compatible.</td>
+</tr>
+<tr><td align=center rowspan=1>Guillemot International</td>
+<td>Maxi Scan A4 Deluxe (SCSI)</td>
+<td>May be a repackaged Vuego 310s or SnapScan 310s.</td>
+</tr>
+
+<tr>
+ <td align=left rowspan=1><a href="http://www.aa.net/~bentson/sane.html">sp15c</a></td>
+ <td align=center rowspan=1>1.12</td>
+ <td align=center rowspan=1><font color=806000>beta</font></td>
+<td align=center rowspan=1><a href="http://www.fujitsu.com/scanners.html">Fujitsu Computer Products of America</a></td>
+<td>SP15C</td>
+<td> </td>
+<td align=center rowspan=1><a href="http://www.mostang.com/sane/man/sane-fujitsu.5.html">sane-fujitsu</a></td>
+
+<tr>
+ <td align=left rowspan=1><a href="http://www.informatik.uni-oldenburg.de/~ingo/sane/">st400</a></td>
+ <td align=center rowspan=1>(1.4)</td>
+ <td align=center rowspan=1><font color=bb0000>alpha</font></td>
+<td align=center rowspan=1><a href="http://www.siemens.de/">Siemens</a></td>
+<td>ST400</td>
+<td>6 bit gray</td>
+<td align=center rowspan=1><a href="http://www.mostang.com/sane/man/sane-st400.5.html">sane-st400</a></td>
+
+<tr>
+ <td align=left rowspan=3>tamarack</td>
+ <td align=center rowspan=3>0.5</td>
+ <td align=center rowspan=3><font color=806000>beta</font></td>
+<td align=center rowspan=3><a href="http://www.tamarack.net/">Tamarack</a></td>
+<td>Artiscan 6000C</td>
+<td>3 pass, 300 DPI</td>
+<td align=center rowspan=3>?</td>
+<tr><td>Artiscan 8000C</td>
+<td>3 pass, 400 DPI</td>
+</tr>
+<tr><td>Artiscan 12000C</td>
+<td>3 pass, 600 DPI</td>
+</tr>
+
+<tr>
+ <td align=left rowspan=48><a href="http://www.wolfsburg.de/~rauch/sane/sane-umax.html">umax</a></td>
+ <td align=center rowspan=48>1.0-18</td>
+ <td align=center rowspan=48><font color=008000>stable</font></td>
+<td align=center rowspan=35><a href="http://support.umax.co.uk/">UMAX</a></td>
+<td>parallel scanners</td>
+<td>Not supported!!!</td>
+<td align=center rowspan=48><a href="http://www.mostang.com/sane/man/sane-umax.5.html">sane-umax</a></td>
+<tr><td>USB scanners</td>
+<td>Not supported!!!</td>
+</tr>
+<tr><td>Vista S6</td>
+<td>OK</td>
+</tr>
+<tr><td>Vista S6E</td>
+<td>OK</td>
+</tr>
+<tr><td>UMAX S-6E</td>
+<td>OK</td>
+</tr>
+<tr><td>UMAX S-6EG</td>
+<td>OK</td>
+</tr>
+<tr><td>Vista-S8</td>
+<td>OK</td>
+</tr>
+<tr><td>Supervista S-12</td>
+<td>OK</td>
+</tr>
+<tr><td>UMAX S-12</td>
+<td>OK</td>
+</tr>
+<tr><td>UMAX S-12G</td>
+<td>OK</td>
+</tr>
+<tr><td>Astra 600S</td>
+<td>OK</td>
+</tr>
+<tr><td>Astra 610S</td>
+<td>OK</td>
+</tr>
+<tr><td>Astra 1200S</td>
+<td>OK</td>
+</tr>
+<tr><td>Astra 1220S</td>
+<td>OK</td>
+</tr>
+<tr><td>Astra 2200W</td>
+<td>OK</td>
+</tr>
+<tr><td>Astra 2400S</td>
+<td>OK</td>
+</tr>
+<tr><td>Mirage D-16L</td>
+<td>OK</td>
+</tr>
+<tr><td>Mirage II</td>
+<td>Not tested</td>
+</tr>
+<tr><td>Mirage IIse</td>
+<td>Not tested</td>
+</tr>
+<tr><td>PSD</td>
+<td>OK</td>
+</tr>
+<tr><td>PowerLook</td>
+<td>Not tested</td>
+</tr>
+<tr><td>PL-II</td>
+<td>Not tested</td>
+</tr>
+<tr><td>PowerLook III</td>
+<td>Not tested</td>
+</tr>
+<tr><td>PowerLook 2000</td>
+<td>Not tested</td>
+</tr>
+<tr><td>PowerLook 3000</td>
+<td>Not tested</td>
+</tr>
+<tr><td>Gemini D-16</td>
+<td>OK</td>
+</tr>
+<tr><td>UMAX VT600</td>
+<td>not tested</td>
+</tr>
+<tr><td>Vista-T630</td>
+<td>OK for some firmwareversions, on others only lineart OK</td>
+</tr>
+<tr><td>UC 630</td>
+<td>Version 1.6(?) or 2.8(?) OK, others only lineart OK</td>
+</tr>
+<tr><td>UG 630</td>
+<td>OK</td>
+</tr>
+<tr><td>UG 80</td>
+<td>OK</td>
+</tr>
+<tr><td>UC 840</td>
+<td>Version 1.6 OK, others only lineart OK</td>
+</tr>
+<tr><td>UC 1200S</td>
+<td>unknown - please try</td>
+</tr>
+<tr><td>UC 1200SE</td>
+<td>unknown - please try</td>
+</tr>
+<tr><td>UC 1260</td>
+<td>Version 1.6 OK, others unknown</td>
+</tr>
+<tr><td align=center rowspan=9><a href="http://www.heidelberg-cps.com/">Linotype Hell</a></td>
+<td>Jade</td>
+<td>OK, SCSI-ID=LinoHell Office</td>
+</tr>
+<tr><td>Jade2</td>
+<td>OK, SCSI-ID=LinoHell Office2</td>
+</tr>
+<tr><td>Saphir</td>
+<td>Not tested</td>
+</tr>
+<tr><td>Saphir2</td>
+<td>OK, SCSI-ID=LinoHell SAPHIR2</td>
+</tr>
+<tr><td>Saphir Ultra</td>
+<td>Not tested</td>
+</tr>
+<tr><td>Saphir Ultra II</td>
+<td>Not tested</td>
+</tr>
+<tr><td>Saphir HiRes</td>
+<td>Not tested</td>
+</tr>
+<tr><td>Opal</td>
+<td>Not tested</td>
+</tr>
+<tr><td>Opal Ultra</td>
+<td>Not tested</td>
+</tr>
+<tr><td align=center rowspan=1><a href="http://www.vobis.de/">Vobis/Highscreen</a></td>
+<td>Scanboostar Premium</td>
+<td>OK, SCSI-ID=LinoHell Office2</td>
+</tr>
+<tr><td align=center rowspan=1>Escom</td>
+<td>Image Scanner 256</td>
+<td>OK, SCSI-ID=UMAX UG 80</td>
+</tr>
+<tr><td align=center rowspan=1><a href="http://www.nikon.com/">Nikon</a></td>
+<td>AX-210</td>
+<td>OK</td>
+</tr>
+<tr><td align=center rowspan=1><a href="http://www.genius.kye.de/">Genius</a></td>
+<td>ColorPage-HR5 (Pro)</td>
+<td>OK, SCSI-ID=KYE ColorPage-HR5</td>
+</tr>
+
+<tr>
+ <td align=left rowspan=1><a href="http://www.franken.de/users/solid/">v4l</a></td>
+ <td align=center rowspan=1>(0.1)</td>
+ <td align=center rowspan=1><font color=bb0000>alpha</font></td>
+<td align=center colspan=2>Interface to Video For Linux API</td>
+<td> </td>
+<td align=center rowspan=1>?</td>
+
+<tr>
+ <td align=left rowspan=1><a href="http://video.inodes.org/sane-v4l2/">v4l2</a></td>
+ <td align=center rowspan=1>(19991125)</td>
+ <td align=center rowspan=1><font color=bb0000>alpha</font></td>
+<td align=center colspan=2>Interface to Video For Linux 2 API</td>
+<td> </td>
+<td align=center rowspan=1>?</td>
+
+
+</table>
+</div>
+
+<font size=-1>
+<h3><a name="legend">Legend:</a></h3>
+<blockquote>
+<dl>
+ <dt><b>Backend:</b></dt>
+ <dd>Name of the backend, with a link to more extensive and detailed
+ information, if it exists.</dd>
+
+ <dt><b>Version:</b></dt>
+ <dd>Version of backend/driver distributed in the lastest SANE release.
+ Newer versions may be available from their home sites. If the
+ version number is in parentheses, the backend is not included in
+ the SANE distribution.</dd>
+
+ <dt><b>Status:</b></dt>
+ <dd>A vague indication of robustness and reliability.
+ <ul><li><font color="000080">NEW!</font> means brand-new to the current release of SANE.
+<li><font color="bb0000">alpha</font> means it must do something, but is not very well
+ tested, probably has bugs, and may even crash your
+ system, etc., etc.
+<li><font color="806000">beta</font> means it works pretty well, and looks stable and
+ functional, but not bullet-proof.
+<li><font color="008000">stable</font> means someone is pulling your leg.
+
+ </ul>
+ </dd>
+
+ <dt><b>Supported Devices:</b></dt>
+ <dd>Which hardware the backend supports.</dd>
+
+ <dt><b>Manual Page:</b></dt>
+ <dd>A link to the man-page on-line, if it exists.</dd>
+</dl>
+
+</blockquote>
+</font>
+
+<hr>
+<a href="http://www.mostang.com/sane/">[Back]</a>
+<address>
+<a href="mailto:sane-devel@mostang.com">sane-devel@mostang.com</a> / SANE Development mailing list
+</address>
+<font size=-1>
+This page was lasted updated on Sun Feb 27 19:52:29 2000
+</font>
+</body> </html>
--- /dev/null
+diff -ru sane-pre1.01-4/ChangeLog sane-pre1.01-4-pere/ChangeLog
+--- sane-pre1.01-4/ChangeLog Sun Apr 4 01:17:20 1999
++++ sane-pre1.01-4-pere/ChangeLog Fri Apr 9 14:25:28 1999
+@@ -1,3 +1,8 @@
++1999-04-08 Petter Reinholdtsen <pere@td.org.uit.no>
++ * include/sane/config.h.in include/sane/sane.h backend/dll.c
++ backend/net.c: Added initial Win32 patches. Win32 dll support
++ should be complete.
++
+ 1999-04-03 David Mosberger-Tang <David.Mosberger@acm.org>
+
+ * include/sane/sanei_debug.h: Define sanei_debug_BACKEND_NAME only
+diff -ru sane-pre1.01-4/backend/dll.c sane-pre1.01-4-pere/backend/dll.c
+--- sane-pre1.01-4/backend/dll.c Sun Feb 28 00:51:37 1999
++++ sane-pre1.01-4-pere/backend/dll.c Fri Apr 9 01:20:39 1999
+@@ -54,6 +54,9 @@
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
++#ifdef HAVE_WINDOWS_H
++# include <windows.h>
++#endif
+
+ #if defined(HAVE_DLOPEN) && defined(HAVE_DLFCN_H)
+ # include <dlfcn.h>
+@@ -68,12 +71,29 @@
+ # ifndef RTLD_LAZY
+ # define RTLD_LAZY 1
+ # endif
++# if defined(_AIX)
++# define DLL_PATH_ENV "LIBPATH"
++# else
++# define DLL_PATH_ENV "LD_LIBRARY_PATH"
++# endif
++# define DLL_PATH_SEPARATOR ":"
++# define DLL_SLASH "/"
++# define DLL_NAME "libsane-%s.so." STRINGIFY(V_MAJOR)
+ # define HAVE_DLL
+-#endif
+-
++#elif defined (HAVE_SHL_LOAD) && defined(HAVE_DL_H)
+ /* HP/UX DLL support */
+-#if defined (HAVE_SHL_LOAD) && defined(HAVE_DL_H)
+ # include <dl.h>
++# define DLL_PATH_ENV "SHLIB_PATH"
++# define DLL_PATH_SEPARATOR ":"
++# define DLL_SLASH "/"
++# define DLL_NAME "libsane-%s.sl." STRINGIFY(V_MAJOR)
++# define HAVE_DLL
++#elif defined(HAVE_LOADLIBRARY)
++/* Win32 */
++# define DLL_PATH_ENV "PATH"
++# define DLL_PATH_SEPARATOR ";"
++# define DLL_SLASH "\\"
++# define DLL_NAME "sane%s.dll"
+ # define HAVE_DLL
+ #endif
+
+@@ -230,24 +250,11 @@
+ load (struct backend *be)
+ {
+ #ifdef HAVE_DLL
+- int mode = 0;
+ char *funcname, *src, *dir, *path = 0;
+ char libname[PATH_MAX];
+ int i;
+ FILE *fp = 0;
+
+-#if defined(HAVE_DLOPEN)
+-# define PREFIX "libsane-"
+-# define POSTFIX ".so.%u"
+- mode = getenv ("LD_BIND_NOW") ? RTLD_NOW : RTLD_LAZY;
+-#elif defined(HAVE_SHL_LOAD)
+-# define PREFIX "libsane-"
+-# define POSTFIX ".sl.%u"
+- mode = BIND_DEFERRED;
+-#else
+-# error "Tried to compile unsupported DLL."
+-#endif /* HAVE_DLOPEN */
+-
+ DBG(1, "loading backend %s\n", be->name);
+
+ /* initialize all ops to "unsupported" so we can "use" the backend
+@@ -260,28 +267,22 @@
+ dir = STRINGIFY(LIBDIR);
+ while (dir)
+ {
+- snprintf (libname, sizeof (libname), "%s/"PREFIX"%s"POSTFIX,
+- dir, be->name, V_MAJOR);
++ snprintf (libname, sizeof (libname), "%s" DLL_SLASH DLL_NAME,
++ dir, be->name);
+ fp = fopen (libname, "r");
+ if (fp)
+ break;
+
+ if (!path)
+ {
+- path = getenv ("LD_LIBRARY_PATH");
+- if (!path)
+- {
+- path = getenv ("SHLIB_PATH"); /* for HP-UX */
+- if (!path)
+- path = getenv ("LIBPATH"); /* for AIX */
+- }
++ path = getenv (DLL_PATH_ENV);
+ if (!path)
+ break;
+
+ path = strdup (path);
+ src = path;
+ }
+- dir = strsep (&src, ":");
++ dir = strsep (&src, DLL_PATH_SEPARATOR);
+ }
+ if (path)
+ free (path);
+@@ -294,9 +295,11 @@
+ DBG(2, "dlopen()ing `%s'\n", libname);
+
+ #ifdef HAVE_DLOPEN
+- be->handle = dlopen (libname, mode);
++ be->handle = dlopen (libname, getenv ("LD_BIND_NOW") ? RTLD_NOW : RTLD_LAZY);
+ #elif defined(HAVE_SHL_LOAD)
+- be->handle = (shl_t)shl_load (libname, mode, 0L);
++ be->handle = (shl_t)shl_load (libname, BIND_DEFERRED, 0L);
++#elif defined(HAVE_LOADLIBRARY)
++ be->handle = LoadLibrary(libname);
+ #else
+ # error "Tried to compile unsupported DLL."
+ #endif /* HAVE_DLOPEN */
+@@ -319,6 +322,8 @@
+ op = (void *(*)()) dlsym (be->handle, funcname + 1);
+ #elif defined(HAVE_SHL_LOAD)
+ shl_findsym ((shl_t*)&(be->handle), funcname + 1, TYPE_UNDEFINED, &op);
++#elif defined(HAVE_LOADLIBRARY)
++ op = GetProcAddress(be->handle, funcname + 1);
+ #else
+ # error "Tried to compile unsupported DLL."
+ #endif /* HAVE_DLOPEN */
+@@ -331,6 +336,8 @@
+ op = (void *(*)()) dlsym (be->handle, funcname);
+ #elif defined(HAVE_SHL_LOAD)
+ shl_findsym (be->handle, funcname, TYPE_UNDEFINED, &op);
++#elif defined(HAVE_LOADLIBRARY)
++ op = GetProcAddress(be->handle, funcname);
+ #else
+ # error "Tried to compile unsupported DLL."
+ #endif /* HAVE_DLOPEN */
+@@ -343,8 +350,6 @@
+
+ return SANE_STATUS_GOOD;
+
+-# undef PREFIX
+-# undef POSTFIX
+ #else /* HAVE_DLL */
+ DBG(1, "load: ignoring attempt to load `%s'; compiled without dl support\n",
+ be->name);
+@@ -379,7 +384,7 @@
+ return SANE_STATUS_GOOD;
+ }
+
+-SANE_Status
++DLLEXPORT SANE_Status DLLCALL
+ sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize)
+ {
+ char backend_name[PATH_MAX];
+@@ -425,7 +430,7 @@
+ return SANE_STATUS_GOOD;
+ }
+
+-void
++DLLEXPORT void DLLCALL
+ sane_exit (void)
+ {
+ struct backend *be, *next;
+@@ -441,15 +446,18 @@
+ (*be->op[OP_EXIT]) ();
+ #ifdef HAVE_DLL
+
+-#ifdef HAVE_DLOPEN
+ if (be->handle)
+- dlclose (be->handle);
++ {
++#ifdef HAVE_DLOPEN
++ dlclose (be->handle);
+ #elif defined(HAVE_SHL_LOAD)
+- if (be->handle)
+- shl_unload(be->handle);
++ shl_unload(be->handle);
++#elif defined(HAVE_LOADLIBRARY)
++ FreeLibrary(be->handle);
+ #else
+ # error "Tried to compile unsupported DLL."
+ #endif /* HAVE_DLOPEN */
++ }
+
+ #endif /* HAVE_DLL */
+ }
+@@ -468,7 +476,7 @@
+ (assuming you know the name of the backend/device). This is
+ appropriate for the command-line interface of SANE, for example.
+ */
+-SANE_Status
++DLLEXPORT SANE_Status DLLCALL
+ sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only)
+ {
+ static int devlist_size = 0, devlist_len = 0;
+@@ -549,7 +557,7 @@
+ return SANE_STATUS_GOOD;
+ }
+
+-SANE_Status
++DLLEXPORT SANE_Status DLLCALL
+ sane_open (SANE_String_Const full_name, SANE_Handle * meta_handle)
+ {
+ const char *be_name, *dev_name;
+@@ -619,7 +627,7 @@
+ return SANE_STATUS_GOOD;
+ }
+
+-void
++DLLEXPORT void DLLCALL
+ sane_close (SANE_Handle handle)
+ {
+ struct meta_scanner *s = handle;
+@@ -629,7 +637,7 @@
+ free (s);
+ }
+
+-const SANE_Option_Descriptor *
++DLLEXPORT const SANE_Option_Descriptor * DLLCALL
+ sane_get_option_descriptor (SANE_Handle handle, SANE_Int option)
+ {
+ struct meta_scanner *s = handle;
+@@ -638,7 +646,7 @@
+ return (*s->be->op[OP_GET_OPTION_DESC]) (s->handle, option);
+ }
+
+-SANE_Status
++DLLEXPORT SANE_Status DLLCALL
+ sane_control_option (SANE_Handle handle, SANE_Int option,
+ SANE_Action action, void *value, SANE_Word * info)
+ {
+@@ -650,7 +658,7 @@
+ value, info);
+ }
+
+-SANE_Status
++DLLEXPORT SANE_Status DLLCALL
+ sane_get_parameters (SANE_Handle handle, SANE_Parameters * params)
+ {
+ struct meta_scanner *s = handle;
+@@ -659,7 +667,7 @@
+ return (long) (*s->be->op[OP_GET_PARAMS]) (s->handle, params);
+ }
+
+-SANE_Status
++DLLEXPORT SANE_Status DLLCALL
+ sane_start (SANE_Handle handle)
+ {
+ struct meta_scanner *s = handle;
+@@ -668,7 +676,7 @@
+ return (long) (*s->be->op[OP_START]) (s->handle);
+ }
+
+-SANE_Status
++DLLEXPORT SANE_Status DLLCALL
+ sane_read (SANE_Handle handle, SANE_Byte * data, SANE_Int max_length,
+ SANE_Int * length)
+ {
+@@ -679,7 +687,7 @@
+ return (long) (*s->be->op[OP_READ]) (s->handle, data, max_length, length);
+ }
+
+-void
++DLLEXPORT void DLLCALL
+ sane_cancel (SANE_Handle handle)
+ {
+ struct meta_scanner *s = handle;
+@@ -688,7 +696,7 @@
+ (*s->be->op[OP_CANCEL]) (s->handle);
+ }
+
+-SANE_Status
++DLLEXPORT SANE_Status DLLCALL
+ sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking)
+ {
+ struct meta_scanner *s = handle;
+@@ -697,7 +705,7 @@
+ return (long) (*s->be->op[OP_SET_IO_MODE]) (s->handle, non_blocking);
+ }
+
+-SANE_Status
++DLLEXPORT SANE_Status DLLCALL
+ sane_get_select_fd (SANE_Handle handle, SANE_Int * fd)
+ {
+ struct meta_scanner *s = handle;
+diff -ru sane-pre1.01-4/backend/net.c sane-pre1.01-4-pere/backend/net.c
+--- sane-pre1.01-4/backend/net.c Sat Apr 3 06:43:01 1999
++++ sane-pre1.01-4-pere/backend/net.c Fri Apr 9 13:02:41 1999
+@@ -63,6 +63,26 @@
+ #include <netinet/in.h>
+ #include <netdb.h> /* OS/2 needs this _after_ <netinet/in.h>, grrr... */
+
++#ifdef HAVE_WINDOWS_H
++# define HAVE_WIN32
++# include <windows.h>
++# include <io.h>
++# include <winsock.h>
++# include <malloc.h>
++# define NETREAD recv
++# define NETWRITE send
++# define NETCLOSE closesocket
++# warning "Username is hardcoded!"
++# define USERNAME "hardcoded"
++# define SOCKET_OK(s) (s != INVALID_SOCKET)
++#else
++# define NETREAD read
++# define NETWRITE write
++# define NETCLOSE close
++# define USERNAME getlogin()
++# define SOCKET_OK(s) (s >= 0)
++#endif
++
+ #include <sane/sane.h>
+ #include <sane/sanei.h>
+ #include <sane/sanei_net.h>
+@@ -149,7 +169,7 @@
+ }
+
+ dev->ctl = socket (dev->addr.sa_family, SOCK_STREAM, 0);
+- if (dev->ctl < 0)
++ if (!SOCKET_OK(dev->ctl))
+ {
+ DBG(1, "connect_dev: failed to obtain socket (%s)\n", strerror (errno));
+ dev->ctl = -1;
+@@ -188,13 +208,13 @@
+
+ sanei_w_init (&dev->wire, sanei_codec_bin_init);
+ dev->wire.io.fd = dev->ctl;
+- dev->wire.io.read = read;
+- dev->wire.io.write = write;
++ dev->wire.io.read = NETREAD;
++ dev->wire.io.write = NETWRITE;
+
+ /* exchange version codes with the server: */
+ req.version_code = SANE_VERSION_CODE (V_MAJOR, V_MINOR,
+ SANEI_NET_PROTOCOL_VERSION);
+- req.username = getlogin ();
++ req.username = USERNAME;
+ sanei_w_call (&dev->wire, SANE_NET_INIT,
+ (WireCodecFunc) sanei_w_init_req, &req,
+ (WireCodecFunc) sanei_w_init_reply, &reply);
+@@ -229,7 +249,7 @@
+ return SANE_STATUS_GOOD;
+
+ fail:
+- close (dev->ctl);
++ NETCLOSE (dev->ctl);
+ dev->ctl = -1;
+ return SANE_STATUS_IO_ERROR;
+ }
+@@ -261,7 +281,7 @@
+ s->hw->auth_active = 0;
+ if (s->data >= 0)
+ {
+- close (s->data);
++ NETCLOSE (s->data);
+ s->data = -1;
+ }
+ return SANE_STATUS_CANCELLED;
+@@ -294,7 +314,7 @@
+ }
+ }
+
+-SANE_Status
++DLLEXPORT SANE_Status DLLCALL
+ sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize)
+ {
+ char device_name[PATH_MAX];
+@@ -305,6 +325,27 @@
+
+ DBG_INIT();
+
++#ifdef HAVE_WIN32
++ {
++ WSADATA wsadata;
++ WORD wVer;
++
++ mVer = MAKEWORD(1,1);
++ if (0 != WSAStartup(wVer, &wsadata))
++ {
++ DBG(1, "WSAStartup(1.1, ptr) failed.");
++ return SANE_STATUS_UNSUPPORTED; /* XXX check this error value */
++ }
++
++ /* Check WINSOCK.DLL version */
++ if (1 != LOBYTE(wsadata.mVersion) || 1 != HIBYTE(wsadata.mVersion))
++ {
++ DBG(1, "WINSOCK.DLL does not support v1.1.");
++ return SANE_STATUS_UNSUPPORTED; /* XXX check this error value */
++ }
++ }
++#endif
++
+ auth_callback = authorize;
+
+ if (version_code)
+@@ -318,7 +359,7 @@
+ saned_port = htons (6566);
+ DBG(1,
+ "init: could not find `sane' service (%s); using default port %d\n",
+- strerror (errno), htons (saned_port));
++ strerror (errno), htons ((unsigned short)saned_port));
+ }
+
+ fp = sanei_config_open (NET_CONFIG_FILE);
+@@ -354,7 +395,7 @@
+ return SANE_STATUS_GOOD;
+ }
+
+-void
++DLLEXPORT void DLLCALL
+ sane_exit (void)
+ {
+ Net_Scanner *handle, *next_handle;
+@@ -382,10 +423,19 @@
+ sanei_w_call (&dev->wire, SANE_NET_EXIT,
+ (WireCodecFunc) sanei_w_void, 0,
+ (WireCodecFunc) sanei_w_void, 0);
+- close (dev->ctl);
++ NETCLOSE (dev->ctl);
+ }
+ free (dev);
+ }
++#ifdef HAVE_WIN32
++ /* Release Windows socket DLL */
++ if (SOCKET_ERROR == WSACleanup())
++ if (WSAEINPROGRESS == WSAGetLastError())
++ {
++ WSACancelBlockingCall();
++ WSACleanup();
++ }
++#endif
+ }
+
+ /* Note that a call to get_devices() implies that we'll have to
+@@ -394,7 +444,7 @@
+ backend/device). This is appropriate for the command-line
+ interface of SANE, for example.
+ */
+-SANE_Status
++DLLEXPORT SANE_Status DLLCALL
+ sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only)
+ {
+ static int devlist_size = 0, devlist_len = 0;
+@@ -500,7 +550,7 @@
+ return SANE_STATUS_GOOD;
+ }
+
+-SANE_Status
++DLLEXPORT SANE_Status DLLCALL
+ sane_open (SANE_String_Const full_name, SANE_Handle * meta_handle)
+ {
+ SANE_Open_Reply reply;
+@@ -609,7 +659,7 @@
+ return SANE_STATUS_GOOD;
+ }
+
+-void
++DLLEXPORT void DLLCALL
+ sane_close (SANE_Handle handle)
+ {
+ Net_Scanner *prev, *s;
+@@ -636,11 +686,11 @@
+ (WireCodecFunc) sanei_w_word, &s->handle,
+ (WireCodecFunc) sanei_w_word, &ack);
+ if (s->data >= 0)
+- close (s->data);
++ NETCLOSE (s->data);
+ free (s);
+ }
+
+-const SANE_Option_Descriptor *
++DLLEXPORT const SANE_Option_Descriptor * DLLCALL
+ sane_get_option_descriptor (SANE_Handle handle, SANE_Int option)
+ {
+ Net_Scanner *s = handle;
+@@ -658,7 +708,7 @@
+ return s->opt.desc[option];
+ }
+
+-SANE_Status
++DLLEXPORT SANE_Status DLLCALL
+ sane_control_option (SANE_Handle handle, SANE_Int option,
+ SANE_Action action, void *value, SANE_Word * info)
+ {
+@@ -733,7 +783,7 @@
+ return status;
+ }
+
+-SANE_Status
++DLLEXPORT SANE_Status DLLCALL
+ sane_get_parameters (SANE_Handle handle, SANE_Parameters * params)
+ {
+ Net_Scanner *s = handle;
+@@ -755,7 +805,7 @@
+ return status;
+ }
+
+-SANE_Status
++DLLEXPORT SANE_Status DLLCALL
+ sane_start (SANE_Handle handle)
+ {
+ Net_Scanner *s = handle;
+@@ -779,7 +829,7 @@
+ }
+
+ fd = socket (s->hw->addr.sa_family, SOCK_STREAM, 0);
+- if (fd < 0)
++ if (!SOCKET_OK(fd))
+ {
+ DBG(1, "start: socket() failed (%s)\n", strerror (errno));
+ return SANE_STATUS_IO_ERROR;
+@@ -802,7 +852,7 @@
+
+ if (status != SANE_STATUS_GOOD)
+ {
+- close (fd);
++ NETCLOSE (fd);
+ return status;
+ }
+ }
+@@ -813,7 +863,7 @@
+ if (connect (fd, (struct sockaddr *) &sin, len) < 0)
+ {
+ DBG(1, "start: connect() failed (%s)\n", strerror (errno));
+- close (fd);
++ NETCLOSE (fd);
+ return SANE_STATUS_IO_ERROR;
+ }
+ shutdown (fd, 1);
+@@ -823,7 +873,7 @@
+ return status;
+ }
+
+-SANE_Status
++DLLEXPORT SANE_Status DLLCALL
+ sane_read (SANE_Handle handle, SANE_Byte * data, SANE_Int max_length,
+ SANE_Int * length)
+ {
+@@ -842,7 +892,7 @@
+ {
+ /* boy, is this painful or what? */
+
+- nread = read (s->data, s->reclen_buf + s->reclen_buf_offset,
++ nread = NETREAD (s->data, s->reclen_buf + s->reclen_buf_offset,
+ 4 - s->reclen_buf_offset);
+ if (nread < 0)
+ {
+@@ -873,7 +923,7 @@
+ fcntl (s->data, F_SETFL, 0);
+
+ /* read the status byte: */
+- if (read (s->data, &ch, sizeof (ch)) != 1)
++ if (NETREAD (s->data, &ch, sizeof (ch)) != 1)
+ ch = SANE_STATUS_IO_ERROR;
+ do_cancel (s);
+ return (SANE_Status) ch;
+@@ -883,7 +933,7 @@
+ if (max_length > s->bytes_remaining)
+ max_length = s->bytes_remaining;
+
+- nread = read (s->data, data, max_length);
++ nread = NETREAD (s->data, data, max_length);
+ if (nread < 0)
+ {
+ if (errno == EAGAIN)
+@@ -899,7 +949,7 @@
+ return SANE_STATUS_GOOD;
+ }
+
+-void
++DLLEXPORT void DLLCALL
+ sane_cancel (SANE_Handle handle)
+ {
+ Net_Scanner *s = handle;
+@@ -911,7 +961,7 @@
+ do_cancel (s);
+ }
+
+-SANE_Status
++DLLEXPORT SANE_Status DLLCALL
+ sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking)
+ {
+ Net_Scanner *s = handle;
+@@ -925,7 +975,7 @@
+ return SANE_STATUS_GOOD;
+ }
+
+-SANE_Status
++DLLEXPORT SANE_Status DLLCALL
+ sane_get_select_fd (SANE_Handle handle, SANE_Int *fd)
+ {
+ Net_Scanner *s = handle;
+diff -ru sane-pre1.01-4/include/sane/config.h.in sane-pre1.01-4-pere/include/sane/config.h.in
+--- sane-pre1.01-4/include/sane/config.h.in Tue Mar 9 06:50:03 1999
++++ sane-pre1.01-4-pere/include/sane/config.h.in Fri Apr 9 01:02:29 1999
+@@ -335,4 +335,9 @@
+ # define __EXTENSIONS__
+ #endif
+
++#ifdef _WINDOWS
++# define HAVE_WINDOWS_H
++# define HAVE_LOADLIBRARY
++#endif
++
+ #endif /* SANE_CONFIG_H */
+diff -ru sane-pre1.01-4/include/sane/sane.h sane-pre1.01-4-pere/include/sane/sane.h
+--- sane-pre1.01-4/include/sane/sane.h Sun Feb 28 00:54:08 1999
++++ sane-pre1.01-4-pere/include/sane/sane.h Fri Apr 9 00:37:53 1999
+@@ -30,6 +30,14 @@
+ #define SANE_FALSE 0
+ #define SANE_TRUE 1
+
++#if defined(_WINDOWS)
++# define DLLEXPORT __declspec( dllexport )
++# define DLLCALL __cdecl
++#else
++# define DLLEXPORT
++# define DLLCALL
++#endif
++
+ typedef unsigned char SANE_Byte;
+ typedef int SANE_Word;
+ typedef SANE_Word SANE_Bool;
+@@ -185,29 +193,29 @@
+ SANE_Char username[SANE_MAX_USERNAME_LEN],
+ SANE_Char password[SANE_MAX_PASSWORD_LEN]);
+
+-extern SANE_Status sane_init (SANE_Int * version_code,
++extern DLLEXPORT SANE_Status DLLCALL sane_init (SANE_Int * version_code,
+ SANE_Auth_Callback authorize);
+-extern void sane_exit (void);
+-extern SANE_Status sane_get_devices (const SANE_Device *** device_list,
++extern DLLEXPORT void DLLCALL sane_exit (void);
++extern DLLEXPORT SANE_Status DLLCALL sane_get_devices (const SANE_Device *** device_list,
+ SANE_Bool local_only);
+-extern SANE_Status sane_open (SANE_String_Const devicename,
++extern DLLEXPORT SANE_Status DLLCALL sane_open (SANE_String_Const devicename,
+ SANE_Handle * handle);
+-extern void sane_close (SANE_Handle handle);
+-extern const SANE_Option_Descriptor *
+- sane_get_option_descriptor (SANE_Handle handle, SANE_Int option);
+-extern SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option,
++extern DLLEXPORT void DLLCALL sane_close (SANE_Handle handle);
++extern DLLEXPORT const SANE_Option_Descriptor *
++ DLLCALL sane_get_option_descriptor (SANE_Handle handle, SANE_Int option);
++extern DLLEXPORT SANE_Status DLLCALL sane_control_option (SANE_Handle handle, SANE_Int option,
+ SANE_Action action, void *value,
+ SANE_Int * info);
+-extern SANE_Status sane_get_parameters (SANE_Handle handle,
++extern DLLEXPORT SANE_Status DLLCALL sane_get_parameters (SANE_Handle handle,
+ SANE_Parameters * params);
+-extern SANE_Status sane_start (SANE_Handle handle);
+-extern SANE_Status sane_read (SANE_Handle handle, SANE_Byte * data,
++extern DLLEXPORT SANE_Status DLLCALL sane_start (SANE_Handle handle);
++extern DLLEXPORT SANE_Status DLLCALL sane_read (SANE_Handle handle, SANE_Byte * data,
+ SANE_Int max_length, SANE_Int * length);
+-extern void sane_cancel (SANE_Handle handle);
+-extern SANE_Status sane_set_io_mode (SANE_Handle handle,
++extern DLLEXPORT void DLLCALL sane_cancel (SANE_Handle handle);
++extern DLLEXPORT SANE_Status DLLCALL sane_set_io_mode (SANE_Handle handle,
+ SANE_Bool non_blocking);
+-extern SANE_Status sane_get_select_fd (SANE_Handle handle,
++extern DLLEXPORT SANE_Status DLLCALL sane_get_select_fd (SANE_Handle handle,
+ SANE_Int * fd);
+-extern SANE_String_Const sane_strstatus (SANE_Status status);
++extern DLLEXPORT SANE_String_Const DLLCALL sane_strstatus (SANE_Status status);
+
+ #endif /* sane_h */
--- /dev/null
+Automatisk kompilering av Store-programmer på alle plattformer
+==============================================================
+Petter Reinholdtsen <pere@td.org.uit.no>, 1999-07-27
+
+IT-avdelingen bruker et system kalt 'build-all' hentet fra NTNU for
+dette. Når det virker går kompilering mye raskere enn før. Når det
+ikke virker gjøres kompilering som før. Kopi av NTNUs buildinfo filer
+ligger i store-applikasjon build-all/ntnu-buildinfo/
+
+For å autokompilere for flere arkitekturer lager du et /bin/sh script
+'buildinfo' i applikasjonskatalogen på master, parallelt med fila
+'registration', for å sette endel variabler. Deretter kjører du
+'build-all'. Hvis alt gikk bra, har du etter en stund kompilert opp
+applikasjonen for alle plattformer. Sjekk out.* for å se hvordan det
+går med bygging av applikasjonen.
+
+Når kompileringen er ferdig på alle plattformer (siste linje i out.*
+er "...done"), så kjøres chkapp og register på vanlig måte.
+
+Eksempelfil for GNU configure programmer:
+
+ appname=zsh
+ version=3.1.5
+ buildtype=GNU
+
+Eksempelfil for Perl5 moduler:
+
+ appname=Net-Netmask.pm
+ version=1.6
+ buildtype=pm
+
+Følgende variabler kan settes:
+
+ appname
+ Navn på applikasjonen som skal genereres, dvs katalognavnet i
+ Master Store. MÃ¥ settes, ingen default.
+ version
+ Versjon på applikasjonen som skal genereres. Må settes, ingen
+ default.
+ buildtype
+ Hvordan kompilering av applikasjonen skal gjøres. Må settes,
+ ingen default. Følgende er støttet:
+
+ X xmkmf og make
+ GNU GNU Autoconf oppsett
+ pm Perl5 module, dvs applikasjon med 'Makefile.PL'
+ make ???. Forutsetter at konfigurering allerede er gjort.
+
+ prefix
+ Kan være blank. Default er '/store'.
+ confstring
+ Kan være blank. Parameter til configure for buildtype GNU.
+ Default er '--prefix=$prefix'.
+ confcmd
+ Kan være blank, da brukes confstring eller standard for buildtype
+ GNU ('./configure $confstring').
+ maketargets
+ Kan være blank. Parameter til make. Default er intet
+ parameter.
+ installtargets
+ Kan være blank. Parameter til make for a installere
+ applikasjonen. Default for X er 'install install.man', for
+ alle andre 'install'
+ linkdownfirst
+ linkupafter
+ Kan være blank. Liste over applikasjoner som linkes henholdsvis
+ ned og opp fra linktreet før og etter installasjon.
+ Space-separert liste.
+ postpostinstcmds
+ Kan være blank. Kommando som kjøres etter postinst på
+ maskinen er installasjonen ble gjennomført.
+ linkupthis
+ Liste over applikasjoner som skal linkes opp før kompilering.
+ Formatet er 'app versjon store', og flere applikasjoner skilles
+ med skråstrek(/). Eksempel:
+ linkupthis='glib 1.2.2/gtk 1.2.2'
+ rsh
+ Kan være blank. Hvilken kommando som brukes for å kjøre
+ kommandoer på andre maskiner. Default er 'ssh -x'.
+ nice
+ Kan være blank. Nive-nivå for 'configure'- og
+ 'make'-kommendoene. Default er 'nice -15'
+ timeout
+ Kan være blank. Timeout-verdi for postinst. Default er 25.
+
+Tilgjengelige shell-variabler i confcmd og postpostinstcmds:
+
+ SARCH Store-arkitektur
+ PMA Perl5 arkitekturnavn (for pm buildtype)
+
+Buildall-systemet består av følgende filer:
+
+ /store/bin/build-all
+ Oppstart-scriptet som kjøres fra master-dir for applikasjonen
+ /store/etc/internal/buildsubs
+ Skriptet som gjør jobben
+ /store/etc/internal/etc/pm-a-by-a
+ Mapping mellom store-arkitektur og Perl5 arkitekturnavn
+ $HOME/etc/buildhosts
+ Liste over hvilke maskiner de forskjellige arkitekturene
+ kompileres på.
+ $HOME/etc/master.conf
+ Informasjon om master-store.
+ $appdir/buildinfo
+ Informasjon om applikasjonen som skal kompileres
+
--- /dev/null
+#!/store/bin/perl5 -w
+#
+# Author: Petter Reinholdtsen <pere@td.org.uit.no>
+# Date: 1999-03-09
+#
+# Change Store version directories. Move <app>/ver-<version>/doc/<app>/ to
+# <app>/ver-<version>/doc/<app>-<version>/.
+
+for $dir (<*/ver-*/doc/*>) {
+ my ($app, $ver, $docdir) =
+ $dir =~ m%^([^/]+)/ver-([^/]+)/doc/(.+)%;
+
+ next if $docdir eq "$app-$ver";
+
+ if ($docdir eq $app) {
+ rename($dir, "$app/ver-$ver/doc/$app-$ver");
+ next;
+ }
+ print " bogus docdir $dir\n";
+}
--- /dev/null
+#!/store/bin/perl5
+#
+# Author: Petter Reinholdtsen <pere@td.org.uit.no>
+# Date: 1999-04-15
+#
+# Parse Store nigthly output, and generate list of ssh/rsh commands to
+# fix suid/sgid changes.
+
+$lasthost = "";
+while (<>) {
+ chomp;
+ if (/^\(Info\) =+ OUTPUT FROM cslave @ (\S+) =+/) {
+ $host = $1;
+ }
+ if (/^ ch(own|grp|mod)/) {
+ if ($lasthost ne $host) {
+ $lasthost = $host;
+ print "\n";
+ print "ssh $host $_";
+ } else {
+ print "\\;$_";
+ }
+ }
+}
--- /dev/null
+From pere@minerva.cc.uit.no Sun Sep 27 12:33:33 1998
+Received: from minerva.cc.uit.no (pere@nb38.stud.cs.UiT.No [129.242.13.48])
+ by yuubin.games.no (8.8.7/8.8.7) with ESMTP id OAA02515
+ for <pere@games.no>; Sun, 27 Sep 1998 14:33:31 +0200
+From: pere@minerva.cc.uit.no
+Received: (from pere@localhost)
+ by minerva.cc.uit.no (8.8.7/8.8.7) id OAA04815;
+ Sun, 27 Sep 1998 14:33:36 +0200
+Date: Sun, 27 Sep 1998 14:33:36 +0200
+Message-Id: <199809271233.OAA04815@minerva.cc.uit.no>
+To: Alexandre Julliard <julliard@lrc.epfl.ch>
+Subject: More patches for Wine 980913
+Status: RO
+
+
+Here are some more patches for Wine 980913. At the end there is
+uuencoded perl script (tools/extractauthors.pl).
+
+Index: ChangeLog
+===================================================================
+RCS file: /home/pere/src/cvsroot/wine/ChangeLog,v
+retrieving revision 1.1.1.2
+diff -u -r1.1.1.2 ChangeLog
+--- ChangeLog 1998/09/15 15:36:01 1.1.1.2
++++ ChangeLog 1998/09/27 12:25:57
+@@ -1,3 +1,22 @@
++Sun Sep 27 01:27:20 1998 Petter Reinholdtsen <pere@td.org.uit.no>
++
++ * [AUTHORS] [Makefile.in] [tools/extractauthors.pl]
++ [include/authors.h]
++ Now generates include/authors.h from AUTHORS using perl script
++ authorsextract.c. No need to keep info in two different places.
++
+ ----------------------------------------------------------------------
+ Fri Sep 11 13:14:35 1998 Andreas Mohr <100.30936@germany.net>
+
+Index: Makefile.in
+===================================================================
+RCS file: /home/pere/src/cvsroot/wine/Makefile.in,v
+retrieving revision 1.1.1.2
+diff -u -r1.1.1.2 Makefile.in
+--- Makefile.in 1998/09/15 15:36:02 1.1.1.2
++++ Makefile.in 1998/09/26 23:41:50
+@@ -123,7 +123,7 @@
+
+ lib: $(LIBSUBDIRS) $(LIB_TARGET)
+
+-wine wine.sym: $(LIBSUBDIRS) $(LIB_TARGET) $(EMUSUBDIRS) dummy
++wine wine.sym: include/authors.h $(LIBSUBDIRS) $(LIB_TARGET) $(EMUSUBDIRS) dummy
+ $(CC) -o wine $(EMUOBJS) $(LIB_TARGET) $(LDOPTIONS) $(X_LIBS) $(XPM_LIB) $(XLIB) $(LIBS)
+ nm -n wine | grep -v _compiled >wine.sym
+
+@@ -205,5 +205,8 @@
+
+ include/config.h.in: configure.in include/acconfig.h
+ autoheader -l include
++
++include/authors.h: AUTHORS tools/extractauthors.pl
++ tools/extractauthors.pl $< > $@
+
+ ### Dependencies:
+
+begin 775 tools/extractauthors.pl
+M(R$O=7-R+V)I;B]P97)L("UW"B,*(R!!=71H;W(Z(%!E='1E<B!296EN:&]L
+M9'1S96X@/'!E<F5`=&0N;W)G+G5I="YN;SX*(R!$871E.B`@(#$Y.3@M,#DM
+M,C8*(PHC($=E;F5R871E(&EN8VQU9&4O875T:&]R<RYH(&9R;VT@05542$]2
+M4PH*<')I;G0@(B\J(%1H:7,@9FEL92!I<R!G96YE<F%T960@9G)O;2!!551(
+M3U)3('5S:6YG("0P("HO7&XB.PIP<FEN="`B+RH@1&\@;F]T(&5D:70@=&AI
+M<R!F:6QE+"!E9&ET('1H92!O<FEG:6YA;"!I;G-T96%D(2`J+UQN(CL*<')I
+M;G0@(B-I9FYD968@7U]724Y%7T%55$A/4E-?2%QN(CL*<')I;G0@(B-D969I
+M;F4@7U]724Y%7T%55$A/4E-?2%QN7&XB.PIP<FEN="`B<W1A=&EC(&-O;G-T
+M(&-H87(@*B!C;VYS="!32$5,3%]096]P;&5;72`]7&XB.PIP<FEN="`B>UQN
+M(CL*"G=H:6QE("@\/BD@>PH@("`@;F5X="!I9B`H+UY<0"\I.R`C(%)E;6]V
+M92!495AI;F9O(&-O;6UE;G1S"B`@("!N97AT(&EF("@O7E=I;F4@:7,@879A
+M:6QA8FQE+RD[(",@4F5M;W9E(&EN:71I86P@=&5X=`H@("`@;F5X="!I9B`H
+M+UY<<RLD+RD["B`@("!S+UYA;F0@+R\["B`@("!S+UXH+BLI6RPN72LO(B0Q
+M(BPO.PH@("`@<')I;G0@(B`@("`D7R(["GT*"G!R:6YT("(@("`@3E5,3%QN
+M(CL*<')I;G0@(GT[7&Y<;B(["G!R:6YT("(C96YD:68@("\J(%]?5TE.15]!
+0551(3U)37T@@*B]<;B(["@``
+`
+end
+--
+##> Petter Reinholdtsen <## | pere@td.org.uit.no
+
--- /dev/null
+From pere@minerva.cc.uit.no Sun Oct 25 20:26:55 1998
+Received: from minerva.cc.uit.no (pere@nb38.stud.cs.UiT.No [129.242.13.48])
+ by yuubin.games.no (8.8.7/8.8.7) with ESMTP id VAA24459
+ for <pere@games.no>; Sun, 25 Oct 1998 21:26:54 +0100
+Received: (from pere@localhost)
+ by minerva.cc.uit.no (8.8.7/8.8.7) id VAA26463;
+ Sun, 25 Oct 1998 21:26:59 +0100
+Date: Sun, 25 Oct 1998 21:26:59 +0100
+Message-Id: <199810252026.VAA26463@minerva.cc.uit.no>
+From: Petter Reinholdtsen <pere@localhost.localdomain>
+To: patches@winehq.com
+Subject: Patch for more warnings when compiling wine
+Status: RO
+
+
+Here is a patch to get more warnings when compiling Wine. There are
+lots of bugs which would be discovered with more warnings, so I
+beleave these new warnings should be default.
+
+ChangeLog entry:
+
+ * configure.in acinclude.m4: Petter Reinholdtsen <pere@td.org.uit.no>
+ Add '-Wstrict-prototypes -Wcomments -pedantic' and '-ansi' when
+ --enable-ansi is used, to CFLAGS when using GCC. The code currently
+ fails to compile when -ansi is used.
+
+Index: configure.in
+===================================================================
+RCS file: /home/wine/wine/configure.in,v
+retrieving revision 1.4
+diff -u -r1.4 configure.in
+--- configure.in 1998/10/11 17:09:05 1.4
++++ configure.in 1998/10/25 20:23:45
+@@ -23,6 +23,9 @@
+ [ --disable-emulator build only the Wine library, not the emulator],
+ [if test "$enableval" = "no"; then MAIN_TARGET="lib"; fi])
+
++AC_ARG_ENABLE(ansi,
++[ --enable-ansi warn on non ANSI C code], )
++
+ AC_ARG_ENABLE(dll,
+ [ --enable-dll build the Wine library as a DLL],
+ [if test "$enableval" = "no"; then : ; else LIB_TARGET="libwine.so.1.0"; fi])
+@@ -127,11 +130,33 @@
+ dnl **** If ln -s doesn't work, use cp instead ****
+ if test "$ac_cv_prog_LN_S" = "ln -s"; then : ; else LN_S=cp ; fi
+
+-dnl **** Check for gcc strength-reduce bug ****
+-
+ if test "x${GCC}" = "xyes"
+ then
+- CFLAGS="$CFLAGS -Wall"
++
++ # We want warnings, lots of warnings :-)
++ WINE_GREP_CFLAGS(-Wall, [
++ CFLAGS="$CFLAGS -Wall"
++ ])
++ WINE_GREP_CFLAGS(-Wstrict-prototypes, [
++ CFLAGS="$CFLAGS -Wstrict-prototypes"
++ ])
++
++ WINE_GREP_CFLAGS(-Wcomments, [
++ CFLAGS="$CFLAGS -Wcomments"
++ ])
++
++ WINE_GREP_CFLAGS(-pedantic, [
++ CFLAGS="$CFLAGS -pedantic"
++ ])
++
++ if eval "test x$enable_ansi = xyes"; then
++ WINE_GREP_CFLAGS(-ansi, [
++ CFLAGS="$CFLAGS -ansi"
++ ])
++ fi
++
++dnl **** Check for gcc strength-reduce bug ****
++
+ AC_CACHE_CHECK( "for gcc strength-reduce bug", ac_cv_c_gcc_strength_bug,
+ AC_TRY_RUN([
+ int main(void) {
+
+============================ acinclude.m4 ================================
+dnl
+dnl Run 'aclocal; autoconf' to get this this include in configure
+dnl
+
+dnl WINE_GREP_CFLAGS(flag, cmd_if_missing, cmd_if_present)
+AC_DEFUN(WINE_GREP_CFLAGS,
+[case "$CFLAGS" in
+"$1" | "$1 "* | *" $1" | *" $1 "* )
+ ifelse($#, 3, [$3], [:])
+ ;;
+*)
+ $2
+ ;;
+esac
+])
+===========================================================================
+--
+##> Petter Reinholdtsen <## | pere@td.org.uit.no
+
--- /dev/null
+From pere@minerva.cc.uit.no Mon Oct 26 18:22:40 1998
+Received: from minerva.cc.uit.no (pere@nb38.stud.cs.UiT.No [129.242.13.48])
+ by yuubin.games.no (8.8.7/8.8.7) with ESMTP id TAA27004
+ for <pere@games.no>; Mon, 26 Oct 1998 19:22:38 +0100
+Received: (from pere@localhost)
+ by minerva.cc.uit.no (8.8.7/8.8.7) id TAA09696;
+ Mon, 26 Oct 1998 19:22:40 +0100
+Date: Mon, 26 Oct 1998 19:22:40 +0100
+Message-Id: <199810261822.TAA09696@minerva.cc.uit.no>
+From: Petter Reinholdtsen <pere@localhost.localdomain>
+To: patches@winehq.com
+Subject: Read ISO 9660 label from /dev/cdrom
+Status: RO
+
+
+ChangeLog entry:
+
+ * files/drive.c: Petter Reinholdtsen <pere@td.org.uit.no>
+ Changed DRIVE_GetLabel to extract ISO 9660 label from CDROMs. It
+ requires read access to /dev/cdrom and 'Device=/dev/cdrom' and
+ 'Type=cdrom' to be set in the [Drive X] section of .winerc.
+
+Index: files/drive.c
+===================================================================
+RCS file: /home/wine/wine/files/drive.c,v
+retrieving revision 1.4
+diff -u -r1.4 drive.c
+--- drive.c 1998/10/20 14:25:50 1.4
++++ drive.c 1998/10/26 18:18:58
+@@ -41,13 +41,19 @@
+ #include "task.h"
+ #include "debug.h"
+
++#define ISO_9660_LABEL_LEN 32 /* 32 */
++#define FAT_LABEL_LEN 11 /* 8+3 */
++
++/* Which should we use? */
++#define LABEL_LEN ISO_9660_LABEL_LEN
++
+ typedef struct
+ {
+ char *root; /* root dir in Unix format without trailing / */
+ char *dos_cwd; /* cwd in DOS format without leading or trailing \ */
+ char *unix_cwd; /* cwd in Unix format without leading or trailing / */
+ char *device; /* raw device path */
+- char label[12]; /* drive label */
++ char label[LABEL_LEN+1]; /* drive label + terminating 0 */
+ DWORD serial; /* drive serial number */
+ DRIVETYPE type; /* drive type */
+ UINT32 flags; /* drive flags */
+@@ -168,12 +174,13 @@
+ drive->ino = drive_stat_buffer.st_ino;
+
+ /* Get the drive label */
+- PROFILE_GetWineIniString( name, "Label", name, drive->label, 12 );
+- if ((len = strlen(drive->label)) < 11)
++ PROFILE_GetWineIniString( name, "Label", name, drive->label,
++ LABEL_LEN+1 );
++ if ((len = strlen(drive->label)) < LABEL_LEN)
+ {
+ /* Pad label with spaces */
+- memset( drive->label + len, ' ', 11 - len );
+- drive->label[12] = '\0';
++ memset( drive->label + len, ' ', LABEL_LEN - len );
++ drive->label[LABEL_LEN+1] = '\0';
+ }
+
+ /* Get the serial number */
+@@ -329,9 +336,11 @@
+ *next = 0;
+
+ if (rootdrive != -1)
++ {
+ TRACE(dosfs, "%s -> drive %c:, root='%s', name='%s'\n",
+ buffer, 'A' + rootdrive,
+ DOSDrives[rootdrive].root, *path );
++ }
+ return rootdrive;
+ }
+
+@@ -387,13 +396,100 @@
+ return DOSDrives[drive].unix_cwd;
+ }
+
++/***********************************************************************
++ * DRIVE_iso9660label [internal]
++ *
++ * Extract the 32 bytes label from ISO 9660 CDROM filesystem.
++ *
++ * Requires read access to the raw device (/dev/cdrom).
++ *
++ * RETURNS
++ * Current label in static char *, only valid until next call to
++ * this method, or NULL if wrong filesystem or something else goes
++ * wrong.
++ *
++ * BUGS
++ * When the Unix kernel provides filesystem label using ioctl, this
++ * method should be changed to use that instead.
++ *
++ * I know nothing about the filesystem layout, and has just been
++ * quessing about where to find the label based on other source
++ * (Linux, etc). All this should be verified by someone who knows
++ * what they are doing. It is tested, and seem to work.
++ */
++
++static char *
++DRIVE_iso9660label(char *device)
++{
++#define LABEL_POS 0x8028-0x8001
++#define READ_LEN LABEL_POS+ISO_9660_LABEL_LEN+1
++ const char magic[] = "CD001";
++ static char buffer[READ_LEN];
++ FILE *dev = NULL;
++
++ if (NULL == device)
++ return NULL;
++
++ /*
++ * Check if ISO 9660 magic 'CD001' is at absolute sector 16. I hope
++ * pos 0x8001 corresponds to the correct position. If this is
++ * correct file system, return the 32 bytes giving the label from pos
++ * 0x8028.
++ */
++ dev = fopen(device, "rb");
++ if (NULL != dev
++ && 0 == fseek(dev, 0x8001, SEEK_SET)
++ && READ_LEN == fread(buffer, 1, READ_LEN, dev)
++ && 0 == memcmp(buffer, magic, sizeof(magic)-1)
++ )
++ {
++ fclose(dev);
++ buffer[READ_LEN] = 0;
++ return buffer+LABEL_POS;
++ }
++
++ /* Something wrong, close and return. */
++ if (NULL != dev)
++ fclose(dev);
++ return NULL;
++#undef LABEL_POS
++#undef READ_LEN
++}
+
+ /***********************************************************************
+ * DRIVE_GetLabel
++ * BUGS
++ * There is no known way to extract the filesystem label using ioctl
++ * or any other decent method. I therefore choose this crude way, using
++ * FS depentend code to read the label from the device file, to extract
++ * the label and fall back to the preset one.
+ */
+ const char * DRIVE_GetLabel( int drive )
+ {
++ char *device = NULL;
++
++ TRACE(dosfs, "(%c:)\n", 'A' + drive);
++
+ if (!DRIVE_IsValid( drive )) return NULL;
++
++ device = DOSDrives[drive].device;
++
++ if (NULL != device && TYPE_CDROM == DRIVE_GetType(drive))
++ {
++ char *label = DRIVE_iso9660label(device);
++ if (NULL != label)
++ {
++ return label;
++ } else {
++ static int first_time = 1;
++ if (first_time) /* It is probably enough to print this once */
++ fprintf(stderr,
++ "Unable to fetch ISO9660 label from %s. Is it readable? (one-time-warning)\n",
++ device);
++ first_time = 0;
++ }
++ }
++
+ return DOSDrives[drive].label;
+ }
+
+@@ -551,7 +647,7 @@
+ new->root = HEAP_strdupA( SystemHeap, 0, old->root );
+ new->dos_cwd = HEAP_strdupA( SystemHeap, 0, old->dos_cwd );
+ new->unix_cwd = HEAP_strdupA( SystemHeap, 0, old->unix_cwd );
+- memcpy ( new->label, old->label, 12 );
++ memcpy ( new->label, old->label, LABEL_LEN+1 );
+ new->serial = old->serial;
+ new->type = old->type;
+ new->flags = old->flags;
+--
+##> Petter Reinholdtsen <## | pere@td.org.uit.no
+
--- /dev/null
+Index: req-status
+===================================================================
+RCS file: /cvsroot/its/sw/wreq/req-status,v
+retrieving revision 1.2
+diff -u -r1.2 req-status
+--- req-status 1999/05/16 00:03:31 1.2
++++ req-status 1999/05/16 14:52:29
+@@ -250,7 +250,12 @@
+ $recdyhin=$wstold+$recdyhin*$dysecs;
+
+ if($FORM{'gif'} eq 'on'){# plot weekly end-of-the-week status
+- use GD;
++ # Make sure this module only fails on missing GD.pm when
++ # GIF graph is requested.
++ eval 'use GD;';
++ $im = new GD::Image(645,401);
++ &html_error("req-status: missing GD.pm.",
++ "<P>Fetch and install from CPAN") unless ($im);
+
+ print "Content-type: image/gif\n";
+ #print "Content-Disposition: inline; filename=\"req$$.gif\"\n";
+@@ -287,7 +292,6 @@
+ #print "<br>$i X $wke X $wks X $openn X $wkopenn $t1 $t2 X $rmax \n";
+ }
+
+- $im = new GD::Image(645,401);
+ $white = $im->colorAllocate(255,255,255);
+ $black = $im->colorAllocate(0,0,0);
+ $red = $im->colorAllocate(255,0,0);
--- /dev/null
+--- ../wreq/req-create Thu Mar 25 16:37:43 1999
++++ req-create Sun May 16 02:16:18 1999
+@@ -609,6 +609,7 @@
+ my $er=&escHTMLChars("$error_from\n$error_cc"); $er=~s/\n/<br>/g;
+
+ my $ginfo=&escHTMLChars($dept[26]); $ginfo=~s/\n/<br>/g;
++ my $header=&escHTMLChars($dept[29]); $header=~s/\n/<br>/g;
+
+ &html_header("<a href=\"$url?create\">Config</a> Info for $dept[0]");
+ print<<"configInfoEOF1";
+@@ -624,7 +625,13 @@
+ </TR>
+
+ <TR>
+-<TD COLSPAN="2">$ginfo </TD>
++<TD><b>Group Info:</b></TD>
++<TD>$ginfo </TD>
++</TR>
++
++<TR>
++<TD><b>Announcement:</b></TD>
++<TD>$header </TD>
+ </TR>
+
+ <TR>
--- /dev/null
+--- req-status.orig Sun May 16 00:36:57 1999
++++ req-status Sun May 16 01:57:06 1999
+@@ -90,7 +90,7 @@
+ $recos{$a[12]}++; $recarea{$a[13]}++;
+ $recwk{int(($a[5]-$wstold)/$wksecs)}++;
+ $recdy{int(($a[5]-$wstold)/$dysecs)}++;
+- if($a[40]){
++ if($a[39]){ # rhost only set for email msgs
+ $recw++; $recuw{$a[2]}++;
+ }else{
+ $recm++; $recum{$a[2]}++;
--- /dev/null
+Index: req-list
+===================================================================
+RCS file: /cvsroot/its/sw/wreq/req-list,v
+retrieving revision 1.1
+retrieving revision 1.2
+diff -u -w -u -r1.1 -r1.2
+--- req-list 1999/05/09 21:51:08 1.1
++++ req-list 1999/05/15 09:58:45 1.2
+@@ -498,7 +498,7 @@
+ print<<"listReqsEOF33";
+ <a href="$url?top-active-$group" target="_top"
+ onMouseOver="window.status='Go to the full window new request submisson form'; return true"
+- >Top</a>
++ >New request</a>
+ </nobr>
+ </BODY>
+ </HTML>
--- /dev/null
+Index: req-newreq
+===================================================================
+RCS file: /cvsroot/its/sw/wreq/req-newreq,v
+retrieving revision 1.1
+retrieving revision 1.2
+diff -u -w -u -r1.1 -r1.2
+--- req-newreq 1999/05/09 21:51:08 1.1
++++ req-newreq 1999/05/15 10:11:32 1.2
+@@ -347,7 +347,8 @@
+ }else{
+ &html_error("Request sent","Please refer to request #$last when " .
+ "you need to <a href=\"$url?list-$group\" target=\"_top\">check " .
+- "its status</a> in the job queue$passwordmsg");
++ "its status</a> in the job queue$passwordmsg\n".
++ "<P>You might also <A HREF=\"$url\">send a new request</A>.");
+ }
+ #&html_trailer;
+ }
--- /dev/null
+Index: req-config
+===================================================================
+RCS file: /cvsroot/its/sw/wreq/req-config,v
+retrieving revision 1.2
+retrieving revision 1.3
+diff -u -w -u -r1.2 -r1.3
+--- req-config 1999/05/10 08:49:43 1.2
++++ req-config 1999/05/15 10:20:04 1.3
+@@ -8,10 +8,6 @@
+ #### The default location is "*/cgi-bin/wreq/data":
+ $top='../../data/wreq';
+
+-#### Directory name where all the req* scripts live:
+-#### No need to change if $top above has not been changed.
+-$scriptdir='..';
+-
+ #### How to call sendmail on your system
+ $sendmail="/usr/lib/sendmail -oi"; # will -db make the page faster to return?
+
+Index: req-mail
+===================================================================
+RCS file: /cvsroot/its/sw/wreq/req-mail,v
+retrieving revision 1.2
+retrieving revision 1.3
+diff -u -w -u -r1.2 -r1.3
+--- req-mail 1999/05/10 08:49:43 1.2
++++ req-mail 1999/05/15 10:22:44 1.3
+@@ -7,9 +7,13 @@
+
+ ### load in the following global config params:
+ ### $wreq_host $wreq_port $wreq_url $error_cc $error_from
+-#require 'req-config';
+-$rcf=$0; $rcf=~s/\-mail$/\-config/;
+-require "$rcf";
++
++# Add 'pwd' to include path
++@F = split('/', $0); pop @F;
++push (@INC,join ('/', @F));
++
++require 'req-config';
++
+ if(-f "$rcf-duke"){# hack to get our web server
+ $wreq_host='caesar';
+ }
+Index: req
+===================================================================
+RCS file: /cvsroot/its/sw/wreq/req,v
+retrieving revision 1.2
+retrieving revision 1.3
+diff -u -w -u -r1.2 -r1.3
+--- req 1999/05/10 08:49:43 1.2
++++ req 1999/05/15 10:19:27 1.3
+@@ -110,7 +110,6 @@
+ # $rhost $raddr browser's hostname and IP number
+ # %DBM OUT IN LOCK gdbm hash, output/input/lock filehandle
+ # $top top dir of the req data
+-# $scriptdir absolute dir name where all the req* scripts reside
+ #
+ # gmtime:
+ # 0sec(0-61) 1min(0-59) 2hour(0-23) 3mday(1-31) 4mon(0-11) 5year(+1900)
+@@ -151,8 +150,11 @@
+ # Make all email address case insentive
+ #
+ ####################################################################
++# Add 'pwd' to include path
++@F = split('/', $0); pop @F;
++push (@INC,join ('/', @F));
+ # load in global config params
+-require "$0-config";
++require "req-config";
+ ####################################################################
+ $url="$ENV{'SCRIPT_NAME'}";
+ $server="$ENV{'SERVER_NAME'}";# set in server's conf file
+@@ -173,7 +175,6 @@
+ &html_error("Error, the req directory \"$top\" doesn't exist.");
+ }
+ chdir $top || &html_error("Error, can't cd to top.");
+-push @INC,$scriptdir; # `pwd` doesn't work here, since perl is interpreted
+ umask 022;
+
+ $oldauth=$auth=$warn='';
--- /dev/null
+Index: req-config
+===================================================================
+RCS file: /cvsroot/its/sw/wreq/req-config,v
+retrieving revision 1.3
+retrieving revision 1.4
+diff -u -w -u -r1.3 -r1.4
+--- req-config 1999/05/15 10:20:04 1.3
++++ req-config 1999/05/15 10:41:24 1.4
+@@ -11,6 +11,9 @@
+ #### How to call sendmail on your system
+ $sendmail="/usr/lib/sendmail -oi"; # will -db make the page faster to return?
+
++#### If $sendmail is '', relay mails thru this host
++$mailhost='mailhost';
++
+ #### The From address for errors in processing email requests
+ #### Note: to prevent mail looping, this address doesn't actually exist.
+ $error_from="Support Online Error <req-error\@localhost>";
+Index: req-common
+===================================================================
+RCS file: /cvsroot/its/sw/wreq/req-common,v
+retrieving revision 1.1
+retrieving revision 1.2
+diff -u -w -u -r1.1 -r1.2
+--- req-common 1999/05/09 21:51:08 1.1
++++ req-common 1999/05/15 10:41:24 1.2
+@@ -445,8 +445,8 @@
+ sub sendMail {# . 0from 1reply-to 2tos 3ccs 4subject 5message
+ if(!$_[2]){return;} # no one to send to
+
+- my $header=''; my $fflag=''; my $to='';
+- if($_[0]){$header.="From: $_[0]\n";}
++ my $header=''; my $fflag=''; my $to=''; my $from='';
++ if($_[0]){$header.="From: $_[0]\n"; $from ="$_[0]";}
+ if($_[2]){$header.="To: $_[2]\n"; $to="$_[2]";}
+ if($_[4]){$header.="Subject: $_[4]\n";}
+ if($_[3]){$header.="Cc: $_[3]\n"; $to.=",$_[3]";}
+@@ -455,6 +455,7 @@
+ $header.="\n$_[5]\n"; # the body
+
+ eval {
++ if ($sendmail) {
+ # note from/tos can be of the form: aa bb <a@b>
+ open(POUT,"|$sendmail $fflag \"$to\">/dev/null 2>&1") || &html_error("cannot run sendmail: $!");
+ # redirect above so it won't mess up the http header, eval{} works too.
+@@ -465,6 +466,23 @@
+ ### -n option should not be used, since we are sending to aliases.
+ print POUT "$header";
+ close (POUT);
++ } else {
++ eval 'use Net::SMTP;';
++ $smtp = Net::SMTP->new($mailhost,
++ Timeout => 30); # seconds
++ if ($smtp) {
++ $smtp->mail($from);
++ for $user (split(/,/, $to)) {
++ $smtp->to($user);
++ }
++ $smtp->data();
++ $smtp->datasend($header);
++ $smtp->dataend();
++ $smtp->quit;
++ } else {
++ &html_error("sendMail: SMTP connect to $mailhost failed");
++ }
++ }
+ };
+ &html_error("sendMail: $@") if $@;
+ }
+Index: req-mail
+===================================================================
+RCS file: /cvsroot/its/sw/wreq/req-mail,v
+retrieving revision 1.3
+retrieving revision 1.4
+diff -u -w -u -r1.3 -r1.4
+--- req-mail 1999/05/15 10:22:44 1.3
++++ req-mail 1999/05/15 10:41:24 1.4
+@@ -264,8 +264,8 @@
+ sub sendMail {# . 0from 1reply-to 2tos 3ccs 4subject 5message
+ if(!$_[2]){return;} # no one to send to
+
+- my $header=''; my $fflag=''; my $to='';
+- if($_[0]){$header.="From: $_[0]\n";}
++ my $header=''; my $fflag=''; my $to=''; my $from='';
++ if($_[0]){$header.="From: $_[0]\n"; $from ="$_[0]";}
+ if($_[2]){$header.="To: $_[2]\n"; $to="$_[2]";}
+ if($_[4]){$header.="Subject: $_[4]\n";}
+ if($_[3]){$header.="Cc: $_[3]\n"; $to.=",$_[3]";}
+@@ -274,6 +274,7 @@
+ $header.="\n$_[5]\n"; # the body
+
+ eval {
++ if ($sendmail) {
+ # note from/tos can be of the form: aa bb <a@b>
+ open(POUT,"|$sendmail $fflag \"$to\">/dev/null 2>&1") || &html_error("cannot run sendmail: $!");
+ # redirect above so it won't mess up the http header, eval{} works too.
+@@ -284,6 +285,23 @@
+ ### -n option should not be used, since we are sending to aliases.
+ print POUT "$header";
+ close (POUT);
++ } else {
++ eval 'use Net::SMTP;';
++ $smtp = Net::SMTP->new($mailhost,
++ Timeout => 30); # seconds
++ if ($smtp) {
++ $smtp->mail($from);
++ for $user (split(/,/, $to)) {
++ $smtp->to($user);
++ }
++ $smtp->data();
++ $smtp->datasend($header);
++ $smtp->dataend();
++ $smtp->quit;
++ } else {
++ &html_error("sendMail: SMTP connect to $mailhost failed");
++ }
++ }
+ };
+ &html_error("sendMail: $@") if $@;
+ }
--- /dev/null
+Index: req-mail
+===================================================================
+RCS file: /cvsroot/its/sw/wreq/req-mail,v
+retrieving revision 1.4
+retrieving revision 1.7
+diff -u -r1.4 -r1.7
+--- req-mail 1999/05/15 10:41:24 1.4
++++ req-mail 1999/05/19 17:02:41 1.7
+@@ -51,6 +51,7 @@
+ @body=();
+ $body=''; # as description field in req
+ $date='';
++$mimetype=''; # If this a mime message, place the type here
+ $warn=''; # error message. if set, no auto reply will be sent to sender
+ # carry along the group name if given as the 1st arg to the alias:
+ $group=defined($ARGV[0])?$ARGV[0]:'';
+@@ -59,6 +60,10 @@
+ while(<STDIN>) {
+ chop;
+ last if(/^\s*$/);
++ if (/^\s+/) {
++ my $prevline = pop(@header);
++ $_ = $prevline . $_;
++ }
+ push(@header, $_);
+ }
+
+@@ -69,7 +74,11 @@
+ }
+
+ $header=join "\n",@header;
+-$body=join "\n",@body;
++
++if (grep(/^MIME-Version: /, @header)) {
++ my ($typeline) = grep(/^Content-Type: /i, @header);
++ ($mimetype) = $typeline =~ m/Content-Type:\s+([^;]+)/i;
++}
+
+ ###parse header for email:
+ foreach (@header){
+@@ -79,6 +88,8 @@
+ ###########################################################
+ }elsif(/^Date:\s+(.*\S)/){ # Date: a b
+ $date=$1;
++ }elsif(/^Subject:\s+(.*)$/){ # Subject: line
++ $subject=$1;
+ }
+ ###########################################################
+ }
+@@ -139,6 +150,44 @@
+ if($uid =~ /^(root|diag|sys|adm|lp|nobody|MAILER-DAEMON|postmaster|\
+ daemon|bin|uucp|powerdown)/i){
+ #$warn.=" Not send auto-reply to uid $uid.";
++}
++
++# Unpack MIME subjects
++if ( $subject =~ m%=\?([^\?]+)\?Q\?.+\?=% ) {
++ $charset = $1;
++ for $supcharset (@supcharsets) {
++ if ($charset =~ /$supcharset/i) { # ignore case
++ $subject =~ s/=\?[^\?]+\?Q\?(.+)\?=/$1/g;
++ $subject =~ s/_/ /g;
++ $subject =~ s/=([0-9a-fA-F]{2})/pack("c",hex($1))/ge;
++ }
++ }
++
++}
++
++# XXX Should parse/unpack MIME mail here. We only handle text/plain for now.
++if ($mimetype && 'text/plain' ne $mimetype) {
++ # send error back to user
++ &sendMail("$error_from", "", "$email", "",
++ "Error in sending your request",
++ "Your request with subject\n\n$subject\n\n" .
++ "was NOT included in bug list!\n\n".
++ "We only handle MIME type text/plain or non-MIME for the moment\n" .
++ "Please resend your request like that, or use the web form.\n\n" .
++ "Thank you\n");
++ exit 0;
++}
++
++# Skip signature
++if ('' eq $mimetype || 'text/plain' eq $mimetype) {
++ $bodylines = 0;
++ foreach (@body) {
++ last if (/^-- $/ && $dropmailsig);
++ $bodylines++;
++ }
++ $body=join "\n",@body[0..$bodylines-1];
++} else {
++ $body=join "\n",@body;
+ }
+
+ ###send the request to the web server
+Index: req-config
+===================================================================
+RCS file: /cvsroot/its/sw/wreq/req-config,v
+retrieving revision 1.5
+retrieving revision 1.6
+diff -u -r1.5 -r1.6
+--- req-config 1999/05/15 11:21:23 1.5
++++ req-config 1999/05/19 17:02:41 1.6
+@@ -14,6 +14,14 @@
+ #### If $sendmail is '', relay mails thru this host
+ $mailhost='mailhost';
+
++#### Set this to '1' to remove signatures (everything from '\n-- \n)
++#### in incoming mail and set to '' if you want to keep the signature
++$dropmailsig = '1';
++
++#### Supported charsets. Unescape these charsets when MIME encoded in
++#### mail subject
++@supcharsets = ("iso-8859-1", "iso8859-1");
++
+ #### The From address for errors in processing email requests
+ #### Note: to prevent mail looping, this address doesn't actually exist.
+ $error_from="Support Online Error <req-error\@student.uit.no>";
--- /dev/null
+Index: req-mail
+===================================================================
+RCS file: /cvsroot/its/sw/wreq/req-mail,v
+retrieving revision 1.4
+retrieving revision 1.6
+diff -u -w -u -r1.4 -r1.6
+--- req-mail 1999/05/15 10:41:24 1.4
++++ req-mail 1999/05/15 11:12:45 1.6
+@@ -51,6 +51,7 @@
+ @body=();
+ $body=''; # as description field in req
+ $date='';
++$mimetype=''; # If this a mime message, place the type here
+ $warn=''; # error message. if set, no auto reply will be sent to sender
+ # carry along the group name if given as the 1st arg to the alias:
+ $group=defined($ARGV[0])?$ARGV[0]:'';
+@@ -69,7 +70,11 @@
+ }
+
+ $header=join "\n",@header;
+-$body=join "\n",@body;
++
++if (grep(/^MIME-Version: /, @header)) {
++ my ($typeline) = grep(/^Content-Type: /i, @header);
++ ($mimetype) = $typeline =~ m/Content-Type:\s+([^;]+)/i;
++}
+
+ ###parse header for email:
+ foreach (@header){
+@@ -79,6 +84,8 @@
+ ###########################################################
+ }elsif(/^Date:\s+(.*\S)/){ # Date: a b
+ $date=$1;
++ }elsif(/^Subject:\s+(.*\S)/){ # Subject: line
++ $subject=$1;
+ }
+ ###########################################################
+ }
+@@ -139,6 +146,31 @@
+ if($uid =~ /^(root|diag|sys|adm|lp|nobody|MAILER-DAEMON|postmaster|\
+ daemon|bin|uucp|powerdown)/i){
+ #$warn.=" Not send auto-reply to uid $uid.";
++}
++
++# XXX Should parse/unpack MIME mail here. We only handle text/plain for now.
++if ($mimetype && 'text/plain' ne $mimetype) {
++ # send error back to user
++ &sendMail("$error_from", "", "$email", "",
++ "Error in sending your request",
++ "Your request with subject\n\n$subject\n\n" .
++ "was NOT included in bug list!\n\n".
++ "We only handle MIME type text/plain or non-MIME for the moment\n" .
++ "Please resend your request like that, or use the web form.\n\n" .
++ "Thank you\n");
++ exit 0;
++}
++
++# Skip signature
++if ('' eq $mimetype || 'text/plain' eq $mimetype) {
++ $bodylines = 0;
++ foreach (@body) {
++ last if (/^-- $/);
++ $bodylines++;
++ }
++ $body=join "\n",@body[0..$bodylines-1];
++} else {
++ $body=join "\n",@body;
+ }
+
+ ###send the request to the web server
--- /dev/null
+Index: req
+===================================================================
+RCS file: /cvsroot/its/sw/wreq/req,v
+retrieving revision 1.3
+diff -u -w -u -r1.3 req
+--- req 1999/05/15 10:19:27 1.3
++++ req 1999/05/16 14:01:20
+@@ -481,7 +481,7 @@
+ }
+ sub html_trailer { # no argv
+ print "\n<hr>\n";
+- print "Wreq version 2.7, Apr. 26, 1999.\n";
++ print "<a href=\"http://www.math.duke.edu/~yu/wreq/\">Wreq</a> version 2.7, Apr. 26, 1999.\n";
+ if($_[0] ne 'F' && $_[0] ne 'Frame'){print "</BODY>\n";}
+ print "</HTML>\n";
+ }
+Index: req-null
+===================================================================
+RCS file: /cvsroot/its/sw/wreq/req-null,v
+retrieving revision 1.1.1.1
+diff -u -w -u -r1.1.1.1 req-null
+--- req-null 1999/05/09 21:51:08 1.1.1.1
++++ req-null 1999/05/16 14:01:22
+@@ -68,7 +68,7 @@
+ David.Seddon\@cmis.CSIRO.AU
+ and many others...
+
+-Source: Available from <a href=\"http://www.math.duke.edu/~yu/wreq\">http://www.math.duke.edu/~yu/wreq</a>
++Source: Available from <a href=\"http://www.math.duke.edu/~yu/wreq/\">http://www.math.duke.edu/~yu/wreq/</a>
+
+ Fine Print:<font size=-2>
+ This program is distributed under the terms of the GNU General
--- /dev/null
+#!/bin/sh
+#
+# Author: Petter Reinholdtsen <pere@hungry.com>
+# Date: 2001-10-12
+# Name: ypserv-closest.sh
+#
+# Fetch the list of NIS servers from NIS, and list the "closest"
+# servers (fastest reply) in yp.conf format.
+#
+# Uses 'ypcat' to find the servers, 'fping' to time the network
+# distance and normal shell tools to make the list.
+
+domain=uio
+count=5
+
+# fping is in /local/sbin/
+PATH="/local/sbin:$PATH"
+export PATH
+
+# ypcat on OSF/1 prints 'key value'
+allservers=`ypcat ypservers | cut -d" " -f1`
+
+# fping options:
+# -a = show targets by address
+# -e = show time elapsed
+# Example output:
+# 129.240.130.23 is alive (0.22 ms)
+# 129.240.130.21 is alive (0.23 ms)
+servers=`fping -A -e $allservers | awk '{print $4,$1}' | cut -d'(' -f2 |
+ sort -n | head -$count | cut -d" " -f2`
+
+for server in $servers; do
+ echo "domain $domain server $server"
+done