13 static int console_owner(uid_t
, int);
15 int main(int argc
, char **argv
)
19 struct vt_stat origstate
;
30 console
=open("/dev/console", O_RDWR
);
36 openlog(argv
[0], LOG_PID
, LOG_DAEMON
);
39 syslog(LOG_WARNING
, "Usage error");
44 syslog(LOG_ERR
, "open(/dev/console): %m");
48 if(ioctl(console
, VT_GETSTATE
, &origstate
)<0) {
49 syslog(LOG_ERR
, "VT_GETSTATE: %m");
54 if(!console_owner(uid
, origstate
.v_active
)) {
57 if(i
!=origstate
.v_active
&& console_owner(uid
, i
))
61 syslog(LOG_WARNING
, "run by uid %lu not at console", (unsigned long)uid
);
67 if(ioctl(console
, VT_OPENQRY
, &openvtnum
)<0) {
68 syslog(LOG_ERR
, "VT_OPENQRY: %m");
72 syslog(LOG_ERR
, "No free VTs");
76 snprintf(openvtname
, sizeof openvtname
, "/dev/tty%d", openvtnum
);
78 openvt
=open(openvtname
, O_RDWR
);
81 syslog(LOG_ERR
, "open(%s): %m", openvtname
);
85 chowned
=fchown(openvt
, uid
, gid
);
88 syslog(LOG_ERR
, "fchown(%s): %m", openvtname
);
94 if(ioctl(openvt
, VT_ACTIVATE
, openvtnum
)<0) {
96 syslog(LOG_ERR
, "VT_ACTIVATE(%d): %m", openvtnum
);
100 while(ioctl(openvt
, VT_WAITACTIVE
, openvtnum
)<0) {
102 ioctl(openvt
, VT_ACTIVATE
, origstate
.v_active
);
104 syslog(LOG_ERR
, "VT_WAITACTIVE(%d): %m", openvtnum
);
110 fp
=fdopen(openvt
, "r+");
113 ioctl(openvt
, VT_ACTIVATE
, origstate
.v_active
);
115 syslog(LOG_ERR
, "fdopen(%s): %m", openvtname
);
119 if(tcgetattr(openvt
, &t
)<0) {
121 ioctl(openvt
, VT_ACTIVATE
, origstate
.v_active
);
123 syslog(LOG_ERR
, "tcgetattr(%s): %m", openvtname
);
127 if(tcsetattr(openvt
, TCSANOW
, &t
)<0) {
129 ioctl(openvt
, VT_ACTIVATE
, origstate
.v_active
);
131 syslog(LOG_ERR
, "tcsetattr(%s): %m", openvtname
);
135 if(fprintf(fp
, "\033[2J\033[H")<0) {
137 ioctl(openvt
, VT_ACTIVATE
, origstate
.v_active
);
139 syslog(LOG_ERR
, "write error on %s: %m", openvtname
);
142 if(argv
[1][0] && argv
[2][0]) {
143 if(fprintf(fp
, "Password for PPP client %s on server %s: ", argv
[1], argv
[2])<0) {
145 ioctl(openvt
, VT_ACTIVATE
, origstate
.v_active
);
147 syslog(LOG_ERR
, "write error on %s: %m", openvtname
);
150 } else if(argv
[1][0] && !argv
[2][0]) {
151 if(fprintf(fp
, "Password for PPP client %s: ", argv
[1])<0) {
152 syslog(LOG_ERR
, "write error on %s: %m", openvtname
);
154 ioctl(openvt
, VT_ACTIVATE
, origstate
.v_active
);
158 } else if(!argv
[1][0] && argv
[2][0]) {
159 if(fprintf(fp
, "Password for PPP on server %s: ", argv
[2])<0) {
161 ioctl(openvt
, VT_ACTIVATE
, origstate
.v_active
);
163 syslog(LOG_ERR
, "write error on %s: %m", openvtname
);
167 if(fprintf(fp
, "Enter PPP password: ")<0) {
169 ioctl(openvt
, VT_ACTIVATE
, origstate
.v_active
);
171 syslog(LOG_ERR
, "write error on %s: %m", openvtname
);
176 if(!fgets(pass
, sizeof pass
, fp
)) {
178 ioctl(openvt
, VT_ACTIVATE
, origstate
.v_active
);
181 syslog(LOG_ERR
, "read error on %s: %m", openvtname
);
185 if((nl
=strchr(pass
, '\n')))
187 passlen
=strlen(pass
);
190 if((wrote
=write(outfd
, pass
, passlen
))!=passlen
) {
192 ioctl(openvt
, VT_ACTIVATE
, origstate
.v_active
);
195 syslog(LOG_ERR
, "write error on outpipe: %m");
197 syslog(LOG_ERR
, "short write on outpipe");
202 ioctl(openvt
, VT_ACTIVATE
, origstate
.v_active
);
207 static int console_owner(uid_t uid
, int cons
)
211 snprintf(name
, sizeof name
, "/dev/tty%d", cons
);
212 if(stat(name
, &st
)<0) {
214 syslog(LOG_ERR
, "stat(%s): %m", name
);
217 return uid
==st
.st_uid
;