source: zwrite.c @ c323405

release-1.10release-1.8release-1.9
Last change on this file since c323405 was d427f08, checked in by Nelson Elhage <nelhage@mit.edu>, 13 years ago
Use G_GNUC_WARN_UNUSED_RESULT Have gcc warn us when we ignore the result of a function that requires the caller to free the result, or an initilization function that can fail. This might help (slightly) with preventing leaks and segfaults. Additionally changed some functions that should never fail to not return values. (The owl_list_* functions changed only fail if list->size < 0, which we assume is not the case elsewhere.)
  • Property mode set to 100644
File size: 9.3 KB
Line 
1#include <string.h>
2#include <pwd.h>
3#include <sys/types.h>
4#include <unistd.h>
5#include "owl.h"
6
7G_GNUC_WARN_UNUSED_RESULT owl_zwrite *owl_zwrite_new(const char *line)
8{
9  owl_zwrite *z = g_new(owl_zwrite, 1);
10  if (owl_zwrite_create_from_line(z, line) < 0) {
11    owl_zwrite_delete(z);
12    return NULL;
13  }
14  return z;
15}
16
17G_GNUC_WARN_UNUSED_RESULT int owl_zwrite_create_from_line(owl_zwrite *z, const char *line)
18{
19  int argc, badargs, myargc;
20  char **argv;
21  const char *const *myargv;
22  char *msg = NULL;
23
24  badargs=0;
25 
26  /* start with null entries */
27  z->cmd=NULL;
28  z->realm=NULL;
29  z->class=NULL;
30  z->inst=NULL;
31  z->opcode=NULL;
32  z->zsig=NULL;
33  z->message=NULL;
34  z->cc=0;
35  z->noping=0;
36  owl_list_create(&(z->recips));
37  z->zwriteline = g_strdup(line);
38
39  /* parse the command line for options */
40  argv=owl_parseline(line, &argc);
41  myargv=strs(argv);
42  if (argc<0) {
43    owl_function_error("Unbalanced quotes in zwrite");
44    return(-1);
45  }
46  myargc=argc;
47  if (myargc && *(myargv[0])!='-') {
48    z->cmd=g_strdup(myargv[0]);
49    myargc--;
50    myargv++;
51  }
52  while (myargc) {
53    if (!strcmp(myargv[0], "-c")) {
54      if (myargc<2) {
55        badargs=1;
56        break;
57      }
58      z->class=owl_validate_utf8(myargv[1]);
59      myargv+=2;
60      myargc-=2;
61    } else if (!strcmp(myargv[0], "-i")) {
62      if (myargc<2) {
63        badargs=1;
64        break;
65      }
66      z->inst=owl_validate_utf8(myargv[1]);
67      myargv+=2;
68      myargc-=2;
69    } else if (!strcmp(myargv[0], "-r")) {
70      if (myargc<2) {
71        badargs=1;
72        break;
73      }
74      z->realm=owl_validate_utf8(myargv[1]);
75      myargv+=2;
76      myargc-=2;
77    } else if (!strcmp(myargv[0], "-s")) {
78      if (myargc<2) {
79        badargs=1;
80        break;
81      }
82      z->zsig=owl_validate_utf8(myargv[1]);
83      myargv+=2;
84      myargc-=2;
85    } else if (!strcmp(myargv[0], "-O")) {
86      if (myargc<2) {
87        badargs=1;
88        break;
89      }
90      z->opcode=owl_validate_utf8(myargv[1]);
91      myargv+=2;
92      myargc-=2;
93    } else if (!strcmp(myargv[0], "-m")) {
94      if (myargc<2) {
95        badargs=1;
96        break;
97      }
98      /* we must already have users or a class or an instance */
99      if (owl_list_get_size(&(z->recips))<1 && (!z->class) && (!z->inst)) {
100        badargs=1;
101        break;
102      }
103
104      /* Once we have -m, gobble up everything else on the line */
105      myargv++;
106      myargc--;
107      msg = g_strjoinv(" ", (char**)myargv);
108      break;
109    } else if (!strcmp(myargv[0], "-C")) {
110      z->cc=1;
111      myargv++;
112      myargc--;
113    } else if (!strcmp(myargv[0], "-n")) {
114      z->noping=1;
115      myargv++;
116      myargc--;
117    } else {
118      /* anything unattached is a recipient */
119      owl_list_append_element(&(z->recips), owl_validate_utf8(myargv[0]));
120      myargv++;
121      myargc--;
122    }
123  }
124
125  g_strfreev(argv);
126
127  if (badargs) {
128    return(-1);
129  }
130
131  if (z->class == NULL &&
132      z->inst == NULL &&
133      owl_list_get_size(&(z->recips))==0) {
134    owl_function_error("You must specify a recipient for zwrite");
135    return(-1);
136  }
137
138  /* now deal with defaults */
139  if (z->class==NULL) z->class=g_strdup("message");
140  if (z->inst==NULL) z->inst=g_strdup("personal");
141  if (z->realm==NULL) z->realm=g_strdup("");
142  if (z->opcode==NULL) z->opcode=g_strdup("");
143  /* z->message is allowed to stay NULL */
144
145  if(msg) {
146    owl_zwrite_set_message(z, msg);
147    g_free(msg);
148  }
149
150  return(0);
151}
152
153void owl_zwrite_populate_zsig(owl_zwrite *z)
154{
155  /* get a zsig, if not given */
156  if (z->zsig != NULL)
157    return;
158
159  z->zsig = owl_perlconfig_execute(owl_global_get_zsigfunc(&g));
160}
161
162void owl_zwrite_send_ping(const owl_zwrite *z)
163{
164  int i, j;
165  char *to;
166
167  if (z->noping) return;
168 
169  if (strcasecmp(z->class, "message")) {
170    return;
171  }
172
173  /* if there are no recipients we won't send a ping, which
174     is what we want */
175  j=owl_list_get_size(&(z->recips));
176  for (i=0; i<j; i++) {
177    to = owl_zwrite_get_recip_n_with_realm(z, i);
178    send_ping(to, z->class, z->inst);
179    g_free(to);
180  }
181
182}
183
184/* Set the message with no post-processing*/
185void owl_zwrite_set_message_raw(owl_zwrite *z, const char *msg)
186{
187  g_free(z->message);
188  z->message = owl_validate_utf8(msg);
189}
190
191void owl_zwrite_set_message(owl_zwrite *z, const char *msg)
192{
193  int i, j;
194  GString *message;
195  char *tmp = NULL, *tmp2;
196
197  g_free(z->message);
198
199  j=owl_list_get_size(&(z->recips));
200  if (j>0 && z->cc) {
201    message = g_string_new("CC: ");
202    for (i=0; i<j; i++) {
203      tmp = owl_zwrite_get_recip_n_with_realm(z, i);
204      g_string_append_printf(message, "%s ", tmp);
205      g_free(tmp);
206      tmp = NULL;
207    }
208    tmp = owl_validate_utf8(msg);
209    tmp2 = owl_text_expand_tabs(tmp);
210    g_string_append_printf(message, "\n%s", tmp2);
211    z->message = g_string_free(message, false);
212    g_free(tmp);
213    g_free(tmp2);
214  } else {
215    tmp=owl_validate_utf8(msg);
216    z->message=owl_text_expand_tabs(tmp);
217    g_free(tmp);
218  }
219}
220
221const char *owl_zwrite_get_message(const owl_zwrite *z)
222{
223  if (z->message) return(z->message);
224  return("");
225}
226
227int owl_zwrite_is_message_set(const owl_zwrite *z)
228{
229  if (z->message) return(1);
230  return(0);
231}
232
233int owl_zwrite_send_message(const owl_zwrite *z)
234{
235  int i, j, ret = 0;
236  char *to = NULL;
237
238  if (z->message==NULL) return(-1);
239
240  j=owl_list_get_size(&(z->recips));
241  if (j>0) {
242    for (i=0; i<j; i++) {
243      to = owl_zwrite_get_recip_n_with_realm(z, i);
244      ret = send_zephyr(z->opcode, z->zsig, z->class, z->inst, to, z->message);
245      /* Abort on the first error, to match the zwrite binary. */
246      if (ret != 0)
247        break;
248      g_free(to);
249      to = NULL;
250    }
251  } else {
252    to = g_strdup_printf( "@%s", z->realm);
253    ret = send_zephyr(z->opcode, z->zsig, z->class, z->inst, to, z->message);
254  }
255  g_free(to);
256  return ret;
257}
258
259int owl_zwrite_create_and_send_from_line(const char *cmd, const char *msg)
260{
261  owl_zwrite z;
262  int rv;
263  rv=owl_zwrite_create_from_line(&z, cmd);
264  if (rv) return(rv);
265  if (!owl_zwrite_is_message_set(&z)) {
266    owl_zwrite_set_message(&z, msg);
267  }
268  owl_zwrite_populate_zsig(&z);
269  owl_zwrite_send_message(&z);
270  owl_zwrite_cleanup(&z);
271  return(0);
272}
273
274const char *owl_zwrite_get_class(const owl_zwrite *z)
275{
276  return(z->class);
277}
278
279const char *owl_zwrite_get_instance(const owl_zwrite *z)
280{
281  return(z->inst);
282}
283
284const char *owl_zwrite_get_opcode(const owl_zwrite *z)
285{
286  return(z->opcode);
287}
288
289void owl_zwrite_set_opcode(owl_zwrite *z, const char *opcode)
290{
291  g_free(z->opcode);
292  z->opcode=owl_validate_utf8(opcode);
293}
294
295const char *owl_zwrite_get_realm(const owl_zwrite *z)
296{
297  return(z->realm);
298}
299
300const char *owl_zwrite_get_zsig(const owl_zwrite *z)
301{
302  if (z->zsig) return(z->zsig);
303  return("");
304}
305
306void owl_zwrite_set_zsig(owl_zwrite *z, const char *zsig)
307{
308  g_free(z->zsig);
309  z->zsig = g_strdup(zsig);
310}
311
312int owl_zwrite_get_numrecips(const owl_zwrite *z)
313{
314  return(owl_list_get_size(&(z->recips)));
315}
316
317const char *owl_zwrite_get_recip_n(const owl_zwrite *z, int n)
318{
319  return(owl_list_get_element(&(z->recips), n));
320}
321
322/* Caller must free the result. */
323G_GNUC_WARN_UNUSED_RESULT char *owl_zwrite_get_recip_n_with_realm(const owl_zwrite *z, int n)
324{
325  if (z->realm[0]) {
326    return g_strdup_printf("%s@%s", owl_zwrite_get_recip_n(z, n), z->realm);
327  } else {
328    return g_strdup(owl_zwrite_get_recip_n(z, n));
329  }
330}
331
332int owl_zwrite_is_personal(const owl_zwrite *z)
333{
334  /* return true if at least one of the recipients is personal */
335  int i, j;
336  char *foo;
337
338  j=owl_list_get_size(&(z->recips));
339  for (i=0; i<j; i++) {
340    foo=owl_list_get_element(&(z->recips), i);
341    if (foo[0]!='@') return(1);
342  }
343  return(0);
344}
345
346void owl_zwrite_delete(owl_zwrite *z)
347{
348  owl_zwrite_cleanup(z);
349  g_free(z);
350}
351
352void owl_zwrite_cleanup(owl_zwrite *z)
353{
354  owl_list_cleanup(&(z->recips), &g_free);
355  g_free(z->cmd);
356  g_free(z->zwriteline);
357  g_free(z->class);
358  g_free(z->inst);
359  g_free(z->opcode);
360  g_free(z->realm);
361  g_free(z->message);
362  g_free(z->zsig);
363}
364
365/*
366 * Returns a zwrite line suitable for replying, specifically the
367 * message field is stripped out. Result should be freed with
368 * g_free.
369 *
370 * If not a CC, only the recip_index'th user will be replied to.
371 */
372G_GNUC_WARN_UNUSED_RESULT char *owl_zwrite_get_replyline(const owl_zwrite *z, int recip_index)
373{
374  /* Match ordering in zwrite help. */
375  GString *buf = g_string_new("");
376  int i;
377
378  /* Disturbingly, it is apparently possible to z->cmd to be null if
379   * owl_zwrite_create_from_line got something starting with -. And we
380   * can't kill it because this is exported to perl. */
381  owl_string_append_quoted_arg(buf, z->cmd ? z->cmd : "zwrite");
382  if (z->noping) {
383    g_string_append(buf, " -n");
384  }
385  if (z->cc) {
386    g_string_append(buf, " -C");
387  }
388  if (strcmp(z->class, "message")) {
389    g_string_append(buf, " -c ");
390    owl_string_append_quoted_arg(buf, z->class);
391  }
392  if (strcmp(z->inst, "personal")) {
393    g_string_append(buf, " -i ");
394    owl_string_append_quoted_arg(buf, z->inst);
395  }
396  if (z->realm && z->realm[0] != '\0') {
397    g_string_append(buf, " -r ");
398    owl_string_append_quoted_arg(buf, z->realm);
399  }
400  if (z->opcode && z->opcode[0] != '\0') {
401    g_string_append(buf, " -O ");
402    owl_string_append_quoted_arg(buf, z->opcode);
403  }
404  if (z->cc) {
405    for (i = 0; i < owl_list_get_size(&(z->recips)); i++) {
406      g_string_append_c(buf, ' ');
407      owl_string_append_quoted_arg(buf, owl_list_get_element(&(z->recips), i));
408    }
409  } else if (recip_index < owl_list_get_size(&(z->recips))) {
410    g_string_append_c(buf, ' ');
411    owl_string_append_quoted_arg(buf, owl_list_get_element(&(z->recips), recip_index));
412  }
413
414  return g_string_free(buf, false);
415}
Note: See TracBrowser for help on using the repository browser.