summaryrefslogtreecommitdiff
path: root/build_windows/dbkill.cpp
blob: bb4633ff5dd90d29c0b219d038af36e1dde54135 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
/*-
 * See the file LICENSE for redistribution information.
 *
 * Copyright (c) 1999, 2015 Oracle and/or its affiliates.  All rights reserved.
 *
 * $Id$
 */
/*
 * Kill -
 * Simulate Unix kill on Windows/NT and Windows/9X.
 * This good enough to support the Berkeley DB test suite,
 * but may be missing some favorite features.
 *
 * Would have used MKS kill, but it didn't seem to work well
 * on Win/9X.  Cygnus kill works within the Gnu/Cygnus environment
 * (where processes are given small pids, with presumably a translation
 * table between small pids and actual process handles), but our test
 * environment, via Tcl, does not use the Cygnus environment.
 *
 * Compile this and install it as c:/tools/kill.exe (or as indicated
 * by build_windows/include.tcl ).
 */

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>

/*
 * Like atol, with specified base.  Would use stdlib, but
 * strtol("0xFFFF1234", NULL, 16) returns 0x7FFFFFFF and
 * strtol("4294712487", NULL, 16) returns 0x7FFFFFFF w/ VC++
 */
long
myatol(char *s, int base)
{
	long result = 0;
	char ch;
	int sign = 1;  /* + */
	if (base == 0)
		base = 10;
	if (base != 10 && base != 16)
		return LONG_MAX;
	while ((ch = *s++) != '\0') {
		if (ch == '-') {
			sign = -sign;
		}
		else if (ch >= '0' && ch <= '9') {
			result = result * base + (ch - '0');
		}
		else if (ch == 'x' || ch == 'X') {
			/* Allow leading 0x..., and switch to base 16 */
			base = 16;
		}
		else if (base == 16 && ch >= 'a' && ch <= 'f') {
			result = result * base + (ch - 'a' + 10);
		}
		else if (base == 16 && ch >= 'A' && ch <= 'F') {
			result = result * base + (ch - 'A' + 10);
		}
		else {
			if (sign > 1)
				return LONG_MAX;
			else
				return LONG_MIN;
		}
	}
	return sign * result;
}

void
usage_exit()
{
	fprintf(stderr, "Usage: kill [ -sig ] pid\n");
	fprintf(stderr, "       for win32, sig must be or 0, 15 (TERM)\n");
	exit(EXIT_FAILURE);
}

int
main(int argc, char **argv)
{
	HANDLE hProcess ;
	DWORD accessflag;
	long pid;
	int sig = 15;

	if (argc > 2) {
		if (argv[1][0] != '-')
			usage_exit();

		if (strcmp(argv[1], "-TERM") == 0)
			sig = 15;
		else {
			/* currently sig is more or less ignored,
			 * we only care if it is zero or not
			 */
			sig = atoi(&argv[1][1]);
			if (sig < 0)
				usage_exit();
		}
		argc--;
		argv++;
	}
	if (argc < 2)
		usage_exit();

	pid = myatol(argv[1], 10);
	/*printf("pid = %ld (0x%lx) (command line %s)\n", pid, pid, argv[1]);*/
	if (pid == LONG_MAX || pid == LONG_MIN)
		usage_exit();

	if (sig == 0)
		accessflag = PROCESS_QUERY_INFORMATION | PROCESS_VM_READ;
	else
		accessflag = STANDARD_RIGHTS_REQUIRED | PROCESS_TERMINATE;
	hProcess = OpenProcess(accessflag, FALSE, pid);
	if (hProcess == NULL) {
		fprintf(stderr, "dbkill: %s: no such process\n", argv[1]);
		exit(EXIT_FAILURE);
	}
	if (sig == 0)
		exit(EXIT_SUCCESS);
	if (!TerminateProcess(hProcess, 99)) {
		DWORD err = GetLastError();
		fprintf(stderr,
		    "dbkill: cannot kill process: error %d (0x%lx)\n", err, err);
		exit(EXIT_FAILURE);
	}
	return EXIT_SUCCESS;
}