1 /***********************************************************************
2 * *
3 * This software is part of the ast package *
4 * Copyright (c) 1990-2011 AT&T Intellectual Property *
5 * and is licensed under the *
6 * Eclipse Public License, Version 1.0 *
7 * by AT&T Intellectual Property *
8 * *
9 * A copy of the License is available at *
10 * http://www.eclipse.org/org/documents/epl-v10.html *
11 * (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12 * *
13 * Information and Software Systems Research *
14 * AT&T Research *
15 * Florham Park NJ *
16 * *
17 * Glenn Fowler <glenn.s.fowler@gmail.com> *
18 * *
19 ***********************************************************************/
20 #pragma prototyped
21 /*
22 * Glenn Fowler
23 * AT&T Research
24 *
25 * cs service test
26 */
27
28 static const char id[] = "@(#)$Id: cs.tst-old (AT&T Research) 1997-11-11 $\0\n";
29
30 #define TST_VERSION "1.0"
31
32 #include <cs.h>
33 #include <ctype.h>
34 #include <error.h>
35 #include <tm.h>
36
37 typedef struct
38 {
39 Cs_id_t id;
40 int clone;
41 char* args;
42 } Connection_t;
43
44 typedef struct
45 {
46 int active;
47 int dormant;
48 Connection_t id[1];
49 } State_t;
50
51 static char buf[1024];
52 static char dat[1024];
53
54 static void*
svc_init(void * handle,int maxfd)55 svc_init(void* handle, int maxfd)
56 {
57 State_t* state;
58
59 NoP(handle);
60 if (!(state = newof(0, State_t, 1, (maxfd - 1) * sizeof(Connection_t)))) exit(1);
61 cstimeout(20 * 1000L);
62 return (void*)state;
63 }
64
65 static int
svc_connect(void * handle,int fd,Cs_id_t * id,int clone,char ** argv)66 svc_connect(void* handle, int fd, Cs_id_t* id, int clone, char** argv)
67 {
68 State_t* state = (State_t*)handle;
69 char* s;
70 Sfio_t* sp;
71 char** ap;
72
73 NoP(clone);
74 state->active++;
75 state->dormant = 0;
76 state->id[fd].id = *id;
77 state->id[fd].clone = clone;
78 state->id[fd].args = 0;
79 if ((ap = argv) && (sp = sfstropen()))
80 {
81 while (s = *ap++)
82 {
83 if (ap > argv + 1)
84 sfputc(sp, ' ');
85 sfputr(sp, s, -1);
86 }
87 state->id[fd].args = strdup(sfstruse(sp));
88 sfclose(sp);
89 }
90 return 0;
91 }
92
93 static int
svc_read(void * handle,int fd)94 svc_read(void* handle, int fd)
95 {
96 State_t* state = (State_t*)handle;
97 int n;
98
99 if ((n = csread(fd, dat, sizeof(dat), CS_LINE)) <= 0) goto drop;
100 dat[--n] = 0;
101 if (isalpha(dat[0]) && (dat[1] == 0 || isdigit(dat[1]))) switch (dat[0])
102 {
103 case 'd':
104 error_info.trace = -(int)strtol(dat + 1, NiL, 0);
105 n = sfsprintf(buf, sizeof(buf), "I debug level %d\n", -error_info.trace);
106 break;
107 case 'Q':
108 if (state->active == 1) exit(0);
109 /*FALLTHROUGH*/
110 case 'q':
111 goto drop;
112 default:
113 n = sfsprintf(buf, sizeof(buf), "E %s: unknown command\n", dat);
114 break;
115 }
116 else
117 n = sfsprintf(buf, sizeof(buf), "I [%s] server=%s version=%s %s=%s server.pid=%d pid=%d uid=%d gid=%d clone=%d args=`%s'\n", fmttime(*dat ? dat : "%K", time(NiL)), csname(0), TST_VERSION, CS_HOST_LOCAL, csntoa(state->id[fd].id.hid), getpid(), state->id[fd].id.pid, state->id[fd].id.uid, state->id[fd].id.gid, state->id[fd].clone, state->id[fd].args);
118 if (cswrite(fd, buf, n) != n) goto drop;
119 return 0;
120 drop:
121 if (state->id[fd].args) free(state->id[fd].args);
122 state->active--;
123 return -1;
124 }
125
126 static int
svc_timeout(void * handle)127 svc_timeout(void* handle)
128 {
129 State_t* state = (State_t*)handle;
130
131 error(1, "timeout active=%d dormant=%d", state->active, state->dormant);
132 if (state->active <= 0)
133 {
134 if (state->dormant)
135 exit(0);
136 state->dormant = 1;
137 }
138 return 0;
139 }
140
141 int
main(int argc,char ** argv)142 main(int argc, char** argv)
143 {
144 NoP(argc);
145 csserve(NiL, argv[1], svc_init, NiL, svc_connect, svc_read, NiL, svc_timeout);
146 exit(1);
147 }
148