1 /*
2     rate  --  statistic traffic analyzer
3     Copyright (C) 2003 Mateusz 'mteg' Golicz
4 
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 2 of the License, or
8     (at your option) any later version.
9 
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14 
15     You should have received a copy of the GNU General Public License
16     along with this program; if not, write to the Free Software
17     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 #include <sys/types.h>
20 #include <pwd.h>
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include <assert.h>
25 #include <unistd.h> /* for getuid() */
26 
27 #define MAX_LINE_SIZE 512
28 
decode_line(char * line)29 static char ** decode_line(char * line)
30 {
31 	int l, i, j = 0, rc = 0;
32 	char line_translated[MAX_LINE_SIZE];
33 	char ** ret = NULL;
34 	char * r;
35 
36 	r = index(line, '\n');
37 	if(r) *r = 0;
38 
39 	l = strlen(line);
40 
41 	for(i = 0; i < l; i++)
42 	{
43 		if(line[i] == '|')
44 		{
45 			line_translated[j++] = 0;
46 			ret = realloc(ret, (rc + 1) * sizeof(char*));
47 			assert(ret);
48 			ret[rc++] = strdup(line_translated);
49 			j = 0;
50 			continue;
51 		}
52 		if(line[i] == '\\')
53 		{
54 			if(line[i + 1])
55 			{
56 				if(line[i + 1] == 'n')
57 					line_translated[j++] = '\n';
58 				else
59 					line_translated[j++] = line[i + 1];
60 
61 				i++;
62 			}
63 		}
64 		else
65 			line_translated[j++] = line[i];
66 	}
67 	line_translated[j++] = 0;
68 	ret = realloc(ret, (rc + 2) * sizeof(char*));
69 	ret[rc++] = strdup(line_translated);
70 	ret[rc++] = NULL;
71 	return(ret);
72 }
73 
encode_line(char ** strtab,int n)74 char * encode_line(char ** strtab, int n)
75 {
76 	int i, sl = 0;
77 	char * ret = NULL;
78 
79 	for(i = 0; i < n; i++)
80 	{
81 		char * str = strtab[i];
82 		char * tstr = (char*) malloc(strlen(strtab[i]) * 2 + 2); /* the worst case */
83 		int j, k = 0;
84 
85 		assert(tstr);
86 		tstr[k++] = '|';
87 		for(j = 0; str[j]; j++)
88 		{
89 			if(str[j] == '|')
90 			{
91 				tstr[k++] = '\\';
92 				tstr[k++] = '|';
93 			}
94 			else if(str[j] == '\n')
95 			{
96 				tstr[k++] = '\\';
97 				tstr[k++] = 'n';
98 			}
99 			else if(str[j] == '\\')
100 			{
101 				tstr[k++] = '\\';
102 				tstr[k++] = '\\';
103 			}
104 			else
105 				tstr[k++] = str[j];
106 		}
107 		tstr[k++] = 0;
108 		ret = realloc(ret, (sl + k) + 1);
109 		memcpy(ret + sl, tstr, k + 1);
110 		sl += k - 1;
111 
112 		free(tstr);
113 	}
114 
115 	return(ret);
116 }
117 
free_strtab(char ** tab)118 static void free_strtab(char ** tab)
119 {
120 	int i = 0;
121 	while(tab[i])
122 		free(tab[i++]);
123 
124 	free(tab);
125 }
126 
count_strtab(char ** tab)127 static int count_strtab(char ** tab)
128 {
129 	int i = 0;
130 	while(tab[i]) i++;
131 	return(i);
132 }
133 
save_args(char * name,char ** argv,int argc)134 void save_args(char * name, char ** argv, int argc)
135 {
136 	FILE *ifh;
137 	FILE *ofh;
138 
139 	struct passwd * pw = getpwuid(getuid());
140 	char * path1;
141 	char * path2;
142 	int stored = 0;
143 
144 	if(!pw)
145 	{
146 		fprintf(stderr, "Unable to save operation mode, unable to get information on user with UID=%d\n", getuid());
147 		exit(1);
148 	}
149 
150 	path1 = (char*) malloc(strlen(pw->pw_dir) + 30);
151 	path2 = (char*) malloc(strlen(pw->pw_dir) + 30);
152 	sprintf(path1, "%s/.rate.modes", pw->pw_dir);
153 	sprintf(path2, "%s/.rate.modes.new", pw->pw_dir);
154 
155 	if(!(ofh = fopen(path2, "w")))
156 	{
157 		perror("fopen");
158 		fprintf(stderr, "Unable to save operation mode, unable to open file '%s' for writing.\n");
159 		exit(1);
160 	}
161 
162 	if((ifh = fopen(path1, "r")))
163 	{
164 		char line[MAX_LINE_SIZE];
165 		char ** translated;
166 
167 		while(fgets(line, MAX_LINE_SIZE, ifh))
168 		{
169 			int i, l = strlen(line);
170 
171 			translated = decode_line(line);
172 
173 			if(strcmp(translated[0], name))
174 				fprintf(ofh, "%s\n", line);
175 			else
176 			{
177 				fprintf(ofh, "%s%s\n", name, encode_line(argv, argc));
178 				stored = 1;
179 			}
180 
181 			free_strtab(translated);
182 		}
183 
184 		fclose(ifh);
185 	}
186 
187 	if(!stored)
188 		fprintf(ofh, "%s%s\n", name, encode_line(argv, argc));
189 
190 	fclose(ofh);
191 	if(rename(path2, path1))
192 	{
193 		perror("rename");
194 		fprintf(stderr, "Unable to save operation mode, unable to rename file '%s' to '%s'\n", path2, path1);
195 		exit(1);
196 	}
197 	free(path1);
198 	free(path2);
199 }
200 
recall_args(char * name,char *** argv,int * argc)201 int recall_args(char * name, char *** argv, int *argc)
202 {
203 	FILE *ifh;
204 	struct passwd * pw = getpwuid(getuid());
205 	char * path1;
206 
207 	if(!pw)
208 	{
209 		fprintf(stderr, "Unable to load operation mode, unable to get information on user with UID=%d\n", getuid());
210 		exit(1);
211 	}
212 
213 	path1 = (char*) malloc(strlen(pw->pw_dir) + 30);
214 	sprintf(path1, "%s/.rate.modes", pw->pw_dir);
215 
216 	if((ifh = fopen(path1, "r")))
217 	{
218 		char line[MAX_LINE_SIZE];
219 		char ** translated;
220 
221 		while(fgets(line, MAX_LINE_SIZE, ifh))
222 		{
223 			int i, l = strlen(line);
224 
225 			translated = decode_line(line);
226 			if(strcmp(translated[0], name) == 0)
227 			{
228 				fclose(ifh);
229 				*argv = translated + 1;
230 				*argc = count_strtab(translated) - 1;
231 				free(path1);
232 				return(1);
233 			}
234 			free_strtab(translated);
235 		}
236 		fclose(ifh);
237 		fprintf(stderr, "No such operation mode: '%s' was stored.\n", name);
238 		exit(1);
239 	}
240 	else
241 	{
242 		perror("fopen");
243 		fprintf(stderr, "Unable to load operation mode, unable to open file '%s' for reading.\n", path1);
244 		exit(1);
245 	}
246 }
247