/* Like the csh builtin time, but from any shell Copyright 2008, David Bremner Distributed under the new BSD license */ #include #include #include #include #include #include #include #include #include #include #include #define errcheck(e) if ((long)(e)==-1L){ perror(progname);exit(1);} #define errcheck2(s,e) if ((long)(e)==-1L){ fprintf(stderr,"%s:",progname);\ perror(s);exit(1);} #define double_time(t) ((double)(t.tv_sec)+(double)(t.tv_usec)/1000000) #if 1 #define fmttime(buf,timer) strftime(buf,sizeof(buf),"%d/%m/%y %T",localtime(timer)) #else #define fmttime(buf,timer) cftime(buf,"%d/%m/%y %T",timer) #endif static pid_t child_pid; void shutdown_rmon(); void ptimes(); void job_done(); void errlog(char *,...); static char* progname; int main(int argc,char *argv[]) { int status; progname=argv[0]; /* Set up signal handlers: SIGTERM,SIGINT: Shutdown gracefully We use sysv signal handling here, in the hopes that it will work on both Irix and SunOS */ errcheck(signal(SIGTERM,shutdown_rmon)); errcheck(signal(SIGINT,shutdown_rmon)); errcheck(child_pid=fork()); if (!child_pid) { /* Create a new process group so that we can kill grandchildren */ errcheck2("setpgid",setpgid(0,0)); errcheck(execvp(argv[1],&argv[1])); } errcheck(waitpid(child_pid, &status,0)); ptimes(); exit(0); } void print_rusage(struct rusage *r) { fprintf(stderr,"%0.3fu %0.3fs %ldKb %ld flts %ld swaps %ld blks-in %ld blks-out\n", double_time(r->ru_utime), double_time(r->ru_stime), r->ru_maxrss,r->ru_majflt,r->ru_nswap, r->ru_inblock,r->ru_oublock); } void shutdown_rmon() { int status; errlog("shutting down\n\n"); errcheck(kill(-1*child_pid,SIGTERM)); errcheck(waitpid(child_pid, &status,0)); ptimes(); exit(1); } void ptimes() { struct rusage rusage; getrusage(RUSAGE_CHILDREN,&rusage); print_rusage(&rusage); } void errlog(char *format,...) { va_list args; char buf[80]; time_t t; va_start(args,format); t=time(0); fmttime(buf,&t); fprintf(stderr,"%s: <%s> ",progname,buf); vfprintf(stderr, format, args); va_end(args); }