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

📄 jobs.c

📁 android-w.song.android.widget
💻 C
📖 第 1 页 / 共 5 页
字号:
      for (i = js.j_jobslots; i; i--)	if (jobs[i - 1])	  break;    }  else    {#if 0      /* This wraps around, but makes it inconvenient to extend the array */      for (i = js.j_lastj+1; i != js.j_lastj; i++)	{	  if (i >= js.j_jobslots)	    i = 0;	  if (jobs[i] == 0)	    break;	}	      if (i == js.j_lastj)        i = js.j_jobslots;#else      /* This doesn't wrap around yet. */      for (i = js.j_lastj ? js.j_lastj + 1 : js.j_lastj; i < js.j_jobslots; i++)	if (jobs[i] == 0)	  break;#endif    }  /* Do we need more room? */  /* First try compaction */  if ((interactive_shell == 0 || subshell_environment) && i == js.j_jobslots && js.j_jobslots >= MAX_JOBS_IN_ARRAY)    i = compact_jobs_list (0);  /* If we can't compact, reallocate */  if (i == js.j_jobslots)    {      js.j_jobslots += JOB_SLOTS;      jobs = (JOB **)xrealloc (jobs, (js.j_jobslots * sizeof (JOB *)));      for (j = i; j < js.j_jobslots; j++)	jobs[j] = (JOB *)NULL;    }  /* Add the current pipeline to the job list. */  if (the_pipeline)    {      register PROCESS *p;      int any_running, any_stopped, n;      newjob = (JOB *)xmalloc (sizeof (JOB));      for (n = 1, p = the_pipeline; p->next != the_pipeline; n++, p = p->next)	;      p->next = (PROCESS *)NULL;      newjob->pipe = REVERSE_LIST (the_pipeline, PROCESS *);      for (p = newjob->pipe; p->next; p = p->next)	;      p->next = newjob->pipe;      the_pipeline = (PROCESS *)NULL;      newjob->pgrp = pipeline_pgrp;      pipeline_pgrp = 0;      newjob->flags = 0;      /* Flag to see if in another pgrp. */      if (job_control)	newjob->flags |= J_JOBCONTROL;      /* Set the state of this pipeline. */      p = newjob->pipe;      any_running = any_stopped = 0;      do	{	  any_running |= PRUNNING (p);	  any_stopped |= PSTOPPED (p);	  p = p->next;	}      while (p != newjob->pipe);      newjob->state = any_running ? JRUNNING : (any_stopped ? JSTOPPED : JDEAD);      newjob->wd = job_working_directory ();      newjob->deferred = deferred;      newjob->j_cleanup = (sh_vptrfunc_t *)NULL;      newjob->cleanarg = (PTR_T) NULL;      jobs[i] = newjob;      if (newjob->state == JDEAD && (newjob->flags & J_FOREGROUND))	setjstatus (i);      if (newjob->state == JDEAD)	{	  js.c_reaped += n;	/* wouldn't have been done since this was not part of a job */	  js.j_ndead++;	}      js.c_injobs += n;      js.j_lastj = i;      js.j_njobs++;    }  else    newjob = (JOB *)NULL;  if (newjob)    js.j_lastmade = newjob;  if (async)    {      if (newjob)	{	  newjob->flags &= ~J_FOREGROUND;	  newjob->flags |= J_ASYNC;	  js.j_lastasync = newjob;	}      reset_current ();    }  else    {      if (newjob)	{	  newjob->flags |= J_FOREGROUND;	  /*	   *		!!!!! NOTE !!!!!  (chet@ins.cwru.edu)	   *	   * The currently-accepted job control wisdom says to set the	   * terminal's process group n+1 times in an n-step pipeline:	   * once in the parent and once in each child.  This is where	   * the parent gives it away.	   *	   * Don't give the terminal away if this shell is an asynchronous	   * subshell.	   *	   */	  if (job_control && newjob->pgrp && (subshell_environment&SUBSHELL_ASYNC) == 0)	    maybe_give_terminal_to (shell_pgrp, newjob->pgrp, 0);	}    }  stop_making_children ();  UNBLOCK_CHILD (oset);  return (newjob ? i : js.j_current);}/* Functions to manage the list of exited background pids whose status has   been saved. */static struct pidstat *bgp_alloc (pid, status)     pid_t pid;     int status;{  struct pidstat *ps;  ps = (struct pidstat *)xmalloc (sizeof (struct pidstat));  ps->pid = pid;  ps->status = status;  ps->next = (struct pidstat *)0;  return ps;}static struct pidstat *bgp_add (pid, status)     pid_t pid;     int status;{  struct pidstat *ps;  ps = bgp_alloc (pid, status);  if (bgpids.list == 0)    {      bgpids.list = bgpids.end = ps;      bgpids.npid = 0;			/* just to make sure */    }  else    {      bgpids.end->next = ps;      bgpids.end = ps;    }  bgpids.npid++;  if (bgpids.npid > js.c_childmax)    bgp_prune ();  return ps;}static intbgp_delete (pid)     pid_t pid;{  struct pidstat *prev, *p;  for (prev = p = bgpids.list; p; prev = p, p = p->next)    if (p->pid == pid)      {	prev->next = p->next;	/* remove from list */	break;      }  if (p == 0)    return 0;		/* not found */#if defined (DEBUG)  itrace("bgp_delete: deleting %d", pid);#endif  /* Housekeeping in the border cases. */  if (p == bgpids.list)    bgpids.list = bgpids.list->next;  else if (p == bgpids.end)    bgpids.end = prev;  bgpids.npid--;  if (bgpids.npid == 0)    bgpids.list = bgpids.end = 0;  else if (bgpids.npid == 1)    bgpids.end = bgpids.list;		/* just to make sure */  free (p);  return 1;}/* Clear out the list of saved statuses */static voidbgp_clear (){  struct pidstat *ps, *p;  for (ps = bgpids.list; ps; )    {      p = ps;      ps = ps->next;      free (p);    }  bgpids.list = bgpids.end = 0;  bgpids.npid = 0;}/* Search for PID in the list of saved background pids; return its status if   found.  If not found, return -1. */static intbgp_search (pid)     pid_t pid;{  struct pidstat *ps;  for (ps = bgpids.list ; ps; ps = ps->next)    if (ps->pid == pid)      return ps->status;  return -1;}static voidbgp_prune (){  struct pidstat *ps;  while (bgpids.npid > js.c_childmax)    {      ps = bgpids.list;      bgpids.list = bgpids.list->next;      free (ps);      bgpids.npid--;    }}/* Reset the values of js.j_lastj and js.j_firstj after one or both have   been deleted.  The caller should check whether js.j_njobs is 0 before   calling this.  This wraps around, but the rest of the code does not.  At   this point, it should not matter. */static voidreset_job_indices (){  int old;  if (jobs[js.j_firstj] == 0)    {      old = js.j_firstj++;      if (old >= js.j_jobslots)	old = js.j_jobslots - 1;      while (js.j_firstj != old)	{	  if (js.j_firstj >= js.j_jobslots)	    js.j_firstj = 0;	  if (jobs[js.j_firstj] || js.j_firstj == old)	/* needed if old == 0 */	    break;	  js.j_firstj++;	}      if (js.j_firstj == old)        js.j_firstj = js.j_lastj = js.j_njobs = 0;    }  if (jobs[js.j_lastj] == 0)    {      old = js.j_lastj--;      if (old < 0)	old = 0;      while (js.j_lastj != old)	{	  if (js.j_lastj < 0)	    js.j_lastj = js.j_jobslots - 1;	  if (jobs[js.j_lastj] || js.j_lastj == old)	/* needed if old == js.j_jobslots */	    break;	  js.j_lastj--;	}      if (js.j_lastj == old)        js.j_firstj = js.j_lastj = js.j_njobs = 0;    }}      /* Delete all DEAD jobs that the user had received notification about. */static voidcleanup_dead_jobs (){  register int i;  int os;  if (js.j_jobslots == 0 || jobs_list_frozen)    return;  QUEUE_SIGCHLD(os);  /* XXX could use js.j_firstj and js.j_lastj here */  for (i = 0; i < js.j_jobslots; i++)    {#if defined (DEBUG)      if (i < js.j_firstj && jobs[i])	itrace("cleanup_dead_jobs: job %d non-null before js.j_firstj (%d)", i, js.j_firstj);      if (i > js.j_lastj && jobs[i])	itrace("cleanup_dead_jobs: job %d non-null after js.j_lastj (%d)", i, js.j_lastj);#endif      if (jobs[i] && DEADJOB (i) && IS_NOTIFIED (i))	delete_job (i, 0);    }#if defined (COPROCESS_SUPPORT)  coproc_reap ();#endif  UNQUEUE_SIGCHLD(os);}static intprocesses_in_job (job)     int job;{  int nproc;  register PROCESS *p;  nproc = 0;  p = jobs[job]->pipe;  do    {      p = p->next;      nproc++;    }  while (p != jobs[job]->pipe);  return nproc;}static voiddelete_old_job (pid)     pid_t pid;{  PROCESS *p;  int job;  job = find_job (pid, 0, &p);  if (job != NO_JOB)    {#ifdef DEBUG      itrace ("delete_old_job: found pid %d in job %d with state %d", pid, job, jobs[job]->state);#endif      if (JOBSTATE (job) == JDEAD)	delete_job (job, DEL_NOBGPID);      else	{	  internal_warning (_("forked pid %d appears in running job %d"), pid, job);	  if (p)	    p->pid = 0;	}    }}/* Reallocate and compress the jobs list.  This returns with a jobs array   whose size is a multiple of JOB_SLOTS and can hold the current number of   jobs.  Heuristics are used to minimize the number of new reallocs. */static voidrealloc_jobs_list (){  sigset_t set, oset;  int nsize, i, j, ncur, nprev;  JOB **nlist;  ncur = nprev = NO_JOB;  nsize = ((js.j_njobs + JOB_SLOTS - 1) / JOB_SLOTS);  nsize *= JOB_SLOTS;  i = js.j_njobs % JOB_SLOTS;  if (i == 0 || i > (JOB_SLOTS >> 1))    nsize += JOB_SLOTS;  BLOCK_CHILD (set, oset);  nlist = (js.j_jobslots == nsize) ? jobs : (JOB **) xmalloc (nsize * sizeof (JOB *));  js.c_reaped = js.j_ndead = 0;  for (i = j = 0; i < js.j_jobslots; i++)    if (jobs[i])      {	if (i == js.j_current)	  ncur = j;	if (i == js.j_previous)	  nprev = j;	nlist[j++] = jobs[i];	if (jobs[i]->state == JDEAD)	  {	    js.j_ndead++;	    js.c_reaped += processes_in_job (i);	  }      }#if defined (DEBUG)  itrace ("realloc_jobs_list: resize jobs list from %d to %d", js.j_jobslots, nsize);  itrace ("realloc_jobs_list: j_lastj changed from %d to %d", js.j_lastj, (j > 0) ? j - 1 : 0);  itrace ("realloc_jobs_list: j_njobs changed from %d to %d", js.j_njobs, j);  itrace ("realloc_jobs_list: js.j_ndead %d js.c_reaped %d", js.j_ndead, js.c_reaped);#endif  js.j_firstj = 0;  js.j_lastj = (j > 0) ? j - 1 : 0;  js.j_njobs = j;  js.j_jobslots = nsize;  /* Zero out remaining slots in new jobs list */  for ( ; j < nsize; j++)    nlist[j] = (JOB *)NULL;  if (jobs != nlist)    {      free (jobs);      jobs = nlist;    }  if (ncur != NO_JOB)    js.j_current = ncur;  if (nprev != NO_JOB)    js.j_previous = nprev;  /* Need to reset these */  if (js.j_current == NO_JOB || js.j_previous == NO_JOB || js.j_current > js.j_lastj || js.j_previous > js.j_lastj)    reset_current ();#ifdef DEBUG  itrace ("realloc_jobs_list: reset js.j_current (%d) and js.j_previous (%d)", js.j_current, js.j_previous);#endif  UNBLOCK_CHILD (oset);}/* Compact the jobs list by removing dead jobs.  Assumed that we have filled   the jobs array to some predefined maximum.  Called when the shell is not   the foreground process (subshell_environment != 0).  Returns the first   available slot in the compacted list.  If that value is js.j_jobslots, then   the list needs to be reallocated.  The jobs array may be in new memory if   this returns > 0 and < js.j_jobslots.  FLAGS is reserved for future use. */static intcompact_jobs_list (flags)     int flags;{  if (js.j_jobslots == 0 || jobs_list_frozen)    return js.j_jobslots;  reap_dead_jobs ();  realloc_jobs_list ();#ifdef DEBUG  itrace("compact_jobs_list: returning %d", (js.j_lastj || jobs[js.j_lastj]) ? js.j_lastj + 1 : 0);#endif  return ((js.j_lastj || jobs[js.j_lastj]) ? js.j_lastj + 1 : 0);}/* Delete the job at INDEX from the job list.  Must be called   with SIGCHLD blocked. */voiddelete_job (job_index, dflags)     int job_index, dflags;{  register JOB *temp;  PROCESS *proc;  int ndel;  if (js.j_jobslots == 0 || jobs_list_frozen)    return;  if ((dflags & DEL_WARNSTOPPED) && subshell_environment == 0 && STOPPED (job_index))    internal_warning (_("deleting stopped job %d with process group %ld"), job_index+1, (long)jobs[job_index]->pgrp);  temp = jobs[job_index];  if (temp == 0)    return;  if ((dflags & DEL_NOBGPID) == 0)    {      proc = find_last_proc (job_index, 0);      /* Could do this just for J_ASYNC jobs, but we save all. */      if (proc)	bgp_add (proc->pid, process_exit_status (proc->status));    }  jobs[job_index] = (JOB *)NULL;  if (temp == js.j_lastmade)    js.j_lastmade = 0;

⌨️ 快捷键说明

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