Project

General

Profile

Bug #6525 ยป locker.c

Marcel Telka, 2015-12-19 12:08 AM

 
1
#include <sys/types.h>
2
#include <sys/stat.h>
3
#include <fcntl.h>
4
#include <stdio.h>
5
#include <unistd.h>
6
#include <string.h>
7
#include <stdlib.h>
8
#include <ctype.h>
9
#include <limits.h>
10
#include <errno.h>
11

    
12
static int
13
convert_int(int *val, char *str)
14
{
15
	long lval;
16

    
17
	if (str == NULL || !isdigit(*str))
18
		return (-1);
19

    
20
	lval = strtol(str, &str, 10);
21
	if (*str != '\0' || lval > INT_MAX)
22
		return (-2);
23

    
24
	*val = (int)lval;
25
	return (0);
26
}
27

    
28
void
29
lock_cmd_usage(void) {
30
	printf("Usage: lock r|R|w|W|u|U start len filename\n");
31
}
32

    
33
void
34
test_cmd_usage(void) {
35
	printf("Usage: test r|w|u start len filename\n");
36
}
37

    
38
int
39
locktest_cmd(int argc, char *argv[])
40
{
41
	int f;
42
	struct flock fl;
43
	int cmd;
44
	int t;
45
	void (*usage_fnc)(void);
46

    
47
	if (argc < 1)
48
		return -1;
49

    
50
	if (strcmp(argv[0], "lock") == 0) {
51
		usage_fnc = lock_cmd_usage;
52
		cmd = F_SETLK;
53
	} else if (strcmp(argv[0], "test") == 0) {
54
		usage_fnc = test_cmd_usage;
55
		cmd = F_GETLK;
56
	} else {
57
		return -1;
58
	}
59

    
60
	if (argc != 5 || strlen(argv[1]) != 1) {
61
		usage_fnc();
62
		return -1;
63
	}
64

    
65
	f = open(argv[4], O_RDWR | O_CREAT, 0777);
66
	if (f == -1) {
67
		printf("open failed\n");
68
		return -1;
69
	}
70

    
71
	switch (argv[1][0]) {
72
	case 'r':
73
	case 'w':
74
	case 'u': break;
75
	case 'R':
76
	case 'W':
77
	case 'U':
78
		if (cmd == F_SETLK) {
79
			cmd = F_SETLKW;
80
			break;
81
		}
82
	default: usage_fnc(); return -1;
83
	}
84

    
85
	switch (argv[1][0]) {
86
	case 'r':
87
	case 'R': fl.l_type = F_RDLCK; break;
88
	case 'w':
89
	case 'W': fl.l_type = F_WRLCK; break;
90
	case 'u':
91
	case 'U': fl.l_type = F_UNLCK; break;
92
	default: usage_fnc(); return -1;
93
	}
94

    
95
	fl.l_whence = SEEK_SET;
96

    
97
	if (convert_int(&t, argv[2]) != 0) {
98
		usage_fnc(); return -1;
99
	}
100
	fl.l_start = t;
101
	if (convert_int(&t, argv[3]) != 0) {
102
		usage_fnc(); return -1;
103
	}
104
	fl.l_len = t;
105

    
106
	if (fcntl(f, cmd, &fl) == -1) {
107
		printf("fcntl failed: (%d) %s\n",
108
		    errno, strerror(errno));
109
		return 0;
110
	}
111

    
112
	if (cmd == F_GETLK) {
113
		char *s;
114

    
115
		switch (fl.l_type) {
116
		case F_WRLCK: s = "F_WRLCK"; break;
117
		case F_RDLCK: s = "F_RDLCK"; break;
118
		case F_UNLCK: s = "F_UNLCK"; break;
119
		default: s = "unknown"; break;
120
		}
121

    
122
		printf("F_GETLK: %s %ld %ld\n", s, fl.l_start, fl.l_len);
123
	}
124

    
125
	return 0;
126
}
127

    
128
int
129
sleep_cmd(int argc, char *argv[])
130
{
131
	int sec;
132

    
133
	if (argc != 2 || convert_int(&sec, argv[1]) != 0) {
134
		printf("Usage: sleep seconds\n");
135
		return -1;
136
	}
137

    
138
	(void) sleep(sec);
139

    
140
	return 0;
141
}
142

    
143
void
144
usage(void)
145
{
146
	printf("syntax error\n");
147
	printf("\nSupported commands:\n\tlock\n\ttest\n\tsleep\n");
148
}
149

    
150
void
151
parse_cmd_v(int argc, char *argv[])
152
{
153
	if (argc < 1) {
154
		usage();
155
		return;
156
	}
157

    
158
	if (strcmp(argv[0], "lock") == 0)
159
		(void) locktest_cmd(argc, argv);
160
	else if (strcmp(argv[0], "test") == 0)
161
		(void) locktest_cmd(argc, argv);
162
	else if (strcmp(argv[0], "sleep") == 0)
163
		(void) sleep_cmd(argc, argv);
164
	else
165
		usage();
166
}
167

    
168
void
169
parse_cmd(char *s)
170
{
171
	char **argv = NULL;
172
	int argc = 0;
173
	int argc_max = 0;
174

    
175
	for (;;) {
176
		while (*s != '\0' && !isgraph(*s))
177
			*s++ = '\0';
178

    
179
		if (*s == '\0')
180
			break;
181

    
182
		if (argc == argc_max) {
183
			char **new_argv;
184
			argc_max += 4;
185
			new_argv = realloc(argv, argc_max * sizeof *argv);
186
			if (new_argv == NULL) {
187
				printf("memory allocation failed\n");
188
				free(argv);
189
				return;
190
			}
191
			argv = new_argv;
192
		}
193

    
194
		argv[argc++] = s;
195

    
196
		while (*s != '\0' && isgraph(*s))
197
			s++;
198
	}
199

    
200
	if (argc == 0) {
201
		free(argv);
202
		return;
203
	}
204

    
205
	parse_cmd_v(argc, argv);
206

    
207
	free(argv);
208
}
209

    
210
int
211
main(int argc, char *argv[])
212
{
213
	char *line;
214
	size_t len;
215

    
216
	if (argc == 1) {
217
		for (;;) {
218
			line = NULL;
219
			len = 0;
220
			printf("> ");
221
			fflush(stdout);
222
			if (getline(&line, &len, stdin) == -1)
223
				break;
224

    
225
			parse_cmd(line);
226
			free(line);
227
		}
228
		printf("\n");
229
	} else {
230
		parse_cmd_v(argc - 1, argv + 1);
231
	}
232

    
233
	return 0;
234
}
    (1-1/1)