⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 simpleinit.c

📁 Util-linux 软件包包含许多工具。其中比较重要的是加载、卸载、格式化、分区和管理硬盘驱动器
💻 C
📖 第 1 页 / 共 3 页
字号:
	do_longjmp = 0;	process_command (command);	return 0;    }    sigemptyset (&ss);  /*  Block SIGCHLD so wait status cannot be lost  */    sigaddset (&ss, SIGCHLD);    sigprocmask (SIG_BLOCK, &ss, NULL);    if ( ( pid = waitpid (-1, status, WNOHANG) ) > 0 )    {	sigprocmask (SIG_UNBLOCK, &ss, NULL);	return process_pidstat (pid, *status);    }    do_longjmp = 1;  /*  After this, SIGCHLD will cause a jump backwards  */    sigprocmask (SIG_UNBLOCK, &ss, NULL);    read (initctl_fd, buffer, COMMAND_SIZE);    do_longjmp = 0;    process_command (command);    return 0;}   /*  End Function mywait  */static pid_t process_pidstat (pid_t pid, 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.*/{    int failed;    struct script_struct *script;    struct service_struct *service;    if ( ( script = find_script_bypid (pid, &starting_list) ) == NULL )	return pid;    remove_entry (&starting_list, script);    if ( WIFEXITED (status) && (WEXITSTATUS (status) == 0) )    {	struct script_struct *provider;	/*  Notify needers and other providers  */	for (service = script->first_service; service != NULL;	     service = service->next)	{	    signal_needers (service, SIG_PRESENT);	    for (provider = service->attempting_providers; provider != NULL;		 provider = provider->next_attempting_provider)		kill (provider->pid, SIG_PRESENT);	    service->attempting_providers = NULL;	}	insert_entry (&available_list, script);	return force_progress ();    }    failed = ( WIFEXITED (status) && (WEXITSTATUS (status) == 2) ) ? 0 : 1;    for (service = script->first_service; service != NULL;	 service = service->next)	service->failed = failed;    handle_nonworking (script);    return force_progress ();}   /*  End Function process_pidstat  */static void process_command (const struct command_struct *command){    int ival;    struct script_struct *script;    struct service_struct *service;    switch (command->command)    {      case COMMAND_TEST:	kill (command->pid,	      (find_script_byname (command->name, &available_list,				   NULL) == NULL) ?	      SIG_NOT_PRESENT : SIG_PRESENT);	break;      case COMMAND_NEED:	ival = run_command (command->name, command->name, command->pid);	if (ival == 0)	{	    ++num_needers;	    force_progress ();	}	else kill (command->pid, ival);	break;      case COMMAND_ROLLBACK:	if (command->name[0] == '\0') script = NULL;	else	{	    if ( ( script = find_script_byname (command->name, &available_list,						NULL) ) == NULL )	    {		kill (command->pid, SIG_NOT_PRESENT);		break;	    }	}	while (script != available_list.first)	{	    pid_t pid;	    struct script_struct *victim = available_list.first;	    char txt[256];	    if ( ( pid = fork () ) == 0 )   /*  Child   */	    {		for (ival = 1; ival < NSIG; ival++) signal (ival, SIG_DFL);		open ("/dev/console", O_RDONLY, 0);		open ("/dev/console", O_RDWR, 0);		dup2 (1, 2);		execlp (get_path (victim->first_service->name),			victim->first_service->name, "stop", NULL);		sprintf (txt, _("error stopping service: \"%s\""),			 victim->first_service->name);		err (txt);		_exit (SIG_NOT_STOPPED);	    }	    else if (pid == -1) break;      /*  Error   */	    else                            /*  Parent  */	    {		while (waitpid (pid, &ival, 0) != pid) /*  Nothing  */;		if ( WIFEXITED (ival) && (WEXITSTATUS (ival) == 0) )		{		    sprintf (txt, "Stopped service: %s\n",			     victim->first_service->name);		    remove_entry (&available_list, victim);		    free (victim);		    err (txt);		}		else break;	    }	}	kill (command->pid,	      (script ==available_list.first) ? SIG_STOPPED : SIG_NOT_STOPPED);	break;      case COMMAND_DUMP_LIST:	if (fork () == 0) /* Do it in a child process so pid=1 doesn't block */	{	    FILE *fp;	    if ( ( fp = fopen (command->name, "w") ) == NULL ) _exit (1);	    show_scripts (fp, available_list.first, "AVAILABLE");	    show_scripts (fp, starting_list.first, "STARTING");	    fputs ("UNAVAILABLE SERVICES:\n", fp);	    for (service = unavailable_services; service != NULL;		 service = service->next)		fprintf (fp, "%s (%s)\n", service->name,			 service->failed ? "FAILED" : "not configured");	    fclose (fp);	    _exit (0);	}	break;      case COMMAND_PROVIDE:	/*  Sanity check  */	if ( ( script = find_script_bypid (command->ppid, &starting_list) )	     == NULL )	{	    kill (command->pid, SIG_NOT_CHILD);	    break;	}	if (find_script_byname (command->name, &available_list, NULL) != NULL)	{	    kill (command->pid, SIG_PRESENT);	    break;	}	if (find_script_byname (command->name, &starting_list, &service)	    != NULL)	{   /*  Someone else is trying to provide  */	    script->next_attempting_provider = service->attempting_providers;	    service->attempting_providers = script;	    break;	}	if ( ( service = find_service_in_list (command->name,					       unavailable_services) )	     == NULL )	{   /*  We're the first to try and provide: create it  */	    if ( ( service =		   calloc (1, strlen (command->name) + sizeof *service) )		 == NULL )	    {		kill (command->pid, SIG_NOT_CHILD);		break;	    }	    strcpy (service->name, command->name);	}	else	{   /*  Orphaned service: unhook and grab it  */	    if (service->prev == NULL) unavailable_services = service->next;	    else service->prev->next = service->next;	    if (service->next != NULL) service->next->prev = service->prev;	    service->next = NULL;	}	service->prev = script->last_service;	script->last_service->next = service;	script->last_service = service;	kill (command->pid, SIG_NOT_PRESENT);	break;      case -1:      default:	break;    }}   /*  End Function process_command  */static int run_command (const char *file, const char *name, pid_t pid){    struct script_struct *script;    struct needer_struct *needer = NULL;    struct service_struct *service;    if (find_script_byname (name, &available_list, NULL) != NULL)	return SIG_PRESENT;    if (pid != 0)    {	needer = calloc (1, sizeof *needer);	if (needer == NULL) return SIG_FAILED;	needer->pid = pid;    }    script = find_script_byname (name, &starting_list, &service);    if (script == NULL)	service = find_service_in_list (name, unavailable_services);    if (service == NULL)    {	int i;	char txt[1024];	if ( ( script = calloc (1, sizeof *script) ) == NULL )	{	    if (needer != NULL) free (needer);	    return SIG_FAILED;	}	service = calloc (1, strlen (name) + sizeof *service);	if (service == NULL)	{	    free (script);	    return SIG_FAILED;	}	strcpy (service->name, name);	switch ( script->pid = fork () )	{	  case 0:   /*  Child   */	    for (i = 1; i < NSIG; i++) signal (i, SIG_DFL);	    execlp (get_path (file), service->name, "start", NULL);	    sprintf (txt, "error running programme: \"%s\"\n", service->name);	    err ( _(txt) );	    _exit (SIG_FAILED);	    break;	  case -1:  /*  Error   */	    service->next = unavailable_services;	    if (unavailable_services != NULL)		unavailable_services->prev = service;	    unavailable_services = service;	    free (script);	    if (needer != NULL) free (needer);	    return SIG_FAILED;	    /*break;*/	  default:  /*  Parent  */	    script->first_service = service;	    script->last_service = service;	    insert_entry (&starting_list, script);	    sched_yield ();	    break;	}    }    if (needer == NULL) return 0;    needer->next = service->needers;    service->needers = needer;    return 0;}   /*  End Function run_command  */static struct service_struct *find_service_in_list (const char *name,						    struct service_struct *sv){    for (; sv != NULL; sv = sv->next)	if (strcmp (sv->name, name) == 0) return (sv);    return NULL;}   /*  End Function find_service_in_list  */static struct script_struct *find_script_byname (const char *name,						 struct list_head *head,						 struct service_struct **service){    struct script_struct *script;    for (script = head->first; script != NULL; script = script->next)    {	struct service_struct *sv;	if ( ( sv = find_service_in_list (name, script->first_service) )	     != NULL )	{	    if (service != NULL) *service = sv;	    return (script);	}    }    if (service != NULL) *service = NULL;    return NULL;}   /*  End Function find_script_byname  */static struct script_struct *find_script_bypid (pid_t pid,						struct list_head *head){    struct script_struct *script;    for (script = head->first; script != NULL; script = script->next)	if (script->pid == pid) return (script);    return NULL;}   /*  End Function find_script_bypid  */static void insert_entry (struct list_head *head, struct script_struct *entry){    if (entry == NULL) return;    entry->prev = NULL;    entry->next = head->first;    if (head->first != NULL) head->first->prev = entry;    head->first = entry;    if (head->last == NULL) head->last = entry;    ++head->num_entries;}   /*  End Function insert_entry  */static void remove_entry (struct list_head *head, struct script_struct *entry){    if (entry->prev == NULL) head->first = entry->next;    else entry->prev->next = entry->next;    if (entry->next == NULL) head->last = entry->prev;    else entry->next->prev = entry->prev;    --head->num_entries;}   /*  End Function remove_entry  */static void signal_needers (struct service_struct *service, int sig){    struct needer_struct *needer, *next_needer;    for (needer = service->needers; needer != NULL; needer = next_needer)    {	kill (needer->pid, sig);	next_needer = needer->next;	free (needer);	--num_needers;    }    service->needers = NULL;}   /*  End Function signal_needers  */static void handle_nonworking (struct script_struct *script){    struct service_struct *service, *next;    for (service = script->first_service; service != NULL; service = next)    {	struct script_struct *provider = service->attempting_providers;	next = service->next;	if (provider == NULL)	{	    service->prev = NULL;	    service->next = unavailable_services;	    if (unavailable_services != NULL)		unavailable_services->prev = service;	    unavailable_services = service;	    continue;	}	service->attempting_providers = provider->next_attempting_provider;	provider->last_service->next = service;	service->prev = provider->last_service;	provider->last_service = service;	service->next = NULL;	kill (provider->pid, SIG_NOT_PRESENT);    }    free (script);}   /*  End Function handle_nonworking  */static int force_progress (void)/*  [RETURNS] 0 if boot scripts are still running, else -1.*/{    struct service_struct *service;    if (starting_list.num_entries > num_needers) return 0;    /*  No progress can be made: signal needers  */    for (service = unavailable_services; service != NULL;	 service = service->next)	signal_needers (service,			service->failed ? SIG_FAILED : SIG_NOT_PRESENT);    return (starting_list.num_entries < 1) ? -1 : 0;}   /*  End Function force_progress  */static void show_scripts (FILE *fp, const struct script_struct *script,			  const char *type){    fprintf (fp, "%s SERVICES:\n", type);    for (; script != NULL; script = script->next)    {	struct service_struct *service = script->first_service;	fputs (service->name, fp);	for (service = service->next; service != NULL; service = service->next)	    fprintf (fp, "  (%s)", service->name);	putc ('\n', fp);    }}   /*  End Function show_scripts  */static const char *get_path (const char *file){    char *p1, *p2;    static char path[PATH_SIZE];    if (file[0] == '/') return file;    if (init_path[0] == '\0') return file;    for (p1 = init_path; *p1 != '\0'; p1 = p2)    {	if ( ( p2 = strchr (p1, ':') ) == NULL )	    p2 = p1 + strlen (p1);	strncpy (path, p1, p2 - p1);	path[p2 - p1] = '/';	strcpy (path + (p2 - p1) + 1, file);	if (*p2 == ':') ++p2;	if (access (path, X_OK) == 0) return path;    }    return file;}   /*  End Function get_path  */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -