Jspice3
spiced.c
Go to the documentation of this file.
1 /**********
2 Copyright 1990 Regents of the University of California. All rights reserved.
3 Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group
4 **********/
5 
6 /*
7  * Do remote spice jobs. The first line transmitted will be of the
8  * format: "user host program". The program field may be left out,
9  * in which case it defaults to SPICE_PATH. The program is then
10  * executed, with the single argument "-S". The remote host should
11  * wait for a response from spiced before sending any data -- so
12  * far the only response sent is "ok".
13  * Eventually we will want to deal with load-balancing
14  * of spice jobs.
15  */
16 
17 #include "spice.h"
18 #include <stdio.h>
19 #ifdef HAVE_STRINGS_H
20 #include <strings.h>
21 #else
22 #include <string.h>
23 #endif
24 #include <errno.h>
25 #include <sys/types.h>
26 
27 #ifdef HAVE_SOCKET
28 #include <sys/socket.h>
29 #include <netinet/in.h>
30 #include <netdb.h>
31 
32 #ifdef HAVE_GETRUSAGE
33 #include <sys/time.h>
34 #include <sys/resource.h>
35 #else
36 
37 #ifdef HAVE_TIMES
38 #include <time.h>
39 #endif
40 #endif
41 
42 #include <sys/ioctl.h>
43 #include <sys/file.h>
44 #ifdef HAVE_GETPWUID
45 #include <pwd.h>
46 #endif
47 
48 /* Better have #ifdef HAS_UNIX_SIGS XXX */
49 #include <signal.h>
50 /* Better have #ifdef HAS_WAIT XXX */
51 #include <sys/wait.h>
52 #include <fcntl.h>
53 
54 typedef RETSIGTYPE (*SigType)();
55 
56 extern char *getenv();
57 extern char *tilde_expand();
58 extern char *copy();
59 char *Spiced_Log = "/tmp/jspice3d.log";
60 char *Spice_Exec_Dir;
61 char *Spice_Lib_Dir;
62 char *Spice_Host;
63 char *Bug_Addr;
64 char *Def_Editor;
65 int AsciiRawFile;
66 
67 #define MAXJOBS 2
68 
69 int nrunning = 0;
70 int maxjobs = MAXJOBS;
71 
72 extern int errno;
73 extern char **environ;
74 
75 /* ARGSUSED */
76 int
77 main(ac, av)
78 char **av;
79 {
80  int s, inetd = 0;
81  struct servent *sp;
82  struct protoent *pp;
83  struct sockaddr_in from, sin;
84  int g, i, len = sizeof (struct sockaddr_in);
85  void dostuff();
86  int sigchild();
87  FILE *fp;
88  char *datestring();
89 
90  /* Process arguments. */
91 
92  ivars( );
93  if (getenv("SPICED_LOG"))
94  Spiced_Log = getenv("SPICED_LOG");
95 
96  av++;
97  while (*av) {
98  if (!strcmp(*av, "-i"))
99  inetd++;
100  else
101  maxjobs = atoi(av[1]);
102  av++;
103  }
104 
105  if (inetd == 0) {
106  /* Find out who we are. */
107  sp = getservbyname("spice", "tcp");
108  if (sp == NULL) {
109  fprintf(stderr, "Error: spice/tcp: unknown service\n");
110  return (1);
111  }
112  pp = getprotobyname("tcp");
113  if (pp == NULL) {
114  fprintf(stderr, "Error: tcp: unknown protocol\n");
115  return (1);
116  }
117 
118  /* Create the socket. */
119  s = socket(AF_INET, SOCK_STREAM, pp->p_proto);
120  if (s < 0) {
121  perror("spiced: socket");
122  return (1);
123  }
124  sin.sin_port = sp->s_port;
125  if (bind(s, (struct sockaddr *) &sin, sizeof
126  (struct sockaddr_in)) < 0) {
127  perror("spiced: bind");
128  return (1);
129  }
130 
131 #ifndef DEBUG
132  /* Disconnect from the controlling terminal. */
133  if (fork())
134  return (0);
135  for (i = 0; i < 10; i++)
136  if (i != s)
137  (void) close(i);
138  (void) open("/", O_RDONLY);
139  (void) dup2(0, 1);
140  (void) dup2(0, 2);
141 
142  setsid();
143  /*
144  i = open("/dev/tty", O_RDWR);
145  if (i > 0) {
146  (void) ioctl(i, TIOCNOTTY, (char *) NULL);
147  (void) close(i);
148  }
149  */
150 
151 #endif
152 
153 #ifdef SIGCHLD
154  (void) signal(SIGCHLD, (SigType)sigchild);
155 #else
156 #ifdef SIGCLD
157  (void) signal(SIGCLD, (SigType)sigchild);
158 #endif
159 #endif
160  fp = fopen(Spiced_Log, "a");
161  fprintf(fp, "\n-- new daemon, pid = %d, date = %s\n\n",
162  getpid(), datestring());
163  (void) fclose(fp);
164 
165  /* Start (void) listening for requests. */
166  (void) listen(s, 5);
167  for (;;) {
168  g = accept(s, (struct sockaddr *) &from, &len);
169  if (g < 0) {
170  if (errno != EINTR) {
171  fp = fopen(Spiced_Log, "a");
172  fprintf(fp, "\n>>> accept: %s\n\n", strerror(errno));
173  return (1);
174  }
175  continue;
176  }
177  if (!fork()) {
178  (void) close(s);
179 #ifdef SIGCHLD
180  (void) signal(SIGCHLD, (SigType)SIG_IGN);
181 #else
182 #ifdef SIGCLD
183  (void) signal(SIGCLD, (SigType)SIG_IGN);
184 #endif
185 #endif
186  dostuff(g);
187  }
188  nrunning++;
189  (void) close(g);
190  }
191  }
192  else {
193  /* All this is already done for us. */
194  dostuff(0);
195  }
196  return (0);
197 }
198 
199 void
200 dostuff(s)
201 {
202  FILE *fp;
203  char *datestring();
204  char buf[BUFSIZ], user[16], host[32], program[128];
205  char *argv[3], *t;
206  int i, rc;
207  int stats;
208 #ifdef HAVE_GETRUSAGE
209  struct rusage ru;
210 #endif
211 
212  /* Should do some sort of verification */
213  i = read(s, buf, BUFSIZ);
214  if (i < 0) {
215  perror("spiced: read");
216  exit(1);
217  }
218  i = sscanf(buf, "%s %s %s", user, host, program);
219  if (i < 2) {
220  fprintf(stderr, "Error: bad init line: %s\n", buf);
221  exit(1);
222  }
223  if (i == 2)
224  (void) strcpy(program, tilde_expand(Spice_Path));
225 
226  if (nrunning > maxjobs - 1) {
227  /* Too many people. */
228  (void) write(s, "toomany", 8);
229  fp = fopen(Spiced_Log, "a");
230  fprintf(fp, "%s: %s@%s: turned down - %d jobs now\n",
231  datestring(), user, host, nrunning);
232  (void) fclose(fp);
233  exit(0);
234  }
235  (void) write(s, "ok", 3);
236 
237  if ((i = fork()) == 0) {
238  (void) dup2(s, 0);
239  (void) dup2(s, 1);
240  (void) dup2(s, 2);
241  argv[0] = program;
242  argv[1] = "-S";
243  argv[2] = NULL;
244  (void) execve(program, argv, environ);
245  perror(program);
246  exit(1);
247  }
248 #ifdef HAVE_GETRUSAGE
249  /* Assume BSDRUSAGE -> wait3( ) XXX */
250  if (wait3(&stats, 0, &ru) != i) {
251  perror("wait");
252  exit(1);
253  }
254 #else
255 #ifdef HAVE_SYS_WAIT_H
256  wait(&stats);
257  rc = 0;
258  rc = WEXITSTATUS(stats);
259 #endif
260 #endif
261 
262  /* Write a log entry. */
263 #ifdef HAVE_GETRUSAGE
264  (void) sprintf(buf, "%d:%d.%6d", ru.ru_utime.tv_sec / 60,
265  ru.ru_utime.tv_sec % 60, ru.ru_utime.tv_usec);
266  for (t = buf; *t; t++)
267  ;
268  for (t--; *t == '0'; *t-- = '\0')
269  ;
270 #else
271  (void) strcpy(buf, "unknown");
272 #endif
273  fp = fopen(Spiced_Log, "a");
274  fprintf(fp, "%s: %s@%s: %s - \n\texit %d, time %s\n",
275  datestring(), user, host, program, rc,
276  buf);
277  (void) fclose(fp);
278  exit(0);
279 }
280 
281 /* Don't care what happens to the child */
282 
283 int
284 sigchild()
285 {
286  int pid;
287  FILE *fp;
288 
289  pid = wait(NULL);
290  if (pid == -1) {
291  fp = fopen(Spiced_Log, "a");
292  fprintf(fp, "\n>>>spiced: wait: %s\n\n", strerror(errno));
293  (void) fclose(fp);
294  } else
295  nrunning--;
296  return (0);
297 }
298 
299 #else /* not HAVE_SOCKET */
301 {
302  fprintf(stderr,
303  "The program \"spiced\" is not available on this system.\n");
304  return (1);
305 }
306 #endif /* HAVE_SOCKET */
307 
308 char *
310 
311 
312 char *string;
313 {
314 #ifdef HAVE_GETPWUID
315  struct passwd *pw;
316  char *tail;
317  char buf[512];
318  char *k, c;
319 
320  if (!string)
321  return (NULL);
322 
323  while (*string && isspace(*string))
324  string++;
325 
326  if (*string != '~')
327  return copy(string);
328 
329  string += 1;
330 
331  if (!*string || *string == '/') {
332  pw = getpwuid(getuid());
333  *buf = 0;
334  }
335  else {
336  k = buf;
337  while ((c = *string) && c != '/')
338  *k++ = c, string++;
339  *k = 0;
340  pw = getpwnam(buf);
341  }
342 
343  if (pw) {
344  strcpy(buf, pw->pw_dir);
345  if (*string)
346  strcat(buf, string);
347  }
348  else
349  return (NULL);
350 
351  return (copy(buf));
352 
353 #else
354  return (copy(string));
355 #endif
356 }
static char buf[MAXPROMPT]
Definition: arg.c:18
char * tilde_expand(char *string)
Definition: spiced.c:309
char * strcpy()
Definition: cddefs.h:119
Definition: objects.c:1183
char * Spice_Exec_Dir
char * datestring()
Definition: time.c:37
char * copy()
char * getenv(char *c)
Definition: libfuncs.c:106
char * Spice_Lib_Dir
void ivars()
Definition: ivars.c:51
char * Def_Editor
int AsciiRawFile
#define NULL
Definition: spdefs.h:121
char * Bug_Addr
static double c
Definition: vectors.c:16
void perror()
double sin()
main()
Definition: spiced.c:300
RETSIGTYPE(* SigType)()
Definition: main.c:439
char * Spice_Path
Definition: ivars.c:11
int getpid()
Definition: libfuncs.c:137
Definition: cddefs.h:227
char * Spice_Host
char * Spiced_Log
Definition: cddefs.h:192