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