📄 simpleinit.c
字号:
{ err (_ ("lstat of path failed\n") ); return 1; } if ( S_ISLNK (statbuf.st_mode) ) { if (stat (path, &statbuf) != 0) { if ( (errno == ENOENT) && ignore_dangling_symlink ) return 0; err (_ ("stat of path failed\n") ); return 1; } } if ( !( statbuf.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH) ) ) return 0; if ( !S_ISDIR (statbuf.st_mode) ) return (*func) (path); if ( ( dp = opendir (path) ) == NULL ) { err (_ ("open of directory failed\n") ); return 1; } while ( ( de = readdir (dp) ) != NULL ) { int retval; char newpath[PATH_SIZE]; if (de->d_name[0] == '.') continue; retval = sprintf (newpath, "%s/%s", path, de->d_name); if (newpath[retval - 1] == '~') continue; /* Common mistake */ if ( ( retval = process_path (newpath, func, 1) ) ) return retval; } closedir (dp); return 0;} /* End Function process_path */static int preload_file (const char *path){ int fd; char ch; if ( ( fd = open (path, O_RDONLY, 0) ) < 0) return 0; while (read (fd, &ch, 1) == 1) lseek (fd, 1024, SEEK_CUR); close (fd); return 0;} /* End Function preload_file */static int run_file (const char *path){ const char *ptr; if ( ( ptr = strrchr ( (char *) path, '/' ) ) == NULL ) ptr = path; else ++ptr; return (run_command (path, ptr, 0) == SIG_FAILED) ? 1 : 0;} /* End Function run_file */static void spawn (int i){ pid_t pid; int j; signed long ds_taken; struct timeval ct; if (inittab[i].toks[0] == NULL) return; /* Check if respawning too fast */ gettimeofday (&ct, NULL); ds_taken = ct.tv_sec - inittab[i].last_start.tv_sec; /* On the first iteration last_start==0 and ds_taken may be very large. Avoid overflow. -- Denis Vlasenko */ if (ds_taken > 10000) ds_taken = 10000; ds_taken *= 10; ds_taken += (ct.tv_usec - inittab[i].last_start.tv_usec) / 100000; if (ds_taken < 1) ds_taken = 1; inittab[i].rate = (9 * inittab[i].rate + 1000 / ds_taken) / 10; if (inittab[i].rate > MAX_RESPAWN_RATE) { char txt[256]; inittab[i].toks[0] = NULL; inittab[i].pid = -1; inittab[i].rate = 0; sprintf (txt,"respawning: \"%s\" too fast: quenching entry\n", inittab[i].tty); err (_(txt)); return; } if((pid = fork()) < 0) { inittab[i].pid = -1; err(_("fork failed\n")); return; } if(pid) { /* this is the parent */ inittab[i].pid = pid; inittab[i].last_start = ct; sched_yield (); return; } else { /* this is the child */ char term[40];#ifdef SET_TZ char tz[CMDSIZ];#endif char *env[3]; setsid(); for(j = 0; j < getdtablesize(); j++) (void) close(j); (void) sprintf(term, "TERM=%s", inittab[i].termcap); env[0] = term; env[1] = (char *)0;#ifdef SET_TZ (void) sprintf(tz, "TZ=%s", tzone); env[1] = tz;#endif env[2] = (char *)0; execve(inittab[i].toks[0], inittab[i].toks, env); err(_("exec failed\n")); sleep(5); _exit(1); }}static void read_inittab (void){ FILE *f; char buf[CMDSIZ]; int i,j,k; int has_prog = 0; char *ptr, *getty; char prog[PATH_SIZE];#ifdef SPECIAL_CONSOLE_TERM char tty[50]; struct stat stb;#endif char *termenv; termenv = getenv("TERM"); /* set by kernel */ /* termenv = "vt100"; */ if(!(f = fopen(_PATH_INITTAB, "r"))) { err(_("cannot open inittab\n")); return; } prog[0] = '\0'; i = 0; while(!feof(f) && i < NUMCMD - 2) { if(fgets(buf, CMDSIZ - 1, f) == 0) break; buf[CMDSIZ-1] = 0; for(k = 0; k < CMDSIZ && buf[k]; k++) { if ((buf[k] == '#') || (buf[k] == '\n')) { buf[k] = 0; break; } } if(buf[0] == 0 || buf[0] == '\n') continue; ptr = strchr (buf, '='); if (ptr) { ptr++; if ( !strncmp (buf, "bootprog", 8) ) { while ( isspace (*ptr) ) ++ptr; strcpy (prog, ptr); has_prog = 1; continue; } if ( !strncmp (buf, "fileprefix", 10) ) { while ( isspace (*ptr) ) ++ptr; strcpy (script_prefix, ptr); continue; } if ( !strncmp (buf, "PATH", 4) ) { while ( isspace (*ptr) ) ++ptr; setenv ("PATH", ptr, 1); continue; } if ( !strncmp (buf, "INIT_PATH", 9) ) { while ( isspace (*ptr) ) ++ptr; strcpy (init_path, ptr); continue; } if ( !strncmp (buf, "finalprog", 8) ) { while ( isspace (*ptr) ) ++ptr; strcpy (final_prog, ptr); continue; } } (void) strcpy(inittab[i].line, buf); (void) strtok(inittab[i].line, ":"); xstrncpy(inittab[i].tty, inittab[i].line, 10); xstrncpy(inittab[i].termcap, strtok((char *)0, ":"), 30); getty = strtok((char *)0, ":"); (void) strtok(getty, " \t\n"); inittab[i].toks[0] = getty; j = 1; while((ptr = strtok((char *)0, " \t\n"))) inittab[i].toks[j++] = ptr; inittab[i].toks[j] = (char *)0;#ifdef SPECIAL_CONSOLE_TERM /* special-case termcap for the console ttys */ (void) sprintf(tty, "/dev/%s", inittab[i].tty); if(!termenv || stat(tty, &stb) < 0) { err(_("no TERM or cannot stat tty\n")); } else { /* is it a console tty? */ if(major(stb.st_rdev) == 4 && minor(stb.st_rdev) < 64) xstrncpy(inittab[i].termcap, termenv, 30); }#endif i++; } fclose(f); numcmd = i; if (has_prog) { int len; char path[PATH_SIZE]; strcpy (path, script_prefix); strcat (path, prog); len = strlen (path); if (path[len - 1] == '/') path[len - 1] = '\0'; if (access (path, R_OK | X_OK) == 0) strcpy (boot_prog, path); }} /* End Function read_inittab */static void sighup_handler (int sig){ int i,j; int oldnum; struct initline savetab[NUMCMD]; int had_already; signal (SIGHUP, SIG_IGN); memcpy(savetab, inittab, NUMCMD * sizeof(struct initline)); oldnum = numcmd; read_inittab (); for(i = 0; i < numcmd; i++) { had_already = 0; for(j = 0; j < oldnum; j++) { if(!strcmp(savetab[j].tty, inittab[i].tty)) { had_already = 1; if((inittab[i].pid = savetab[j].pid) < 0) spawn(i); } } if (!had_already) spawn (i); } signal (SIGHUP, sighup_handler);} /* End Function sighup_handler */static void sigtstp_handler (int sig){ stopped = ~stopped; if (!stopped) sighup_handler (sig);} /* End Function sigtstp_handler */static void sigterm_handler (int sig){ int i; for (i = 0; i < numcmd; i++) if (inittab[i].pid > 0) kill (inittab[i].pid, SIGTERM);} /* End Function sigterm_handler */static void sigint_handler (int sig){ pid_t pid; caught_sigint = 1; kill (rc_child, SIGKILL); if (no_reboot) _exit (1) /*kill (0, SIGKILL)*/; sync (); sync (); pid = fork (); if (pid > 0) return; /* Parent */ if (pid == 0) /* Child: reboot properly... */ execl (_PATH_REBOOT, _PATH_REBOOT, (char *) 0); /* fork or exec failed, try the hard way... */ my_reboot (LINUX_REBOOT_CMD_RESTART);} /* End Function sigint_handler */static void sigchild_handler (int sig){ if (!do_longjmp) return; siglongjmp (jmp_env, 1);}static void sigquit_handler (int sig){ execl (_PATH_REBOOT, _PATH_REBOOT, NULL); /* It knows pid=1 must sleep */}#ifdef SET_TZstatic void set_tz (void){ FILE *f; int len; if((f=fopen(TZFILE, "r")) == (FILE *)NULL) return; fgets(tzone, CMDSIZ-2, f); fclose(f); if((len=strlen(tzone)) < 2) return; tzone[len-1] = 0; /* get rid of the '\n' */ setenv("TZ", tzone, 0);}#endifstatic void write_wtmp (void){ int fd, lf; struct utmp ut; memset((char *)&ut, 0, sizeof(ut)); strcpy(ut.ut_line, "~"); memset(ut.ut_name, 0, sizeof(ut.ut_name)); time(&ut.ut_time); ut.ut_type = BOOT_TIME; if ((lf = open(_PATH_WTMPLOCK, O_CREAT|O_WRONLY, 0660)) >= 0) { flock(lf, LOCK_EX|LOCK_NB); /* make sure init won't hang */ if((fd = open(_PATH_WTMP, O_WRONLY|O_APPEND)) >= 0) { write(fd, (char *)&ut, sizeof(ut)); close(fd); } flock(lf, LOCK_UN|LOCK_NB); close(lf); }} /* End Function write_wtmp */struct needer_struct{ struct needer_struct *next; pid_t pid;};struct service_struct{ struct service_struct *prev, *next; /* Script services chain */ struct needer_struct *needers; /* Needers waiting for service */ struct script_struct *attempting_providers; int failed; /* TRUE if attempting provider failed badly */ char name[1];};struct script_struct{ pid_t pid; struct script_struct *prev, *next; /* For the list */ struct service_struct *first_service, *last_service; /*First is true name*/ struct script_struct *next_attempting_provider; /* Provider chain */};struct list_head{ struct script_struct *first, *last; unsigned int num_entries;};static struct list_head available_list = {NULL, NULL, 0};static struct list_head starting_list = {NULL, NULL, 0};static struct service_struct *unavailable_services = NULL; /* For needers */static int num_needers = 0;static int process_pidstat (pid_t pid, int status);static void process_command (const struct command_struct *command);static struct service_struct *find_service_in_list (const char *name, struct service_struct *sv);static struct script_struct *find_script_byname (const char *name,struct list_head *head, struct service_struct **service);static struct script_struct *find_script_bypid (pid_t pid, struct list_head *head);static void insert_entry (struct list_head *head, struct script_struct *entry);static void remove_entry (struct list_head *head, struct script_struct *entry);static void signal_needers (struct service_struct *service, int sig);static void handle_nonworking (struct script_struct *script);static int force_progress (void);static void show_scripts (FILE *fp, const struct script_struct *script, const char *type);static const char *get_path (const char *file);static pid_t mywait (int *status)/* [RETURNS] The pid for a process to be reaped, 0 if no process is to be reaped, and less than 0 if the boot scripts appear to have finished.*/{ pid_t pid; sigset_t ss; long buffer[COMMAND_SIZE / sizeof (long)]; struct command_struct *command = (struct command_struct *) buffer; if (initctl_fd < 0) return wait (status); /* Some magic to avoid races which can result in lost signals */ command->command = -1; if ( sigsetjmp (jmp_env, 1) ) { /* Jump from signal handler */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -