root/src/noit_console.c

Revision 37cf7d8f9e336376dc0ecdb1b80e4776721a950b, 4.3 kB (checked in by Theo Schlossnagle <jesus@omniti.com>, 6 years ago)

A 'simple' tokenizer to help us with the console

  • Property mode set to 100644
Line 
1 /*
2  * Copyright (c) 2007, OmniTI Computer Consulting, Inc.
3  * All rights reserved.
4  */
5
6 #include "noit_defines.h"
7
8 #include <stdio.h>
9 #include <unistd.h>
10 #include <errno.h>
11
12 #include "eventer/eventer.h"
13 #include "utils/noit_log.h"
14 #include "noit_listener.h"
15 #include "noit_console.h"
16 #include "noit_tokenizer.h"
17
18 struct __noit_console_closure {
19   char *outbuf;
20   int   outbuf_allocd;
21   int   outbuf_len;
22   int   outbuf_completed;
23 };
24
25 int
26 nc_printf(noit_console_closure_t ncct, const char *fmt, ...) {
27   int len;
28   va_list arg;
29   va_start(arg, fmt);
30   len = nc_vprintf(ncct, fmt, arg);
31   va_end(arg);
32   return len;
33 }
34 int
35 nc_vprintf(noit_console_closure_t ncct, const char *fmt, va_list arg) {
36 #ifdef va_copy
37   va_list copy;
38 #endif
39   int lenwanted;
40  
41   if(!ncct->outbuf_allocd) {
42     ncct->outbuf = malloc(4096);
43     if(!ncct->outbuf) return 0;
44     ncct->outbuf_allocd = 4096;
45   }
46   while(1) {
47     char *newbuf;
48 #ifdef va_copy
49     va_copy(copy, arg);
50     lenwanted = vsnprintf(ncct->outbuf + ncct->outbuf_len,
51                           ncct->outbuf_allocd - ncct->outbuf_len,
52                           fmt, copy);
53     va_end(copy);
54 #else
55     lenwanted = vsnprintf(ncct->outbuf + ncct->outbuf_len,
56                           ncct->outbuf_allocd - ncct->outbuf_len,
57                           fmt, arg);
58 #endif
59     if(ncct->outbuf_len + lenwanted < ncct->outbuf_allocd) {
60       /* All went well, things are as we want them. */
61       ncct->outbuf_len += lenwanted;
62       return lenwanted;
63     }
64
65     /* We need to enlarge the buffer */
66     lenwanted += ncct->outbuf_len;
67     lenwanted /= 4096;
68     lenwanted += 1;
69     lenwanted *= 4096;
70     newbuf = realloc(ncct->outbuf, lenwanted);
71     if(!newbuf) {
72       return 0;
73     }
74     ncct->outbuf = newbuf;
75     ncct->outbuf_allocd = lenwanted;
76   }
77   return -1;
78 }
79 void
80 noit_console_closure_free(noit_console_closure_t ncct) {
81   if(ncct->outbuf) free(ncct->outbuf);
82   free(ncct);
83 }
84
85 noit_console_closure_t
86 noit_console_closure_alloc() {
87   noit_console_closure_t new_ncct;
88   new_ncct = calloc(1, sizeof(*new_ncct));
89   return new_ncct;
90 }
91
92 int
93 noit_console_continue_sending(eventer_t e, noit_console_closure_t ncct,
94                               int *mask) {
95   int len;
96   if(!ncct->outbuf_len) return 0;
97   while(ncct->outbuf_len > ncct->outbuf_completed) {
98     len = e->opset->write(e->fd, ncct->outbuf + ncct->outbuf_completed,
99                           ncct->outbuf_len - ncct->outbuf_completed,
100                           mask, e);
101     if(len < 0) {
102       if(errno == EAGAIN) return -1;
103       /* Do something else here? */
104       return -1;
105     }
106     ncct->outbuf_completed += len;
107   }
108   len = ncct->outbuf_len;
109   free(ncct->outbuf);
110   ncct->outbuf = NULL;
111   ncct->outbuf_allocd = 0;
112   ncct->outbuf_len = ncct->outbuf_completed = 0;
113   return len;
114 }
115
116 void
117 noit_console_init() {
118   eventer_name_callback("noit_console", noit_console_handler);
119 }
120
121 void
122 noit_console_dispatch(eventer_t e, const char *buffer,
123                       noit_console_closure_t ncct) {
124   char *cmds[32];
125   int i, cnt = 32;
126   nc_printf(ncct, "You said: %s", buffer);
127   i = noit_tokenize(buffer, cmds, &cnt);
128   if(i>cnt) nc_printf(ncct, "Command length too long.\n");
129   if(i<0) nc_printf(ncct, "Error at offset: %d\n", 0-i);
130   for(i=0;i<cnt;i++) {
131     nc_printf(ncct, "[%d] '%s'\n", i, cmds[i]);
132     free(cmds[i]);
133   }
134 }
135
136 int
137 noit_console_handler(eventer_t e, int mask, void *closure,
138                      struct timeval *now) {
139   int newmask = EVENTER_READ;
140   noit_console_closure_t ncct = closure;
141
142   if(mask & EVENTER_EXCEPTION) {
143     /* Exceptions cause us to simply snip the connection */
144     eventer_remove_fd(e->fd);
145     e->opset->close(e->fd, &newmask, e);
146     if(ncct) noit_console_closure_free(ncct);
147     return 0;
148   }
149
150   if(!ncct) ncct = closure = e->closure = noit_console_closure_alloc();
151
152   /* If we still have data to send back to the client, this will take
153    * care of that
154    */
155   if(noit_console_continue_sending(e, ncct, &newmask) == -1)
156     return newmask;
157
158   if(mask & EVENTER_READ) {
159     int len;
160     char buffer[4096];
161     len = e->opset->read(e->fd, buffer, sizeof(buffer)-1, &newmask, e);
162     if(len <= 0) {
163       eventer_remove_fd(e->fd);
164       close(e->fd);
165       return 0;
166     }
167     buffer[len] = '\0';
168     printf("IN: %s", buffer);
169     noit_console_dispatch(e, buffer, ncct);
170     if(noit_console_continue_sending(e, ncct, &newmask) == -1)
171       return newmask;
172   }
173   return newmask | EVENTER_EXCEPTION;
174 }
175
Note: See TracBrowser for help on using the browser.