first public release of samba4 code
[jelmer/samba4-debian.git] / source / utils / net_cache.c
1 /* 
2    Samba Unix/Linux SMB client library 
3    Distributed SMB/CIFS Server Management Utility 
4    Copyright (C) Rafal Szczesniak    2002
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10    
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15    
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
19  
20
21 #include "includes.h"
22 #include "net.h"
23
24 /**
25  * @file net_cache.c
26  * @brief This is part of the net tool which is basically command
27  *        line wrapper for gencache.c functions (mainly for testing)
28  *
29  **/
30
31
32 /*
33  * These routines are used via gencache_iterate() to display the cache's contents
34  * (print_cache_entry) and to flush it (delete_cache_entry).
35  * Both of them are defined by first arg of gencache_iterate() routine.
36  */
37 static void print_cache_entry(const char* keystr, const char* datastr,
38                               const time_t timeout, void* dptr)
39 {
40         char* timeout_str;
41         time_t now_t = time(NULL);
42         struct tm timeout_tm, *now_tm;
43         /* localtime returns statically allocated pointer, so timeout_tm
44            has to be copied somewhere else */
45         memcpy(&timeout_tm, localtime(&timeout), sizeof(struct tm));
46         now_tm = localtime(&now_t);
47
48         /* form up timeout string depending whether it's today's date or not */
49         if (timeout_tm.tm_year != now_tm->tm_year ||
50             timeout_tm.tm_mon != now_tm->tm_mon ||
51             timeout_tm.tm_mday != now_tm->tm_mday) {
52             
53             timeout_str = asctime(&timeout_tm);
54             timeout_str[strlen(timeout_str) - 1] = '\0';        /* remove tailing CR */
55         } else
56                 asprintf(&timeout_str, "%.2d:%.2d:%.2d", timeout_tm.tm_hour,
57                          timeout_tm.tm_min, timeout_tm.tm_sec);
58         
59         d_printf("Key: %s\t Timeout: %s\t Value: %s  %s\n", keystr,
60                  timeout_str, datastr, timeout > now_t ? "": "(expired)");
61 }
62
63 static void delete_cache_entry(const char* keystr, const char* datastr,
64                                const time_t timeout, void* dptr)
65 {
66         if (!gencache_del(keystr))
67                 d_printf("Couldn't delete entry! key = %s", keystr);
68 }
69
70
71 /**
72  * Parse text representation of timeout value
73  *
74  * @param timeout_str string containing text representation of the timeout
75  * @return numeric timeout of time_t type
76  **/
77 static time_t parse_timeout(const char* timeout_str)
78 {
79         char sign = '\0', *number = NULL, unit = '\0';
80         int len, number_begin, number_end;
81         time_t timeout;
82
83         /* sign detection */
84         if (timeout_str[0] == '!' || timeout_str[0] == '+') {
85                 sign = timeout_str[0];
86                 number_begin = 1;
87         } else {
88                 number_begin = 0;
89         }
90         
91         /* unit detection */
92         len = strlen(timeout_str);
93         switch (timeout_str[len - 1]) {
94         case 's':
95         case 'm':
96         case 'h':
97         case 'd':
98         case 'w': unit = timeout_str[len - 1];
99         }
100         
101         /* number detection */
102         len = (sign) ? strlen(&timeout_str[number_begin]) : len;
103         number_end = (unit) ? len - 1 : len;
104         number = strndup(&timeout_str[number_begin], number_end);
105         
106         /* calculate actual timeout value */
107         timeout = (time_t)atoi(number);
108
109         switch (unit) {
110         case 'm': timeout *= 60; break;
111         case 'h': timeout *= 60*60; break;
112         case 'd': timeout *= 60*60*24; break;
113         case 'w': timeout *= 60*60*24*7; break;  /* that's fair enough, I think :) */
114         }
115         
116         switch (sign) {
117         case '!': timeout = time(NULL) - timeout; break;
118         case '+':
119         default:  timeout += time(NULL); break;
120         }
121         
122         if (number) SAFE_FREE(number);
123         return timeout; 
124 }
125
126
127 /**
128  * Add an entry to the cache. If it does exist, then set it.
129  * 
130  * @param argv key, value and timeout are passed in command line
131  * @return 0 on success, otherwise failure
132  **/
133 static int net_cache_add(int argc, const char **argv)
134 {
135         const char *keystr, *datastr, *timeout_str;
136         time_t timeout;
137         
138         if (argc < 3) {
139                 d_printf("\nUsage: net cache add <key string> <data string> <timeout>\n");
140                 return -1;
141         }
142         
143         keystr = argv[0];
144         datastr = argv[1];
145         timeout_str = argv[2];
146         
147         /* parse timeout given in command line */
148         timeout = parse_timeout(timeout_str);
149         if (!timeout) {
150                 d_printf("Invalid timeout argument.\n");
151                 return -1;
152         }
153         
154         if (gencache_set(keystr, datastr, timeout)) {
155                 d_printf("New cache entry stored successfully.\n");
156                 gencache_shutdown();
157                 return 0;
158         }
159         
160         d_printf("Entry couldn't be added. Perhaps there's already such a key.\n");
161         gencache_shutdown();
162         return -1;
163 }
164
165
166 /**
167  * Set new value of an existing entry in the cache. Fail If the entry doesn't
168  * exist.
169  * 
170  * @param argv key being searched and new value and timeout to set in the entry
171  * @return 0 on success, otherwise failure
172  **/
173 static int net_cache_set(int argc, const char **argv)
174 {
175         const char *keystr, *datastr, *timeout_str;
176         time_t timeout;
177         
178         if (argc < 3) {
179                 d_printf("\nUsage: net cache set <key string> <data string> <timeout>\n");
180                 return -1;
181         }
182         
183         keystr = argv[0];
184         datastr = argv[1];
185         timeout_str = argv[2];
186         
187         /* parse timeout given in command line */
188         timeout = parse_timeout(timeout_str);
189         if (!timeout) {
190                 d_printf("Invalid timeout argument.\n");
191                 return -1;
192         }
193         
194         if (gencache_set_only(keystr, datastr, timeout)) {
195                 d_printf("Cache entry set successfully.\n");
196                 gencache_shutdown();
197                 return 0;
198         }
199
200         d_printf("Entry couldn't be set. Perhaps there's no such a key.\n");
201         gencache_shutdown();
202         return -1;
203 }
204
205
206 /**
207  * Delete an entry in the cache
208  * 
209  * @param argv key to delete an entry of
210  * @return 0 on success, otherwise failure
211  **/
212 static int net_cache_del(int argc, const char **argv)
213 {
214         const char *keystr = argv[0];
215         
216         if (argc < 1) {
217                 d_printf("\nUsage: net cache add <key string>\n");
218                 return -1;
219         }
220         
221         if(gencache_del(keystr)) {
222                 d_printf("Entry deleted.\n");
223                 return 0;
224         }
225
226         d_printf("Couldn't delete specified entry\n");
227         return -1;
228 }
229
230
231 /**
232  * Get and display an entry from the cache
233  * 
234  * @param argv key to search an entry of
235  * @return 0 on success, otherwise failure
236  **/
237 static int net_cache_get(int argc, const char **argv)
238 {
239         const char* keystr = argv[0];
240         char* valuestr;
241         time_t timeout;
242
243         if (argc < 1) {
244                 d_printf("\nUsage: net cache get <key>\n");
245                 return -1;
246         }
247         
248         if (gencache_get(keystr, &valuestr, &timeout)) {
249                 print_cache_entry(keystr, valuestr, timeout, NULL);
250                 return 0;
251         }
252
253         d_printf("Failed to find entry\n");
254         return -1;
255 }
256
257
258 /**
259  * Search an entry/entries in the cache
260  * 
261  * @param argv key pattern to match the entries to
262  * @return 0 on success, otherwise failure
263  **/
264 static int net_cache_search(int argc, const char **argv)
265 {
266         const char* pattern;
267         
268         if (argc < 1) {
269                 d_printf("Usage: net cache search <pattern>\n");
270                 return -1;
271         }
272         
273         pattern = argv[0];
274         gencache_iterate(print_cache_entry, NULL, pattern);
275         return 0;
276 }
277
278
279 /**
280  * List the contents of the cache
281  * 
282  * @param argv ignored in this functionailty
283  * @return always returns 0
284  **/
285 static int net_cache_list(int argc, const char **argv)
286 {
287         const char* pattern = "*";
288         gencache_iterate(print_cache_entry, NULL, pattern);
289         gencache_shutdown();
290         return 0;
291 }
292
293
294 /**
295  * Flush the whole cache
296  * 
297  * @param argv ignored in this functionality
298  * @return always returns 0
299  **/
300 static int net_cache_flush(int argc, const char **argv)
301 {
302         const char* pattern = "*";
303         gencache_iterate(delete_cache_entry, NULL, pattern);
304         gencache_shutdown();
305         return 0;
306 }
307
308
309 /**
310  * Short help
311  *
312  * @param argv ignored in this functionality
313  * @return always returns -1
314  **/
315 static int net_cache_usage(int argc, const char **argv)
316 {
317         d_printf("  net cache add \t add add new cache entry\n");
318         d_printf("  net cache set \t set new value for existing cache entry\n");
319         d_printf("  net cache del \t delete existing cache entry by key\n");
320         d_printf("  net cache flush \t delete all entries existing in the cache\n");
321         d_printf("  net cache get \t get cache entry by key\n");
322         d_printf("  net cache search \t search for entries in the cache, by given pattern\n");
323         d_printf("  net cache list \t list all cache entries (just like search for \"*\")\n");
324         return -1;
325 }
326
327
328 /**
329  * Entry point to 'net cache' subfunctionality
330  *
331  * @param argv arguments passed to further called functions
332  * @return whatever further functions return
333  **/
334 int net_cache(int argc, const char **argv)
335 {
336         struct functable func[] = {
337                 {"add", net_cache_add},
338                 {"set", net_cache_set},
339                 {"del", net_cache_del},
340                 {"get", net_cache_get},
341                 {"search", net_cache_search},
342                 {"list", net_cache_list},
343                 {"flush", net_cache_flush},
344                 {NULL, NULL}
345         };
346
347         return net_run_function(argc, argv, func, net_cache_usage);
348 }