comparison lib-src/gnuclient.c @ 151:59463afc5666 r20-3b2

Import from CVS: tag r20-3b2
author cvs
date Mon, 13 Aug 2007 09:37:19 +0200
parents 538048ae2ab8
children 25f70ba0133c
comparison
equal deleted inserted replaced
150:8ebb1c0f0f6f 151:59463afc5666
122 Emacs, but I think it's better not to. I can see no reason why 122 Emacs, but I think it's better not to. I can see no reason why
123 Emacs should SIGSEGV whenever gnuclient SIGSEGV-s, etc. */ 123 Emacs should SIGSEGV whenever gnuclient SIGSEGV-s, etc. */
124 signal (SIGHUP, pass_signal_to_emacs); 124 signal (SIGHUP, pass_signal_to_emacs);
125 signal (SIGQUIT, pass_signal_to_emacs); 125 signal (SIGQUIT, pass_signal_to_emacs);
126 signal (SIGINT, pass_signal_to_emacs); 126 signal (SIGINT, pass_signal_to_emacs);
127 #ifdef SIGWINCH
128 signal (SIGWINCH, pass_signal_to_emacs);
129 #endif
127 130
128 /* We want emacs to realize that we are resuming */ 131 /* We want emacs to realize that we are resuming */
129 signal (SIGCONT, tell_emacs_to_resume); 132 signal (SIGCONT, tell_emacs_to_resume);
130 } 133 }
131 134
188 191
189 strcat (fullpath,filename); 192 strcat (fullpath,filename);
190 193
191 } /* filename_expand */ 194 } /* filename_expand */
192 195
196 /* Encase the string in quotes, escape all the backslashes and quotes
197 in string. */
198 char *
199 clean_string (CONST char *s)
200 {
201 int i = 0;
202 char *p, *res;
203
204 for (p = s; *p; p++, i++)
205 {
206 if (*p == '\\' || *p == '\"')
207 ++i;
208 else if (*p == '\004')
209 i += 3;
210 }
211 p = res = (char *)malloc (i + 2 + 1);
212 *p++ = '\"';
213 for (; *s; p++, s++)
214 {
215 switch (*s)
216 {
217 case '\\':
218 *p++ = '\\';
219 *p = '\\';
220 break;
221 case '\"':
222 *p++ = '\\';
223 *p = '\"';
224 break;
225 case '\004':
226 *p++ = '\\';
227 *p++ = 'C';
228 *p++ = '-';
229 *p = 'd';
230 break;
231 default:
232 *p = *s;
233 }
234 }
235 *p++ = '\"';
236 *p = '\0';
237 return res;
238 }
239
240 #define GET_ARGUMENT(var, desc) do { \
241 if (*(p + 1)) (var) = p + 1; \
242 else \
243 { \
244 if (!argv[++i]) \
245 { \
246 fprintf (stderr, "%s: `%s' must be followed by an argument\n", \
247 progname, desc); \
248 exit (1); \
249 } \
250 (var) = argv[i]; \
251 } \
252 over = 1; \
253 } while (0)
254
255
193 int 256 int
194 main (int argc, char *argv[]) 257 main (int argc, char *argv[])
195 { 258 {
196 int starting_line = 1; /* line to start editing at */ 259 int starting_line = 1; /* line to start editing at */
197 char command[MAXPATHLEN+50]; /* emacs command buffer */ 260 char command[MAXPATHLEN+50]; /* emacs command buffer */
198 char fullpath[MAXPATHLEN+1]; /* full pathname to file */ 261 char fullpath[MAXPATHLEN+1]; /* full pathname to file */
199 int qflg = 0; /* quick edit, don't wait for 262 char *eval_form = NULL; /* form to evaluate with `-eval' */
200 * user to finish */ 263 char *eval_function = NULL; /* function to evaluate with `-f' */
201 int view = 0; /* view only. */ 264 char *load_library = NULL; /* library to load */
202 int errflg = 0; /* option error */ 265 int quick = 0; /* quick edit, don't wait for user to
203 int c; /* char from getopt */ 266 finish */
204 int s; /* socket / msqid to server */ 267 int batch = 0; /* batch mode */
205 int connect_type; /* CONN_UNIX, CONN_INTERNET, or 268 int view = 0; /* view only. */
206 * CONN_IPC */ 269 int nofiles = 0;
270 int errflg = 0; /* option error */
271 int c; /* char from getopt */
272 int s; /* socket / msqid to server */
273 int connect_type; /* CONN_UNIX, CONN_INTERNET, or
274 * CONN_IPC */
207 int suppress_windows_system = 0; 275 int suppress_windows_system = 0;
208 char *display; 276 char *display;
209 #ifdef INTERNET_DOMAIN_SOCKETS 277 #ifdef INTERNET_DOMAIN_SOCKETS
210 char *hostarg = NULL; /* remote hostname */ 278 char *hostarg = NULL; /* remote hostname */
211 char thishost[HOSTNAMSZ]; /* this hostname */ 279 char *remotearg;
212 char remotepath[MAXPATHLEN+1]; /* remote pathname */ 280 char thishost[HOSTNAMSZ]; /* this hostname */
213 int rflg = 0; /* pathname given on cmdline */ 281 char remotepath[MAXPATHLEN+1]; /* remote pathname */
214 u_short portarg = 0; /* port to server */ 282 char *path;
215 char *ptr; /* return from getenv */ 283 int rflg = 0; /* pathname given on cmdline */
284 char *portarg;
285 u_short port = 0; /* port to server */
216 #endif /* INTERNET_DOMAIN_SOCKETS */ 286 #endif /* INTERNET_DOMAIN_SOCKETS */
217 #ifdef SYSV_IPC 287 #ifdef SYSV_IPC
218 struct msgbuf *msgp; /* message */ 288 struct msgbuf *msgp; /* message */
219 #endif /* SYSV_IPC */ 289 #endif /* SYSV_IPC */
220 char *tty; 290 char *tty;
221 char buffer[GSERV_BUFSZ+1]; /* buffer to read pid */ 291 char buffer[GSERV_BUFSZ + 1]; /* buffer to read pid */
292 char result[GSERV_BUFSZ + 1];
293 int i;
222 294
223 #ifdef INTERNET_DOMAIN_SOCKETS 295 #ifdef INTERNET_DOMAIN_SOCKETS
224 memset (remotepath, 0, sizeof (remotepath)); 296 memset (remotepath, 0, sizeof (remotepath));
225 #endif /* INTERNET_DOMAIN_SOCKETS */ 297 #endif /* INTERNET_DOMAIN_SOCKETS */
226 298
227 progname = argv[0]; 299 progname = strrchr (argv[0], '/');
300 if (progname)
301 ++progname;
302 else
303 progname = argv[0];
228 304
229 display = getenv ("DISPLAY"); 305 display = getenv ("DISPLAY");
230 if (!display) 306 if (!display)
231 suppress_windows_system = 1; 307 suppress_windows_system = 1;
232 308
233 while ((c = getopt (argc, argv, 309 for (i = 1; argv[i] && !errflg; i++)
234 310 {
311 if (*argv[i] != '-')
312 break;
313 if (!strcmp (argv[i], "-batch"))
314 batch = 1;
315 else if (!strcmp (argv[i], "-eval"))
316 {
317 if (!argv[++i])
318 {
319 fprintf (stderr, "%s: `-eval' must be followed by an argument\n",
320 progname);
321 exit (1);
322 }
323 eval_form = argv[i];
324 }
325 else if (!strcmp (argv[i], "-display"))
326 {
327 suppress_windows_system = 0;
328 if (!argv[++i])
329 {
330 fprintf (stderr, "%s: `-display' must be followed by an argument\n",
331 progname);
332 exit (1);
333 }
334 display = argv[i];
335 }
336 else if (!strcmp (argv[i], "-nw"))
337 suppress_windows_system = 1;
338 else
339 {
340 /* Iterate over one-letter options. */
341 char *p;
342 int over = 0;
343 for (p = argv[i] + 1; *p && !over; p++)
344 {
345 switch (*p)
346 {
347 case 'q':
348 quick = 1;
349 break;
350 case 'v':
351 view = 1;
352 break;
353 case 'f':
354 GET_ARGUMENT (eval_function, "-f");
355 break;
356 case 'l':
357 GET_ARGUMENT (load_library, "-l");
358 break;
235 #ifdef INTERNET_DOMAIN_SOCKETS 359 #ifdef INTERNET_DOMAIN_SOCKETS
236 "n:h:p:r:qv" 360 case 'h':
237 #else /* !INTERNET_DOMAIN_SOCKETS */ 361 GET_ARGUMENT (hostarg, "-h");
238 "n:qv" 362 break;
239 #endif /* !INTERNET_DOMAIN_SOCKETS */ 363 case 'p':
240 364 GET_ARGUMENT (portarg, "-p");
241 )) != EOF) 365 port = atoi (portarg);
242 switch (c) 366 break;
243 { 367 case 'r':
244 case 'n': 368 GET_ARGUMENT (remotearg, "-r");
245 if (*optarg == 'w') 369 strcpy (remotepath, remotearg);
246 suppress_windows_system++; 370 rflg = 1;
247 else 371 break;
248 errflg++;
249 break;
250 case 'q': /* quick mode specified */
251 qflg++;
252 break;
253 case 'v':
254 view++;
255 break;
256
257 #ifdef INTERNET_DOMAIN_SOCKETS
258 case 'h': /* server host name specified */
259 hostarg = optarg;
260 break;
261 case 'r': /* remote path from server specifed */
262 strcpy (remotepath,optarg);
263 rflg++;
264 break;
265 case 'p': /* port number specified */
266 portarg = atoi (optarg);
267 break;
268 #endif /* INTERNET_DOMAIN_SOCKETS */ 372 #endif /* INTERNET_DOMAIN_SOCKETS */
269 373 default:
270 case '?': 374 errflg = 1;
271 errflg++; 375 }
272 } /* switch */ 376 } /* for */
377 } /* else */
378 } /* for */
273 379
274 if (errflg) 380 if (errflg)
275 { 381 {
276 fprintf (stderr, 382 fprintf (stderr,
277 #ifdef INTERNET_DOMAIN_SOCKETS 383 #ifdef INTERNET_DOMAIN_SOCKETS
278 "usage: %s [-q] [-h hostname] [-p port] [-r pathname] " 384 "usage: %s [-nw] [-q] [-v] [-l library] [-f function] [-eval expr]\n"
385 " [-h host] [-p port] [-r file-name] [[+line] file] ...\n",
386 #else /* !INTERNET_DOMAIN_SOCKETS */
387 "usage: %s [-nw] [-q] [-v] [-l library] [-f function] [-eval expr] "
279 "[[+line] path] ...\n", 388 "[[+line] path] ...\n",
280 #else /* !INTERNET_DOMAIN_SOCKETS */
281 "usage: %s [-nw] [-q] [[+line] path] ...\n",
282 #endif /* !INTERNET_DOMAIN_SOCKETS */ 389 #endif /* !INTERNET_DOMAIN_SOCKETS */
283 progname); 390 progname);
284 exit (1); 391 exit (1);
285 } /* if */
286
287 if (suppress_windows_system)
288 {
289 tty = ttyname (0);
290 if (!tty)
291 {
292 fprintf (stderr, "%s: Not connected to a tty", progname);
293 exit (1);
294 }
295 } 392 }
296 /* This next stuff added in an attempt to make handling of the tty 393 if (batch && argv[i])
297 do the right thing when dealing with signals. The idea is to 394 {
298 pass all the appropriate signals to the emacs process. */ 395 fprintf (stderr, "%s: Cannot specify `-batch' with file names\n",
299
300 connect_type = make_connection (NULL, (u_short) 0, &s);
301
302 send_string (s, "(gnuserv-eval '(emacs-pid))");
303 send_string (s, EOT_STR);
304
305 if (read_line (s, buffer) == 0)
306 {
307 fprintf (stderr, "%s: Could not establish emacs procces id\n",
308 progname); 396 progname);
309 exit (1); 397 exit (1);
310 } 398 }
311 /* Don't do disconnect_from_server becasue we have already read 399 *result = '\0';
312 data, and disconnect doesn't do anything else. */ 400 if (eval_function || eval_form || load_library)
313 #ifdef SYSV_IPC 401 {
314 if (connect_type == (int) CONN_IPC) 402 #if defined(INTERNET_DOMAIN_SOCKETS)
315 disconnect_from_ipc_server (s, msgp, FALSE); 403 connect_type = make_connection (hostarg, port, &s);
404 #else
405 connect_type = make_connection (NULL, (u_short) 0, &s);
406 #endif
407 sprintf (command, "(gnuserv-eval%s '(progn ", quick ? "-quickly" : "");
408 send_string (s, command);
409 if (load_library)
410 {
411 sprintf (command, " (load-library %s)", clean_string (load_library));
412 send_string (s, command);
413 }
414 if (eval_form)
415 {
416 sprintf (command, " %s", eval_form);
417 send_string (s, command);
418 }
419 if (eval_function)
420 {
421 sprintf (command, " (%s)", eval_function);
422 send_string (s, command);
423 }
424 send_string (s, "))");
425 send_string (s, EOT_STR);
426 if (read_line (s, result) == 0)
427 {
428 fprintf (stderr, "%s: Could not read\n", progname);
429 exit (1);
430 }
431 } /* eval_function || eval_form || load_library */
432 else if (batch)
433 {
434 fprintf (stderr, "%s: `-batch' requires an evaluation\n",
435 progname);
436 exit (1);
437 }
438
439 if (!batch)
440 {
441 if (suppress_windows_system)
442 {
443 tty = ttyname (0);
444 if (!tty)
445 {
446 fprintf (stderr, "%s: Not connected to a tty", progname);
447 exit (1);
448 }
449 }
450
451 #if defined(INTERNET_DOMAIN_SOCKETS)
452 connect_type = make_connection (hostarg, port, &s);
453 #else
454 connect_type = make_connection (NULL, (u_short) 0, &s);
455 #endif
456
457 send_string (s, "(gnuserv-eval '(emacs-pid))");
458 send_string (s, EOT_STR);
459
460 if (read_line (s, buffer) == 0)
461 {
462 fprintf (stderr, "%s: Could not establish emacs procces id\n",
463 progname);
464 exit (1);
465 }
466 /* Don't do disconnect_from_server becasue we have already read
467 data, and disconnect doesn't do anything else. */
468 #ifndef INTERNET_DOMAIN_SOCKETS
469 if (connect_type == (int) CONN_IPC)
470 disconnect_from_ipc_server (s, msgp, FALSE);
316 #endif /* !SYSV_IPC */ 471 #endif /* !SYSV_IPC */
317 472
318 emacs_pid = (pid_t)atol(buffer); 473 emacs_pid = (pid_t)atol(buffer);
319 initialize_signals(); 474 initialize_signals();
320 475
321 #if defined(INTERNET_DOMAIN_SOCKETS) && !defined(GNUATTACH) 476 #if defined(INTERNET_DOMAIN_SOCKETS)
322 connect_type = make_connection (hostarg, portarg, &s); 477 connect_type = make_connection (hostarg, port, &s);
323 #else 478 #else
324 connect_type = make_connection (NULL, (u_short) 0, &s); 479 connect_type = make_connection (NULL, (u_short) 0, &s);
325 #endif 480 #endif
326 481
327 #ifdef INTERNET_DOMAIN_SOCKETS 482 #ifdef INTERNET_DOMAIN_SOCKETS
328 if (connect_type == (int) CONN_INTERNET) 483 if (connect_type == (int) CONN_INTERNET)
329 { 484 {
330 gethostname (thishost, HOSTNAMSZ); 485 char *ptr;
331 if (!rflg) 486 gethostname (thishost, HOSTNAMSZ);
332 { /* attempt to generate a path 487 if (!rflg)
488 { /* attempt to generate a path
333 * to this machine */ 489 * to this machine */
334 if ((ptr = getenv ("GNU_NODE")) != NULL) 490 if ((ptr = getenv ("GNU_NODE")) != NULL)
335 /* user specified a path */ 491 /* user specified a path */
336 strcpy (remotepath, ptr); 492 strcpy (remotepath, ptr);
337 } 493 }
338 #if 0 /* This is really bogus... re-enable it if you must have it! */ 494 #if 0 /* This is really bogus... re-enable it if you must have it! */
339 #if defined (hp9000s300) || defined (hp9000s800) 495 #if defined (hp9000s300) || defined (hp9000s800)
340 else if (strcmp (thishost,hostarg)) 496 else if (strcmp (thishost,hostarg))
341 { /* try /net/thishost */ 497 { /* try /net/thishost */
342 strcpy (remotepath, "/net/"); /* (this fails using internet 498 strcpy (remotepath, "/net/"); /* (this fails using internet
343 addresses) */ 499 addresses) */
344 strcat (remotepath, thishost); 500 strcat (remotepath, thishost);
345 } 501 }
346 #endif 502 #endif
347 #endif 503 #endif
348 } 504 }
349 else 505 else
350 { /* same machines, no need for path */ 506 { /* same machines, no need for path */
351 remotepath[0] = '\0'; /* default is the empty path */ 507 remotepath[0] = '\0'; /* default is the empty path */
352 } 508 }
353 #endif /* INTERNET_DOMAIN_SOCKETS */ 509 #endif /* INTERNET_DOMAIN_SOCKETS */
354 510
355 #ifdef SYSV_IPC 511 #ifdef SYSV_IPC
356 if ((msgp = (struct msgbuf *) 512 if ((msgp = (struct msgbuf *)
357 malloc (sizeof *msgp + GSERV_BUFSZ)) == NULL) 513 malloc (sizeof *msgp + GSERV_BUFSZ)) == NULL)
358 { 514 {
359 fprintf (stderr, "%s: not enough memory for message buffer\n", progname); 515 fprintf (stderr, "%s: not enough memory for message buffer\n", progname);
360 exit (1); 516 exit (1);
361 } /* if */ 517 } /* if */
362 518
363 msgp->mtext[0] = '\0'; /* ready for later strcats */ 519 msgp->mtext[0] = '\0'; /* ready for later strcats */
364 #endif /* SYSV_IPC */ 520 #endif /* SYSV_IPC */
365 521
366 if (suppress_windows_system) 522 if (suppress_windows_system)
367 { 523 {
368 ptr = getenv ("TERM"); 524 char *term = getenv ("TERM");
369 if (!ptr) 525 if (!term)
370 { 526 {
371 fprintf (stderr, "%s: unknown terminal type\n", progname); 527 fprintf (stderr, "%s: unknown terminal type\n", progname);
372 exit (1); 528 exit (1);
373 } 529 }
374 sprintf (command, 530 sprintf (command, "(gnuserv-edit-files '(tty %s %s %d) '(",
375 "(gnuserv-edit-files '(tty \"%s\" \"%s\" %d) '(", 531 clean_string (tty), clean_string (term), getpid ());
376 tty, ptr, getpid ()); 532 }
377 } 533 else /* !suppress_windows_system */
378 else /* !suppress_windows_system */ 534 {
379 { 535 sprintf (command, "(gnuserv-edit-files '(x %s) '(",
380 sprintf (command, "(gnuserv-edit-files '(x \"%s\") '(", 536 clean_string (display));
381 display); 537 } /* !suppress_windows_system */
382 } /* !suppress_windows_system */ 538 send_string (s, command);
383 send_string (s, command); 539
384 540 if (!argv[i])
385 if (!suppress_windows_system && (optind == argc)) 541 nofiles = 1;
386 qflg = 1; 542
387 543 for (; argv[i]; i++)
388 for (; optind < argc; optind++) 544 {
389 { 545 if (i < argc - 1 && *argv[i] == '+')
390 if (optind < argc - 1 && *argv[optind] == '+') 546 starting_line = atoi (argv[i++]);
391 starting_line = atoi (argv[optind++]); 547 else
392 else 548 starting_line = 1;
393 starting_line = 1; 549 /* If the last argument is +something, treat it as a file. */
394 /* If the last argument is +something, treat it as a file. */ 550 if (i == argc)
395 if (optind == argc) 551 {
396 { 552 starting_line = 1;
397 starting_line = 1; 553 --i;
398 --optind; 554 }
399 } 555 filename_expand (fullpath, argv[i]);
400 filename_expand (fullpath, argv[optind]);
401 sprintf (command, "(%d . \"%s%s\")", starting_line,
402 #ifdef INTERNET_DOMAIN_SOCKETS 556 #ifdef INTERNET_DOMAIN_SOCKETS
403 remotepath, 557 path = malloc (strlen (remotepath) + strlen (fullpath) + 1);
404 #else /* !INTERNET_DOMAIN_SOCKETS */ 558 sprintf (path, "%s%s", remotepath, fullpath);
405 "", 559 #else
406 #endif 560 path = malloc (strlen (fullpath));
407 fullpath); 561 strcpy (path, fullpath);
562 #endif
563 sprintf (command, "(%d . %s)", starting_line, clean_string (path));
564 send_string (s, command);
565 free (path);
566 } /* for */
567
568 sprintf (command, ")%s%s",
569 (quick || (nofiles && !suppress_windows_system)) ? " 'quick" : "",
570 view ? " 'view" : "");
408 send_string (s, command); 571 send_string (s, command);
409 } /* for */ 572 send_string (s, ")");
410
411 sprintf (command, ") %s)", qflg ? "'quick" : (view ? "'view" : ""));
412 send_string (s, command);
413 573
414 #ifdef SYSV_IPC 574 #ifdef SYSV_IPC
415 if (connect_type == (int) CONN_IPC) 575 if (connect_type == (int) CONN_IPC)
416 disconnect_from_ipc_server (s, msgp, FALSE); 576 disconnect_from_ipc_server (s, msgp, FALSE);
417 #else /* !SYSV_IPC */ 577 #else /* !SYSV_IPC */
418 if (connect_type != (int) CONN_IPC) 578 if (connect_type != (int) CONN_IPC)
419 disconnect_from_server (s, FALSE); 579 disconnect_from_server (s, FALSE);
420 #endif /* !SYSV_IPC */ 580 #endif /* !SYSV_IPC */
581 } /* not batch */
582
583 if (batch && !quick)
584 printf ("%s\n", result);
421 585
422 return 0; 586 return 0;
423 587
424 } /* main */ 588 } /* main */
425 589