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