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;