-
Notifications
You must be signed in to change notification settings - Fork 0
/
cc.c
executable file
·4597 lines (3587 loc) · 158 KB
/
cc.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*static char *sccsid = "%Z% %M% %I% - %G% %U%";*/
/***************************************************************
*
* ARPUS/Ce text editor and terminal emulator modeled after the
* Apollo(r) Domain systems.
* Copyright 1988 - 2002 Enabling Technologies Group
* Copyright 2003 - 2005 Robert Styma Consulting
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* Original Authors: Robert Styma and Kevin Plyler
* Email: [email protected]
*
***************************************************************/
/***************************************************************
*
* module cc.c
*
* This module provides the cc (carbon copy) DM command and the routines
* it detect, identify, and syncronize the multiple copies of the editor
* open on the same file.
*
* The basic idea is that a cc open the display a second time and creates
* a new set of windows. The main window in each case is backed by the
* same memdata database. Other windows are independent.
* A separate display description is used for each set of windows.
*
* If someone types ce on a file from the command line for a file that is already
* open, routine initial_file_open calls the check other window routine to see
* if there is a ce session already open on this file. If so, a cc request is
* sent to the window which already has the file open.
*
* The information about what file a ce edit session has open, and about what
* control terminal and shell processes a ceterm session has open is put in a
* resource hung off the main window. The main windows on the screen are scanned
* for this information.
*
* Routines:
* cc_check_other_windows - check other windows to see if they are open on this file.
* cc_set_pad_mode - Set the cc configuration to pad mode.
* cc_register_file - register a file with the X server.
* dm_cc - perform the cc command
* cc_shutdown - Remove the cclist property from the WM window
* cc_get_update - process an update sent via property change from another window
* cc_plbn - send a line as a result of a PutLine_By_Number
* cc_ca - Tranmit color impacts to other displays
* cc_dlbn - Tell the other windows to delete a line (Delete Line By Number)
* cc_joinln - Flush cc windows prior to a join
* cc_titlebar - Tell the other windows about a titlebar change
* cc_line_chk - Check if a line to be processed is already in use
* cc_typing_chk - Update typing on a CC screens
* cc_padname - Tell the other windows about a pad_name command
* cc_ttyinfo_send - Send the slave tty name in pad mode to the main process
* cc_ttyinfo_receive - Receive the slave tty name from cc_ttyinfo_send and save in the CC_LIST
* ce_gethostid - Get the Internet host id
* cc_xdmc - Send a dm command to a window.
* cc_debug_cclist_data - Print this windows cc_list info
* ccdump - Print the cc_list (called from xdmc.c)
* cc_to_next - Move to the next window.
* cc_icon - Flag the window iconned or not iconned
* cc_is_iconned - Check if the window is iconned
* cc_obscured - Mark a window obscurred or non-obscurred
* cc_receive_cc_request - Process a request to cc sent via property change from another window
* send_api_stats - Send current stats to the ceapi
* dm_delcc - Delete the cc list
*
* Internal:
* get_cclist_data - Read the CC list property for this window
* put_cclist_data - Write the CC list property for this window
* chk_cclist_data - Validate that a window manager window has good cclist data
* child_of_root - Find the window which is a child of the root window
* check_atoms - Make sure we have all the atoms we need to get.
* adjust_tty_inode - Special manipulation on the tty inode
* dumpcc - Dump all the cclist data hung off the main window.
* dump_saved_cmd - Dump the window manager saved command and machine
* dump_cc_data - Dump the sessions manager saved command
*
*
* OVERVIEW of CC operations:
* When Ce comes up it checks to see if there is another edit session open on
* this file (details later). If this is false, as part of start up it registers
* the file in a property hung off the immeditate child of the root window named
* which contains the main window. The property's name is CE_CCLIST. The
* format of the property is described in structure CC_LIST.
*
* If Ce checks the window list and finds this file is being edited by another Ce
* Ce session, it sets a property on the first window which has the file open to
* request a cc. The value put into
* the property is the cc command which would be entered to achieve the desired result.
*
*
*
***************************************************************/
#include <stdio.h> /* /usr/include/stdio.h */
#include <string.h> /* /usr/include/string.h */
#include <errno.h> /* /usr/include/errno.h /usr/include/sys/errno.h */
#include <ctype.h> /* /usr/include/ctype.h */
#include <stdlib.h>
#include <sys/types.h> /* /usr/include/sys/types.h */
#ifdef OMVS
typedef unsigned short ushort;
#endif
#include <sys/stat.h> /* /usr/include/sys/types.h */
#include <time.h>
#ifndef WIN32
#include <netinet/in.h> /* /usr/include/netinet/in.h */
#include <unistd.h> /* /usr/include/unistd.h */
#ifndef OMVS
#include <arpa/inet.h> /* /usr/include/arpa/inet.h */
#endif
#include <sys/socket.h> /* /usr/include/sys/socket.h */
#include <netdb.h> /* /usr/include/netdb.h */
#include <fcntl.h> /* /usr/include/fcntl.h */
#else
#include <winsock.h>
#include <time.h>
#include <process.h>
#endif
#include <signal.h> /* /usr/include/signal.h */
#include <limits.h> /* /usr/include/limits.h */
#ifndef MAXPATHLEN
#define MAXPATHLEN 1024
#endif
#ifdef WIN32
#define GETPGRP(a) _getpid()
#define GETPPID(a) _getpid()
#define getuid() -1
#else
#define GETPPID(a) getppid()
#define GETPGRP(a) getpgrp()
#endif
/***************************************************************
*
* PGM_XDMC is defined in xdmc.c which includes this entire
* .c file.
*
***************************************************************/
#ifndef PGM_XDMC
#include "apistats.h"
#endif
#include "cc.h"
#include "netlist.h"
#ifndef PGM_XDMC
#include "dmwin.h"
#include "dmsyms.h"
#include "display.h"
#include "emalloc.h"
#include "getevent.h"
#include "getxopts.h"
#include "hsearch.h"
#include "ind.h"
#include "init.h"
#include "kd.h" /* needed for HASH_SIZE */
#include "mvcursor.h"
#include "pad.h"
#include "parms.h"
#include "parsedm.h"
#include "pastebuf.h"
#include "pw.h" /* needed for STDIN_FILE_STRING */
#include "redraw.h"
#include "sendevnt.h"
#include "serverdef.h"
#include "txcursor.h"
#include "typing.h" /* needed for flush */
#include "undo.h"
#include "window.h"
#include "windowdefs.h"
#include "winsetup.h"
#endif
#include "xerror.h"
#include "xerrorpos.h"
#include "hexdump.h"
/***************************************************************
*
* When compiled for xdmc we do not use the fancy malloc nor
* do we use dm_error.
*
***************************************************************/
#ifdef PGM_XDMC
#define CE_MALLOC(size) malloc(size)
#define dm_error(m,j) fprintf(stderr, "%s\n", m)
#define CE_PROPERTY(a) a
static Atom ce_cc_line_atom = 0;
static Atom ce_cc_atom = 0;
static Atom ce_cclist_atom = 0;
static Atom ce_cc_visibility_atom = 0;
#else
#define CE_PROPERTY(a) dspl_descr->properties->a
#endif
#if !defined(IBMRS6000) && !defined(linux)
void sleep(int secs);
void usleep(int usecs);
#endif
/*void srand(int seed); remove for freebsd, can't see where this is needed */
/*int rand(void); remove for freebsd, can't see where this is needed */
#ifndef WIN32
char *ttyname(int fd);
#endif
/***************************************************************
*
* Structure used to describe the CC_LIST property saved in the
* server. These are all 4 type (32 bit) quantities, we let
* the X server do the big endian/little endian conversions.
*
* Window_lcl is defined for the DEC Alpha where Window is 8
* bytes long but only the low 4 are used.
*
***************************************************************/
#ifdef WIN32
#define Window_lcl Window
#else
typedef unsigned int Window_lcl;
#endif
#define CC_LIST_VERSION 1
/* Value of CC_LIST_VERSION is 0 */
typedef struct {
unsigned int dev; /* device id for the file */
unsigned int inode; /* inode number for the file */
unsigned int host_id; /* 4 part internet id of the host */
unsigned int uid; /* uid of the person opening the file */
Window_lcl main_window; /* main window for the session */
int shpid; /* pid of shell run from a ceterm */
int shgrp; /* pgrp of shell run from a ceterm */
int pgrp; /* process group id for pid */
int cepid; /* pid of ce or ceterm */
int obscured; /* True if window is partially or fully obscured */
int iconned; /* True if window is unmapped, iconned */
unsigned short version; /* CC_LIST structure version number = 1 */
unsigned short display_no; /* Display number */
Window_lcl wm_window; /* window manager window for the session*/
unsigned int create_time; /* Create time for file */
unsigned int file_size; /* Current disk file size */
} CC_LIST;
/***************************************************************
*
* Structure used to send a put line to other windows.
* total_lines_infile is used to make deletes are idempotent.
*
* Ints are stored in the server using htonl (network order).
*
***************************************************************/
typedef struct {
int msg_len; /* len of this message, is padded to mult of 4 */
int lineno; /* line to be replaced, deleted, or inserted after */
short int type; /* one of the below constants (CMD_XDMC or CMD_TOWINDOW)*/
short int count; /* count of lines to be deleted for DELLINE (always 1) */
int total_lines_infile; /* total lines for the file at this time. */
char line[4]; /* the array */
} CC_MSG;
#define CMD_XDMC 1
#define CMD_TOWINDOW 2
#define CMD_PING 3
/***************************************************************
*
* List of cc windows known to this routine. Includes current session.
*
***************************************************************/
#define MAX_CC_WINDOWS 100
#define MAX_CCLIST_TRIES 3
#define MAX_CCLIST_LOOPS 30
#define PAD_MODE_DEV -1
#define PAD_MODE_INODE -1
#define PAD_MODE_HASH -1
static unsigned int saved_dev = (unsigned)PAD_MODE_DEV;
static unsigned int saved_inode = (unsigned)PAD_MODE_INODE;
static unsigned int saved_host_id = (unsigned)PAD_MODE_HASH;
static unsigned int saved_create_time = 0;
static unsigned int saved_file_size = 0;
/*static int this_shpid; RES 6/27/95 get rid of lint msg */
#define MAX_CC_ARGS 256
#define MASK_4 (UINT_MAX & (UINT_MAX << 2))
#define ROUND4(n) ((n + 3) & MASK_4)
/***************************************************************
*
* Atoms for communicating with other windows
* CE_CC_LINE is the property used to pass off line updates to
* other windows. Properties are hung off CE windows.
* CE_CC is the property used to pass a cc request to
* another window. This is done during initialization.
* This property is humg off the CE window of the
* session we are requesting to do a CC
* CE_CCLIST is used as a selection and a property to keep a list
* of the CE edit sessions currently in use. This
* property is hung off the root window.
* CE_CC_VISIBILITY is exists on the main window for the ce
* session. It contains the flags showing whether the
* window is iconned or obscured.
*
* The atom declarations are held in the cc.h file since they are
* needed in the main event loop.
*
***************************************************************/
#define CE_CC_LINE_ATOM_NAME "CE_CC_LINE"
#define CE_CC_ATOM_NAME "CE_CC"
#define CE_CCLIST_ATOM_NAME "CE_CCLIST"
#define CE_CC_VISIBILITY_ATOM_NAME "CE_CC_VISIBILITY"
/***************************************************************
*
* System routines which have no built in defines
*
***************************************************************/
char *getenv(const char *name);
int fork(void);
int getpid(void);
#if !defined(_XOPEN_SOURCE_EXTENDED) && !defined(linux)
int setpgrp(int pid, int pgrp); /* bsd version */
#endif
int isatty(int fd);
#if !defined(WIN32) && !defined(_XOPEN_SOURCE_EXTENDED) && !defined(linux)
int gethostname(char *target, int size);
#endif
/***************************************************************
*
* Local prototypes
*
***************************************************************/
static CC_LIST *get_cclist_data(Display *display,
Window wm_window,
int *new);
static void put_cclist_data(Display *display,
Window wm_window,
CC_LIST *buff);
static int chk_cclist_data(Display *display,
Window wm_window,
Window main_window);
static Window child_of_root(Display *display,
Window window);
static void check_atoms(Display *display);
#ifndef PGM_XDMC
static ino_t adjust_tty_inode(char *slave_tty_name,
ino_t inode);
#endif
#if defined(DebuG) || defined(PGM_XDMC)
static void dump_cc_data(char *buff,
int buff_len,
Window wm_window,
FILE *stream);
#endif
#if defined(DebuG) || defined(PGM_XDMC)
static void dump_saved_cmd(Display *display,
Window ce_window,
FILE *stream);
#endif
#ifdef CE_LITTLE_ENDIAN
static void to_net_cc_list(CC_LIST *buff,
int len);
static void to_host_cc_list(CC_LIST *buff,
int len);
#endif
#ifndef PGM_XDMC
/************************************************************************
NAME: cc_check_other_windows - check other windows to see if they are open on this file.
PURPOSE: This routine detects if the passed file is already open in another window
and signals that window to do the cc.
NOTE: This routine is always called first, before any other routines in this module.
The exception is pad mode, when this routine does not get called at all.
PARAMETERS:
1. stat_buff - pointer to (struct stat) (INPUT)
This is a stat buff for the passed edit file.
It so happens that the routine with calls this routine
(intial_file_open), has already done a stat. There is
no point in pretending we are Interleaf and doing extra stats.
2. dspl_descr - pointer to DISPLAY_DESCR (INPUT)
This is the current display description.
3. writable - int (INPUT)
This flag is true if the open it to be writable.
GLOBAL DATA:
saved_dev - int (OUTPUT)
The device number is saved globally
saved_inode - int (OUTPUT)
The inode number is saved globally
saved_host_id - int (OUTPUT)
The host net id is saved.
saved_create_time - int (OUTPUT)
The create_time from the stat buff is saved
saved_file_size - int (OUTPUT)
The file size from the stat buff is saved
FUNCTIONS :
1. Get the host name from the system.
2. Build the file key from the device and inode of the file and the
hashed host name and the users uid.
3. Save the device, inode, create_time, file size, and host_id
in the area global to this module.
4. Get the CC_LIST property off the root window of the server. If it
does not exist, we are done.
5. Scan the cc list to see if this file exists there. If not, we are done.
6. If the file exist there but is opened under another uid, flag an error
and return. We will have to bail out.
7. Build the cc command into a string and attempt to append it to the
CE_CC_REQUEST property on the window from the cc list. Flush the X queue and
reread the property. This will trigger a bad window error which we
trap (in xerror.c) and let us know the window has gone away.
9. If the window is good, sleep 4 seconds and reread the property. The window
list should have changed in size or content. If not, the there is
something wrong with the server? Or could the window be icon'ed.
This will have to be tried out. If the list changes as expected,
exit the program, control has been passed to the other window.
RETURNED VALUE:
If a match is found, this routine does not return.
rc - return code
0 - No match found
-1 - Error detected, message already output. must abort.
*************************************************************************/
int cc_check_other_windows(struct stat *file_stats,
DISPLAY_DESCR *dspl_descr,
int writable)
{
int i;
int window_idx;
Atom actual_type;
int actual_format;
int keydef_property_size;
unsigned long nitems;
unsigned long bytes_after;
char *buff = NULL;
CC_LIST *buff_pos;
char *buff2 = NULL;
char cmd[1024];
Window root_return;
Window parent_return;
Window *child_windows = NULL;
unsigned int nchildren;
char *p;
int argc;
char *argv[256];
char arg0[10];
/***************************************************************
*
* Make sure all the atoms are defined.
* Save the device, inode, and hashed host name for the
* file being edited.
*
* We set this_window to the root window until cc_register_file
* sets it to the window we will create. So far we do not
* have a window to use. This value only gets used in the
* case of bad_window errors.
*
***************************************************************/
check_atoms(dspl_descr->display);
saved_dev = file_stats->st_dev;
saved_inode = file_stats->st_ino;
saved_host_id = ce_gethostid();
saved_create_time = file_stats->st_ctime;
saved_file_size = file_stats->st_size;
DEBUG18(
fprintf(stderr, "@cc_check_other_windows: file id: 0x%X 0x%X 0x%X 0x%X %d\n",
saved_dev, saved_inode, saved_host_id, saved_create_time, saved_file_size);
)
/***************************************************************
*
* See if there is another window open on the file and try
* to signal it if there is.
* 1. Get the current list windows.
* 2. Get the cclist property from each window and see if it matches.
*
***************************************************************/
DEBUG9(XERRORPOS)
if (!XQueryTree(dspl_descr->display, /* input */
RootWindow(dspl_descr->display, DefaultScreen(dspl_descr->display)), /* input */
&root_return, /* output */
&parent_return, /* output */
&child_windows, /* output */
&nchildren)) /* output */
{
dm_error("Could not get window list from server", DM_ERROR_BEEP);
return(0);
}
for (window_idx = 0; window_idx < (int)nchildren; window_idx++)
{
/***************************************************************
* buff may be dirty from a previous loop
***************************************************************/
if (buff)
{
XFree(buff);
buff = NULL;
}
/***************************************************************
* Deal with windows which have just gone away.
***************************************************************/
ce_error_bad_window_flag = False;
ce_error_generate_message = False;
DEBUG9(XERRORPOS)
XGetWindowProperty(dspl_descr->display,
child_windows[window_idx],
CE_PROPERTY(ce_cclist_atom),
0, /* offset zero from start of property */
INT_MAX / 4,
False, /* do not delete the property */
AnyPropertyType,
&actual_type,
&actual_format,
&nitems,
&bytes_after,
(unsigned char **)&buff);
keydef_property_size = nitems * (actual_format / 8);
if (ce_error_bad_window_flag || (keydef_property_size != sizeof(CC_LIST)))
{
DEBUG18(
if (ce_error_bad_window_flag)
fprintf(stderr, "Can't use window 0x%X, Bad window\n", child_windows[window_idx]);
else
if (keydef_property_size == 0)
fprintf(stderr, "Can't use window 0x%X, Not registered as Ce\n", child_windows[window_idx]);
else
fprintf(stderr, "Can't use window 0x%X, Property wrong size, is %d, should be %d\n", child_windows[window_idx], keydef_property_size, sizeof(CC_LIST));
)
continue;
}
else
buff_pos = (CC_LIST *)buff;
DEBUG9(XERRORPOS)
DEBUG18(
if (actual_type != None)
p = XGetAtomName(dspl_descr->display, actual_type);
else
p = "None";
fprintf(stderr, "cc_check_other_windows: Window = 0x%X, Size = %d, actual_type = %d (%s), actual_format = %d, nitems = %d, &bytes_after = %d\n",
child_windows[window_idx],
keydef_property_size, actual_type, p,
actual_format, nitems, bytes_after);
if (actual_type != None)
XFree(p);
)
#ifdef CE_LITTLE_ENDIAN
to_host_cc_list(buff_pos, keydef_property_size);
#endif
/***************************************************************
* See if this window is the one we want.
***************************************************************/
DEBUG18(dump_cc_data(buff, keydef_property_size, child_windows[window_idx], stderr);)
if (buff_pos->version == 0) /* Ce Release 2.3 and 2.3.1 */
{
if ((buff_pos->dev != file_stats->st_dev) || (buff_pos->inode != file_stats->st_ino) || (buff_pos->host_id != saved_host_id))
continue;
}
else
{
if ((buff_pos->inode != file_stats->st_ino) ||
(buff_pos->create_time != saved_create_time) ||
(buff_pos->file_size != saved_file_size))
continue;
}
DEBUG18(
fprintf(stderr, "cc_check_other_windows: Found window for dev 0x%X inode 0x%X host 0x%X ctime 0x%X size %d\n",
file_stats->st_dev, file_stats->st_ino, saved_host_id, buff_pos->create_time, buff_pos->file_size);
)
if (chk_cclist_data(dspl_descr->display, child_windows[window_idx], buff_pos->main_window) == False)
continue;
#ifndef WIN32
/***************************************************************
* Make sure the uid matches.
***************************************************************/
if (buff_pos->uid != getuid())
{
dm_error("File is open under another userid", DM_ERROR_BEEP);
return(-1);
}
#endif
/***************************************************************
* Get the args we need to use
***************************************************************/
arg0[0] = 'c';
if (writable)
arg0[1] = 'e';
else
arg0[1] = 'v';
arg0[2] = '\0';
build_cmd_args(dspl_descr,
"",
arg0,
&argc,
argv);
/***************************************************************
* Build the cc command
***************************************************************/
cmd[0] = 'c';
if (writable)
cmd[1] = 'e';
else
cmd[1] = 'v';
cmd[2] = ' ';
cmd[3] = '\0';
p = &cmd[3];
for (i = 1; i < argc; i++)
{
if (argv[i][0] != '\0')
if (argv[i][0] == '-')
snprintf(p, (sizeof(cmd)-(p-cmd))," %s", argv[i]);
else
snprintf(p, (sizeof(cmd)-(p-cmd)), " \"%s\"", argv[i]);
p += strlen(p);
}
DEBUG18(fprintf(stderr, "cc_check_other_windows: sending cmd '%s'\n", cmd);)
/***************************************************************
* Send the property to the other window.
***************************************************************/
ce_error_bad_window_flag = False;
ce_error_generate_message = False;
DEBUG18(ce_error_generate_message = True;)
DEBUG9(XERRORPOS)
XChangeProperty(dspl_descr->display,
buff_pos->main_window,
CE_PROPERTY(ce_cc_atom),
XA_STRING,
8, /* 8 bit quantities, we handle littleendin ourselves */
PropModeAppend,
(unsigned char *)cmd,
strlen(cmd)+1);
XFlush(dspl_descr->display);
/***************************************************************
* Reread the property, or trap the error check to see if the
* badwindow flag went on, It is set in xerror.c. If so,
* this window just went away. Skip it. Otherwise, we have
* just sent the cc request to the file. We are done.
***************************************************************/
DEBUG9(XERRORPOS)
XGetWindowProperty(dspl_descr->display,
buff_pos->main_window,
CE_PROPERTY(ce_cc_atom),
0, /* offset zero from start of property */
INT_MAX / 4,
False, /* do not delete the property */
XA_STRING,
&actual_type,
&actual_format,
&nitems,
&bytes_after,
(unsigned char **)&buff2);
if (!ce_error_bad_window_flag)
{
DEBUG(fprintf(stderr, "Passing cc off to window 0x%X WM window 0x%X and exiting\n", buff_pos->main_window, child_windows[window_idx]);)
exit(0);
}
else
{
DEBUG18(fprintf(stderr, "Bad window flag was true for window 0x%X WM window 0x%X\n", buff_pos->main_window, child_windows[window_idx]);)
}
/***************************************************************
* Free up storage allocated.
***************************************************************/
if (buff)
{
XFree(buff);
buff = NULL;
}
if (buff2)
{
XFree(buff2);
buff = NULL;
}
} /* for in the list of child windows off the Root window */
ce_error_generate_message = True;
if (child_windows)
{
XFree((char *)child_windows);
buff = NULL;
}
return(0);
} /* end of cc_check_other_windows */
/************************************************************************
NAME: cc_set_pad_mode - Set variables to show we are in pad mode
PURPOSE: This routine takes care of showing we are in pad mode.
It sets the device and inode numbers to their default values.
It is required when doing a cp from an edit session.
Note: for pad mode, this routine is called in place of cc_check_other_windows
PARAMETERS:
1. display - pointer to Display (INPUT)
This is the display handle needed for X calls.
GLOBAL DATA:
saved_dev - int (INPUT)
The device number of the file being edited is used.
saved_inode - int (INPUT)
The inode number of the file being edited is used.
saved_host_id - int (INPUT)
The internet id of the host of the file being edited is used.
FUNCTIONS :
1. Set the global variables to their default values.
*************************************************************************/
void cc_set_pad_mode(Display *display)
{
check_atoms(display);
saved_dev = (unsigned int)PAD_MODE_DEV;
saved_inode = (unsigned int)PAD_MODE_INODE;
saved_host_id = ce_gethostid();
saved_create_time = (unsigned int)time(NULL);
saved_file_size = 0;
DEBUG18(
fprintf(stderr, "@cc_set_pad_mode: file id: 0x%X 0x%X 0x%X 0x%X %d\n",
saved_dev, saved_inode, saved_host_id, saved_create_time, saved_file_size);
)
} /* end of cc_set_pad_mode */
/************************************************************************
NAME: cc_register_file - register a file with the X server.
PURPOSE: This routine takes care of registering a file with the X server.
PARAMETERS:
1. dspl_descr - pointer to DISPLAY_DESCR (INPUT/OUTPUT)
This is the display description being set up.
2. main_window - Window (INPUT - Xlib type)
This is the window to be registered. It is the main window for
the ce session.
3. shell_pid - int (INPUT)
This is the process id of the shell process started by a ceterm.
For non ceterm runs, zero is passed.
GLOBAL DATA:
saved_dev - int (INPUT)
The device number of the file being edited is used.
saved_inode - int (INPUT)
The inode number of the file being edited is used.
saved_host_id - int (INPUT)
The network id of the host of the file being edited is used.
FUNCTIONS :
1. Save the main window in the variable global to this module.
2. Call the routine to update the CC_LIST adding a window.
3. Put this window in the window list.
RETURNED VALUE:
An X error which prevents saving the property causes a non-zero returned value.
*************************************************************************/
int cc_register_file(DISPLAY_DESCR *dspl_descr,
int shell_pid,
char *edit_file)
{
int rc;
int new;
CC_LIST *buff_pos;
/***************************************************************
*
* In pad mode, cc_check_other_windows is never called.
* we use the special dev name and the inode is the pid.
*
***************************************************************/
if (strcmp(edit_file, STDIN_FILE_STRING) == 0) /* takes care of stdin */
{
saved_inode = getpid();
saved_host_id = ce_gethostid();
saved_create_time = (unsigned int)time(NULL);
}
/*this_shpid = shell_pid; RES 6/27/95 get rid of lint msg */
DEBUG18(
fprintf(stderr, "@cc_register_file: file id: 0x%X 0x%X 0x%X 0x%X %d shell pid = %d\n",
saved_dev, saved_inode, saved_host_id, saved_create_time, saved_file_size, shell_pid);
)
dspl_descr->wm_window = child_of_root(dspl_descr->display, dspl_descr->main_pad->x_window);
DEBUG18(
fprintf(stderr, "cc_register_file: window 0x%X, FILE ID: 0x%X 0x%X 0x%X 0x%X %d - WM window 0x%X\n",
dspl_descr->main_pad->x_window, saved_dev, saved_inode, saved_host_id,
saved_create_time, saved_file_size, dspl_descr->wm_window);
)
buff_pos = get_cclist_data(dspl_descr->display, dspl_descr->wm_window, &new);
if (buff_pos)
{
buff_pos->dev = saved_dev;
buff_pos->inode = saved_inode;
buff_pos->host_id = saved_host_id;
buff_pos->create_time = saved_create_time;
buff_pos->file_size = saved_file_size;
buff_pos->uid = getuid();
buff_pos->main_window = dspl_descr->main_pad->x_window;
buff_pos->shpid = shell_pid;
buff_pos->shgrp = GETPGRP(shell_pid);
buff_pos->pgrp = GETPGRP(0);
buff_pos->cepid = getpid();
buff_pos->display_no = dspl_descr->display_no;
buff_pos->version = CC_LIST_VERSION;
buff_pos->wm_window = dspl_descr->wm_window;
buff_pos->iconned = (dspl_descr->currently_mapped == 0);
put_cclist_data(dspl_descr->display, dspl_descr->wm_window, buff_pos);
if (new)
free((char *)buff_pos);
else
XFree((char *)buff_pos);
rc = 0;
}
else
rc = -1;
#ifdef blah
/**************** DEBUG START *************************/
{
Atom ws_atom;
Atom actual_type;
int actual_format;
int property_size;
int i;
unsigned long nitems;
unsigned long bytes_after;
char *buff = NULL;
char *p = NULL;
FILE *cedump = NULL;
char name[50];
snprintf(name, sizeof(name), "/tmp/cedump.%d", getpid());
cedump = fopen(name, "w");
DEBUG9(XERRORPOS)
ws_atom = XInternAtom(dspl_descr->display, "_DT_WORKSPACE_PRESENCE", True);
if (ws_atom != None)
{
fprintf(cedump, "\n _DT_WORKSPACE_PRESENCE is %d\n", ws_atom);
DEBUG9(XERRORPOS)
XGetWindowProperty(dspl_descr->display,
dspl_descr->main_pad->x_window,
ws_atom,
0, /* offset zero from start of property */
INT_MAX / 4,
False, /* do not delete the property */
AnyPropertyType,
&actual_type,
&actual_format,
&nitems,