github.com/bgentry/go@v0.0.0-20150121062915-6cf5a733d54d/src/lib9/await.c (about)

     1  // +build !plan9
     2  // +build !windows
     3  
     4  /*
     5  Plan 9 from User Space src/lib9/await.c
     6  http://code.swtch.com/plan9port/src/tip/src/lib9/await.c
     7  
     8  Copyright 2001-2007 Russ Cox.  All Rights Reserved.
     9  Portions Copyright 2009 The Go Authors.  All Rights Reserved.
    10  
    11  Permission is hereby granted, free of charge, to any person obtaining a copy
    12  of this software and associated documentation files (the "Software"), to deal
    13  in the Software without restriction, including without limitation the rights
    14  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    15  copies of the Software, and to permit persons to whom the Software is
    16  furnished to do so, subject to the following conditions:
    17  
    18  The above copyright notice and this permission notice shall be included in
    19  all copies or substantial portions of the Software.
    20  
    21  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    22  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    23  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
    24  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    25  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    26  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    27  THE SOFTWARE.
    28  */
    29  
    30  #define NOPLAN9DEFINES
    31  #include <u.h>
    32  #include <libc.h>
    33  
    34  #include <signal.h>
    35  #include <sys/types.h>
    36  #include <sys/wait.h>
    37  #include <sys/time.h>
    38  #include <sys/resource.h>
    39  
    40  #ifndef WCOREDUMP	/* not on Mac OS X Tiger */
    41  #define WCOREDUMP(status) 0
    42  #endif
    43  
    44  static struct {
    45  	int sig;
    46  	char *str;
    47  } tab[] = {
    48  	SIGHUP,		"hangup",
    49  	SIGINT,		"interrupt",
    50  	SIGQUIT,		"quit",
    51  	SIGILL,		"sys: illegal instruction",
    52  	SIGTRAP,		"sys: breakpoint",
    53  	SIGABRT,		"sys: abort",
    54  #ifdef SIGEMT
    55  	SIGEMT,		"sys: emulate instruction executed",
    56  #endif
    57  	SIGFPE,		"sys: fp: trap",
    58  	SIGKILL,		"sys: kill",
    59  	SIGBUS,		"sys: bus error",
    60  	SIGSEGV,		"sys: segmentation violation",
    61  	SIGALRM,		"alarm",
    62  	SIGTERM,		"kill",
    63  	SIGURG,		"sys: urgent condition on socket",
    64  	SIGSTOP,		"sys: stop",
    65  	SIGTSTP,		"sys: tstp",
    66  	SIGCONT,		"sys: cont",
    67  	SIGCHLD,		"sys: child",
    68  	SIGTTIN,		"sys: ttin",
    69  	SIGTTOU,		"sys: ttou",
    70  #ifdef SIGIO	/* not on Mac OS X Tiger */
    71  	SIGIO,		"sys: i/o possible on fd",
    72  #endif
    73  	SIGXCPU,		"sys: cpu time limit exceeded",
    74  	SIGXFSZ,		"sys: file size limit exceeded",
    75  	SIGVTALRM,	"sys: virtual time alarm",
    76  	SIGPROF,		"sys: profiling timer alarm",
    77  #ifdef SIGWINCH	/* not on Mac OS X Tiger */
    78  	SIGWINCH,	"sys: window size change",
    79  #endif
    80  #ifdef SIGINFO
    81  	SIGINFO,		"sys: status request",
    82  #endif
    83  	SIGUSR1,		"sys: usr1",
    84  	SIGUSR2,		"sys: usr2",
    85  	SIGPIPE,		"sys: write on closed pipe",
    86  };
    87  
    88  char*
    89  _p9sigstr(int sig, char *tmp)
    90  {
    91  	int i;
    92  
    93  	for(i=0; i<nelem(tab); i++)
    94  		if(tab[i].sig == sig)
    95  			return tab[i].str;
    96  	if(tmp == nil)
    97  		return nil;
    98  	sprint(tmp, "sys: signal %d", sig);
    99  	return tmp;
   100  }
   101  
   102  int
   103  _p9strsig(char *s)
   104  {
   105  	int i;
   106  
   107  	for(i=0; i<nelem(tab); i++)
   108  		if(strcmp(s, tab[i].str) == 0)
   109  			return tab[i].sig;
   110  	return 0;
   111  }
   112  
   113  static Waitmsg*
   114  _wait(int pid4, int opt)
   115  {
   116  	int pid, status, cd;
   117  	struct rusage ru;
   118  	char tmp[64];
   119  	ulong u, s;
   120  	Waitmsg *w;
   121  
   122  	w = malloc(sizeof *w + 200);
   123  	if(w == nil)
   124  		return nil;
   125  	memset(w, 0, sizeof *w);
   126  	w->msg = (char*)&w[1];
   127  
   128  	for(;;){
   129  		/* On Linux, pid==-1 means anyone; on SunOS, it's pid==0. */
   130  		if(pid4 == -1)
   131  			pid = wait3(&status, opt, &ru);
   132  		else
   133  			pid = wait4(pid4, &status, opt, &ru);
   134  		if(pid <= 0) {
   135  			free(w);
   136  			return nil;
   137  		}
   138  		u = (ulong)(ru.ru_utime.tv_sec*1000+((ru.ru_utime.tv_usec+500)/1000));
   139  		s = (ulong)(ru.ru_stime.tv_sec*1000+((ru.ru_stime.tv_usec+500)/1000));
   140  		w->pid = pid;
   141  		w->time[0] = u;
   142  		w->time[1] = s;
   143  		w->time[2] = u+s;
   144  		if(WIFEXITED(status)){
   145  			if(status)
   146  				sprint(w->msg, "%d", status);
   147  			return w;
   148  		}
   149  		if(WIFSIGNALED(status)){
   150  			cd = WCOREDUMP(status);
   151  			sprint(w->msg, "signal: %s", _p9sigstr(WTERMSIG(status), tmp));
   152  			if(cd)
   153  				strcat(w->msg, " (core dumped)");
   154  			return w;
   155  		}
   156  	}
   157  }
   158  
   159  Waitmsg*
   160  p9wait(void)
   161  {
   162  	return _wait(-1, 0);
   163  }
   164  
   165  Waitmsg*
   166  p9waitfor(int pid)
   167  {
   168  	return _wait(pid, 0);
   169  }
   170  
   171  Waitmsg*
   172  p9waitnohang(void)
   173  {
   174  	return _wait(-1, WNOHANG);
   175  }
   176  
   177  int
   178  p9waitpid(void)
   179  {
   180  	int status;
   181  	return wait(&status);
   182  }