This is Modem.m in view mode; [Download] [Up]
#import "Modem.h" #import <stdio.h> #import <libc.h> /* int usleep(unsigned int); */ /* Call 'capture' instead of 'write' to perform filtering. For now, we replace cr/lf with lf */ void capture(int fd, char *buf, int size) { static int lastchar=0; while (size>0) { if (*buf!='\r') write(fd,buf,1); if (lastchar=='\r' && *buf!='\n') { write(fd,&lastchar,1); write(fd,buf,1); } lastchar = *(buf++); size--; } } /* need to catch interrupt if user wished to kill child process */ void handler(int sig) { return; } @implementation Modem + newPort:(char *)dev speed:(int)bps { self = [super newReadWriteDevice:dev]; if (self==nil) return self; capturefd = (-1); sendProt = xmodem1k; receiveProt = zmodem; [[[[self setRaw] setParity:NOPARITY] unSetCrmod] unSetEcho]; [self setSpeed:bps]; return self; } + newA { return [self newPort:'a' speed:2400]; } + newB { return [self newPort:'b' speed:2400]; } - hangup // by clearing Data Terminal Ready signal to modem { char buf[200]; /* the following apparently doesn't work */ printf("\nAttempting to hang up phone via DTR\n"); ioctl(fd,TIOCCDTR,0); sleep(1); ioctl(fd,TIOCSDTR,0); printf("\nAttempting to hang up phone\n"); [self readInto:buf]; // flush modems buffer [self writeOut:"+++"]; sleep(4); if ([self readInto:buf] && strncmp(buf,"OK",2)) { [self writeOut:"ATH\r"]; printf("success\n"); } return self; } - forkExecArgv:(char **)argv { int pid; void (*oldhandler)(int); pid = fork(); if (pid!=0) { oldhandler = signal(SIGINT, handler); wait(0); fprintf(stderr,"\r\nFile transfer process ended\r\n"); signal(SIGINT, oldhandler); return self; } /* the child runs with stdin and stdout redirected to modem */ dup2(fd,0); dup2(fd,1); execv(argv[0],argv); return self; // this line is never reached } - receiveZmodem { char *argv[]={"/usr/local/bin/rz",NULL}; return [self forkExecArgv:argv]; } - sendZmodemFile:(char *)filename { char *argv[10]; argv[0]="/usr/local/bin/sz"; argv[1]=filename; argv[2]=NULL; return [self forkExecArgv:argv]; } - receiveYmodem { char *argv[]={"/usr/local/bin/rb",NULL}; return [self forkExecArgv:argv]; } - sendYmodemFile:(char *)filename { char *argv[10]; argv[0]="/usr/local/bin/sb"; argv[1]=filename; argv[2]=NULL; return [self forkExecArgv:argv]; } - receiveXmodemFile:(char *)filename { char *argv[10]; argv[0]="/usr/local/bin/rx"; argv[1]=filename; argv[2]=NULL; return [self forkExecArgv:argv]; } - sendXmodemFile:(char *)filename { char *argv[10]; argv[0]="/usr/local/bin/sx"; argv[1]=filename; argv[2]=NULL; return [self forkExecArgv:argv]; } - receiveXmodem1kFile:(char *)filename { char *argv[10]; argv[0]="/usr/local/bin/rx"; argv[1]="-k"; argv[2]=filename; argv[3]=NULL; return [self forkExecArgv:argv]; } - sendXmodem1kFile:(char *)filename { char *argv[10]; argv[0]="/usr/local/bin/sx"; argv[1]="-k"; argv[2]=filename; argv[3]=NULL; return [self forkExecArgv:argv]; } - receive { char file[200]; switch (receiveProt) { case xmodem: printf("\nEnter file in which to receive:"); scanf("%s",file); [self receiveXmodemFile:file]; break; case xmodem1k: printf("\nEnter file in which to receive:"); scanf("%s",file); [self receiveXmodem1kFile:file]; break; case ymodem: [self receiveYmodem]; break; case zmodem: [self receiveZmodem]; break; default: fprintf(stderr,"\nIllegal protocol\n\n"); break; } return self; } - sendFile:(char *)filename { switch (sendProt) { case xmodem: [self sendXmodemFile:filename]; break; case xmodem1k: [self sendXmodem1kFile:filename]; break; case ymodem: [self sendYmodemFile:filename]; break; case zmodem: [self sendZmodemFile:filename]; break; default: fprintf(stderr,"\nIllegal protocol\n\n"); break; } return self; } - setProtocol:(char)p dir:(enum direction)dir { enum protocol *prot; prot = (dir==tohost)? &sendProt: &receiveProt; switch (p) { case 'x': case 'X': *prot = xmodem; break; case '1': *prot = xmodem1k; break; case 'y': case 'Y': *prot = ymodem; break; case 'z': case 'Z': *prot = zmodem; break; default: fprintf(stderr,"\nIllegal protocol, specify x,y,or z\n\n"); break; } return self; } - (int) getProtocolDir:(enum direction)dir { enum protocol prot; prot = (dir==tohost)? sendProt: receiveProt; switch (prot) { case xmodem: return 'x'; break; case xmodem1k: return '1'; break; case ymodem: return 'y'; break; case zmodem: return 'z'; break; default: fprintf(stderr,"\nProtocol Undefined value = %d\n\n",prot); break; } return 0; } - captureSessionInFile:(char *)filename { capturefd = open(filename, O_WRONLY | O_APPEND | O_CREAT, 0644); return self; } - endCapture { close(capturefd); capturefd = (-1); return self; } - (BOOL) isCapturing { return (capturefd >= 0); } - (int) readInto:(char *)buf //returns number of characters read into buf { int chars; chars = [super readInto:buf]; if (capturefd >= 0) capture(capturefd, buf, chars); return chars; } /* When sending several character strings to a modem, * sometimes need to limit the rate. This simulates * typing by hand. * The delay is in microseconds, and is only a lower * limit. Because of the overhead of calling usleep(), * the pacing is noticeable even when delay = 1 uSec, * so I imagine a value of 1 will usually suffice. */ - (int) writeOut:(char *)buf paced:(unsigned long)delay { int len = strlen(buf); char onechar[2]; onechar[1]=0; while (len-- > 0) { onechar[0]=*buf++; if ([self writeOut:onechar] < 0) return -1; usleep(delay); } return len; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.