mark@zok.UUCP (Mark W. Snitily) (02/01/91)
The Logitech bus mouse device driver that was just posted did not contain a proper copyright notice. Its posting was a surprise to me. If you saved a copy of that posting, *please* delete it and use this version instead. See the README file for details. -- Mark Mark W. Snitily Consulting Services: 894 Brookgrove Lane Graphics, Operating Systems, Compilers Cupertino, CA 95014 (408) 252-0456 mark@zok.uucp West Coast UUCP X11 archive site If your mailer doesn't like the .uucp domain, these also work: ...!{mips,sgi}!zok!mark, mark%zok@mips.com, mark%zok@sgi.com ---<cut here>------------------------------------------------------------------ #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of archive 1 (of 1)." # Contents: README lmouse.c lmouse.node lmouse.sdevice mt.c # Wrapped by mark@zok on Thu Jan 31 10:41:15 1991 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'README' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'README'\" else echo shar: Extracting \"'README'\" \(3664 characters\) sed "s/^X//" >'README' <<'END_OF_FILE' X31-Jan-1991 X XI screwed up. Last month in the newsgroup comp.unix.sysv386 I wrote: X X>If you really want a logitech bus mouse driver, I wrote one for ISC 2.x X>a long time ago (before ISC included one in their distribution). Haven't X>used it in a long time (since the ISC version works ok.) BTW, my version X>supported VP/ix too. If you really want a source version, email me a X>note. Or, if I receive more than, let's say, 5 requests, I'll post it X>to alt.sources. X XTo the few people that responded I sent a shar file of the original X29-May-1989 code. Without asking for permission, one person (who will Xremain nameless) posted the code to alt.sources. This was quite a surprise Xto me! (Was also ironic because I had to send the shar file to this person Xtwice because he accidentally deleted his first copy.) X XThough I don't mind that he posted the code, I wish he would have asked Xfirst because that version of the driver did not have a proper copyright Xnotice in it. This version does. (It's actually just a cut and paste of Xthe copyright and permission notice from my ppmtoxpm filter which you'll Xfind comp.sources.misc archives and Jef Poskanzer's new pbmplus release.) XThis driver is now copyrighted `freely available' code. X XSo, if you are one of the individuals who received this driver by email, Xor if you saved a copy of the version that was posted to alt.sources, X*please* delete it and use this one instead. Thank you. X XTwo additional items: (1) This code will become part of Thomas Roell's XX11R4 distribution, and (2) in my original README file I forgot to mention Xthe mdevice entry. This is the entry that I have in my /etc/conf/cf.d/mdevice Xfile, (note that the fields are separated by tabs, not spaces): X Xlmouse Ioci iHc logm 0 19 1 1 -1 X XThe test program "mt2.c" was removed from this distribution because it was Xa redundant copy of the "mt.c" test program. Only difference was the device Xname specified in the code. X XWhat follows is the original README file: X X14-Jan-1991 X XI wrote this Logitech bus mouse driver for ISC 2.x a long time ago, before XISC provided one in their distribution. (The last date of modification of Xthe driver source is May 29, 1989). Back in Dec '89 my system suffered a Xmajor disk crash resulting in the lose of my entire /usr/local directory Xtree. It was pure luck that I happened to have an extra copy of the driver Xsource elsewhere. Any/all Makefiles, install scripts, and miscellaneous Xnotes were unfortunately lost. Have never taken the time to recreate them. X XSo, ... you're totally on your own. Here's a quick summary of the files Xenclosed, (the following assumes an ISC directory strcture for installing Xdevice drivers, don't know if ESIX follows the same conventions): X X lmouse.c -- Driver source. After compiled the object file needs X to be placed in /etc/conf/pack.d/lmouse/Driver.o X X lmouse.node -- Copy this file to /etc/conf/node.d/lmouse X X lmouse.sdevice -- Copy this file to /etc/conf/sdevice.d/lmouse X X mt.c and mt2.c -- Test programs. X XFinally, you'll need to add the following line to the X/etc/conf/kconfig.d/description file, (note that the fields are separated Xby tabs not spaces): X Xlmouse 0 19 io lmouse My Logitech Bus Mouse Driver X XGood luck and happy hacking... X X-- Mark X XMark W. Snitily Consulting Services: X894 Brookgrove Lane Graphics, Operating Systems, Compilers XCupertino, CA 95014 (408) 252-0456 Xmark@zok.uucp West Coast UUCP X11 archive site X XIf your mailer doesn't like the .uucp domain, these also work: X...!{mips,sgi}!zok!mark, mark%zok@mips.com, mark%zok@sgi.com END_OF_FILE if test 3664 -ne `wc -c <'README'`; then echo shar: \"'README'\" unpacked with wrong size! fi # end of 'README' fi if test -f 'lmouse.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'lmouse.c'\" else echo shar: Extracting \"'lmouse.c'\" \(13038 characters\) sed "s/^X//" >'lmouse.c' <<'END_OF_FILE' X/* lmouse.c - Logitech Bus Mouse Device Driver for SysV/386 R3.2 X** X** Copyright (C) 1989,1991 by Mark W. Snitily X** X** Permission to use, copy, modify, and distribute this software and its X** documentation for any purpose and without fee is hereby granted, provided X** that the above copyright notice appear in all copies and that both that X** copyright notice and this permission notice appear in supporting X** documentation. This software is provided "as is" without express or X** implied warranty. X** X** 29-May-89 MWS Initial code completed and debugged X** 31-Jan-91 MWS Copyright notice added for general distribution X** X*/ X X#define VPIX X X#include "sys/param.h" X#include "sys/types.h" X#include "sys/sysmacros.h" X#include "sys/dir.h" X#include "sys/signal.h" X#include "sys/user.h" X#include "sys/errno.h" X X/* Definitions for Logitech Mouse */ X X/* Base I/O addresses of mouse registers */ X#define DATA_REG 0x23c /* Data register (read only) */ X#define SIGNATURE_REG 0x23d /* Signature register (read/write) */ X#define INTERRUPT_REG 0x23e /* Interrupt register (read only) */ X#define CONTROL_REG 0x23e /* Control register (write only) */ X#define CONFIG_REG 0x23f /* Configuration register (read/write) */ X X/* Definitions of bits in interrupt register. */ X#define IRQ5 0x01 X#define IRQ4 0x02 X#define IRQ3 0x04 X#define IRQ2 0x08 X X/* Definitions of bits in control register. */ X#define DINT 0x10 /* Disable Interrupts */ X#define SHL 0x20 /* Select Hi/Lo (0/1) nibble */ X#define SXY 0x40 /* Select X/Y (0/1) counter */ X#define HC 0x80 /* Hold Counters (latch counters on 0->1 edge) */ X X/* Magic number needed for configuration register. */ X#define CONFIG_BYTE 0x91 X X#define BUT3STAT 0x01 X#define BUT2STAT 0x02 X#define BUT1STAT 0x04 X X#define BUT3CHNG 0x08 X#define BUT2CHNG 0x10 X#define BUT1CHNG 0x20 X#define MOVEMENT 0x40 X X#define BUTSTATMASK 0x07 X#define BUTCHNGMASK 0x38 X Xstruct mouseinfo X{ unsigned char status; X char xmotion, ymotion; X}; X X/* Ioctl definitions */ X#define MOUSEIOC ('M'<<8) X#define MOUSEIOCREAD (MOUSEIOC|60) X X#ifdef VPIX X#define VPC_MOUSE_READ MOUSEIOCREAD X#endif /* VPIX */ X X#ifdef VPIX X#include "sys/immu.h" X#include "sys/region.h" X#include "sys/proc.h" X#include "sys/tss.h" X#include "sys/v86.h" X#endif /* VPIX */ X Xstatic char mousepresent; Xstatic char mouseinuse; Xstatic char mousemode; Xstatic char last_buttons; Xstatic char mousestatus; Xstatic int xmotion, ymotion; X#ifdef VPIX Xstatic struct proc *ectproc; Xstatic char rupted; X#endif /* VPIX */ X X#define UPPERLIM 127 X#define LOWERLIM -128 X#define ONEBYTE(x) ((x)>UPPERLIM ? UPPERLIM : (x)<LOWERLIM ? LOWERLIM : (x)) X X/*---------------------------------------------------------------------------*/ Xvoid logminit() X{ X unsigned char id1, id2, toggles, irq; X int i; X X /* Assume no mouse in system. */ X mouseinuse = mousepresent = 0; X X /* Initialize configuration register with the required magic number. */ X outb(CONFIG_REG, CONFIG_BYTE); X X /* See if we can store into the signature register. If not return. */ X outb(SIGNATURE_REG, 0xA5); X for (i=0; i<1000; i++); /* busy loop */ X id1 = inb(SIGNATURE_REG); X if (id1 != 0xA5) { X printf("logminit: SIGNATURE_REG = 0x%x (should equal 0xA5)\n", id1); X printf("Logitech Bus Mouse not loaded.\n"); X return; X } X X /* See which bits toggle in the interrupt register. */ X outb(CONTROL_REG, 0); /* Make sure interrupts are enabled. */ X id1 = inb(INTERRUPT_REG); X#ifdef DEBUG Xprintf("logminit: Initial value of interrupt reg = 0x%x\n", id1); X#endif /* DEBUG */ X toggles = 0; X for (i=0; i<10000; i++) { X id2 = inb(INTERRUPT_REG); X toggles |= id1 ^ id2; X id1 = id2; X } X outb(CONTROL_REG, DINT); /* Disable interrupts just to be safe. */ X X /* Based upon which bit(s) toggled, determine which IRQ is being used. X If nothing toggled, then something is wrong so don't set the X mousepresent flag. */ X if (toggles & IRQ5) irq = 5; X else if (toggles & IRQ2) irq = 2; X else if (toggles & IRQ3) irq = 3; X else if (toggles & IRQ4) irq = 4; X else { X printf("logminit: IRQ line did not respond (INTERRUPT_REG = 0x%x)\n", X toggles); X printf("Logitech Bus Mouse not loaded.\n"); X return; X } X printf("Logitech Bus Mouse loaded with IRQ%d\n", irq); X X /* Set control register. Set HC to 1: A rising edge of HC transfers X the content of the counters into latches and resets the counters; X Disable interrupts; (also selects low nibble of the X counter.) */ X outb(CONTROL_REG, HC | DINT); X X mousepresent = 1; X X} /* logminit */ X X/*---------------------------------------------------------------------------*/ Xvoid logmopen(dev, flag) Xint dev, flag; X{ X#ifdef DEBUG Xprintf("logmopen: dev = 0x%x, flag = 0x%x\n", dev, flag); X#endif /* DEBUG */ X X /* Insist on minor device 0 */ X if (minor(dev)) { u.u_error = ENXIO; return; } X X /* Make sure there is a mouse. */ X if (!mousepresent) { u.u_error = ENXIO; return; } X X /* Enforce exclusive use. */ X if (mouseinuse) { u.u_error = EBUSY; return; } X X xmotion = ymotion = 0; X mousestatus = last_buttons = 0; X X#ifdef VPIX X ectproc = u.u_procp; X rupted = 0; X#endif /* VPIX */ X X mouseinuse = 1; X X /* Set HC to 0 and enable interrupts. */ X outb(CONTROL_REG, 0); X X} /* logmopen */ X X/*---------------------------------------------------------------------------*/ Xvoid logmclose(dev) Xint dev; X{ X#ifdef DEBUG Xprintf("logmclose\n"); X#endif /* DEBUG */ X X /* Insist on minor device 0 */ X if (minor(dev)) { u.u_error = ENXIO; return; } X X /* Make sure there is a mouse. */ X if (!mousepresent) { u.u_error = ENXIO; return; } X X /* Make sure mouse has been opened. */ X if (!mouseinuse) { u.u_error = EACCES; return; } X X /* Reset the mouse to make sure it does not interrupt. */ X outb(CONTROL_REG, DINT); X mouseinuse = 0; X X} /* logmclose */ X X/*---------------------------------------------------------------------------*/ Xvoid logmioctl(dev, cmd, arg, flag) Xint dev, cmd, flag; Xcaddr_t arg; X{ X struct mouseinfo info; X register int intmask; X X#ifdef DEBUG X unsigned char ir; X X printf("logmioctl\n"); X#endif /* DEBUG */ X X /* Insist on minor device 0 */ X if (minor(dev)) { u.u_error = ENXIO; return; } X X /* Make sure there is a mouse. */ X if (!mousepresent) { u.u_error = ENXIO; return; } X X /* Make sure mouse has been opened. */ X if (!mouseinuse) { u.u_error = EACCES; return; } X X switch (cmd) { X#ifdef DEBUG X case 0: X printf("logmioctl: outb(CONTROL_REG, 0 )\n"); X outb(CONTROL_REG, 0 ); X break; X case 1: X printf("logmioctl: outb(CONTROL_REG, DINT)\n"); X outb(CONTROL_REG, DINT); X break; X case 2: X printf("logmioctl: outb(CONTROL_REG, SHL )\n"); X outb(CONTROL_REG, SHL ); X break; X case 3: X printf("logmioctl: outb(CONTROL_REG, SHL | DINT)\n"); X outb(CONTROL_REG, SHL | DINT); X break; X case 4: X printf("logmioctl: outb(CONTROL_REG, SXY )\n"); X outb(CONTROL_REG, SXY ); X break; X case 5: X printf("logmioctl: outb(CONTROL_REG, SXY | DINT)\n"); X outb(CONTROL_REG, SXY | DINT); X break; X case 6: X printf("logmioctl: outb(CONTROL_REG, SXY | SHL )\n"); X outb(CONTROL_REG, SXY | SHL ); X break; X case 7: X printf("logmioctl: outb(CONTROL_REG, SXY | SHL | DINT)\n"); X outb(CONTROL_REG, SXY | SHL | DINT); X break; X case 8: X printf("logmioctl: outb(CONTROL_REG, HC )\n"); X outb(CONTROL_REG, HC ); X break; X case 9: X printf("logmioctl: outb(CONTROL_REG, HC | DINT)\n"); X outb(CONTROL_REG, HC | DINT); X break; X case 10: X printf("logmioctl: outb(CONTROL_REG, HC | SHL )\n"); X outb(CONTROL_REG, HC | SHL ); X break; X case 11: X printf("logmioctl: outb(CONTROL_REG, HC | SHL | DINT)\n"); X outb(CONTROL_REG, HC | SHL | DINT); X break; X case 12: X printf("logmioctl: outb(CONTROL_REG, HC | SXY )\n"); X outb(CONTROL_REG, HC | SXY ); X break; X case 13: X printf("logmioctl: outb(CONTROL_REG, HC | SXY | DINT)\n"); X outb(CONTROL_REG, HC | SXY | DINT); X break; X case 14: X printf("logmioctl: outb(CONTROL_REG, HC | SXY | SHL )\n"); X outb(CONTROL_REG, HC | SXY | SHL ); X break; X case 15: X printf("logmioctl: outb(CONTROL_REG, HC | SXY | SHL | DINT)\n"); X outb(CONTROL_REG, HC | SXY | SHL | DINT); X break; X X case 20: X ir = inb(DATA_REG); X printf("logmioctl: inb(DATA_REG) = 0x%x\n", ir); X break; X case 21: X ir = inb(SIGNATURE_REG); X printf("logmioctl: inb(SIGNATURE_REG) = 0x%x\n", ir); X break; X case 22: X ir = inb(INTERRUPT_REG); X printf("logmioctl: inb(INTERRUPT_REG) = 0x%x\n", ir); X break; X case 23: X ir = inb(CONFIG_REG); X printf("logmioctl: inb(CONFIG_REG) = 0x%x\n", ir); X break; X case 24: X outb(CONFIG_REG, CONFIG_BYTE); X printf("logmioctl: outb(CONFIG_REG, CONFIG_BYTE)\n"); X break; X#endif /* DEBUG */ X X default: X /* Return error "Invalid argument". */ X u.u_error = EINVAL; X#ifdef DEBUG X printf("logmioctl: unknown cmd = 0x%x\n", cmd); X#endif /* DEBUG */ X break; X X case MOUSEIOCREAD: X /* Prevent mouse interrupts during update. */ X intmask = splhi(); X X /* Read and reset the accumulated interrupt info. */ X X /* This emulates the microsoft bus mouse status return. */ X info.status = mousestatus; X if (xmotion || ymotion) info.status |= MOVEMENT; X X info.xmotion = ONEBYTE(xmotion); X info.ymotion = ONEBYTE(ymotion); X xmotion = ymotion = 0; X mousestatus &= ~BUTCHNGMASK; /* clear "button changed" bits */ X#ifdef VPIX X rupted = 0; X#endif /* VPIX */ X X /* Resume mouse interrupts. */ X splx(intmask); X X if (copyout(&info, arg, sizeof info)) u.u_error = EFAULT; X break; X } /* switch */ X} /* logmioctl */ X X/*---------------------------------------------------------------------------*/ Xvoid logmintr(ivect) Xint ivect; X{ X unsigned char lo, hi, buttons, changed_buttons; X int dx, dy; X X /* Ignore if mouse is not present. */ X if (!mousepresent) return; X X /* Print error on console if mouse has not been opened. */ X if (!mouseinuse) { X#ifdef DEBUG X printf("logmintr: Unsolicited INT %d\n", ivect); X#endif /* DEBUG */ X outb(CONTROL_REG, DINT); /* disable interrupts */ X return; X } X X /* Read low X nibble. */ X outb(CONTROL_REG, HC); X lo = inb(DATA_REG) & 0x0F; X X /* Read high X nibble. */ X outb(CONTROL_REG, HC | SHL); X hi = inb(DATA_REG) & 0x0F; X X /* Combine high and low X nibbles. */ X dx = (char) ((hi << 4) | lo); /* force dx to be signed */ X X /* Read low Y nibble. */ X outb(CONTROL_REG, HC | SXY); X lo = inb(DATA_REG) & 0x0F; X X /* Read high Y nibble. */ X outb(CONTROL_REG, HC | SXY | SHL); X hi = inb(DATA_REG); X X /* Extract and invert the button bits. X After inverting, a set bit means the button was pressed down. */ X buttons = (~hi >> 5) & 0x07; X changed_buttons = buttons ^ last_buttons; X last_buttons = buttons; X X /* Combine high and low X nibbles. */ X dy = (char) (((hi & 0x0F) << 4) | lo); /* force dy to be signed */ X X /* This code emulates the Microsoft bus mouse status (except for the MOTION X bit which is set in the ioctl routine). State changes are or'ed over X any number of interrupts, but the buttons bits are always set to the X current state. (The state changes are cleared when read in the ioctl X routine.) */ X mousestatus = buttons | (mousestatus & ~BUTSTATMASK) X | (changed_buttons << 3); X X /* Reset HC to 0. */ X outb(CONTROL_REG, 0); X X /* If nothing has changed, nothing needs to be done, so return. */ X if (!(dx || dy || changed_buttons)) return; X X /* Update global variables with info just read. */ X xmotion += dx; X ymotion += dy; X#ifdef DEBUG X printf("logmintr: dx = %d, dy = %d, buttons = %d\n", dx, dy, buttons); X#endif /* DEBUG */ X X#ifdef VPIX X /* Send a pseudorupt if this is an ECT and the mouse has been read since X the last pseudorupt. */ X if (ectproc && ectproc->p_v86 && !rupted) { X v86setint(ectproc->p_v86, V86VI_MOUSE); X rupted = 1; X } X#endif /* VPIX */ X X} /* logmintr */ END_OF_FILE if test 13038 -ne `wc -c <'lmouse.c'`; then echo shar: \"'lmouse.c'\" unpacked with wrong size! fi # end of 'lmouse.c' fi if test -f 'lmouse.node' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'lmouse.node'\" else echo shar: Extracting \"'lmouse.node'\" \(18 characters\) sed "s/^X//" >'lmouse.node' <<'END_OF_FILE' Xlmouse lmouse c 0 END_OF_FILE if test 18 -ne `wc -c <'lmouse.node'`; then echo shar: \"'lmouse.node'\" unpacked with wrong size! fi # end of 'lmouse.node' fi if test -f 'lmouse.sdevice' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'lmouse.sdevice'\" else echo shar: Extracting \"'lmouse.sdevice'\" \(29 characters\) sed "s/^X//" >'lmouse.sdevice' <<'END_OF_FILE' Xlmouse N 1 6 1 5 23c 23f 0 0 END_OF_FILE if test 29 -ne `wc -c <'lmouse.sdevice'`; then echo shar: \"'lmouse.sdevice'\" unpacked with wrong size! fi # end of 'lmouse.sdevice' fi if test -f 'mt.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'mt.c'\" else echo shar: Extracting \"'mt.c'\" \(2677 characters\) sed "s/^X//" >'mt.c' <<'END_OF_FILE' X/*--------------------------*/ X#include "sys/param.h" X#include "sys/types.h" X#include "sys/sysmacros.h" X#include "sys/dir.h" X#include "sys/signal.h" X#include "sys/user.h" X#include "sys/errno.h" X#include "sys/inline.h" X/*--------------------------*/ X#include <stdio.h> X#include <fcntl.h> X#include <sys/mouse.h> X Xstatic int _fd = -1; X Xextern int errno; X X/*---------------------------------------------------------------------------*/ Xint ms_init() X{ X struct mouseinfo pkt; X X if ((_fd = open("/dev/lmouse", O_RDONLY)) == -1) { X printf("errno = %d\n", errno); X perror("ms_init: open"); X return -1; X } X/* X else if (ioctl(_fd, MOUSEIOCREAD, &pkt) == -1 ) { X perror("ms_init: ioctl"); X close(_fd ); X return -1; X } X*/ X return 0; X} /* ms_init */ X X/*---------------------------------------------------------------------------*/ Xint ms_ioctl(cmd) Xint cmd; X{ X struct mouseinfo pkt; X X if (cmd == 25) { X if (ioctl(_fd, MOUSEIOCREAD, &pkt) == -1 ) { X perror("ms_init: ioctl"); X/* close(_fd ); */ X return -1; X } X printf("ms_ioctl: status = 0x%x, xmotion = %d, ymotion = %d\n", X pkt.status, pkt.xmotion, pkt.ymotion); X } X else if (ioctl(_fd, cmd, &pkt) == -1 ) { X perror("ms_ioctl: ioctl"); X/* close(_fd ); */ X return -1; X } X X return 0; X} /* ms_ioctl */ X X/*---------------------------------------------------------------------------*/ Xint ms_close() X{ X int rc = -1; X X if (_fd != -1) { X rc = close(_fd ); X _fd = -1; X } X return rc; X} /* ms_close */ X X#ifdef NOT_NOW X X/* X * FUNCTION: BMSEMD_READ X * a routine to call when mouse data is available X * X * INPUT PARAMETERS X * none X * OUTPUT PARAMETERS X * none X */ Xvoid bmsemd_read() X{ X MSEPKT pkt; X X if ( _fd == -1 || ioctl(_fd,VPC_MOUSE_READ,&pkt) == -1 ) X { X#ifdef DEBUG X v86error(VERR_WARNING,"unable to get mouse data"); X#endif X return; X } X X if ( pkt.status & MOVEMENT ) /* if the mouse moved */ X xy_bmouse( pkt.xmotion, pkt.ymotion ); X X if ( pkt.status & BUT1CHNG ) /* if button 1 changed */ X btn_bmouse( 0, (int)(pkt.status & BUT1STAT) ); X X if ( pkt.status & BUT2CHNG ) /* if button 2 changed */ X btn_bmouse( 1, (int)(pkt.status & BUT2STAT) ); X X if ( pkt.status & BUT3CHNG ) /* if button 3 changed */ X btn_bmouse( 2, (int)(pkt.status & BUT3STAT) ); X} X#endif /* NOT_NOW */ X Xmain() X{ X char str[80]; X int cmd; X X ms_init(); X for (cmd = 0; 0 <= cmd && cmd <= 25;) { X printf("cmd? (0-25) > "); X (void) gets(str); X cmd = atoi(str); X printf("mt: cmd = %d\n", cmd); X if (0 <= cmd && cmd <= 25) ms_ioctl(cmd); X else printf("exiting\n"); X } X ms_close(); X} END_OF_FILE if test 2677 -ne `wc -c <'mt.c'`; then echo shar: \"'mt.c'\" unpacked with wrong size! fi # end of 'mt.c' fi echo shar: End of archive 1 \(of 1\). cp /dev/null ark1isdone MISSING="" for I in 1 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have the archive. rm -f ark[1-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0