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.