1: /* 2: * Rewritten to look like the more modern versions of gcore on other systems. 3: * The -s option for stopping the process was added, the ability to name 4: * the core file was added, and to follow changes to the kernel the default 5: * corefile name was changed to be 'pid.core' rather than simply 'core'. 6: * Only one process may be gcore'd at a time now however. 4/15/94 - sms. 7: * 8: * Originally written for V7 Unix, later changed to handle 2.9BSD, later 9: * still brought up on 2.10BSD. Pretty close the 4.XBSD except for 10: * handling swapped out processes (it doesn't). - sms 11: */ 12: 13: #include <sys/param.h> 14: #include <sys/user.h> 15: #include <sys/proc.h> 16: #include <sys/file.h> 17: #include <stdio.h> 18: #include <nlist.h> 19: #include <varargs.h> 20: 21: #define NLIST "/vmunix" 22: #define MEM "/dev/mem" 23: 24: struct nlist nl[] = { 25: { "_proc" }, 26: #define X_PROC 0 27: { "_nproc" }, 28: #define X_NPROC 1 29: { 0 }, 30: }; 31: 32: int mem, cor, nproc, sflag; 33: struct proc *pbuf; 34: char *corefile, *program_name; 35: 36: extern int optind, opterr; 37: extern char *optarg, *rindex(); 38: extern off_t lseek(); 39: 40: main(argc, argv) 41: int argc; 42: char **argv; 43: { 44: register int pid, c; 45: char fname[32]; 46: 47: if (program_name = rindex(argv[0], '/')) 48: program_name++; 49: else 50: program_name = argv[0]; 51: 52: opterr = 0; 53: while ((c = getopt(argc, argv, "c:s")) != EOF) 54: { 55: switch (c) 56: { 57: case 'c': 58: corefile = optarg; 59: break; 60: case 's': 61: sflag++; 62: break; 63: default: 64: usage(); 65: break; 66: } 67: } 68: argv += optind; 69: argc -= optind; 70: if (argc != 1) 71: usage(); 72: pid = atoi(argv[0]); 73: if (corefile == 0) 74: { 75: sprintf(fname, "%d.core", pid); 76: corefile = fname; 77: } 78: 79: openfiles(); 80: getkvars(); 81: (void)lseek(mem, (long)nl[X_NPROC].n_value, L_SET); 82: (void)read(mem, &nproc, sizeof nproc); 83: pbuf = (struct proc *)calloc(nproc, sizeof (struct proc)); 84: if (pbuf == NULL) 85: error("not enough core"); 86: (void)lseek(mem, (long)nl[X_PROC].n_value, L_SET); 87: (void)read(mem, pbuf, nproc * sizeof (struct proc)); 88: 89: core(pid); 90: exit(0); 91: } 92: 93: void 94: core(pid) 95: register int pid; 96: { 97: register int i; 98: register struct proc *pp; 99: uid_t uid, getuid(); 100: char ubuf[USIZE*64]; 101: 102: for (i = 0, pp = pbuf;; pp++) { 103: if (pp->p_pid == pid) 104: break; 105: if (i++ == nproc) 106: error("%d: not found", pid); 107: } 108: if (pp->p_uid != (uid = getuid()) && uid != 0) 109: error("%d: not owner", pid); 110: if ((pp->p_flag & SLOAD) == 0) 111: error("%d: swapped out", pid); 112: if (pp->p_stat == SZOMB) 113: error("%d: zombie", pid); 114: if (pp->p_flag & SSYS) 115: error("%d: system process", pid); 116: if (sflag && kill(pid, SIGSTOP) < 0) 117: warning("%d: could not send stop signal", pid); 118: if (lseek(mem, (long)pp->p_addr << 6, L_SET) < 0) 119: error("bad mem seek"); 120: if (read(mem, &ubuf, sizeof ubuf) != sizeof ubuf) 121: error("bad mem read"); 122: if ((cor = open(corefile, O_RDWR|O_CREAT|O_TRUNC, 0666)) < 0) { 123: perror(corefile); 124: exit(1); 125: } 126: (void)write(cor, &ubuf, sizeof ubuf); 127: (void)lseek(mem, (long)pp->p_daddr << 6, L_SET); 128: dump(pp->p_dsize); 129: (void)lseek(mem, (long)pp->p_saddr << 6, L_SET); 130: dump(pp->p_ssize); 131: 132: if (sflag && kill(pid, SIGCONT) < 0) 133: warning("%d: could not send continue signal", pid); 134: (void)close(cor); 135: } 136: 137: void 138: dump(size) 139: register u_int size; 140: { 141: register int blocks, i; 142: int bytes; 143: char buffer[BUFSIZ * 2]; 144: 145: size <<= 6; 146: blocks = size / sizeof (buffer); 147: bytes = size % sizeof (buffer); 148: 149: for (i = 0; i < blocks; i++) { 150: (void)read(mem, buffer, sizeof (buffer)); 151: (void)write(cor, buffer, sizeof (buffer)); 152: } 153: if (bytes) { 154: (void)read(mem, buffer, bytes); 155: (void)write(cor, buffer, bytes); 156: } 157: } 158: 159: void 160: openfiles() 161: { 162: mem = open(MEM, 0); 163: if (mem < 0) { 164: perror(MEM); 165: exit(1); 166: } 167: } 168: 169: void 170: getkvars() 171: { 172: nlist(NLIST, nl); 173: if (nl[0].n_type == 0) 174: error("%s: no namelist\n", NLIST); 175: } 176: 177: void 178: usage() 179: { 180: fprintf(stderr, "usage: %s [ -s ] [ -c core ] pid\n", program_name); 181: exit(1); 182: } 183: 184: /* VARARGS */ 185: void 186: error(va_alist) 187: va_dcl 188: { 189: va_list ap; 190: register char *cp; 191: 192: (void)fprintf(stderr, "%s: ", program_name); 193: 194: va_start(ap); 195: cp = va_arg(ap, char *); 196: (void)vfprintf(stderr, cp, ap); 197: va_end(ap); 198: if (*cp) 199: { 200: cp += strlen(cp); 201: if (cp[-1] != '\n') 202: (void)fputc('\n', stderr); 203: } 204: exit(1); 205: /* NOTREACHED */ 206: } 207: 208: /* VARARGS */ 209: void 210: warning(va_alist) 211: va_dcl 212: { 213: va_list ap; 214: register char *cp; 215: 216: (void)fprintf(stderr, "%s: warning: ", program_name); 217: 218: va_start(ap); 219: cp = va_arg(ap, char *); 220: (void)vfprintf(stderr, cp, ap); 221: va_end(ap); 222: if (*cp) 223: { 224: cp += strlen(cp); 225: if (cp[-1] != '\n') 226: (void)fputc('\n', stderr); 227: } 228: }