Project

General

Profile

Bug #6124 ยป lock.c

Marcel Telka, 2015-08-14 03:13 PM

 
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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
94
	fl.l_whence = SEEK_SET;
95

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

    
105
	if (fcntl(f, cmd, &fl) == -1) {
106
		printf("fcntl failed\n");
107
		return 0;
108
	}
109

    
110
	if (cmd == F_GETLK) {
111
		char *s;
112

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

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

    
123
	return 0;
124
}
125

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

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

    
136
	(void) sleep(sec);
137

    
138
	return 0;
139
}
140

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

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

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

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

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

    
177
		if (*s == '\0')
178
			break;
179

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

    
192
		argv[argc++] = s;
193

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

    
198
	if (argc == 0) {
199
		free(argv);
200
		return;
201
	}
202

    
203
	parse_cmd_v(argc, argv);
204

    
205
	free(argv);
206
}
207

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

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

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

    
231
	return 0;
232
}
    (1-1/1)