1 #include <signal.h> 2 #include <sys/types.h> 3 #include <utmp.h> 4 #include <setjmp.h> 5 #include <sys/reboot.h> 6 7 #define LINSIZ sizeof(wtmp.ut_line) 8 #define TABSIZ 100 9 #define ALL p = &itab[0]; p < &itab[TABSIZ]; p++ 10 #define EVER ;; 11 #define SCPYN(a, b) strncpy(a, b, sizeof(a)) 12 #define SCMPN(a, b) strncmp(a, b, sizeof(a)) 13 14 char shell[] = "/bin/sh"; 15 char getty[] = "/etc/getty"; 16 char minus[] = "-"; 17 char runc[] = "/etc/rc"; 18 char ifile[] = "/etc/ttys"; 19 char utmp[] = "/etc/utmp"; 20 char wtmpf[] = "/usr/adm/wtmp"; 21 char ctty[] = "/dev/console"; 22 char dev[] = "/dev/"; 23 24 struct utmp wtmp; 25 struct 26 { 27 char line[LINSIZ]; 28 char comn; 29 char flag; 30 } line; 31 struct tab 32 { 33 char line[LINSIZ]; 34 char comn; 35 char xflag; 36 int pid; 37 } itab[TABSIZ]; 38 39 int fi; 40 int mergflag; 41 char tty[20]; 42 jmp_buf sjbuf; 43 44 int reset(); 45 char *strcpy(), *strcat(); 46 long lseek(); 47 48 main() 49 { 50 register int r11; /* passed thru from boot */ 51 int howto, oldhowto; 52 53 howto = r11; 54 setjmp(sjbuf); 55 signal(SIGTERM, reset); 56 signal(SIGSTOP, SIG_IGN); 57 signal(SIGTSTP, SIG_IGN); 58 signal(SIGTTIN, SIG_IGN); 59 signal(SIGTTOU, SIG_IGN); 60 for(EVER) { 61 oldhowto = howto; 62 howto = RB_SINGLE; 63 shutdown(); 64 if (oldhowto & RB_SINGLE) 65 single(); 66 if (runcom(oldhowto) == 0) 67 continue; 68 merge(); 69 multiple(); 70 } 71 } 72 73 shutdown() 74 { 75 register i; 76 register struct tab *p; 77 78 close(creat(utmp, 0644)); 79 signal(SIGHUP, SIG_IGN); 80 for(ALL) { 81 term(p); 82 p->line[0] = 0; 83 } 84 signal(SIGALRM, reset); 85 alarm(60); 86 for(i=0; i<5; i++) 87 kill(-1, SIGKILL); 88 while(wait((int *)0) != -1) 89 ; 90 alarm(0); 91 signal(SIGALRM, SIG_DFL); 92 for(i=0; i<10; i++) 93 close(i); 94 } 95 96 single() 97 { 98 register pid; 99 100 pid = fork(); 101 if(pid == 0) { 102 /* 103 alarm(300); 104 */ 105 signal(SIGTERM, SIG_DFL); 106 signal(SIGHUP, SIG_DFL); 107 signal(SIGALRM, SIG_DFL); 108 open(ctty, 2); 109 dup(0); 110 dup(0); 111 execl(shell, minus, (char *)0); 112 exit(0); 113 } 114 while(wait((int *)0) != pid) 115 ; 116 } 117 118 runcom(oldhowto) 119 int oldhowto; 120 { 121 register pid, f; 122 int status; 123 124 pid = fork(); 125 if(pid == 0) { 126 open("/", 0); 127 dup(0); 128 dup(0); 129 if (oldhowto & RB_SINGLE) 130 execl(shell, shell, runc, (char *)0); 131 else 132 execl(shell, shell, runc, "autoboot", (char *)0); 133 exit(1); 134 } 135 while(wait(&status) != pid) 136 ; 137 if(status) 138 return(0); 139 f = open(wtmpf, 1); 140 if (f >= 0) { 141 lseek(f, 0L, 2); 142 SCPYN(wtmp.ut_line, "~"); 143 SCPYN(wtmp.ut_name, "reboot"); 144 time(&wtmp.ut_time); 145 write(f, (char *)&wtmp, sizeof(wtmp)); 146 close(f); 147 } 148 return(1); 149 } 150 151 setmerge() 152 { 153 154 signal(SIGHUP, setmerge); 155 mergflag = 1; 156 } 157 158 multiple() 159 { 160 register struct tab *p; 161 register pid; 162 163 loop: 164 mergflag = 0; 165 signal(SIGHUP, setmerge); 166 for(EVER) { 167 pid = wait((int *)0); 168 if(mergflag) { 169 merge(); 170 goto loop; 171 } 172 if(pid == -1) 173 return; 174 for(ALL) 175 if(p->pid == pid || p->pid == -1) { 176 rmut(p); 177 dfork(p); 178 } 179 } 180 } 181 182 term(p) 183 register struct tab *p; 184 { 185 186 if(p->pid != 0) { 187 rmut(p); 188 kill(p->pid, SIGKILL); 189 } 190 p->pid = 0; 191 } 192 193 rline() 194 { 195 register c, i; 196 197 loop: 198 c = get(); 199 if(c < 0) 200 return(0); 201 if(c == 0) 202 goto loop; 203 line.flag = c; 204 c = get(); 205 if(c <= 0) 206 goto loop; 207 line.comn = c; 208 SCPYN(line.line, ""); 209 for (i=0; i<LINSIZ; i++) { 210 c = get(); 211 if(c <= 0) 212 break; 213 line.line[i] = c; 214 } 215 while(c > 0) 216 c = get(); 217 if(line.line[0] == 0) 218 goto loop; 219 if(line.flag == '0') 220 goto loop; 221 strcpy(tty, dev); 222 strncat(tty, line.line, LINSIZ); 223 if(access(tty, 06) < 0) 224 goto loop; 225 return(1); 226 } 227 228 get() 229 { 230 char b; 231 232 if(read(fi, &b, 1) != 1) 233 return(-1); 234 if(b == '\n') 235 return(0); 236 return(b); 237 } 238 239 #define FOUND 1 240 #define CHANGE 2 241 242 merge() 243 { 244 register struct tab *p; 245 246 fi = open(ifile, 0); 247 if(fi < 0) 248 return; 249 for(ALL) 250 p->xflag = 0; 251 while(rline()) { 252 for(ALL) { 253 if (SCMPN(p->line, line.line)) 254 continue; 255 p->xflag |= FOUND; 256 if(line.comn != p->comn) { 257 p->xflag |= CHANGE; 258 p->comn = line.comn; 259 } 260 goto contin1; 261 } 262 for(ALL) { 263 if(p->line[0] != 0) 264 continue; 265 SCPYN(p->line, line.line); 266 p->xflag |= FOUND|CHANGE; 267 p->comn = line.comn; 268 goto contin1; 269 } 270 contin1: 271 ; 272 } 273 close(fi); 274 for(ALL) { 275 if((p->xflag&FOUND) == 0) { 276 term(p); 277 p->line[0] = 0; 278 } 279 if((p->xflag&CHANGE) != 0) { 280 term(p); 281 dfork(p); 282 } 283 } 284 } 285 286 dfork(p) 287 struct tab *p; 288 { 289 register pid; 290 291 pid = fork(); 292 if(pid == 0) { 293 signal(SIGTERM, SIG_DFL); 294 signal(SIGHUP, SIG_IGN); 295 strcpy(tty, dev); 296 strncat(tty, p->line, LINSIZ); 297 chown(tty, 0, 0); 298 chmod(tty, 0622); 299 open(tty, 2); 300 vhangup(); 301 signal(SIGHUP, SIG_DFL); 302 open(tty, 2); 303 close(0); 304 dup(1); 305 dup(0); 306 tty[0] = p->comn; 307 tty[1] = 0; 308 execl(getty, minus, tty, (char *)0); 309 exit(0); 310 } 311 p->pid = pid; 312 } 313 314 rmut(p) 315 register struct tab *p; 316 { 317 register f; 318 319 f = open(utmp, 2); 320 if(f >= 0) { 321 while(read(f, (char *)&wtmp, sizeof(wtmp)) == sizeof(wtmp)) { 322 if (SCMPN(wtmp.ut_line, p->line)) 323 continue; 324 lseek(f, -(long)sizeof(wtmp), 1); 325 SCPYN(wtmp.ut_name, ""); 326 time(&wtmp.ut_time); 327 write(f, (char *)&wtmp, sizeof(wtmp)); 328 } 329 close(f); 330 } 331 f = open(wtmpf, 1); 332 if (f >= 0) { 333 SCPYN(wtmp.ut_line, p->line); 334 SCPYN(wtmp.ut_name, ""); 335 time(&wtmp.ut_time); 336 lseek(f, (long)0, 2); 337 write(f, (char *)&wtmp, sizeof(wtmp)); 338 close(f); 339 } 340 } 341 342 reset() 343 { 344 longjmp(sjbuf, 1); 345 } 346 347 348