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