static char sccsid
[] = "@(#)acucntrl.c 5.1 (Berkeley) %G%";
/* acucntrl - turn around tty line between dialin and dialout
* Usage: acucntrl {enable,disable} /dev/ttydX
* First written by Allan Wilkes (fisher!allan)
* Modified June 8,1983 by W.Sebok (astrovax!wls) to poke kernel rather
* than use kernel hack to turn on/off modem control, using subroutine
* stolen from program written by Tsutomu Shimomura
* {astrovax,escher}!tsutomu
* Worked over many times by W.Sebok (i.e. hacked to death)
* disable (i.e. setup for dialing out)
* (1) check input arguments
* (2) look in /etc/utmp to check that the line is not in use by another
* (3) disable modem control on terminal
* (4) check for carrier on device
* (5) change owner of device to real id
* (6) edit /etc/ttys, changing the first character of the appropriate
* (7) send a hangup to process 1 to poke init to disable getty
* (8) post uid name in capitals in /etc/utmp to let world know device has
* (9) make sure that DTR is on
* enable (i.e.) restore for dialin
* (1) check input arguments
* (2) look in /etc/utmp to check that the line is not in use by another
* (3) make sure modem control on terminal is disabled
* (4) turn off DTR to make sure line is hung up
* (5) condition line: clear exclusive use and set hangup on close modes
* (6) turn on modem control
* (7) edit /etc/ttys, changing the first character of the appropriate
* (8) send a hangup to process 1 to poke init to enable getty
* (9) clear uid name for /etc/utmp
/* #define SENSECARRIER */
#include "/sys/vaxuba/ubavar.h"
#define NDZLINE 8 /* lines/dz */
#define NDHLINE 16 /* lines/dh */
#define NDMFLINE 8 /* lines/dmf */
#define NLVALUE(val) (nl[val].n_value)
char Etcutmp
[] = "/etc/utmp";
char Etcttys
[] = "/etc/ttys";
char usage
[] = "Usage: acucntrl {dis|en}able ttydX\n";
char resettty
, resetmodem
;
#define NAMSIZ sizeof(utmp.ut_name)
#define LINSIZ sizeof(utmp.ut_line)
char uname
[NAMSIZ
], Uname
[NAMSIZ
];
struct passwd
*getpwuid();
extern char *sys_errlist
[];
/* check input arguments */
/* interpret command type */
if (prefix(argv
[1], "disable") || strcmp(argv
[1],"dialout")==0)
else if (prefix(argv
[1], "enable") || strcmp(argv
[1],"dialin")==0)
device
= rindex(argv
[2],'/');
device
= (device
== NULL
) ? argv
[2]: device
+1;
/* only recognize devices of the form ttydX */
if (strncmp(device
,"ttyd",4)!=0) {
fprintf(stderr
,"Bad Device Name %s",device
);
fprintf(stderr
, "Cannot chdir to %s: %s\r\n",
Devhome
, sys_errlist
[errno
]);
/* Get uid information */
p
= getpwuid(uid
)->pw_name
;
fprintf(stderr
,"cannot get uid name\n");
Uname
[i
] = (*p
>='a' && *p
<='z') ? (*p
- ('a'-'A')) : *p
;
} while (*p
&& i
<NAMSIZ
);
/* check to see if line is being used */
if( (etcutmp
= open(Etcutmp
, 2)) < 0) {
fprintf(stderr
,"On open %s open: %s\n",
Etcutmp
,sys_errlist
[errno
]);
(void)lseek(etcutmp
,utmploc
, 0);
i
= read(etcutmp
,&utmp
,sizeof(struct utmp
));
i
== sizeof(struct utmp
) &&
utmp
.ut_line
[0] != '\0' &&
utmp
.ut_name
[0] != '\0' &&
!upcase(utmp
.ut_name
,NAMSIZ
) ||
strncmp(utmp
.ut_name
,Uname
,NAMSIZ
) != 0
fprintf(stderr
, "%s in use by %s\n", device
, utmp
.ut_name
);
/* Disable modem control */
if (setmodem(device
,DISABLE
)<0) {
fprintf(stderr
,"Unable to disable modem control\n");
if((devfile
= open(device
, 1)) < 0) {
fprintf(stderr
,"On open of %s: %s\n",
device
, sys_errlist
[errno
]);
(void)setmodem(device
,resetmodem
);
/* Try one last time to hang up */
if (ioctl(devfile
,TIOCCDTR
,0) < 0)
fprintf(stderr
,"On TIOCCDTR ioctl: %s\n",
if (ioctl(devfile
, TIOCNXCL
,0) < 0)
"Cannot clear Exclusive Use on %s: %s\n",
device
, sys_errlist
[errno
]);
if (ioctl(devfile
, TIOCHPCL
,0) < 0)
"Cannot set hangup on close on %s: %s\n",
device
, sys_errlist
[errno
]);
if (setmodem(device
,ENABLE
) < 0) {
fprintf(stderr
,"Cannot Enable modem control\n");
(void)setmodem(device
,i
);
pokeinit(device
,Uname
,enable
);
#if defined(TIOCMGET) && defined(SENSECARRIER)
/* check for presence of carrier */
sleep(2); /* need time after modem control turnoff */
if((devfile
= open(device
, 1)) < 0) {
fprintf(stderr
,"On open of %s: %s\n",
device
, sys_errlist
[errno
]);
(void)setmodem(device
,resetmodem
);
(void)ioctl(devfile
,TIOCMGET
,&linestat
);
if (linestat
&TIOCM_CAR
) {
fprintf(stderr
,"%s is in use (Carrier On)\n",
(void)setmodem(device
,resetmodem
);
if(chown(device
, uid
, gid
) < 0)
fprintf(stderr
, "Cannot chown %s: %s\n",
device
, sys_errlist
[errno
]);
pokeinit(device
,Uname
,enable
);
if((devfile
= open(device
, 1)) < 0) {
fprintf(stderr
, "On %s open: %s\n",
device
, sys_errlist
[errno
]);
if(ioctl(devfile
, TIOCSDTR
, 0) < 0)
"Cannot set DTR on %s: %s\n",
device
, sys_errlist
[errno
]);
/* return true if no lower case */
for (; *str
, --len
>= 0 ; str
++)
if (*str
>='a' && *str
<='z')
/* Post name to public */
(void)time(&utmp
.ut_time
);
strcpyn(utmp
.ut_line
, device
, LINSIZ
);
strcpyn(utmp
.ut_name
, name
, NAMSIZ
);
if (lseek(etcutmp
, utmploc
, 0)<0)
fprintf(stderr
,"on lseek in /etc/utmp: %s",
if (write(etcutmp
, (char *)&utmp
, sizeof(utmp
))<0)
fprintf(stderr
,"on write in /etc/utmp: %s",
/* poke process 1 and wait for it to do its thing */
pokeinit(device
,uname
,enable
)
char *uname
, *device
; int enable
;
"Cannot send hangup to init process: %s\n",
(void)setmodem(device
,resetmodem
);
/* wait till init has responded, clearing the utmp entry */
if (lseek(etcutmp
,utmploc
,0)<0)
fprintf(stderr
,"On lseek in /etc/utmp: %s",
if (read(etcutmp
,&utmp
,sizeof utmp
)<0)
fprintf(stderr
,"On read from /etc/utmp: %s",
} while (utmp
.ut_name
[0] !='\0');
/* identify terminal line in ttys */
register int ndevice
, lnsiz
;
ttysfile
= fopen(Etcttys
, "r");
fprintf(stderr
, "Cannot open %s: %s\n", Etcttys
,
ndevice
= strlen(device
);
while(fgets(linebuf
, sizeof(linebuf
) - 1, ttysfile
) != NULL
) {
if ((p
= index(linebuf
,'\n')) != NULL
)
if(strncmp(device
, &linebuf
[2], ndevice
) == 0) {
fprintf(stderr
, "%s not found in %s\n", device
, Etcttys
);
/* modify appropriate line in /etc/ttys to turn on/off the device */
int lnbeg
, foundit
, ndevice
;
ittysfil
= open(Etcttys
, 2);
fprintf(stderr
, "Cannot open %s for output: %s\n",
Etcttys
, sys_errlist
[errno
]);
(void)lseek(ittysfil
,(long)ttyslnbeg
,0);
if(read(ittysfil
,&in
,1)<0) {
fprintf(stderr
,"On %s write: %s\n",
Etcttys
, sys_errlist
[errno
]);
out
= enable
? '1' : '0';
(void)lseek(ittysfil
,(long)ttyslnbeg
,0);
if(write(ittysfil
,&out
,1)<0) {
fprintf(stderr
,"On %s write: %s\n",
Etcttys
, sys_errlist
[errno
]);
* Excerpted from (June 8,1983 W.Sebok)
* > ttymodem.c - enable/disable modem control for tty lines.
* > Knows about DZ11s and DH11/DM11s.
* > modified to know about DMF's (hasn't been tested) Nov 8,1984 - WLS
char *ttyline
; int enable
;
int unit
,line
,nlines
,addr
,tflags
;
struct uba_device
*ubinfo
;
if(nl
[CDEVSW
].n_type
== 0) {
fprintf(stderr
,"No namelist.\n");
if((kmem
= open("/dev/kmem", 2)) < 0) {
fprintf(stderr
,"/dev/kmem open: %s\n", sys_errlist
[errno
]);
if(stat(ttyline
,&statb
) < 0) {
fprintf(stderr
,"%s stat: %s\n", ttyline
, sys_errlist
[errno
]);
if(statb
.st_mode
&S_IFMT
!= S_IFCHR
) {
fprintf(stderr
,"%s is not a character device.\n",ttyline
);
(int) &(((struct cdevsw
*)NLVALUE(CDEVSW
))[major(dev
)]),0);
(void)read(kmem
,(char *) &cdevsw
,sizeof cdevsw
);
if((int)(cdevsw
.d_open
) == NLVALUE(DZOPEN
)) {
unit
= minor(dev
) / NDZLINE
;
line
= minor(dev
) % NDZLINE
;
addr
= (int) &(((int *)NLVALUE(DZINFO
))[unit
]);
(void)lseek(kmem
,(int) NLVALUE(NDZ11
),0);
} else if((int)(cdevsw
.d_open
) == NLVALUE(DHOPEN
)) {
unit
= minor(dev
) / NDHLINE
;
line
= minor(dev
) % NDHLINE
;
addr
= (int) &(((int *)NLVALUE(DHINFO
))[unit
]);
(void)lseek(kmem
,(int) NLVALUE(NDH11
),0);
} else if((int)(cdevsw
.d_open
) == NLVALUE(DMFOPEN
)) {
unit
= minor(dev
) / NDMFLINE
;
line
= minor(dev
) % NDMFLINE
;
addr
= (int) &(((int *)NLVALUE(DMFINFO
))[unit
]);
(void)lseek(kmem
,(int) NLVALUE(NDMF
),0);
fprintf(stderr
,"Device %s (%d/%d) unknown.\n",ttyline
,
(void)read(kmem
,(char *) &nlines
,sizeof nlines
);
if(minor(dev
) >= nlines
) {
fprintf(stderr
,"Sub-device %d does not exist (only %d).\n",
(void)lseek(kmem
,addr
,0);
(void)read(kmem
,(char *) &ubinfo
,sizeof ubinfo
);
(void)lseek(kmem
,(int) &(ubinfo
->ui_flags
),0);
(void)read(kmem
,(char *) &flags
,sizeof flags
);
resetmodem
= ((flags
&tflags
) == 0);
flags
= enable
? (flags
& ~tflags
) : (flags
| tflags
);
(void)lseek(kmem
,(int) &(ubinfo
->ui_flags
),0);
(void)write(kmem
,(char *) &flags
, sizeof flags
);
if((addr
= NLVALUE(DZSCAR
)) == 0) {
fprintf(stderr
,"No dzsoftCAR.\n");
(void)lseek(kmem
,(int) &(((char *)addr
)[unit
]),0);
(void)write(kmem
,(char *) &flags
, sizeof flags
);
if((addr
= NLVALUE(DHSCAR
)) == 0) {
fprintf(stderr
,"No dhsoftCAR.\n");
(void)lseek(kmem
,(int) &(((short *)addr
)[unit
]),0);
(void)write(kmem
,(char *) &flags
, sizeof flags
);
if((addr
= NLVALUE(DMFSCAR
)) == 0) {
fprintf(stderr
,"No dmfsoftCAR.\n");
(void)lseek(kmem
,(int) &(((short *)addr
)[unit
]),0);
(void)write(kmem
,(char *) &flags
,2);
fprintf(stderr
,"Unknown device type\n");
while ((c
= *s1
++) == *s2
++)