00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00040
00041
00042 #include "midas.h"
00043 #include "msystem.h"
00044
00045 #ifdef OS_UNIX
00046 #include <sys/mount.h>
00047 #endif
00048
00049 static INT ss_in_async_routine_flag = 0;
00050 #ifdef LOCAL_ROUTINES
00051 #include <signal.h>
00052
00053
00054
00055
00056
00057 BOOL disable_shm_write = FALSE;
00058
00059
00060 INT ss_set_async_flag(INT flag)
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080 {
00081 INT old_flag;
00082
00083 old_flag = ss_in_async_routine_flag;
00084 ss_in_async_routine_flag = flag;
00085 return old_flag;
00086 }
00087
00088 #ifdef OS_UNIX
00089
00090 #define OS_UNIX_SHM 1
00091 #endif
00092
00093 #ifdef OS_UNIX_MMAP
00094
00095 #include <sys/mman.h>
00096
00097 #define MAX_MMAP 100
00098 static void *mmap_addr[MAX_MMAP];
00099 static int mmap_size[MAX_MMAP];
00100
00101 #endif
00102
00103
00104 INT ss_shm_open(char *name, INT size, void **adr, HNDLE *handle, BOOL get_size)
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131 {
00132 INT status;
00133 char mem_name[256], file_name[256], path[256];
00134
00135
00136 sprintf(mem_name, "SM_%s", name);
00137
00138
00139 cm_get_path(path);
00140 if (path[0] == 0) {
00141 getcwd(path, 256);
00142 #if defined(OS_VMS)
00143 #elif defined(OS_UNIX)
00144 strcat(path, "/");
00145 #elif defined(OS_WINNT)
00146 strcat(path, "\\");
00147 #endif
00148 }
00149
00150 strcpy(file_name, path);
00151 #if defined (OS_UNIX)
00152 strcat(file_name, ".");
00153 #endif
00154 strcat(file_name, name);
00155 strcat(file_name, ".SHM");
00156
00157 #ifdef OS_WINNT
00158
00159 status = SS_SUCCESS;
00160
00161 {
00162 HANDLE hFile, hMap;
00163 char str[256], *p;
00164 DWORD file_size;
00165
00166
00167
00168
00169
00170 strcpy(str, path);
00171
00172
00173 while (strpbrk(str, "\\: "))
00174 *strpbrk(str, "\\: ") = '*';
00175 strcat(str, mem_name);
00176
00177
00178 p = str;
00179 while (*p)
00180 *p++ = (char) toupper(*p);
00181
00182 hMap = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, str);
00183 if (hMap == 0) {
00184 hFile = CreateFile(file_name, GENERIC_READ | GENERIC_WRITE,
00185 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
00186 OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
00187 if (!hFile) {
00188 cm_msg(MERROR, "ss_shm_open", "CreateFile() failed");
00189 return SS_FILE_ERROR;
00190 }
00191
00192 file_size = GetFileSize(hFile, NULL);
00193 if (get_size) {
00194 if (file_size != 0xFFFFFFFF && file_size > 0)
00195 size = file_size;
00196 } else {
00197 if (file_size != 0xFFFFFFFF && file_size > 0 && file_size != size) {
00198 cm_msg(MERROR, "ss_shm_open", "Requested size (%d) differs from existing size (%d)",
00199 size, file_size);
00200 return SS_SIZE_MISMATCH;
00201 }
00202 }
00203
00204 hMap = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, size, str);
00205
00206 if (!hMap) {
00207 status = GetLastError();
00208 cm_msg(MERROR, "ss_shm_open", "CreateFileMapping() failed, error %d", status);
00209 return SS_FILE_ERROR;
00210 }
00211
00212 CloseHandle(hFile);
00213 status = SS_CREATED;
00214 }
00215
00216 *adr = MapViewOfFile(hMap, FILE_MAP_ALL_ACCESS, 0, 0, 0);
00217 *handle = (HNDLE) hMap;
00218
00219 if (adr == NULL) {
00220 cm_msg(MERROR, "ss_shm_open", "MapViewOfFile() failed");
00221 return SS_NO_MEMORY;
00222 }
00223
00224 return status;
00225 }
00226
00227 #endif
00228 #ifdef OS_VMS
00229
00230 status = SS_SUCCESS;
00231
00232 {
00233 int addr[2];
00234 $DESCRIPTOR(memname_dsc, "dummy");
00235 $DESCRIPTOR(filename_dsc, "dummy");
00236 memname_dsc.dsc$w_length = strlen(mem_name);
00237 memname_dsc.dsc$a_pointer = mem_name;
00238 filename_dsc.dsc$w_length = strlen(file_name);
00239 filename_dsc.dsc$a_pointer = file_name;
00240
00241 addr[0] = size;
00242 addr[1] = 0;
00243
00244 status = ppl$create_shared_memory(&memname_dsc, addr, &PPL$M_NOUNI, &filename_dsc);
00245
00246 if (status == PPL$_CREATED)
00247 status = SS_CREATED;
00248 else if (status != PPL$_NORMAL)
00249 status = SS_FILE_ERROR;
00250
00251 *adr = (void *) addr[1];
00252 *handle = 0;
00253
00254 if (adr == NULL)
00255 return SS_NO_MEMORY;
00256
00257 return status;
00258 }
00259
00260 #endif
00261 #ifdef OS_UNIX_SHM
00262
00263 status = SS_SUCCESS;
00264
00265 {
00266 int key, shmid, fh, file_size;
00267 struct shmid_ds buf;
00268
00269
00270 key = ftok(file_name, 'M');
00271
00272
00273 if (key == -1) {
00274 fh = open(file_name, O_CREAT | O_TRUNC | O_BINARY | O_RDWR, 0644);
00275 if (fh > 0) {
00276 ftruncate(fh, size);
00277 close(fh);
00278 }
00279 key = ftok(file_name, 'M');
00280
00281 if (key == -1) {
00282 cm_msg(MERROR, "ss_shm_open", "ftok() failed");
00283 return SS_FILE_ERROR;
00284 }
00285
00286 status = SS_CREATED;
00287
00288
00289
00290 shmid = shmget(key, 0, 0);
00291 shmctl(shmid, IPC_RMID, &buf);
00292 } else {
00293
00294 file_size = (INT) ss_file_size(file_name);
00295 if (get_size) {
00296 size = file_size;
00297 } else if (size != file_size) {
00298 cm_msg(MERROR, "ss_shm_open", "Existing file \'%s\' has size %d, different from requested size %d", file_name, file_size, size);
00299 return SS_SIZE_MISMATCH;
00300 }
00301 }
00302
00303
00304 shmid = shmget(key, size, 0);
00305 if (shmid == -1) {
00306
00307 shmid = shmget(key, size, IPC_CREAT | IPC_EXCL);
00308 if (shmid == -1 && errno == EEXIST) {
00309 cm_msg(MERROR, "ss_shm_open",
00310 "Shared memory segment with key 0x%x already exists, please remove it manually: ipcrm -M 0x%x",
00311 key, key);
00312 return SS_NO_MEMORY;
00313 }
00314 status = SS_CREATED;
00315 }
00316
00317 if (shmid == -1) {
00318 cm_msg(MERROR, "ss_shm_open", "shmget(key=0x%x,size=%d) failed, errno %d (%s)",
00319 key, size, errno, strerror(errno));
00320 return SS_NO_MEMORY;
00321 }
00322
00323 memset(&buf, 0, sizeof(buf));
00324 buf.shm_perm.uid = getuid();
00325 buf.shm_perm.gid = getgid();
00326 buf.shm_perm.mode = 0666;
00327 shmctl(shmid, IPC_SET, &buf);
00328
00329 *adr = shmat(shmid, 0, 0);
00330 *handle = (HNDLE) shmid;
00331
00332 if ((*adr) == (void *) (-1)) {
00333 cm_msg(MERROR, "ss_shm_open", "shmat(shmid=%d) failed, errno %d (%s)", shmid,
00334 errno, strerror(errno));
00335 return SS_NO_MEMORY;
00336 }
00337
00338
00339 if (status == SS_CREATED) {
00340 fh = open(file_name, O_RDONLY, 0644);
00341 if (fh == -1)
00342 fh = open(file_name, O_CREAT | O_RDWR, 0644);
00343 else
00344 read(fh, *adr, size);
00345 close(fh);
00346 }
00347
00348 return status;
00349 }
00350
00351 #endif
00352 #ifdef OS_UNIX_MMAP
00353
00354 if (1) {
00355 static int once = 1;
00356 if (once && strstr(file_name, "ODB")) {
00357 once = 0;
00358 cm_msg(MINFO, "ss_shm_open",
00359 "WARNING: This version of MIDAS system.c uses the experimental mmap() based implementation of MIDAS shared memory.");
00360 }
00361 }
00362
00363 status = SS_SUCCESS;
00364
00365 {
00366 int ret;
00367 int fh, file_size;
00368 int i;
00369
00370 fh = open(file_name, O_RDWR | O_BINARY | O_LARGEFILE, 0644);
00371
00372 if (fh < 0) {
00373 if (errno == ENOENT) {
00374 fh = open(file_name, O_CREAT | O_RDWR | O_BINARY | O_LARGEFILE, 0644);
00375 }
00376
00377 if (fh < 0) {
00378 cm_msg(MERROR, "ss_shm_open",
00379 "Cannot create shared memory file \'%s\', errno %d (%s)", file_name,
00380 errno, strerror(errno));
00381 return SS_FILE_ERROR;
00382 }
00383
00384 ret = lseek(fh, size - 1, SEEK_SET);
00385
00386 if (ret == (off_t) - 1) {
00387 cm_msg(MERROR, "ss_shm_open",
00388 "Cannot create shared memory file \'%s\', size %d, lseek() errno %d (%s)",
00389 file_name, size, errno, strerror(errno));
00390 return SS_FILE_ERROR;
00391 }
00392
00393 ret = 0;
00394 ret = write(fh, &ret, 1);
00395 assert(ret == 1);
00396
00397 ret = lseek(fh, 0, SEEK_SET);
00398 assert(ret == 0);
00399
00400 cm_msg(MINFO, "ss_shm_open", "Created shared memory file \'%s\', size %d",
00401 file_name, size);
00402
00403 status = SS_CREATED;
00404 }
00405
00406
00407 file_size = (INT) ss_file_size(file_name);
00408 if (file_size < size) {
00409 cm_msg(MERROR, "ss_shm_open",
00410 "Shared memory file \'%s\' size %d is smaller than requested size %d. Please remove it and try again",
00411 file_name, file_size, size);
00412 return SS_NO_MEMORY;
00413 }
00414
00415 size = file_size;
00416
00417 *adr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fh, 0);
00418
00419 if ((*adr) == MAP_FAILED) {
00420 cm_msg(MERROR, "ss_shm_open", "mmap() failed, errno %d (%s)", errno,
00421 strerror(errno));
00422 return SS_NO_MEMORY;
00423 }
00424
00425 *handle = -1;
00426 for (i = 0; i < MAX_MMAP; i++)
00427 if (mmap_addr[i] == NULL) {
00428 mmap_addr[i] = *adr;
00429 mmap_size[i] = size;
00430 *handle = i;
00431 break;
00432 }
00433 assert((*handle) >= 0);
00434
00435 return status;
00436 }
00437
00438 #endif
00439 }
00440
00441
00442 INT ss_shm_close(char *name, void *adr, HNDLE handle, INT destroy_flag)
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466 {
00467 char mem_name[256], file_name[256], path[256];
00468
00469
00470
00471
00472
00473 sprintf(mem_name, "SM_%s", name);
00474
00475
00476 cm_get_path(path);
00477 if (path[0] == 0) {
00478 getcwd(path, 256);
00479 #if defined(OS_VMS)
00480 #elif defined(OS_UNIX)
00481 strcat(path, "/");
00482 #elif defined(OS_WINNT)
00483 strcat(path, "\\");
00484 #endif
00485 }
00486
00487 strcpy(file_name, path);
00488 #if defined (OS_UNIX)
00489 strcat(file_name, ".");
00490 #endif
00491 strcat(file_name, name);
00492 strcat(file_name, ".SHM");
00493
00494 #ifdef OS_WINNT
00495
00496 if (!UnmapViewOfFile(adr))
00497 return SS_INVALID_ADDRESS;
00498
00499 CloseHandle((HANDLE) handle);
00500
00501 return SS_SUCCESS;
00502
00503 #endif
00504 #ifdef OS_VMS
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528 return SS_INVALID_ADDRESS;
00529
00530 #endif
00531 #ifdef OS_UNIX_SHM
00532
00533 {
00534 struct shmid_ds buf;
00535 FILE *fh;
00536 int i;
00537
00538 i = destroy_flag;
00539
00540
00541 memset(&buf, 0, sizeof(buf));
00542 if (shmctl(handle, IPC_STAT, &buf) < 0) {
00543 cm_msg(MERROR, "ss_shm_close", "shmctl(shmid=%d,IPC_STAT) failed, errno %d (%s)",
00544 handle, errno, strerror(errno));
00545 return SS_INVALID_HANDLE;
00546 }
00547
00548
00549 if (buf.shm_nattch == 1) {
00550 if (!disable_shm_write) {
00551 fh = fopen(file_name, "w");
00552
00553 if (fh == NULL) {
00554 cm_msg(MERROR, "ss_shm_close",
00555 "Cannot write to file %s, please check protection", file_name);
00556 } else {
00557
00558 fwrite(adr, 1, buf.shm_segsz, fh);
00559 fclose(fh);
00560 }
00561 }
00562
00563 if (shmdt(adr) < 0) {
00564 cm_msg(MERROR, "ss_shm_close", "shmdt(shmid=%d) failed, errno %d (%s)",
00565 handle, errno, strerror(errno));
00566 return SS_INVALID_ADDRESS;
00567 }
00568
00569 if (shmctl(handle, IPC_RMID, &buf) < 0) {
00570 cm_msg(MERROR, "ss_shm_close",
00571 "shmctl(shmid=%d,IPC_RMID) failed, errno %d (%s)", handle, errno,
00572 strerror(errno));
00573 return SS_INVALID_ADDRESS;
00574 }
00575 } else
00576
00577 if (shmdt(adr) < 0) {
00578 cm_msg(MERROR, "ss_shm_close", "shmdt(shmid=%d) failed, errno %d (%s)", handle,
00579 errno, strerror(errno));
00580 return SS_INVALID_ADDRESS;
00581 }
00582
00583 return SS_SUCCESS;
00584 }
00585
00586 #endif
00587 #ifdef OS_UNIX_MMAP
00588
00589 if (1) {
00590 int ret;
00591
00592 ret = destroy_flag;
00593
00594 assert(adr == mmap_addr[handle]);
00595
00596 ret = munmap(mmap_addr[handle], mmap_size[handle]);
00597 if (ret != 0) {
00598 cm_msg(MERROR, "ss_shm_protect",
00599 "Cannot munmap(): return value %d, errno %d (%s)", ret, errno,
00600 strerror(errno));
00601 return SS_INVALID_ADDRESS;
00602 }
00603
00604 mmap_addr[handle] = NULL;
00605 mmap_size[handle] = 0;
00606
00607 return SS_SUCCESS;
00608 }
00609 #endif
00610 }
00611
00612
00613 INT ss_shm_protect(HNDLE handle, void *adr)
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633 {
00634 #ifdef OS_WINNT
00635
00636 if (!UnmapViewOfFile(adr))
00637 return SS_INVALID_ADDRESS;
00638
00639 #endif
00640 #ifdef OS_UNIX_SHM
00641
00642 int i;
00643 i = handle;
00644
00645 if (shmdt(adr) < 0) {
00646 cm_msg(MERROR, "ss_shm_protect", "shmdt() failed");
00647 return SS_INVALID_ADDRESS;
00648 }
00649 #endif
00650 #ifdef OS_UNIX_MMAP
00651
00652 int i;
00653 i = handle;
00654
00655 if (1) {
00656 int ret;
00657
00658 assert(adr == mmap_addr[handle]);
00659
00660 ret = mprotect(mmap_addr[handle], mmap_size[handle], PROT_NONE);
00661 if (ret != 0) {
00662 cm_msg(MERROR, "ss_shm_protect",
00663 "Cannot mprotect(): return value %d, errno %d (%s)", ret, errno,
00664 strerror(errno));
00665 return SS_INVALID_ADDRESS;
00666 }
00667 }
00668 #endif
00669 return SS_SUCCESS;
00670 }
00671
00672
00673 INT ss_shm_unprotect(HNDLE handle, void **adr)
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693 {
00694 #ifdef OS_WINNT
00695
00696 *adr = MapViewOfFile((HANDLE) handle, FILE_MAP_ALL_ACCESS, 0, 0, 0);
00697
00698 if (*adr == NULL) {
00699 cm_msg(MERROR, "ss_shm_unprotect", "MapViewOfFile() failed");
00700 return SS_NO_MEMORY;
00701 }
00702 #endif
00703 #ifdef OS_UNIX_SHM
00704
00705 *adr = shmat(handle, 0, 0);
00706
00707 if ((*adr) == (void *) (-1)) {
00708 cm_msg(MERROR, "ss_shm_unprotect", "shmat() failed, errno = %d", errno);
00709 return SS_NO_MEMORY;
00710 }
00711 #endif
00712 #ifdef OS_UNIX_MMAP
00713
00714 if (1) {
00715 int ret;
00716
00717 assert(adr == mmap_addr[handle]);
00718
00719 ret = mprotect(mmap_addr[handle], mmap_size[handle], PROT_READ | PROT_WRITE);
00720 if (ret != 0) {
00721 cm_msg(MERROR, "ss_shm_unprotect",
00722 "Cannot mprotect(): return value %d, errno %d (%s)", ret, errno,
00723 strerror(errno));
00724 return SS_INVALID_ADDRESS;
00725 }
00726 }
00727 #endif
00728
00729 return SS_SUCCESS;
00730 }
00731
00732
00733 INT ss_shm_flush(char *name, void *adr, INT size)
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753 {
00754 char mem_name[256], file_name[256], path[256];
00755
00756
00757
00758
00759
00760 sprintf(mem_name, "SM_%s", name);
00761
00762
00763 cm_get_path(path);
00764 if (path[0] == 0) {
00765 getcwd(path, 256);
00766 #if defined(OS_VMS)
00767 #elif defined(OS_UNIX)
00768 strcat(path, "/");
00769 #elif defined(OS_WINNT)
00770 strcat(path, "\\");
00771 #endif
00772 }
00773
00774 strcpy(file_name, path);
00775 #if defined (OS_UNIX)
00776 strcat(file_name, ".");
00777 #endif
00778 strcat(file_name, name);
00779 strcat(file_name, ".SHM");
00780
00781 #ifdef OS_WINNT
00782
00783 if (!FlushViewOfFile(adr, size))
00784 return SS_INVALID_ADDRESS;
00785
00786 return SS_SUCCESS;
00787
00788 #endif
00789 #ifdef OS_VMS
00790
00791 return SS_SUCCESS;
00792
00793 #endif
00794 #ifdef OS_UNIX_SHM
00795
00796 if (!disable_shm_write) {
00797 FILE *fh;
00798
00799 fh = fopen(file_name, "w");
00800
00801 if (fh == NULL) {
00802 cm_msg(MERROR, "ss_shm_flush",
00803 "Cannot write to file %s, please check protection", file_name);
00804 } else {
00805
00806 fwrite(adr, 1, size, fh);
00807 fclose(fh);
00808 }
00809 }
00810 return SS_SUCCESS;
00811
00812 #endif
00813 #ifdef OS_UNIX_MMAP
00814
00815 if (1) {
00816 int ret = msync(adr, size, MS_ASYNC);
00817 if (ret != 0) {
00818 cm_msg(MERROR, "ss_shm_flush",
00819 "Cannot msync(): return value %d, errno %d (%s)", ret, errno,
00820 strerror(errno));
00821 return SS_INVALID_ADDRESS;
00822 }
00823 }
00824
00825 return SS_SUCCESS;
00826
00827 #endif
00828 }
00829
00830
00831 INT ss_getthandle(void)
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848 {
00849 #ifdef OS_WINNT
00850 HANDLE hThread;
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861 DuplicateHandle(GetCurrentProcess(), GetCurrentThread(),
00862 GetCurrentProcess(), &hThread, THREAD_ALL_ACCESS, TRUE, 0);
00863
00864 return (INT) hThread;
00865
00866 #endif
00867 #ifdef OS_VMS
00868
00869 return 0;
00870
00871 #endif
00872 #ifdef OS_UNIX
00873
00874 return ss_getpid();
00875
00876 #endif
00877 }
00878
00879 #endif
00880
00881
00882 struct {
00883 char c;
00884 double d;
00885 } test_align;
00886
00887 INT ss_get_struct_align()
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909 {
00910 return (POINTER_T) (&test_align.d) - (POINTER_T) & test_align.c;
00911 }
00912
00913
00914 INT ss_getpid(void)
00915
00916
00917
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931 {
00932 #ifdef OS_WINNT
00933
00934 return (int) GetCurrentProcessId();
00935
00936 #endif
00937 #ifdef OS_VMS
00938
00939 return getpid();
00940
00941 #endif
00942 #ifdef OS_UNIX
00943
00944 return getpid();
00945
00946 #endif
00947 #ifdef OS_VXWORKS
00948
00949 return 0;
00950
00951 #endif
00952 #ifdef OS_MSDOS
00953
00954 return 0;
00955
00956 #endif
00957 }
00958
00959
00960
00961 static BOOL _single_thread = FALSE;
00962
00963 void ss_force_single_thread()
00964 {
00965 _single_thread = TRUE;
00966 }
00967
00968 INT ss_gettid(void)
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983
00984
00985 {
00986
00987 if (_single_thread)
00988 return 1;
00989
00990 #if defined OS_MSDOS
00991
00992 return 0;
00993
00994 #elif defined OS_WINNT
00995
00996 return (int) GetCurrentThreadId();
00997
00998 #elif defined OS_VMS
00999
01000 return ss_getpid();
01001
01002 #elif defined OS_DARWIN
01003
01004 return pthread_self();
01005
01006 #elif defined OS_CYGWIN
01007
01008 return pthread_self();
01009
01010 #elif defined OS_UNIX
01011
01012 return syscall(SYS_gettid);
01013
01014 #elif defined OS_VXWORKS
01015
01016 return ss_getpid();
01017
01018 #else
01019 #error Do not know how to do ss_gettid()
01020 #endif
01021 }
01022
01023
01024
01025 #ifdef OS_UNIX
01026 void catch_sigchld(int signo)
01027 {
01028 int status;
01029
01030 status = signo;
01031 wait(&status);
01032 return;
01033 }
01034 #endif
01035
01036 INT ss_spawnv(INT mode, char *cmdname, char *argv[])
01037
01038
01039
01040
01041
01042
01043
01044
01045
01046
01047
01048
01049
01050
01051
01052
01053
01054
01055
01056
01057
01058
01059 {
01060 #ifdef OS_WINNT
01061
01062 if (spawnvp(mode, cmdname, argv) < 0)
01063 return SS_INVALID_NAME;
01064
01065 return SS_SUCCESS;
01066
01067 #endif
01068
01069 #ifdef OS_MSDOS
01070
01071 spawnvp((int) mode, cmdname, argv);
01072
01073 return SS_SUCCESS;
01074
01075 #endif
01076
01077 #ifdef OS_VMS
01078
01079 {
01080 char cmdstring[500], *pc;
01081 INT i, flags, status;
01082 va_list argptr;
01083
01084 $DESCRIPTOR(cmdstring_dsc, "dummy");
01085
01086 if (mode & P_DETACH) {
01087 cmdstring_dsc.dsc$w_length = strlen(cmdstring);
01088 cmdstring_dsc.dsc$a_pointer = cmdstring;
01089
01090 status = sys$creprc(0, &cmdstring_dsc,
01091 0, 0, 0, 0, 0, NULL, 4, 0, 0, PRC$M_DETACH);
01092 } else {
01093 flags = (mode & P_NOWAIT) ? 1 : 0;
01094
01095 for (pc = argv[0] + strlen(argv[0]); *pc != ']' && pc != argv[0]; pc--);
01096 if (*pc == ']')
01097 pc++;
01098
01099 strcpy(cmdstring, pc);
01100
01101 if (strchr(cmdstring, ';'))
01102 *strchr(cmdstring, ';') = 0;
01103
01104 strcat(cmdstring, " ");
01105
01106 for (i = 1; argv[i] != NULL; i++) {
01107 strcat(cmdstring, argv[i]);
01108 strcat(cmdstring, " ");
01109 }
01110
01111 cmdstring_dsc.dsc$w_length = strlen(cmdstring);
01112 cmdstring_dsc.dsc$a_pointer = cmdstring;
01113
01114 status = lib$spawn(&cmdstring_dsc, 0, 0, &flags, NULL, 0, 0, 0, 0, 0, 0, 0, 0);
01115 }
01116
01117 return BM_SUCCESS;
01118 }
01119
01120 #endif
01121 #ifdef OS_UNIX
01122 pid_t child_pid;
01123
01124 #ifdef OS_ULTRIX
01125 union wait *status;
01126 #else
01127 int status;
01128 #endif
01129
01130 if ((child_pid = fork()) < 0)
01131 return (-1);
01132
01133 if (child_pid == 0) {
01134
01135 child_pid = execvp(cmdname, argv);
01136 return SS_SUCCESS;
01137 } else {
01138
01139 if (mode == P_WAIT)
01140 #ifdef OS_ULTRIX
01141 waitpid(child_pid, status, WNOHANG);
01142 #else
01143 waitpid(child_pid, &status, WNOHANG);
01144 #endif
01145
01146 else
01147
01148 signal(SIGCHLD, catch_sigchld);
01149 }
01150
01151 return SS_SUCCESS;
01152
01153 #endif
01154 }
01155
01156
01157 INT ss_shell(int sock)
01158
01159
01160
01161
01162
01163
01164
01165
01166
01167
01168
01169
01170
01171
01172
01173
01174 {
01175 #ifdef OS_WINNT
01176
01177 HANDLE hChildStdinRd, hChildStdinWr, hChildStdinWrDup,
01178 hChildStdoutRd, hChildStdoutWr,
01179 hChildStderrRd, hChildStderrWr, hSaveStdin, hSaveStdout, hSaveStderr;
01180
01181 SECURITY_ATTRIBUTES saAttr;
01182 PROCESS_INFORMATION piProcInfo;
01183 STARTUPINFO siStartInfo;
01184 char buffer[256], cmd[256];
01185 DWORD dwRead, dwWritten, dwAvail, i, i_cmd;
01186 fd_set readfds;
01187 struct timeval timeout;
01188
01189
01190 saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
01191 saAttr.bInheritHandle = TRUE;
01192 saAttr.lpSecurityDescriptor = NULL;
01193
01194
01195 hSaveStdout = GetStdHandle(STD_OUTPUT_HANDLE);
01196
01197
01198 if (!CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, 0))
01199 return 0;
01200
01201
01202 if (!SetStdHandle(STD_OUTPUT_HANDLE, hChildStdoutWr))
01203 return 0;
01204
01205
01206
01207 hSaveStderr = GetStdHandle(STD_ERROR_HANDLE);
01208
01209
01210 if (!CreatePipe(&hChildStderrRd, &hChildStderrWr, &saAttr, 0))
01211 return 0;
01212
01213
01214 if (!SetStdHandle(STD_ERROR_HANDLE, hChildStderrWr))
01215 return 0;
01216
01217
01218
01219 hSaveStdin = GetStdHandle(STD_INPUT_HANDLE);
01220
01221
01222 if (!CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, 0))
01223 return 0;
01224
01225
01226 if (!SetStdHandle(STD_INPUT_HANDLE, hChildStdinRd))
01227 return 0;
01228
01229
01230 if (!DuplicateHandle(GetCurrentProcess(), hChildStdinWr, GetCurrentProcess(), &hChildStdinWrDup, 0, FALSE,
01231 DUPLICATE_SAME_ACCESS))
01232 return 0;
01233
01234 CloseHandle(hChildStdinWr);
01235
01236
01237 memset(&siStartInfo, 0, sizeof(siStartInfo));
01238 siStartInfo.cb = sizeof(STARTUPINFO);
01239 siStartInfo.lpReserved = NULL;
01240 siStartInfo.lpReserved2 = NULL;
01241 siStartInfo.cbReserved2 = 0;
01242 siStartInfo.lpDesktop = NULL;
01243 siStartInfo.dwFlags = 0;
01244
01245 if (!CreateProcess(NULL, "cmd /Q",
01246 NULL,
01247 NULL,
01248 TRUE,
01249 0,
01250 NULL,
01251 NULL,
01252 &siStartInfo,
01253 &piProcInfo))
01254 return 0;
01255
01256
01257 SetStdHandle(STD_INPUT_HANDLE, hSaveStdin);
01258 SetStdHandle(STD_OUTPUT_HANDLE, hSaveStdout);
01259 SetStdHandle(STD_ERROR_HANDLE, hSaveStderr);
01260
01261 i_cmd = 0;
01262
01263 do {
01264
01265 do {
01266 if (!PeekNamedPipe(hChildStderrRd, buffer, 256, &dwRead, &dwAvail, NULL))
01267 break;
01268
01269 if (dwRead > 0) {
01270 ReadFile(hChildStderrRd, buffer, 256, &dwRead, NULL);
01271 send(sock, buffer, dwRead, 0);
01272 }
01273 } while (dwAvail > 0);
01274
01275
01276 do {
01277 if (!PeekNamedPipe(hChildStdoutRd, buffer, 256, &dwRead, &dwAvail, NULL))
01278 break;
01279 if (dwRead > 0) {
01280 ReadFile(hChildStdoutRd, buffer, 256, &dwRead, NULL);
01281 send(sock, buffer, dwRead, 0);
01282 }
01283 } while (dwAvail > 0);
01284
01285
01286
01287 if (!GetExitCodeProcess(piProcInfo.hProcess, &i))
01288 break;
01289 if (i != STILL_ACTIVE)
01290 break;
01291
01292
01293 FD_ZERO(&readfds);
01294 FD_SET(sock, &readfds);
01295 timeout.tv_sec = 0;
01296 timeout.tv_usec = 100;
01297 select(FD_SETSIZE, &readfds, NULL, NULL, &timeout);
01298
01299 if (FD_ISSET(sock, &readfds)) {
01300 i = recv(sock, cmd + i_cmd, 1, 0);
01301 if (i <= 0)
01302 break;
01303
01304
01305 if (cmd[i_cmd] == 8) {
01306 if (i_cmd > 0) {
01307 send(sock, "\b \b", 3, 0);
01308 i_cmd -= 1;
01309 }
01310 } else if (cmd[i_cmd] >= ' ' || cmd[i_cmd] == 13 || cmd[i_cmd] == 10) {
01311 send(sock, cmd + i_cmd, 1, 0);
01312 i_cmd += i;
01313 }
01314 }
01315
01316
01317 if (cmd[i_cmd - 1] == 10) {
01318 WriteFile(hChildStdinWrDup, cmd, i_cmd, &dwWritten, NULL);
01319 i_cmd = 0;
01320 }
01321
01322 } while (TRUE);
01323
01324 CloseHandle(hChildStdinWrDup);
01325 CloseHandle(hChildStdinRd);
01326 CloseHandle(hChildStderrRd);
01327 CloseHandle(hChildStdoutRd);
01328
01329 return SS_SUCCESS;
01330
01331 #endif
01332
01333 #ifdef OS_UNIX
01334 #ifndef NO_PTY
01335 pid_t pid;
01336 int i, p;
01337 char line[32], buffer[1024], shell[32];
01338 fd_set readfds;
01339
01340 if ((pid = forkpty(&p, line, NULL, NULL)) < 0)
01341 return 0;
01342 else if (pid > 0) {
01343
01344
01345 do {
01346 FD_ZERO(&readfds);
01347 FD_SET(sock, &readfds);
01348 FD_SET(p, &readfds);
01349
01350 select(FD_SETSIZE, (void *) &readfds, NULL, NULL, NULL);
01351
01352 if (FD_ISSET(sock, &readfds)) {
01353 memset(buffer, 0, sizeof(buffer));
01354 i = recv(sock, buffer, sizeof(buffer), 0);
01355 if (i <= 0)
01356 break;
01357 if (write(p, buffer, i) != i)
01358 break;
01359 }
01360
01361 if (FD_ISSET(p, &readfds)) {
01362 memset(buffer, 0, sizeof(buffer));
01363 i = read(p, buffer, sizeof(buffer));
01364 if (i <= 0)
01365 break;
01366 send(sock, buffer, i, 0);
01367 }
01368
01369 } while (1);
01370 } else {
01371
01372
01373 if (getenv("SHELL"))
01374 strlcpy(shell, getenv("SHELL"), sizeof(shell));
01375 else
01376 strcpy(shell, "/bin/sh");
01377 execl(shell, shell, NULL);
01378 }
01379 #else
01380 send(sock, "not implemented\n", 17, 0);
01381 #endif
01382
01383 return SS_SUCCESS;
01384
01385 #endif
01386 }
01387
01388
01389 static BOOL _daemon_flag;
01390
01391 INT ss_daemon_init(BOOL keep_stdout)
01392
01393
01394
01395
01396
01397
01398
01399
01400
01401
01402
01403
01404
01405
01406
01407
01408
01409 {
01410 #ifdef OS_UNIX
01411
01412
01413 int i, fd, pid;
01414
01415 if ((pid = fork()) < 0)
01416 return SS_ABORT;
01417 else if (pid != 0)
01418 exit(0);
01419
01420
01421
01422 _daemon_flag = TRUE;
01423
01424
01425
01426 for (i = 0; i < 3; i++) {
01427 if (keep_stdout && ((i == 1) || (i == 2)))
01428 continue;
01429
01430 close(i);
01431 fd = open("/dev/null", O_RDWR, 0);
01432 if (fd < 0)
01433 fd = open("/dev/null", O_WRONLY, 0);
01434 if (fd < 0) {
01435 cm_msg(MERROR, "ss_system", "Can't open /dev/null");
01436 return SS_ABORT;
01437 }
01438 if (fd != i) {
01439 cm_msg(MERROR, "ss_system", "Did not get file descriptor");
01440 return SS_ABORT;
01441 }
01442 }
01443
01444 setsid();
01445 umask(0);
01446
01447 #endif
01448
01449 return SS_SUCCESS;
01450 }
01451
01452
01453 BOOL ss_existpid(INT pid)
01454
01455
01456
01457
01458
01459
01460
01461
01462
01463
01464
01465
01466
01467
01468
01469
01470
01471 {
01472 #ifdef OS_UNIX
01473
01474 return (kill(pid, 0) == 0 ? TRUE : FALSE);
01475 #else
01476 cm_msg(MINFO, "ss_existpid", "implemented for UNIX only");
01477 return FALSE;
01478 #endif
01479 }
01480
01481
01482
01483 #endif
01484
01485
01486
01487
01488
01489
01490
01491
01492
01493
01494
01495
01496
01497
01498
01499
01500
01501
01502
01503 INT ss_system(char *command)
01504 {
01505 #ifdef OS_UNIX
01506 INT childpid;
01507
01508 return ss_exec(command, &childpid);
01509
01510 #else
01511
01512 system(command);
01513 return SS_SUCCESS;
01514
01515 #endif
01516 }
01517
01518
01519 #ifndef DOXYGEN_SHOULD_SKIP_THIS
01520
01521
01522 INT ss_exec(char *command, INT * pid)
01523
01524
01525
01526
01527
01528
01529
01530
01531
01532
01533
01534
01535
01536
01537
01538
01539
01540
01541 {
01542 #ifdef OS_UNIX
01543
01544
01545 int i, fd;
01546
01547 if ((*pid = fork()) < 0)
01548 return SS_ABORT;
01549 else if (*pid != 0) {
01550
01551 signal(SIGCHLD, catch_sigchld);
01552 return SS_SUCCESS;
01553 }
01554
01555
01556
01557
01558 for (i = 0; i < 256; i++)
01559 close(i);
01560
01561
01562
01563 for (i = 0; i < 3; i++) {
01564 fd = open("/dev/null", O_RDWR, 0);
01565 if (fd < 0)
01566 fd = open("/dev/null", O_WRONLY, 0);
01567 if (fd < 0) {
01568 cm_msg(MERROR, "ss_exec", "Can't open /dev/null");
01569 return SS_ABORT;
01570 }
01571 if (fd != i) {
01572 cm_msg(MERROR, "ss_exec", "Did not get file descriptor");
01573 return SS_ABORT;
01574 }
01575 }
01576
01577 setsid();
01578
01579 umask(0);
01580
01581
01582 execl("/bin/sh", "sh", "-c", command, NULL);
01583
01584 #else
01585
01586 system(command);
01587
01588 #endif
01589
01590 return SS_SUCCESS;
01591 }
01592
01593
01594 #endif
01595
01596
01597
01598
01599
01600
01601
01602
01603
01604
01605
01606
01607
01608
01609
01610
01611
01612
01613
01614
01615
01616
01617
01618
01619
01620
01621
01622
01623
01624
01625
01626
01627
01628
01629 midas_thread_t ss_thread_create(INT(*thread_func) (void *), void *param)
01630 {
01631 #if defined(OS_WINNT)
01632
01633 HANDLE status;
01634 DWORD thread_id;
01635
01636 if (thread_func == NULL) {
01637 return 0;
01638 }
01639
01640 status = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) thread_func,
01641 (LPVOID) param, 0, &thread_id);
01642
01643 return status == NULL ? 0 : (midas_thread_t) thread_id;
01644
01645 #elif defined(OS_MSDOS)
01646
01647 return 0;
01648
01649 #elif defined(OS_VMS)
01650
01651 return 0;
01652
01653 #elif defined(OS_VXWORKS)
01654
01655
01656
01657
01658
01659
01660
01661
01662 INT status;
01663 VX_TASK_SPAWN *ts;
01664
01665 ts = (VX_TASK_SPAWN *) param;
01666 status =
01667 taskSpawn(ts->name, ts->priority, ts->options, ts->stackSize,
01668 (FUNCPTR) thread_func, ts->arg1, ts->arg2, ts->arg3,
01669 ts->arg4, ts->arg5, ts->arg6, ts->arg7, ts->arg8, ts->arg9, ts->arg10);
01670
01671 return status == ERROR ? 0 : status;
01672
01673 #elif defined(OS_UNIX)
01674
01675 INT status;
01676 pthread_t thread_id;
01677
01678 status = pthread_create(&thread_id, NULL, (void *) thread_func, param);
01679
01680 return status != 0 ? 0 : thread_id;
01681
01682 #endif
01683 }
01684
01685
01686
01687
01688
01689
01690
01691
01692
01693
01694
01695
01696
01697
01698
01699
01700
01701
01702
01703 INT ss_thread_kill(midas_thread_t thread_id)
01704 {
01705 #if defined(OS_WINNT)
01706
01707 DWORD status;
01708
01709 status = TerminateThread(thread_id, 0);
01710
01711 return status != 0 ? SS_SUCCESS : SS_NO_THREAD;
01712
01713 #elif defined(OS_MSDOS)
01714
01715 return 0;
01716
01717 #elif defined(OS_VMS)
01718
01719 return 0;
01720
01721 #elif defined(OS_VXWORKS)
01722
01723 INT status;
01724 status = taskDelete(thread_id);
01725 return status == OK ? 0 : ERROR;
01726
01727 #elif defined(OS_UNIX)
01728
01729 INT status;
01730 status = pthread_kill(thread_id, SIGKILL);
01731 return status == 0 ? SS_SUCCESS : SS_NO_THREAD;
01732
01733 #endif
01734 }
01735
01736
01737 #ifndef DOXYGEN_SHOULD_SKIP_THIS
01738
01739
01740 static INT skip_mutex_handle = -1;
01741
01742 INT ss_mutex_create(const char *name, HNDLE * mutex_handle)
01743
01744
01745
01746
01747
01748
01749
01750
01751
01752
01753
01754
01755
01756
01757
01758
01759
01760
01761
01762
01763
01764
01765
01766
01767
01768
01769 {
01770 char mutex_name[256], path[256], file_name[256];
01771
01772
01773 sprintf(mutex_name, "MX_%s", name);
01774
01775 #ifdef OS_VXWORKS
01776
01777
01778
01779 if ((*((SEM_ID *) mutex_handle) = semBCreate(SEM_Q_FIFO, SEM_EMPTY)) == NULL)
01780 return SS_NO_MUTEX;
01781 return SS_CREATED;
01782
01783 #endif
01784
01785
01786 cm_get_path(path);
01787 if (path[0] == 0) {
01788 getcwd(path, 256);
01789 #if defined(OS_VMS)
01790 #elif defined(OS_UNIX)
01791 strcat(path, "/");
01792 #elif defined(OS_WINNT)
01793 strcat(path, "\\");
01794 #endif
01795 }
01796
01797 strcpy(file_name, path);
01798 #if defined (OS_UNIX)
01799 strcat(file_name, ".");
01800 #endif
01801 strcat(file_name, name);
01802 strcat(file_name, ".SHM");
01803
01804 #ifdef OS_WINNT
01805
01806 *mutex_handle = (HNDLE) CreateMutex(NULL, FALSE, mutex_name);
01807
01808 if (*mutex_handle == 0)
01809 return SS_NO_MUTEX;
01810
01811 return SS_CREATED;
01812
01813 #endif
01814 #ifdef OS_VMS
01815
01816
01817
01818 {
01819 INT status;
01820 $DESCRIPTOR(mutexname_dsc, "dummy");
01821 mutexname_dsc.dsc$w_length = strlen(mutex_name);
01822 mutexname_dsc.dsc$a_pointer = mutex_name;
01823
01824 *mutex_handle = (HNDLE) malloc(8);
01825
01826 status = sys$enqw(0, LCK$K_NLMODE, *mutex_handle, 0, &mutexname_dsc,
01827 0, 0, 0, 0, 0, 0);
01828
01829 if (status != SS$_NORMAL) {
01830 free((void *) *mutex_handle);
01831 *mutex_handle = 0;
01832 }
01833
01834 if (*mutex_handle == 0)
01835 return SS_NO_MUTEX;
01836
01837 return SS_CREATED;
01838 }
01839
01840 #endif
01841 #ifdef OS_UNIX
01842
01843 {
01844 INT key, status, fh;
01845 struct semid_ds buf;
01846
01847 #if (defined(OS_LINUX) && !defined(_SEM_SEMUN_UNDEFINED) && !defined(OS_CYGWIN)) || defined(OS_FREEBSD)
01848 union semun arg;
01849 #else
01850 union semun {
01851 INT val;
01852 struct semid_ds *buf;
01853 ushort *array;
01854 } arg;
01855 #endif
01856
01857 status = SS_SUCCESS;
01858
01859
01860 key = ftok(file_name, 'M');
01861 if (key < 0) {
01862 fh = open(file_name, O_CREAT, 0644);
01863 close(fh);
01864 key = ftok(file_name, 'M');
01865 status = SS_CREATED;
01866 }
01867
01868
01869 *mutex_handle = (HNDLE) semget(key, 1, 0);
01870 if (*mutex_handle < 0) {
01871 *mutex_handle = (HNDLE) semget(key, 1, IPC_CREAT);
01872 status = SS_CREATED;
01873 }
01874
01875 if (*mutex_handle < 0) {
01876 cm_msg(MERROR, "ss_mutex_mutex", "semget() failed, errno = %d", errno);
01877 return SS_NO_MUTEX;
01878 }
01879
01880 memset(&buf, 0, sizeof(buf));
01881 buf.sem_perm.uid = getuid();
01882 buf.sem_perm.gid = getgid();
01883 buf.sem_perm.mode = 0666;
01884 arg.buf = &buf;
01885
01886 semctl(*mutex_handle, 0, IPC_SET, arg);
01887
01888
01889 if (status == SS_CREATED) {
01890 arg.val = 1;
01891 if (semctl(*mutex_handle, 0, SETVAL, arg) < 0)
01892 return SS_NO_MUTEX;
01893 }
01894
01895 return SS_SUCCESS;
01896 }
01897 #endif
01898
01899 #ifdef OS_MSDOS
01900 return SS_NO_MUTEX;
01901 #endif
01902 }
01903
01904
01905 INT ss_mutex_wait_for(HNDLE mutex_handle, INT timeout)
01906
01907
01908
01909
01910
01911
01912
01913
01914
01915
01916
01917
01918
01919
01920
01921
01922
01923
01924
01925 {
01926 INT status;
01927
01928 #ifdef OS_WINNT
01929
01930 status = WaitForSingleObject((HANDLE) mutex_handle, timeout == 0 ? INFINITE : timeout);
01931 if (status == WAIT_FAILED)
01932 return SS_NO_MUTEX;
01933 if (status == WAIT_TIMEOUT)
01934 return SS_TIMEOUT;
01935
01936 return SS_SUCCESS;
01937 #endif
01938 #ifdef OS_VMS
01939 status = sys$enqw(0, LCK$K_EXMODE, mutex_handle, LCK$M_CONVERT, 0, 0, 0, 0, 0, 0, 0);
01940 if (status != SS$_NORMAL)
01941 return SS_NO_MUTEX;
01942 return SS_SUCCESS;
01943
01944 #endif
01945 #ifdef OS_VXWORKS
01946
01947 status = semTake((SEM_ID) mutex_handle, timeout == 0 ? WAIT_FOREVER : timeout >> 4);
01948 if (status == ERROR)
01949 return SS_NO_MUTEX;
01950 return SS_SUCCESS;
01951
01952 #endif
01953 #ifdef OS_UNIX
01954 {
01955 DWORD start_time;
01956 struct sembuf sb;
01957
01958 #if (defined(OS_LINUX) && !defined(_SEM_SEMUN_UNDEFINED) && !defined(OS_CYGWIN)) || defined(OS_FREEBSD)
01959 union semun arg;
01960 #else
01961 union semun {
01962 INT val;
01963 struct semid_ds *buf;
01964 ushort *array;
01965 } arg;
01966 #endif
01967
01968 sb.sem_num = 0;
01969 sb.sem_op = -1;
01970 sb.sem_flg = SEM_UNDO;
01971
01972 memset(&arg, 0, sizeof(arg));
01973
01974
01975
01976 if (ss_in_async_routine_flag)
01977 if (semctl(mutex_handle, 0, GETPID, arg) == getpid())
01978 if (semctl(mutex_handle, 0, GETVAL, arg) == 0) {
01979 skip_mutex_handle = mutex_handle;
01980 return SS_SUCCESS;
01981 }
01982
01983 skip_mutex_handle = -1;
01984
01985 start_time = ss_millitime();
01986
01987 do {
01988 status = semop(mutex_handle, &sb, 1);
01989
01990
01991 if (status == 0)
01992 break;
01993
01994
01995 if (errno == EINTR) {
01996
01997 if (timeout > 0 && (int) (ss_millitime() - start_time) > timeout)
01998 return SS_TIMEOUT;
01999
02000 continue;
02001 }
02002
02003 return SS_NO_MUTEX;
02004 } while (1);
02005
02006 return SS_SUCCESS;
02007 }
02008 #endif
02009
02010 #ifdef OS_MSDOS
02011 return SS_NO_MUTEX;
02012 #endif
02013 }
02014
02015
02016 INT ss_mutex_release(HNDLE mutex_handle)
02017
02018
02019
02020
02021
02022
02023
02024
02025
02026
02027
02028
02029
02030
02031
02032
02033
02034 {
02035 INT status;
02036
02037 #ifdef OS_WINNT
02038
02039 status = ReleaseMutex((HANDLE) mutex_handle);
02040
02041 if (status == FALSE)
02042 return SS_NO_MUTEX;
02043
02044 return SS_SUCCESS;
02045
02046 #endif
02047 #ifdef OS_VMS
02048
02049 status = sys$enqw(0, LCK$K_NLMODE, mutex_handle, LCK$M_CONVERT, 0, 0, 0, 0, 0, 0, 0);
02050
02051 if (status != SS$_NORMAL)
02052 return SS_NO_MUTEX;
02053
02054 return SS_SUCCESS;
02055
02056 #endif
02057
02058 #ifdef OS_VXWORKS
02059
02060 if (semGive((SEM_ID) mutex_handle) == ERROR)
02061 return SS_NO_MUTEX;
02062 return SS_SUCCESS;
02063 #endif
02064
02065 #ifdef OS_UNIX
02066 {
02067 struct sembuf sb;
02068
02069 sb.sem_num = 0;
02070 sb.sem_op = 1;
02071 sb.sem_flg = SEM_UNDO;
02072
02073 if (mutex_handle == skip_mutex_handle) {
02074 skip_mutex_handle = -1;
02075 return SS_SUCCESS;
02076 }
02077
02078 do {
02079 status = semop(mutex_handle, &sb, 1);
02080
02081
02082 if (status == 0)
02083 break;
02084
02085
02086 if (errno == EINTR)
02087 continue;
02088
02089 return SS_NO_MUTEX;
02090 } while (1);
02091
02092 return SS_SUCCESS;
02093 }
02094 #endif
02095
02096 #ifdef OS_MSDOS
02097 return SS_NO_MUTEX;
02098 #endif
02099 }
02100
02101
02102 INT ss_mutex_delete(HNDLE mutex_handle, INT destroy_flag)
02103
02104
02105
02106
02107
02108
02109
02110
02111
02112
02113
02114
02115
02116
02117
02118
02119
02120 {
02121 #ifdef OS_WINNT
02122
02123 if (CloseHandle((HANDLE) mutex_handle) == FALSE)
02124 return SS_NO_MUTEX;
02125
02126 return SS_SUCCESS;
02127
02128 #endif
02129 #ifdef OS_VMS
02130
02131 free((void *) mutex_handle);
02132 return SS_SUCCESS;
02133
02134 #endif
02135
02136 #ifdef OS_VXWORKS
02137
02138 if (semDelete((SEM_ID) mutex_handle) == ERROR)
02139 return SS_NO_MUTEX;
02140 return SS_SUCCESS;
02141 #endif
02142
02143 #ifdef OS_UNIX
02144 #if (defined(OS_LINUX) && !defined(_SEM_SEMUN_UNDEFINED) && !defined(OS_CYGWIN)) || defined(OS_FREEBSD)
02145 union semun arg;
02146 #else
02147 union semun {
02148 INT val;
02149 struct semid_ds *buf;
02150 ushort *array;
02151 } arg;
02152 #endif
02153
02154 memset(&arg, 0, sizeof(arg));
02155
02156 if (destroy_flag)
02157 if (semctl(mutex_handle, 0, IPC_RMID, arg) < 0)
02158 return SS_NO_MUTEX;
02159
02160 return SS_SUCCESS;
02161
02162 #endif
02163
02164 #ifdef OS_MSDOS
02165 return SS_NO_MUTEX;
02166 #endif
02167 }
02168
02169
02170 #endif
02171
02172
02173
02174
02175
02176
02177
02178
02179
02180
02181
02182
02183
02184
02185
02186
02187
02188
02189
02190 DWORD ss_millitime()
02191 {
02192 #ifdef OS_WINNT
02193
02194 return (int) GetTickCount();
02195
02196 #endif
02197 #ifdef OS_MSDOS
02198
02199 return clock() * 55;
02200
02201 #endif
02202 #ifdef OS_VMS
02203
02204 {
02205 char time[8];
02206 DWORD lo, hi;
02207
02208 sys$gettim(time);
02209
02210 lo = *((DWORD *) time);
02211 hi = *((DWORD *) (time + 4));
02212
02213
02214
02215 return lo / 10000 + hi * 429496.7296;
02216
02217 }
02218
02219 #endif
02220 #ifdef OS_UNIX
02221 {
02222 struct timeval tv;
02223
02224 gettimeofday(&tv, NULL);
02225
02226 return tv.tv_sec * 1000 + tv.tv_usec / 1000;
02227 }
02228
02229 #endif
02230 #ifdef OS_VXWORKS
02231 {
02232 int count;
02233 static int ticks_per_msec = 0;
02234
02235 if (ticks_per_msec == 0)
02236 ticks_per_msec = 1000 / sysClkRateGet();
02237
02238 return tickGet() * ticks_per_msec;
02239 }
02240 #endif
02241 }
02242
02243
02244
02245
02246
02247
02248
02249
02250
02251
02252
02253
02254
02255
02256
02257 DWORD ss_time()
02258 {
02259 #if !defined(OS_VXWORKS)
02260 #if !defined(OS_VMS)
02261 tzset();
02262 #endif
02263 #endif
02264 return (DWORD) time(NULL);
02265 }
02266
02267
02268 #ifndef DOXYGEN_SHOULD_SKIP_THIS
02269
02270
02271 DWORD ss_settime(DWORD seconds)
02272
02273
02274
02275
02276
02277
02278
02279
02280
02281
02282
02283
02284
02285
02286
02287 {
02288 #if defined(OS_WINNT)
02289 SYSTEMTIME st;
02290 struct tm *ltm;
02291
02292 tzset();
02293 ltm = localtime((time_t *) & seconds);
02294
02295 st.wYear = ltm->tm_year + 1900;
02296 st.wMonth = ltm->tm_mon + 1;
02297 st.wDay = ltm->tm_mday;
02298 st.wHour = ltm->tm_hour;
02299 st.wMinute = ltm->tm_min;
02300 st.wSecond = ltm->tm_sec;
02301 st.wMilliseconds = 0;
02302
02303 SetLocalTime(&st);
02304
02305 #elif defined(OS_DARWIN)
02306
02307 assert(!"ss_settime() is not supported");
02308
02309 return SS_NO_DRIVER;
02310
02311 #elif defined(OS_CYGWIN)
02312
02313 assert(!"ss_settime() is not supported");
02314
02315 return SS_NO_DRIVER;
02316
02317 #elif defined(OS_UNIX)
02318
02319 stime((void *) &seconds);
02320
02321 #elif defined(OS_VXWORKS)
02322
02323 struct timespec ltm;
02324
02325 ltm.tv_sec = seconds;
02326 ltm.tv_nsec = 0;
02327 clock_settime(CLOCK_REALTIME, <m);
02328
02329 #endif
02330 return SS_SUCCESS;
02331 }
02332
02333
02334 char *ss_asctime()
02335
02336
02337
02338
02339
02340
02341
02342
02343
02344
02345
02346
02347
02348
02349
02350
02351 {
02352 static char str[32];
02353 time_t seconds;
02354
02355 seconds = (time_t) ss_time();
02356
02357 #if !defined(OS_VXWORKS)
02358 #if !defined(OS_VMS)
02359 tzset();
02360 #endif
02361 #endif
02362 strcpy(str, asctime(localtime(&seconds)));
02363
02364
02365 str[24] = 0;
02366
02367 return str;
02368 }
02369
02370
02371 INT ss_timezone()
02372
02373
02374
02375
02376
02377
02378
02379
02380
02381
02382
02383
02384
02385
02386
02387
02388
02389 {
02390 #if defined(OS_DARWIN) || defined(OS_VXWORKS)
02391 return 0;
02392 #else
02393 return (INT) timezone;
02394 #endif
02395 }
02396
02397
02398
02399
02400 #ifdef OS_UNIX
02401
02402 void ss_cont()
02403 {
02404 }
02405 #endif
02406
02407
02408 #endif
02409
02410
02411
02412
02413
02414
02415
02416
02417
02418
02419
02420
02421
02422 INT ss_sleep(INT millisec)
02423 {
02424 if (millisec == 0) {
02425 #ifdef OS_WINNT
02426 SuspendThread(GetCurrentThread());
02427 #endif
02428 #ifdef OS_VMS
02429 sys$hiber();
02430 #endif
02431 #ifdef OS_UNIX
02432 signal(SIGCONT, ss_cont);
02433 pause();
02434 #endif
02435 return SS_SUCCESS;
02436 }
02437
02438 #ifdef OS_WINNT
02439 Sleep(millisec);
02440 #endif
02441 #ifdef OS_UNIX
02442 struct timespec ts;
02443 int status;
02444
02445 ts.tv_sec = millisec / 1000;
02446 ts.tv_nsec = (millisec % 1000) * 1E6;
02447
02448 do {
02449 status = nanosleep(&ts, &ts);
02450 } while (status == -1 && errno == EINTR);
02451 #endif
02452
02453 return SS_SUCCESS;
02454 }
02455
02456
02457 #ifndef DOXYGEN_SHOULD_SKIP_THIS
02458
02459
02460 BOOL ss_kbhit()
02461
02462
02463
02464
02465
02466
02467
02468
02469
02470
02471
02472
02473
02474
02475
02476
02477
02478 {
02479 #ifdef OS_MSDOS
02480
02481 return kbhit();
02482
02483 #endif
02484 #ifdef OS_WINNT
02485
02486 return kbhit();
02487
02488 #endif
02489 #ifdef OS_VMS
02490
02491 return FALSE;
02492
02493 #endif
02494 #ifdef OS_UNIX
02495
02496 int n;
02497
02498 if (_daemon_flag)
02499 return 0;
02500
02501 ioctl(0, FIONREAD, &n);
02502 return (n > 0);
02503
02504 #endif
02505 #ifdef OS_VXWORKS
02506
02507 int n;
02508 ioctl(0, FIONREAD, (long) &n);
02509 return (n > 0);
02510
02511 #endif
02512 }
02513
02514
02515
02516 #ifdef LOCAL_ROUTINES
02517
02518 INT ss_wake(INT pid, INT tid, INT thandle)
02519
02520
02521
02522
02523
02524
02525
02526
02527
02528
02529
02530
02531
02532
02533
02534
02535
02536
02537
02538
02539
02540 {
02541 #ifdef OS_WINNT
02542 HANDLE process_handle;
02543 HANDLE dup_thread_handle;
02544
02545
02546
02547
02548
02549
02550
02551
02552
02553
02554 process_handle = OpenProcess(PROCESS_ALL_ACCESS, TRUE, pid);
02555
02556 if (process_handle == 0)
02557 return SS_NO_PROCESS;
02558
02559 DuplicateHandle(process_handle, (HANDLE) thandle, GetCurrentProcess(),
02560 &dup_thread_handle, THREAD_ALL_ACCESS, TRUE, 0);
02561
02562
02563 CloseHandle(process_handle);
02564
02565 if (dup_thread_handle == 0)
02566 return SS_NO_PROCESS;
02567
02568 ResumeThread(dup_thread_handle);
02569
02570
02571 CloseHandle(dup_thread_handle);
02572
02573 return SS_SUCCESS;
02574
02575 #endif
02576 #ifdef OS_VMS
02577
02578 if (sys$wake(&pid, 0) == SS$_NONEXPR)
02579 return SS_NO_PROCESS;
02580
02581 return SS_SUCCESS;
02582
02583 #endif
02584 #ifdef OS_UNIX
02585
02586 int i;
02587 i = tid;
02588 i = thandle;
02589
02590 if (kill(pid, SIGCONT) < 0)
02591 return SS_NO_PROCESS;
02592
02593 return SS_SUCCESS;
02594
02595
02596
02597
02598
02599
02600
02601
02602
02603 #endif
02604 }
02605
02606
02607 #ifdef OS_WINNT
02608
02609 static void (*UserCallback) (int);
02610 static UINT _timer_id = 0;
02611
02612 VOID CALLBACK _timeCallback(UINT idEvent, UINT uReserved, DWORD dwUser,
02613 DWORD dwReserved1, DWORD dwReserved2)
02614 {
02615 _timer_id = 0;
02616 if (UserCallback != NULL)
02617 UserCallback(0);
02618 }
02619
02620 #endif
02621
02622 INT ss_alarm(INT millitime, void (*func) (int))
02623
02624
02625
02626
02627
02628
02629
02630
02631
02632
02633
02634
02635
02636
02637
02638
02639
02640
02641
02642 {
02643 #ifdef OS_WINNT
02644
02645 UserCallback = func;
02646 if (millitime > 0)
02647 _timer_id =
02648 timeSetEvent(millitime, 100, (LPTIMECALLBACK) _timeCallback, 0, TIME_ONESHOT);
02649 else {
02650 if (_timer_id)
02651 timeKillEvent(_timer_id);
02652 _timer_id = 0;
02653 }
02654
02655 return SS_SUCCESS;
02656
02657 #endif
02658 #ifdef OS_VMS
02659
02660 signal(SIGALRM, func);
02661 alarm(millitime / 1000);
02662 return SS_SUCCESS;
02663
02664 #endif
02665 #ifdef OS_UNIX
02666
02667 signal(SIGALRM, func);
02668 alarm(millitime / 1000);
02669 return SS_SUCCESS;
02670
02671 #endif
02672 }
02673
02674
02675 void (*MidasExceptionHandler) ();
02676
02677 #ifdef OS_WINNT
02678
02679 LONG MidasExceptionFilter(LPEXCEPTION_POINTERS pexcep)
02680 {
02681 if (MidasExceptionHandler != NULL)
02682 MidasExceptionHandler();
02683
02684 return EXCEPTION_CONTINUE_SEARCH;
02685 }
02686
02687 INT MidasExceptionSignal(INT sig)
02688 {
02689 if (MidasExceptionHandler != NULL)
02690 MidasExceptionHandler();
02691
02692 raise(sig);
02693
02694 return 0;
02695 }
02696
02697
02698
02699
02700
02701
02702
02703
02704
02705
02706
02707 #endif
02708
02709 #ifdef OS_VMS
02710
02711 INT MidasExceptionFilter(INT * sigargs, INT * mechargs)
02712 {
02713 if (MidasExceptionHandler != NULL)
02714 MidasExceptionHandler();
02715
02716 return (SS$_RESIGNAL);
02717 }
02718
02719 void MidasExceptionSignal(INT sig)
02720 {
02721 if (MidasExceptionHandler != NULL)
02722 MidasExceptionHandler();
02723
02724 kill(getpid(), sig);
02725 }
02726
02727 #endif
02728
02729
02730 INT ss_exception_handler(void (*func) ())
02731
02732
02733
02734
02735
02736
02737
02738
02739
02740
02741
02742
02743
02744
02745
02746
02747
02748
02749 {
02750 #ifdef OS_WINNT
02751
02752 MidasExceptionHandler = func;
02753
02754
02755
02756
02757
02758
02759
02760
02761
02762
02763
02764 #elif defined (OS_VMS)
02765
02766 MidasExceptionHandler = func;
02767 lib$establish(MidasExceptionFilter);
02768
02769 signal(SIGINT, MidasExceptionSignal);
02770 signal(SIGILL, MidasExceptionSignal);
02771 signal(SIGQUIT, MidasExceptionSignal);
02772 signal(SIGFPE, MidasExceptionSignal);
02773 signal(SIGSEGV, MidasExceptionSignal);
02774 signal(SIGTERM, MidasExceptionSignal);
02775
02776 #else
02777 void *p;
02778 p = func;
02779 #endif
02780
02781 return SS_SUCCESS;
02782 }
02783
02784 #endif
02785
02786
02787 void *ss_ctrlc_handler(void (*func) (int))
02788
02789
02790
02791
02792
02793
02794
02795
02796
02797
02798
02799
02800
02801
02802
02803
02804
02805
02806
02807 {
02808 #ifdef OS_WINNT
02809
02810 if (func == NULL) {
02811 signal(SIGBREAK, SIG_DFL);
02812 return signal(SIGINT, SIG_DFL);
02813 } else {
02814 signal(SIGBREAK, func);
02815 return signal(SIGINT, func);
02816 }
02817 return NULL;
02818
02819 #endif
02820 #ifdef OS_VMS
02821
02822 return signal(SIGINT, func);
02823
02824 #endif
02825
02826 #ifdef OS_UNIX
02827
02828 if (func == NULL) {
02829 signal(SIGTERM, SIG_DFL);
02830 return (void *) signal(SIGINT, SIG_DFL);
02831 } else {
02832 signal(SIGTERM, func);
02833 return (void *) signal(SIGINT, func);
02834 }
02835
02836 #endif
02837 }
02838
02839
02840
02841
02842
02843
02844
02845
02846
02847
02848
02849
02850
02851
02852
02853
02854
02855
02856
02857 typedef struct {
02858 BOOL in_use;
02859 INT thread_id;
02860 INT ipc_port;
02861 INT ipc_recv_socket;
02862 INT ipc_send_socket;
02863 INT(*ipc_dispatch) (char *, INT);
02864 INT listen_socket;
02865 INT(*listen_dispatch) (INT);
02866 RPC_SERVER_CONNECTION *server_connection;
02867 INT(*client_dispatch) (INT);
02868 RPC_SERVER_ACCEPTION *server_acception;
02869 INT(*server_dispatch) (INT, int, BOOL);
02870 struct sockaddr_in bind_addr;
02871 } SUSPEND_STRUCT;
02872
02873 SUSPEND_STRUCT *_suspend_struct = NULL;
02874 INT _suspend_entries;
02875
02876
02877 INT ss_suspend_init_ipc(INT idx)
02878
02879
02880
02881
02882
02883
02884
02885
02886
02887
02888
02889
02890
02891
02892
02893
02894
02895
02896 {
02897 INT status, sock;
02898 int i;
02899 struct sockaddr_in bind_addr;
02900 char local_host_name[HOST_NAME_LENGTH];
02901 struct hostent *phe;
02902
02903 #ifdef OS_WINNT
02904 {
02905 WSADATA WSAData;
02906
02907
02908 if (WSAStartup(MAKEWORD(1, 1), &WSAData) != 0)
02909 return SS_SOCKET_ERROR;
02910 }
02911 #endif
02912
02913
02914 sock = socket(AF_INET, SOCK_DGRAM, 0);
02915 if (sock == -1)
02916 return SS_SOCKET_ERROR;
02917
02918
02919 memset(&bind_addr, 0, sizeof(bind_addr));
02920 bind_addr.sin_family = AF_INET;
02921 bind_addr.sin_addr.s_addr = 0;
02922 bind_addr.sin_port = 0;
02923
02924 gethostname(local_host_name, sizeof(local_host_name));
02925
02926 #ifdef OS_VXWORKS
02927 {
02928 INT host_addr;
02929
02930 host_addr = hostGetByName(local_host_name);
02931 memcpy((char *) &(bind_addr.sin_addr), &host_addr, 4);
02932 }
02933 #else
02934 phe = gethostbyname(local_host_name);
02935 if (phe == NULL) {
02936 cm_msg(MERROR, "ss_suspend_init_ipc", "cannot get host name");
02937 return SS_SOCKET_ERROR;
02938 }
02939 memcpy((char *) &(bind_addr.sin_addr), phe->h_addr, phe->h_length);
02940 #endif
02941
02942 status = bind(sock, (struct sockaddr *) &bind_addr, sizeof(bind_addr));
02943 if (status < 0)
02944 return SS_SOCKET_ERROR;
02945
02946
02947 i = sizeof(bind_addr);
02948 getsockname(sock, (struct sockaddr *) &bind_addr, (int *) &i);
02949
02950 _suspend_struct[idx].ipc_recv_socket = sock;
02951 _suspend_struct[idx].ipc_port = ntohs(bind_addr.sin_port);
02952
02953
02954 sock = socket(AF_INET, SOCK_DGRAM, 0);
02955
02956 if (sock == -1)
02957 return SS_SOCKET_ERROR;
02958
02959
02960 memset(&bind_addr, 0, sizeof(bind_addr));
02961 bind_addr.sin_family = AF_INET;
02962 bind_addr.sin_addr.s_addr = 0;
02963
02964 #ifdef OS_VXWORKS
02965 {
02966 INT host_addr;
02967
02968 host_addr = hostGetByName(local_host_name);
02969 memcpy((char *) &(bind_addr.sin_addr), &host_addr, 4);
02970 }
02971 #else
02972 memcpy((char *) &(bind_addr.sin_addr), phe->h_addr, phe->h_length);
02973 #endif
02974
02975 memcpy(&_suspend_struct[idx].bind_addr, &bind_addr, sizeof(bind_addr));
02976 _suspend_struct[idx].ipc_send_socket = sock;
02977
02978 return SS_SUCCESS;
02979 }
02980
02981
02982 INT ss_suspend_get_index(INT * pindex)
02983
02984
02985
02986
02987
02988
02989
02990
02991
02992
02993
02994
02995
02996
02997
02998
02999
03000
03001
03002 {
03003 INT idx;
03004
03005 if (_suspend_struct == NULL) {
03006
03007 _suspend_struct = (SUSPEND_STRUCT *) malloc(sizeof(SUSPEND_STRUCT));
03008 memset(_suspend_struct, 0, sizeof(SUSPEND_STRUCT));
03009 if (_suspend_struct == NULL)
03010 return SS_NO_MEMORY;
03011
03012 _suspend_entries = 1;
03013 *pindex = 0;
03014 _suspend_struct[0].thread_id = ss_gettid();
03015 _suspend_struct[0].in_use = TRUE;
03016 } else {
03017
03018 for (idx = 0; idx < _suspend_entries; idx++)
03019 if (_suspend_struct[idx].thread_id == ss_gettid()) {
03020 if (pindex != NULL)
03021 *pindex = idx;
03022
03023 return SS_SUCCESS;
03024 }
03025
03026
03027 for (idx = 0; idx < _suspend_entries; idx++)
03028 if (!_suspend_struct[idx].in_use)
03029 break;
03030
03031 if (idx == _suspend_entries) {
03032
03033 _suspend_struct = (SUSPEND_STRUCT *) realloc(_suspend_struct,
03034 sizeof
03035 (SUSPEND_STRUCT) *
03036 (_suspend_entries + 1));
03037 memset(&_suspend_struct[_suspend_entries], 0, sizeof(SUSPEND_STRUCT));
03038
03039 _suspend_entries++;
03040 if (_suspend_struct == NULL) {
03041 _suspend_entries--;
03042 return SS_NO_MEMORY;
03043 }
03044 }
03045 *pindex = idx;
03046 _suspend_struct[idx].thread_id = ss_gettid();
03047 _suspend_struct[idx].in_use = TRUE;
03048 }
03049
03050 return SS_SUCCESS;
03051 }
03052
03053
03054 INT ss_suspend_exit()
03055
03056
03057
03058
03059
03060
03061
03062
03063
03064
03065
03066
03067
03068
03069
03070
03071
03072 {
03073 INT i, status;
03074
03075 status = ss_suspend_get_index(&i);
03076
03077 if (status != SS_SUCCESS)
03078 return status;
03079
03080 if (_suspend_struct[i].ipc_recv_socket) {
03081 closesocket(_suspend_struct[i].ipc_recv_socket);
03082 closesocket(_suspend_struct[i].ipc_send_socket);
03083 }
03084
03085 memset(&_suspend_struct[i], 0, sizeof(SUSPEND_STRUCT));
03086
03087
03088 for (i = _suspend_entries - 1; i >= 0; i--)
03089 if (_suspend_struct[i].in_use)
03090 break;
03091
03092 _suspend_entries = i + 1;
03093
03094 if (_suspend_entries == 0) {
03095 free(_suspend_struct);
03096 _suspend_struct = NULL;
03097 }
03098
03099 return SS_SUCCESS;
03100 }
03101
03102
03103 INT ss_suspend_set_dispatch(INT channel, void *connection, INT(*dispatch) ())
03104
03105
03106
03107
03108
03109
03110
03111
03112
03113
03114
03115
03116
03117
03118
03119
03120
03121
03122
03123
03124
03125
03126
03127
03128
03129
03130
03131
03132 {
03133 INT i, status;
03134
03135 status = ss_suspend_get_index(&i);
03136
03137 if (status != SS_SUCCESS)
03138 return status;
03139
03140 if (channel == CH_IPC) {
03141 _suspend_struct[i].ipc_dispatch = (INT(*)(char *, INT)) dispatch;
03142
03143 if (!_suspend_struct[i].ipc_recv_socket)
03144 ss_suspend_init_ipc(i);
03145 }
03146
03147 if (channel == CH_LISTEN) {
03148 _suspend_struct[i].listen_socket = *((INT *) connection);
03149 _suspend_struct[i].listen_dispatch = (INT(*)(INT)) dispatch;
03150 }
03151
03152 if (channel == CH_CLIENT) {
03153 _suspend_struct[i].server_connection = (RPC_SERVER_CONNECTION *) connection;
03154 _suspend_struct[i].client_dispatch = (INT(*)(INT)) dispatch;
03155 }
03156
03157 if (channel == CH_SERVER) {
03158 _suspend_struct[i].server_acception = (RPC_SERVER_ACCEPTION *) connection;
03159 _suspend_struct[i].server_dispatch = (INT(*)(INT, int, BOOL)) dispatch;
03160 }
03161
03162 return SS_SUCCESS;
03163 }
03164
03165
03166 INT ss_suspend_get_port(INT * port)
03167
03168
03169
03170
03171
03172
03173
03174
03175
03176
03177
03178
03179
03180
03181
03182
03183
03184
03185
03186
03187 {
03188 INT idx, status;
03189
03190 status = ss_suspend_get_index(&idx);
03191
03192 if (status != SS_SUCCESS)
03193 return status;
03194
03195 if (!_suspend_struct[idx].ipc_port)
03196 ss_suspend_init_ipc(idx);
03197
03198 *port = _suspend_struct[idx].ipc_port;
03199
03200 return SS_SUCCESS;
03201 }
03202
03203
03204 INT ss_suspend(INT millisec, INT msg)
03205
03206
03207
03208
03209
03210
03211
03212
03213
03214
03215
03216
03217
03218
03219
03220
03221
03222
03223
03224
03225
03226
03227
03228
03229
03230
03231
03232
03233
03234
03235 {
03236 fd_set readfds;
03237 struct timeval timeout;
03238 INT sock, server_socket;
03239 INT idx, status, i, return_status;
03240 int size;
03241 struct sockaddr from_addr;
03242 char str[100], buffer[80], buffer_tmp[80];
03243
03244
03245 status = ss_suspend_get_index(&idx);
03246
03247 if (status != SS_SUCCESS)
03248 return status;
03249
03250 return_status = SS_TIMEOUT;
03251
03252 do {
03253 FD_ZERO(&readfds);
03254
03255
03256 if (_suspend_struct[idx].listen_socket)
03257 FD_SET(_suspend_struct[idx].listen_socket, &readfds);
03258
03259
03260 if (_suspend_struct[idx].server_acception)
03261 for (i = 0; i < MAX_RPC_CONNECTION; i++) {
03262
03263 sock = _suspend_struct[idx].server_acception[i].recv_sock;
03264
03265
03266 if (!sock || _suspend_struct[idx].server_acception[i].tid != ss_gettid())
03267 continue;
03268
03269
03270 if (recv_tcp_check(sock) == 0)
03271 FD_SET(sock, &readfds);
03272
03273
03274 else if (msg == 0)
03275 millisec = 0;
03276
03277
03278 sock = _suspend_struct[idx].server_acception[i].event_sock;
03279
03280 if (!sock)
03281 continue;
03282
03283
03284 if (recv_event_check(sock) == 0)
03285 FD_SET(sock, &readfds);
03286
03287
03288 else if (msg == 0)
03289 millisec = 0;
03290 }
03291
03292
03293 if (_suspend_struct[idx].server_connection) {
03294 sock = _suspend_struct[idx].server_connection->recv_sock;
03295 if (sock)
03296 FD_SET(sock, &readfds);
03297 }
03298
03299
03300 if (_suspend_struct[idx].ipc_recv_socket)
03301 FD_SET(_suspend_struct[idx].ipc_recv_socket, &readfds);
03302
03303 timeout.tv_sec = millisec / 1000;
03304 timeout.tv_usec = (millisec % 1000) * 1000;
03305
03306 do {
03307 if (millisec < 0)
03308 status = select(FD_SETSIZE, &readfds, NULL, NULL, NULL);
03309 else
03310 status = select(FD_SETSIZE, &readfds, NULL, NULL, &timeout);
03311
03312
03313 if (status == -1 && timeout.tv_sec >= WATCHDOG_INTERVAL / 1000)
03314 timeout.tv_sec -= WATCHDOG_INTERVAL / 1000;
03315
03316 } while (status == -1);
03317
03318
03319 if (_suspend_struct[idx].listen_socket &&
03320 FD_ISSET(_suspend_struct[idx].listen_socket, &readfds)) {
03321 sock = _suspend_struct[idx].listen_socket;
03322
03323 if (_suspend_struct[idx].listen_dispatch) {
03324 status = _suspend_struct[idx].listen_dispatch(sock);
03325 if (status == RPC_SHUTDOWN)
03326 return status;
03327 }
03328 }
03329
03330
03331 if (_suspend_struct[idx].server_acception)
03332 for (i = 0; i < MAX_RPC_CONNECTION; i++) {
03333
03334 sock = _suspend_struct[idx].server_acception[i].recv_sock;
03335
03336
03337 if (!sock || _suspend_struct[idx].server_acception[i].tid != ss_gettid())
03338 continue;
03339
03340
03341
03342 if (recv_tcp_check(sock) || FD_ISSET(sock, &readfds)) {
03343 if (_suspend_struct[idx].server_dispatch) {
03344 status = _suspend_struct[idx].server_dispatch(i, sock, msg != 0);
03345 _suspend_struct[idx].server_acception[i].
03346 last_activity = ss_millitime();
03347
03348 if (status == SS_ABORT || status == SS_EXIT || status == RPC_SHUTDOWN)
03349 return status;
03350
03351 return_status = SS_SERVER_RECV;
03352 }
03353 }
03354
03355
03356 sock = _suspend_struct[idx].server_acception[i].event_sock;
03357 if (!sock)
03358 continue;
03359
03360 if (recv_event_check(sock) || FD_ISSET(sock, &readfds)) {
03361 if (_suspend_struct[idx].server_dispatch) {
03362 status = _suspend_struct[idx].server_dispatch(i, sock, msg != 0);
03363 _suspend_struct[idx].server_acception[i].
03364 last_activity = ss_millitime();
03365
03366 if (status == SS_ABORT || status == SS_EXIT || status == RPC_SHUTDOWN)
03367 return status;
03368
03369 return_status = SS_SERVER_RECV;
03370 }
03371 }
03372 }
03373
03374
03375 if (_suspend_struct[idx].server_connection) {
03376 sock = _suspend_struct[idx].server_connection->recv_sock;
03377
03378 if (sock && FD_ISSET(sock, &readfds)) {
03379 if (_suspend_struct[idx].client_dispatch)
03380 status = _suspend_struct[idx].client_dispatch(sock);
03381 else {
03382 status = SS_SUCCESS;
03383 size = recv_tcp(sock, buffer, sizeof(buffer), 0);
03384
03385 if (size <= 0)
03386 status = SS_ABORT;
03387 }
03388
03389 if (status == SS_ABORT) {
03390 sprintf(str, "Server connection broken to \'%s\'",
03391 _suspend_struct[idx].server_connection->host_name);
03392 cm_msg(MINFO, "ss_suspend", str);
03393
03394
03395 closesocket(_suspend_struct[idx].server_connection->send_sock);
03396 closesocket(_suspend_struct[idx].server_connection->recv_sock);
03397 closesocket(_suspend_struct[idx].server_connection->event_sock);
03398
03399 memset(_suspend_struct[idx].server_connection,
03400 0, sizeof(RPC_CLIENT_CONNECTION));
03401
03402
03403 return SS_ABORT;
03404 }
03405
03406 return_status = SS_CLIENT_RECV;
03407 }
03408 }
03409
03410
03411 if (_suspend_struct[idx].ipc_recv_socket &&
03412 FD_ISSET(_suspend_struct[idx].ipc_recv_socket, &readfds)) {
03413
03414 size = sizeof(struct sockaddr);
03415 size = recvfrom(_suspend_struct[idx].ipc_recv_socket,
03416 buffer, sizeof(buffer), 0, &from_addr, (int *) &size);
03417
03418
03419 server_socket = 0;
03420 if (_suspend_struct[idx].server_acception &&
03421 rpc_get_server_option(RPC_OSERVER_TYPE) != ST_REMOTE)
03422 for (i = 0; i < MAX_RPC_CONNECTION; i++) {
03423 sock = _suspend_struct[idx].server_acception[i].send_sock;
03424 if (sock && _suspend_struct[idx].server_acception[i].tid == ss_gettid())
03425 server_socket = sock;
03426 }
03427
03428
03429 do {
03430 FD_ZERO(&readfds);
03431 FD_SET(_suspend_struct[idx].ipc_recv_socket, &readfds);
03432
03433 timeout.tv_sec = 0;
03434 timeout.tv_usec = 0;
03435
03436 status = select(FD_SETSIZE, &readfds, NULL, NULL, &timeout);
03437
03438 if (status != -1
03439 && FD_ISSET(_suspend_struct[idx].ipc_recv_socket, &readfds)) {
03440 size = sizeof(struct sockaddr);
03441 size =
03442 recvfrom(_suspend_struct[idx].ipc_recv_socket,
03443 buffer_tmp, sizeof(buffer_tmp), 0, &from_addr, &size);
03444
03445
03446 if (buffer_tmp[0] != 'B' || strcmp(buffer_tmp, buffer) != 0)
03447 if (_suspend_struct[idx].ipc_dispatch)
03448 _suspend_struct[idx].ipc_dispatch(buffer_tmp, server_socket);
03449 }
03450
03451 } while (FD_ISSET(_suspend_struct[idx].ipc_recv_socket, &readfds));
03452
03453
03454 if (msg == MSG_BM && buffer[0] == 'B')
03455 return SS_SUCCESS;
03456 if (msg == MSG_ODB && buffer[0] == 'O')
03457 return SS_SUCCESS;
03458
03459
03460 if (_suspend_struct[idx].ipc_dispatch)
03461 _suspend_struct[idx].ipc_dispatch(buffer, server_socket);
03462
03463 return_status = SS_SUCCESS;
03464 }
03465
03466 } while (millisec < 0);
03467
03468 return return_status;
03469 }
03470
03471
03472 INT ss_resume(INT port, char *message)
03473
03474
03475
03476
03477
03478
03479
03480
03481
03482
03483
03484
03485
03486
03487
03488
03489
03490
03491
03492
03493
03494
03495 {
03496 INT status, idx;
03497
03498 if (ss_in_async_routine_flag) {
03499
03500 idx = 0;
03501 } else {
03502 status = ss_suspend_get_index(&idx);
03503
03504 if (status != SS_SUCCESS)
03505 return status;
03506 }
03507
03508 _suspend_struct[idx].bind_addr.sin_port = htons((short) port);
03509
03510 status = sendto(_suspend_struct[idx].ipc_send_socket, message,
03511 strlen(message) + 1, 0,
03512 (struct sockaddr *) &_suspend_struct[idx].bind_addr,
03513 sizeof(struct sockaddr_in));
03514
03515 if (status != (INT) strlen(message) + 1)
03516 return SS_SOCKET_ERROR;
03517
03518 return SS_SUCCESS;
03519 }
03520
03521
03522
03523
03524
03525
03526
03527
03528
03529 INT send_tcp(int sock, char *buffer, DWORD buffer_size, INT flags)
03530
03531
03532
03533
03534
03535
03536
03537
03538
03539
03540
03541
03542
03543
03544
03545
03546
03547
03548
03549
03550 {
03551 DWORD count;
03552 INT status;
03553
03554
03555
03556 for (count = 0; (INT) count < (INT) buffer_size - NET_TCP_SIZE;) {
03557 status = send(sock, buffer + count, NET_TCP_SIZE, flags & 0xFFFF);
03558 if (status != -1)
03559 count += status;
03560 else {
03561 if ((flags & 0x10000) == 0)
03562 cm_msg(MERROR, "send_tcp",
03563 "send(socket=%d,size=%d) returned %d, errno: %d (%s)",
03564 sock, NET_TCP_SIZE, status, errno, strerror(errno));
03565 return status;
03566 }
03567 }
03568
03569 while (count < buffer_size) {
03570 status = send(sock, buffer + count, buffer_size - count, flags & 0xFFFF);
03571 if (status != -1)
03572 count += status;
03573 else {
03574 if ((flags & 0x10000) == 0)
03575 cm_msg(MERROR, "send_tcp",
03576 "send(socket=%d,size=%d) returned %d, errno: %d (%s)",
03577 sock, (int) (buffer_size - count), status, errno, strerror(errno));
03578 return status;
03579 }
03580 }
03581
03582 return count;
03583 }
03584
03585
03586 INT recv_string(int sock, char *buffer, DWORD buffer_size, INT millisec)
03587
03588
03589
03590
03591
03592
03593
03594
03595
03596
03597
03598
03599
03600
03601
03602
03603
03604
03605
03606
03607
03608
03609
03610
03611 {
03612 INT i, status;
03613 DWORD n;
03614 fd_set readfds;
03615 struct timeval timeout;
03616
03617 n = 0;
03618 memset(buffer, 0, buffer_size);
03619
03620 do {
03621 if (millisec > 0) {
03622 FD_ZERO(&readfds);
03623 FD_SET(sock, &readfds);
03624
03625 timeout.tv_sec = millisec / 1000;
03626 timeout.tv_usec = (millisec % 1000) * 1000;
03627
03628 do {
03629 status = select(FD_SETSIZE, &readfds, NULL, NULL, &timeout);
03630
03631
03632 if (status == -1 && timeout.tv_sec >= WATCHDOG_INTERVAL / 1000)
03633 timeout.tv_sec -= WATCHDOG_INTERVAL / 1000;
03634
03635 } while (status == -1);
03636
03637 if (!FD_ISSET(sock, &readfds))
03638 break;
03639 }
03640
03641 i = recv(sock, buffer + n, 1, 0);
03642
03643 if (i <= 0)
03644 break;
03645
03646 n++;
03647
03648 if (n >= buffer_size)
03649 break;
03650
03651 } while (buffer[n - 1] && buffer[n - 1] != 10);
03652
03653 return n - 1;
03654 }
03655
03656
03657 INT recv_tcp(int sock, char *net_buffer, DWORD buffer_size, INT flags)
03658
03659
03660
03661
03662
03663
03664
03665
03666
03667
03668
03669
03670
03671
03672
03673
03674
03675
03676
03677
03678
03679
03680
03681
03682
03683
03684
03685
03686
03687 {
03688 INT param_size, n_received, n;
03689 NET_COMMAND *nc;
03690
03691 if (buffer_size < sizeof(NET_COMMAND_HEADER)) {
03692 cm_msg(MERROR, "recv_tcp", "parameters too large for network buffer");
03693 return -1;
03694 }
03695
03696
03697 n_received = 0;
03698 do {
03699 #ifdef OS_UNIX
03700 do {
03701 n = recv(sock, net_buffer + n_received, sizeof(NET_COMMAND_HEADER), flags);
03702
03703
03704 } while (n == -1 && errno == EINTR);
03705 #else
03706 n = recv(sock, net_buffer + n_received, sizeof(NET_COMMAND_HEADER), flags);
03707 #endif
03708
03709 if (n == 0) {
03710 cm_msg(MERROR, "recv_tcp",
03711 "header: recv returned %d, n_received = %d, unexpected connection closure",
03712 n, n_received);
03713 return n;
03714 }
03715
03716 if (n < 0) {
03717 cm_msg(MERROR, "recv_tcp",
03718 "header: recv returned %d, n_received = %d, errno: %d (%s)",
03719 n, n_received, errno, strerror(errno));
03720 return n;
03721 }
03722
03723 n_received += n;
03724
03725 } while (n_received < (int) sizeof(NET_COMMAND_HEADER));
03726
03727
03728
03729 nc = (NET_COMMAND *) net_buffer;
03730 param_size = nc->header.param_size;
03731 n_received = 0;
03732
03733 if (param_size == 0)
03734 return sizeof(NET_COMMAND_HEADER);
03735
03736 do {
03737 #ifdef OS_UNIX
03738 do {
03739 n = recv(sock,
03740 net_buffer + sizeof(NET_COMMAND_HEADER) + n_received,
03741 param_size - n_received, flags);
03742
03743
03744 } while (n == -1 && errno == EINTR);
03745 #else
03746 n = recv(sock, net_buffer + sizeof(NET_COMMAND_HEADER) + n_received,
03747 param_size - n_received, flags);
03748 #endif
03749
03750 if (n == 0) {
03751 cm_msg(MERROR, "recv_tcp",
03752 "param: recv returned %d, n_received = %d, unexpected connection closure",
03753 n, n_received);
03754 return n;
03755 }
03756
03757 if (n < 0) {
03758 cm_msg(MERROR, "recv_tcp",
03759 "param: recv returned %d, n_received = %d, errno: %d (%s)",
03760 n, n_received, errno, strerror(errno));
03761 return n;
03762 }
03763
03764 n_received += n;
03765 } while (n_received < param_size);
03766
03767 return sizeof(NET_COMMAND_HEADER) + param_size;
03768 }
03769
03770
03771 INT send_udp(int sock, char *buffer, DWORD buffer_size, INT flags)
03772
03773
03774
03775
03776
03777
03778
03779
03780
03781
03782
03783
03784
03785
03786
03787
03788
03789
03790
03791
03792
03793
03794 {
03795 INT status;
03796 UDP_HEADER *udp_header;
03797 static char udp_buffer[NET_UDP_SIZE];
03798 static INT serial_number = 0, n_received = 0;
03799 DWORD i, data_size;
03800
03801 udp_header = (UDP_HEADER *) udp_buffer;
03802 data_size = NET_UDP_SIZE - sizeof(UDP_HEADER);
03803
03804
03805
03806
03807
03808 if (buffer_size >= NET_UDP_SIZE / 2 && buffer_size <= data_size) {
03809
03810
03811
03812 if (n_received) {
03813 udp_header->serial_number = UDP_FIRST | n_received;
03814 udp_header->sequence_number = ++serial_number;
03815
03816 send(sock, udp_buffer, n_received + sizeof(UDP_HEADER), flags);
03817 n_received = 0;
03818 }
03819
03820 udp_header->serial_number = UDP_FIRST | buffer_size;
03821 udp_header->sequence_number = ++serial_number;
03822
03823 memcpy(udp_header + 1, buffer, buffer_size);
03824 status = send(sock, udp_buffer, buffer_size + sizeof(UDP_HEADER), flags);
03825 if (status == (INT) buffer_size + (int) sizeof(UDP_HEADER))
03826 status -= sizeof(UDP_HEADER);
03827
03828 return status;
03829 }
03830
03831
03832
03833
03834
03835 if (buffer_size <= data_size) {
03836
03837 if (buffer_size + n_received < data_size) {
03838 memcpy(udp_buffer + sizeof(UDP_HEADER) + n_received, buffer, buffer_size);
03839
03840 n_received += buffer_size;
03841 return buffer_size;
03842 }
03843
03844
03845 udp_header->serial_number = UDP_FIRST | n_received;
03846 udp_header->sequence_number = ++serial_number;
03847
03848 status = send(sock, udp_buffer, n_received + sizeof(UDP_HEADER), flags);
03849
03850 n_received = 0;
03851
03852 memcpy(udp_header + 1, buffer, buffer_size);
03853 n_received = buffer_size;
03854
03855 return buffer_size;
03856 }
03857
03858
03859
03860
03861
03862
03863
03864 if (n_received) {
03865 udp_header->serial_number = UDP_FIRST | n_received;
03866 udp_header->sequence_number = ++serial_number;
03867
03868 send(sock, udp_buffer, n_received + sizeof(UDP_HEADER), flags);
03869 n_received = 0;
03870 }
03871
03872 for (i = 0; i < ((buffer_size - 1) / data_size); i++) {
03873 if (i == 0) {
03874 udp_header->serial_number = UDP_FIRST | buffer_size;
03875 udp_header->sequence_number = ++serial_number;
03876 } else {
03877 udp_header->serial_number = serial_number;
03878 udp_header->sequence_number = i;
03879 }
03880
03881 memcpy(udp_header + 1, buffer + i * data_size, data_size);
03882 send(sock, udp_buffer, NET_UDP_SIZE, flags);
03883 }
03884
03885
03886 udp_header->serial_number = serial_number;
03887 udp_header->sequence_number = i;
03888 memcpy(udp_header + 1, buffer + i * data_size, buffer_size - i * data_size);
03889 status =
03890 send(sock, udp_buffer, sizeof(UDP_HEADER) + buffer_size - i * data_size, flags);
03891 if ((DWORD) status == sizeof(UDP_HEADER) + buffer_size - i * data_size)
03892 return buffer_size;
03893
03894 return status;
03895 }
03896
03897
03898 INT recv_udp(int sock, char *buffer, DWORD buffer_size, INT flags)
03899
03900
03901
03902
03903
03904
03905
03906
03907
03908
03909
03910
03911
03912
03913
03914
03915
03916
03917
03918
03919
03920 {
03921 INT i, status;
03922 UDP_HEADER *udp_header;
03923 char udp_buffer[NET_UDP_SIZE];
03924 DWORD serial_number, sequence_number, total_buffer_size;
03925 DWORD data_size, n_received;
03926 fd_set readfds;
03927 struct timeval timeout;
03928
03929 udp_header = (UDP_HEADER *) udp_buffer;
03930 data_size = NET_UDP_SIZE - sizeof(UDP_HEADER);
03931
03932
03933 #ifdef OS_UNIX
03934 do {
03935 i = recv(sock, udp_buffer, NET_UDP_SIZE, flags);
03936
03937
03938 } while (i == -1 && errno == EINTR);
03939 #else
03940 i = recv(sock, udp_buffer, NET_UDP_SIZE, flags);
03941 #endif
03942
03943 start:
03944
03945
03946 while (!(udp_header->serial_number & UDP_FIRST)) {
03947
03948 FD_ZERO(&readfds);
03949 FD_SET(sock, &readfds);
03950
03951 timeout.tv_sec = 0;
03952 timeout.tv_usec = 100000;
03953
03954 do {
03955 status = select(FD_SETSIZE, &readfds, NULL, NULL, &timeout);
03956 } while (status == -1);
03957
03958
03959
03960
03961
03962 if (!FD_ISSET(sock, &readfds))
03963 return 0;
03964
03965 #ifdef OS_UNIX
03966 do {
03967 i = recv(sock, udp_buffer, NET_UDP_SIZE, flags);
03968
03969
03970 } while (i == -1 && errno == EINTR);
03971 #else
03972 i = recv(sock, udp_buffer, NET_UDP_SIZE, flags);
03973 #endif
03974 }
03975
03976
03977 total_buffer_size = udp_header->serial_number & ~UDP_FIRST;
03978 serial_number = udp_header->sequence_number;
03979 sequence_number = 0;
03980
03981 if (total_buffer_size <= data_size) {
03982 if (buffer_size < total_buffer_size) {
03983 memcpy(buffer, udp_header + 1, buffer_size);
03984 return buffer_size;
03985 } else {
03986 memcpy(buffer, udp_header + 1, total_buffer_size);
03987 return total_buffer_size;
03988 }
03989 }
03990
03991
03992 n_received = data_size;
03993
03994 if (buffer_size < data_size) {
03995 memcpy(buffer, udp_header + 1, buffer_size);
03996 return buffer_size;
03997 }
03998
03999 memcpy(buffer, udp_header + 1, data_size);
04000
04001
04002 do {
04003
04004 FD_ZERO(&readfds);
04005 FD_SET(sock, &readfds);
04006
04007 timeout.tv_sec = 0;
04008 timeout.tv_usec = 100000;
04009
04010 do {
04011 status = select(FD_SETSIZE, &readfds, NULL, NULL, &timeout);
04012 } while (status == -1);
04013
04014
04015
04016
04017
04018 if (!FD_ISSET(sock, &readfds))
04019 return 0;
04020
04021 #ifdef OS_UNIX
04022 do {
04023 i = recv(sock, udp_buffer, NET_UDP_SIZE, flags);
04024
04025
04026 } while (i == -1 && errno == EINTR);
04027 #else
04028 i = recv(sock, udp_buffer, NET_UDP_SIZE, flags);
04029 #endif
04030
04031 sequence_number++;
04032
04033
04034 if (udp_header->serial_number != serial_number ||
04035 udp_header->sequence_number != sequence_number)
04036
04037 goto start;
04038
04039
04040 memcpy(buffer + n_received, udp_header + 1, i - sizeof(UDP_HEADER));
04041
04042 n_received += (i - sizeof(UDP_HEADER));
04043
04044 } while (n_received < total_buffer_size);
04045
04046 return n_received;
04047 }
04048
04049
04050
04051 #ifdef OS_MSDOS
04052 #ifdef sopen
04053
04054
04055
04056
04057
04058
04059 #undef sopen
04060
04061 int sopen(const char *path, int access, int shflag, int mode)
04062 {
04063 return open(path, (access) | (shflag), mode);
04064 }
04065
04066 #endif
04067 #endif
04068
04069
04070
04071
04072
04073
04074
04075
04076
04077 INT ss_tape_open(char *path, INT oflag, INT * channel)
04078
04079
04080
04081
04082
04083
04084
04085
04086
04087
04088
04089
04090
04091
04092
04093
04094
04095
04096
04097
04098
04099 {
04100 #ifdef OS_UNIX
04101 struct mtop arg;
04102
04103 cm_enable_watchdog(FALSE);
04104
04105 *channel = open(path, oflag, 0644);
04106
04107 cm_enable_watchdog(TRUE);
04108
04109 if (*channel < 0)
04110 cm_msg(MERROR, "ss_tape_open", strerror(errno));
04111
04112 if (*channel < 0) {
04113 if (errno == EIO)
04114 return SS_NO_TAPE;
04115 if (errno == EBUSY)
04116 return SS_DEV_BUSY;
04117 return errno;
04118 }
04119 #ifdef MTSETBLK
04120
04121 arg.mt_op = MTSETBLK;
04122 arg.mt_count = 0;
04123
04124 ioctl(*channel, MTIOCTOP, &arg);
04125 #endif
04126
04127 #endif
04128
04129 #ifdef OS_WINNT
04130 INT status;
04131 TAPE_GET_MEDIA_PARAMETERS m;
04132
04133 *channel = (INT) CreateFile(path, GENERIC_READ | GENERIC_WRITE, 0,
04134 0, OPEN_EXISTING, 0, NULL);
04135
04136 if (*channel == (INT) INVALID_HANDLE_VALUE) {
04137 status = GetLastError();
04138 if (status == ERROR_SHARING_VIOLATION) {
04139 cm_msg(MERROR, "ss_tape_open", "tape is used by other process");
04140 return SS_DEV_BUSY;
04141 }
04142 if (status == ERROR_FILE_NOT_FOUND) {
04143 cm_msg(MERROR, "ss_tape_open", "tape device \"%s\" doesn't exist", path);
04144 return SS_NO_TAPE;
04145 }
04146
04147 cm_msg(MERROR, "ss_tape_open", "unknown error %d", status);
04148 return status;
04149 }
04150
04151 status = GetTapeStatus((HANDLE) (*channel));
04152 if (status == ERROR_NO_MEDIA_IN_DRIVE || status == ERROR_BUS_RESET) {
04153 cm_msg(MERROR, "ss_tape_open", "no media in drive");
04154 return SS_NO_TAPE;
04155 }
04156
04157
04158 memset(&m, 0, sizeof(m));
04159 m.BlockSize = TAPE_BUFFER_SIZE;
04160 SetTapeParameters((HANDLE) (*channel), SET_TAPE_MEDIA_INFORMATION, &m);
04161
04162 #endif
04163
04164 return SS_SUCCESS;
04165 }
04166
04167
04168 INT ss_tape_close(INT channel)
04169
04170
04171
04172
04173
04174
04175
04176
04177
04178
04179
04180
04181
04182
04183
04184
04185
04186 {
04187 INT status;
04188
04189 #ifdef OS_UNIX
04190
04191 status = close(channel);
04192
04193 if (status < 0) {
04194 cm_msg(MERROR, "ss_tape_close", strerror(errno));
04195 return errno;
04196 }
04197 #endif
04198
04199 #ifdef OS_WINNT
04200
04201 if (!CloseHandle((HANDLE) channel)) {
04202 status = GetLastError();
04203 cm_msg(MERROR, "ss_tape_close", "unknown error %d", status);
04204 return status;
04205 }
04206 #endif
04207
04208 return SS_SUCCESS;
04209 }
04210
04211
04212 INT ss_tape_status(char *path)
04213
04214
04215
04216
04217
04218
04219
04220
04221
04222
04223
04224
04225
04226
04227
04228
04229 {
04230 #ifdef OS_UNIX
04231 char str[256];
04232
04233 sprintf(str, "mt -f %s status", path);
04234 system(str);
04235 #endif
04236
04237 #ifdef OS_WINNT
04238 INT status, channel;
04239 DWORD size;
04240 TAPE_GET_MEDIA_PARAMETERS m;
04241 TAPE_GET_DRIVE_PARAMETERS d;
04242 double x;
04243
04244 channel = (INT) CreateFile(path, GENERIC_READ | GENERIC_WRITE, 0,
04245 0, OPEN_EXISTING, 0, NULL);
04246
04247 if (channel == (INT) INVALID_HANDLE_VALUE) {
04248 status = GetLastError();
04249 if (status == ERROR_SHARING_VIOLATION) {
04250 cm_msg(MINFO, "ss_tape_status", "tape is used by other process");
04251 return SS_SUCCESS;
04252 }
04253 if (status == ERROR_FILE_NOT_FOUND) {
04254 cm_msg(MINFO, "ss_tape_status", "tape device \"%s\" doesn't exist", path);
04255 return SS_SUCCESS;
04256 }
04257
04258 cm_msg(MINFO, "ss_tape_status", "unknown error %d", status);
04259 return status;
04260 }
04261
04262
04263 GetTapeParameters((HANDLE) channel, GET_TAPE_DRIVE_INFORMATION, &size, &d);
04264 GetTapeParameters((HANDLE) channel, GET_TAPE_DRIVE_INFORMATION, &size, &d);
04265
04266 status = GetTapeStatus((HANDLE) channel);
04267 if (status == ERROR_NO_MEDIA_IN_DRIVE || status == ERROR_BUS_RESET) {
04268 cm_msg(MINFO, "ss_tape_status", "no media in drive");
04269 CloseHandle((HANDLE) channel);
04270 return SS_SUCCESS;
04271 }
04272
04273 GetTapeParameters((HANDLE) channel, GET_TAPE_DRIVE_INFORMATION, &size, &d);
04274 GetTapeParameters((HANDLE) channel, GET_TAPE_MEDIA_INFORMATION, &size, &m);
04275
04276 printf("Hardware error correction is %s\n", d.ECC ? "on" : "off");
04277 printf("Hardware compression is %s\n", d.Compression ? "on" : "off");
04278 printf("Tape %s write protected\n", m.WriteProtected ? "is" : "is not");
04279
04280 if (d.FeaturesLow & TAPE_DRIVE_TAPE_REMAINING) {
04281 x = ((double) m.Remaining.LowPart + (double) m.Remaining.HighPart * 4.294967295E9)
04282 / 1024.0 / 1000.0;
04283 printf("Tape capacity remaining is %d MB\n", (int) x);
04284 } else
04285 printf("Tape capacity is not reported by tape\n");
04286
04287 CloseHandle((HANDLE) channel);
04288
04289 #endif
04290
04291 return SS_SUCCESS;
04292 }
04293
04294
04295 INT ss_tape_write(INT channel, void *pdata, INT count)
04296
04297
04298
04299
04300
04301
04302
04303
04304
04305
04306
04307
04308
04309
04310
04311
04312
04313
04314
04315
04316 {
04317 #ifdef OS_UNIX
04318 INT status;
04319
04320 do {
04321 status = write(channel, pdata, count);
04322
04323
04324
04325
04326 } while (status == -1 && errno == EINTR);
04327
04328 if (status != count) {
04329 cm_msg(MERROR, "ss_tape_write", strerror(errno));
04330
04331 if (errno == EIO)
04332 return SS_IO_ERROR;
04333 else
04334 return SS_TAPE_ERROR;
04335 }
04336 #endif
04337
04338 #ifdef OS_WINNT
04339 INT status;
04340 DWORD written;
04341
04342 WriteFile((HANDLE) channel, pdata, count, &written, NULL);
04343 if (written != (DWORD) count) {
04344 status = GetLastError();
04345 cm_msg(MERROR, "ss_tape_write", "error %d", status);
04346
04347 return SS_IO_ERROR;
04348 }
04349 #endif
04350
04351 return SS_SUCCESS;
04352 }
04353
04354
04355 INT ss_tape_read(INT channel, void *pdata, INT * count)
04356
04357
04358
04359
04360
04361
04362
04363
04364
04365
04366
04367
04368
04369
04370
04371
04372
04373
04374
04375 {
04376 #ifdef OS_UNIX
04377 INT n, status;
04378
04379 do {
04380 n = read(channel, pdata, *count);
04381 } while (n == -1 && errno == EINTR);
04382
04383 if (n == -1) {
04384 if (errno == ENOSPC || errno == EIO)
04385 status = SS_END_OF_TAPE;
04386 else {
04387 if (n == 0 && errno == 0)
04388 status = SS_END_OF_FILE;
04389 else {
04390 cm_msg(MERROR, "ss_tape_read",
04391 "unexpected tape error: n=%d, errno=%d\n", n, errno);
04392 status = errno;
04393 }
04394 }
04395 } else
04396 status = SS_SUCCESS;
04397 *count = n;
04398
04399 return status;
04400
04401 #elif defined(OS_WINNT)
04402
04403 INT status;
04404 DWORD read;
04405
04406 if (!ReadFile((HANDLE) channel, pdata, *count, &read, NULL)) {
04407 status = GetLastError();
04408 if (status == ERROR_NO_DATA_DETECTED)
04409 status = SS_END_OF_TAPE;
04410 else if (status == ERROR_FILEMARK_DETECTED)
04411 status = SS_END_OF_FILE;
04412 else if (status == ERROR_MORE_DATA)
04413 status = SS_SUCCESS;
04414 else
04415 cm_msg(MERROR, "ss_tape_read",
04416 "unexpected tape error: n=%d, errno=%d\n", read, status);
04417 } else
04418 status = SS_SUCCESS;
04419
04420 *count = read;
04421 return status;
04422
04423 #else
04424
04425 return SS_SUCCESS;
04426
04427 #endif
04428 }
04429
04430
04431 INT ss_tape_write_eof(INT channel)
04432
04433
04434
04435
04436
04437
04438
04439
04440
04441
04442
04443
04444
04445
04446
04447
04448
04449 {
04450 INT status;
04451
04452 #ifdef OS_UNIX
04453 struct mtop arg;
04454
04455 arg.mt_op = MTWEOF;
04456 arg.mt_count = 1;
04457
04458 cm_enable_watchdog(FALSE);
04459
04460 status = ioctl(channel, MTIOCTOP, &arg);
04461
04462 cm_enable_watchdog(TRUE);
04463
04464 if (status < 0) {
04465 cm_msg(MERROR, "ss_tape_write_eof", strerror(errno));
04466 return errno;
04467 }
04468 #endif
04469
04470 #ifdef OS_WINNT
04471
04472 TAPE_GET_DRIVE_PARAMETERS d;
04473 DWORD size;
04474
04475 size = sizeof(TAPE_GET_DRIVE_PARAMETERS);
04476 GetTapeParameters((HANDLE) channel, GET_TAPE_DRIVE_INFORMATION, &size, &d);
04477
04478 if (d.FeaturesHigh & TAPE_DRIVE_WRITE_FILEMARKS)
04479 status = WriteTapemark((HANDLE) channel, TAPE_FILEMARKS, 1, FALSE);
04480 else if (d.FeaturesHigh & TAPE_DRIVE_WRITE_LONG_FMKS)
04481 status = WriteTapemark((HANDLE) channel, TAPE_LONG_FILEMARKS, 1, FALSE);
04482 else if (d.FeaturesHigh & TAPE_DRIVE_WRITE_SHORT_FMKS)
04483 status = WriteTapemark((HANDLE) channel, TAPE_SHORT_FILEMARKS, 1, FALSE);
04484 else
04485 cm_msg(MERROR, "ss_tape_write_eof", "tape doesn't support writing of filemarks");
04486
04487 if (status != NO_ERROR) {
04488 cm_msg(MERROR, "ss_tape_write_eof", "unknown error %d", status);
04489 return status;
04490 }
04491 #endif
04492
04493 return SS_SUCCESS;
04494 }
04495
04496
04497 INT ss_tape_fskip(INT channel, INT count)
04498
04499
04500
04501
04502
04503
04504
04505
04506
04507
04508
04509
04510
04511
04512
04513
04514
04515
04516 {
04517 INT status;
04518
04519 #ifdef OS_UNIX
04520 struct mtop arg;
04521
04522 if (count > 0)
04523 arg.mt_op = MTFSF;
04524 else
04525 arg.mt_op = MTBSF;
04526 arg.mt_count = abs(count);
04527
04528 cm_enable_watchdog(FALSE);
04529
04530 status = ioctl(channel, MTIOCTOP, &arg);
04531
04532 cm_enable_watchdog(TRUE);
04533
04534 if (status < 0) {
04535 cm_msg(MERROR, "ss_tape_fskip", strerror(errno));
04536 return errno;
04537 }
04538 #endif
04539
04540 #ifdef OS_WINNT
04541
04542 status = SetTapePosition((HANDLE) channel, TAPE_SPACE_FILEMARKS, 0,
04543 (DWORD) count, 0, FALSE);
04544
04545 if (status == ERROR_END_OF_MEDIA)
04546 return SS_END_OF_TAPE;
04547
04548 if (status != NO_ERROR) {
04549 cm_msg(MERROR, "ss_tape_fskip", "error %d", status);
04550 return status;
04551 }
04552 #endif
04553
04554 return SS_SUCCESS;
04555 }
04556
04557
04558 INT ss_tape_rskip(INT channel, INT count)
04559
04560
04561
04562
04563
04564
04565
04566
04567
04568
04569
04570
04571
04572
04573
04574
04575
04576
04577 {
04578 INT status;
04579
04580 #ifdef OS_UNIX
04581 struct mtop arg;
04582
04583 if (count > 0)
04584 arg.mt_op = MTFSR;
04585 else
04586 arg.mt_op = MTBSR;
04587 arg.mt_count = abs(count);
04588
04589 cm_enable_watchdog(FALSE);
04590
04591 status = ioctl(channel, MTIOCTOP, &arg);
04592
04593 cm_enable_watchdog(TRUE);
04594
04595 if (status < 0) {
04596 cm_msg(MERROR, "ss_tape_rskip", strerror(errno));
04597 return errno;
04598 }
04599 #endif
04600
04601 #ifdef OS_WINNT
04602
04603 status =
04604 SetTapePosition((HANDLE) channel, TAPE_SPACE_RELATIVE_BLOCKS, 0,
04605 (DWORD) count, 0, FALSE);
04606 if (status != NO_ERROR) {
04607 cm_msg(MERROR, "ss_tape_rskip", "error %d", status);
04608 return status;
04609 }
04610 #endif
04611
04612 return CM_SUCCESS;
04613 }
04614
04615
04616 INT ss_tape_rewind(INT channel)
04617
04618
04619
04620
04621
04622
04623
04624
04625
04626
04627
04628
04629
04630
04631
04632
04633
04634 {
04635 INT status;
04636
04637 #ifdef OS_UNIX
04638 struct mtop arg;
04639
04640 arg.mt_op = MTREW;
04641 arg.mt_count = 0;
04642
04643 cm_enable_watchdog(FALSE);
04644
04645 status = ioctl(channel, MTIOCTOP, &arg);
04646
04647 cm_enable_watchdog(TRUE);
04648
04649 if (status < 0) {
04650 cm_msg(MERROR, "ss_tape_rewind", strerror(errno));
04651 return errno;
04652 }
04653 #endif
04654
04655 #ifdef OS_WINNT
04656
04657 status = SetTapePosition((HANDLE) channel, TAPE_REWIND, 0, 0, 0, FALSE);
04658 if (status != NO_ERROR) {
04659 cm_msg(MERROR, "ss_tape_rewind", "error %d", status);
04660 return status;
04661 }
04662 #endif
04663
04664 return CM_SUCCESS;
04665 }
04666
04667
04668 INT ss_tape_spool(INT channel)
04669
04670
04671
04672
04673
04674
04675
04676
04677
04678
04679
04680
04681
04682
04683
04684
04685
04686 {
04687 INT status;
04688
04689 #ifdef OS_UNIX
04690 struct mtop arg;
04691
04692 #ifdef MTEOM
04693 arg.mt_op = MTEOM;
04694 #else
04695 arg.mt_op = MTSEOD;
04696 #endif
04697 arg.mt_count = 0;
04698
04699 cm_enable_watchdog(FALSE);
04700
04701 status = ioctl(channel, MTIOCTOP, &arg);
04702
04703 cm_enable_watchdog(TRUE);
04704
04705 if (status < 0) {
04706 cm_msg(MERROR, "ss_tape_rewind", strerror(errno));
04707 return errno;
04708 }
04709 #endif
04710
04711 #ifdef OS_WINNT
04712
04713 status = SetTapePosition((HANDLE) channel, TAPE_SPACE_END_OF_DATA, 0, 0, 0, FALSE);
04714 if (status != NO_ERROR) {
04715 cm_msg(MERROR, "ss_tape_spool", "error %d", status);
04716 return status;
04717 }
04718 #endif
04719
04720 return CM_SUCCESS;
04721 }
04722
04723
04724 INT ss_tape_mount(INT channel)
04725
04726
04727
04728
04729
04730
04731
04732
04733
04734
04735
04736
04737
04738
04739
04740
04741
04742 {
04743 INT status;
04744
04745 #ifdef OS_UNIX
04746 struct mtop arg;
04747
04748 #ifdef MTLOAD
04749 arg.mt_op = MTLOAD;
04750 #else
04751 arg.mt_op = MTNOP;
04752 #endif
04753 arg.mt_count = 0;
04754
04755 cm_enable_watchdog(FALSE);
04756
04757 status = ioctl(channel, MTIOCTOP, &arg);
04758
04759 cm_enable_watchdog(TRUE);
04760
04761 if (status < 0) {
04762 cm_msg(MERROR, "ss_tape_mount", strerror(errno));
04763 return errno;
04764 }
04765 #endif
04766
04767 #ifdef OS_WINNT
04768
04769 status = PrepareTape((HANDLE) channel, TAPE_LOAD, FALSE);
04770 if (status != NO_ERROR) {
04771 cm_msg(MERROR, "ss_tape_mount", "error %d", status);
04772 return status;
04773 }
04774 #endif
04775
04776 return CM_SUCCESS;
04777 }
04778
04779
04780 INT ss_tape_unmount(INT channel)
04781
04782
04783
04784
04785
04786
04787
04788
04789
04790
04791
04792
04793
04794
04795
04796
04797
04798 {
04799 INT status;
04800
04801 #ifdef OS_UNIX
04802 struct mtop arg;
04803
04804 #ifdef MTOFFL
04805 arg.mt_op = MTOFFL;
04806 #else
04807 arg.mt_op = MTUNLOAD;
04808 #endif
04809 arg.mt_count = 0;
04810
04811 cm_enable_watchdog(FALSE);
04812
04813 status = ioctl(channel, MTIOCTOP, &arg);
04814
04815 cm_enable_watchdog(TRUE);
04816
04817 if (status < 0) {
04818 cm_msg(MERROR, "ss_tape_unmount", strerror(errno));
04819 return errno;
04820 }
04821 #endif
04822
04823 #ifdef OS_WINNT
04824
04825 status = PrepareTape((HANDLE) channel, TAPE_UNLOAD, FALSE);
04826 if (status != NO_ERROR) {
04827 cm_msg(MERROR, "ss_tape_unmount", "error %d", status);
04828 return status;
04829 }
04830 #endif
04831
04832 return CM_SUCCESS;
04833 }
04834
04835
04836 INT ss_tape_get_blockn(INT channel)
04837
04838
04839
04840
04841
04842
04843
04844
04845 {
04846 #if defined(OS_DARWIN)
04847
04848 return 0;
04849
04850 #elif defined(OS_UNIX)
04851
04852 INT status;
04853 struct mtpos arg;
04854
04855 cm_enable_watchdog(FALSE);
04856 status = ioctl(channel, MTIOCPOS, &arg);
04857 cm_enable_watchdog(TRUE);
04858 if (status < 0) {
04859 if (errno == EIO)
04860 return 0;
04861 else {
04862 cm_msg(MERROR, "ss_tape_get_blockn", strerror(errno));
04863 return -errno;
04864 }
04865 }
04866 return (arg.mt_blkno);
04867
04868 #elif defined(OS_WINNT)
04869
04870 INT status;
04871 TAPE_GET_MEDIA_PARAMETERS media;
04872 unsigned long size;
04873
04874 status =
04875 GetTapeParameters((HANDLE) channel, GET_TAPE_MEDIA_INFORMATION, &size, &media);
04876 return (media.PartitionCount);
04877
04878 #endif
04879 }
04880
04881
04882
04883
04884
04885
04886
04887
04888
04889
04890 double ss_disk_free(char *path)
04891
04892
04893
04894
04895
04896
04897
04898
04899
04900
04901
04902
04903
04904
04905
04906 {
04907 #ifdef OS_UNIX
04908 #if defined(OS_OSF1)
04909 struct statfs st;
04910 statfs(path, &st, sizeof(st));
04911 return (double) st.f_bavail * st.f_bsize;
04912 #elif defined(OS_LINUX)
04913 struct statfs st;
04914 statfs(path, &st);
04915 return (double) st.f_bavail * st.f_bsize;
04916 #elif defined(OS_SOLARIS)
04917 struct statvfs st;
04918 statvfs(path, &st);
04919 return (double) st.f_bavail * st.f_bsize;
04920 #elif defined(OS_IRIX)
04921 struct statfs st;
04922 statfs(path, &st, sizeof(struct statfs), 0);
04923 return (double) st.f_bfree * st.f_bsize;
04924 #else
04925 struct fs_data st;
04926 statfs(path, &st);
04927 return (double) st.fd_otsize * st.fd_bfree;
04928 #endif
04929
04930 #elif defined(OS_WINNT)
04931 DWORD SectorsPerCluster;
04932 DWORD BytesPerSector;
04933 DWORD NumberOfFreeClusters;
04934 DWORD TotalNumberOfClusters;
04935 char str[80];
04936
04937 strcpy(str, path);
04938 if (strchr(str, ':') != NULL) {
04939 *(strchr(str, ':') + 1) = 0;
04940 strcat(str, DIR_SEPARATOR_STR);
04941 GetDiskFreeSpace(str, &SectorsPerCluster, &BytesPerSector,
04942 &NumberOfFreeClusters, &TotalNumberOfClusters);
04943 } else
04944 GetDiskFreeSpace(NULL, &SectorsPerCluster, &BytesPerSector,
04945 &NumberOfFreeClusters, &TotalNumberOfClusters);
04946
04947 return (double) NumberOfFreeClusters *SectorsPerCluster * BytesPerSector;
04948 #else
04949
04950 return 1e9;
04951
04952 #endif
04953 }
04954
04955 #if defined(OS_ULTRIX) || defined(OS_WINNT)
04956 int fnmatch(const char *pat, const char *str, const int flag)
04957 {
04958 while (*str != '\0') {
04959 if (*pat == '*') {
04960 pat++;
04961 if ((str = strchr(str, *pat)) == NULL)
04962 return -1;
04963 }
04964 if (*pat == *str) {
04965 pat++;
04966 str++;
04967 } else
04968 return -1;
04969 }
04970 if (*pat == '\0')
04971 return 0;
04972 else
04973 return -1;
04974 }
04975 #endif
04976
04977 #ifdef OS_WINNT
04978 HANDLE pffile;
04979 LPWIN32_FIND_DATA lpfdata;
04980 #endif
04981 INT ss_file_find(char *path, char *pattern, char **plist)
04982
04983
04984
04985
04986
04987
04988
04989
04990
04991
04992
04993
04994
04995
04996
04997
04998
04999 {
05000 int i;
05001 #ifdef OS_UNIX
05002 DIR *dir_pointer;
05003 struct dirent *dp;
05004
05005 if ((dir_pointer = opendir(path)) == NULL)
05006 return 0;
05007 *plist = (char *) malloc(MAX_STRING_LENGTH);
05008 i = 0;
05009 for (dp = readdir(dir_pointer); dp != NULL; dp = readdir(dir_pointer)) {
05010 if (fnmatch(pattern, dp->d_name, 0) == 0) {
05011 *plist = (char *) realloc(*plist, (i + 1) * MAX_STRING_LENGTH);
05012 strncpy(*plist + (i * MAX_STRING_LENGTH), dp->d_name, strlen(dp->d_name));
05013 *(*plist + (i * MAX_STRING_LENGTH) + strlen(dp->d_name)) = '\0';
05014 i++;
05015 seekdir(dir_pointer, telldir(dir_pointer));
05016 }
05017 }
05018 closedir(dir_pointer);
05019 #endif
05020 #ifdef OS_WINNT
05021 char str[255];
05022 int first;
05023
05024 strcpy(str, path);
05025 strcat(str, "\\");
05026 strcat(str, pattern);
05027 first = 1;
05028 i = 0;
05029 lpfdata = (WIN32_FIND_DATA *) malloc(sizeof(WIN32_FIND_DATA));
05030 *plist = (char *) malloc(MAX_STRING_LENGTH);
05031 pffile = FindFirstFile(str, lpfdata);
05032 if (pffile == INVALID_HANDLE_VALUE)
05033 return 0;
05034 first = 0;
05035 *plist = (char *) realloc(*plist, (i + 1) * MAX_STRING_LENGTH);
05036 strncpy(*plist + (i * MAX_STRING_LENGTH), lpfdata->cFileName,
05037 strlen(lpfdata->cFileName));
05038 *(*plist + (i * MAX_STRING_LENGTH) + strlen(lpfdata->cFileName)) = '\0';
05039 i++;
05040 while (FindNextFile(pffile, lpfdata)) {
05041 *plist = (char *) realloc(*plist, (i + 1) * MAX_STRING_LENGTH);
05042 strncpy(*plist + (i * MAX_STRING_LENGTH), lpfdata->cFileName,
05043 strlen(lpfdata->cFileName));
05044 *(*plist + (i * MAX_STRING_LENGTH) + strlen(lpfdata->cFileName)) = '\0';
05045 i++;
05046 }
05047 free(lpfdata);
05048 #endif
05049 return i;
05050 }
05051
05052 INT ss_file_remove(char *path)
05053
05054
05055
05056
05057
05058
05059
05060
05061
05062
05063
05064
05065
05066
05067
05068 {
05069 return remove(path);
05070 }
05071
05072 double ss_file_size(char *path)
05073
05074
05075
05076
05077
05078
05079
05080
05081
05082
05083
05084
05085
05086
05087
05088 {
05089 struct stat stat_buf;
05090
05091
05092 stat(path, &stat_buf);
05093 return (double) stat_buf.st_size;
05094 }
05095
05096 double ss_disk_size(char *path)
05097
05098
05099
05100
05101
05102
05103
05104
05105
05106
05107
05108
05109
05110
05111
05112 {
05113 #ifdef OS_UNIX
05114 #if defined(OS_OSF1)
05115 struct statfs st;
05116 statfs(path, &st, sizeof(st));
05117 return (double) st.f_blocks * st.f_fsize;
05118 #elif defined(OS_LINUX)
05119 struct statfs st;
05120 statfs(path, &st);
05121 return (double) st.f_blocks * st.f_bsize;
05122 #elif defined(OS_SOLARIS)
05123 struct statvfs st;
05124 statvfs(path, &st);
05125 if (st.f_frsize > 0)
05126 return (double) st.f_blocks * st.f_frsize;
05127 else
05128 return (double) st.f_blocks * st.f_bsize;
05129 #elif defined(OS_ULTRIX)
05130 struct fs_data st;
05131 statfs(path, &st);
05132 return (double) st.fd_btot * 1024;
05133 #elif defined(OS_IRIX)
05134 struct statfs st;
05135 statfs(path, &st, sizeof(struct statfs), 0);
05136 return (double) st.f_blocks * st.f_bsize;
05137 #else
05138 #error ss_disk_size not defined for this OS
05139 #endif
05140 #endif
05141
05142 #ifdef OS_WINNT
05143 DWORD SectorsPerCluster;
05144 DWORD BytesPerSector;
05145 DWORD NumberOfFreeClusters;
05146 DWORD TotalNumberOfClusters;
05147 char str[80];
05148
05149 strcpy(str, path);
05150 if (strchr(str, ':') != NULL) {
05151 *(strchr(str, ':') + 1) = 0;
05152 strcat(str, DIR_SEPARATOR_STR);
05153 GetDiskFreeSpace(str, &SectorsPerCluster, &BytesPerSector,
05154 &NumberOfFreeClusters, &TotalNumberOfClusters);
05155 } else
05156 GetDiskFreeSpace(NULL, &SectorsPerCluster, &BytesPerSector,
05157 &NumberOfFreeClusters, &TotalNumberOfClusters);
05158
05159 return (double) TotalNumberOfClusters *SectorsPerCluster * BytesPerSector;
05160 #endif
05161
05162 return 1e9;
05163 }
05164
05165
05166
05167
05168
05169
05170
05171
05172
05173 void ss_clear_screen()
05174
05175
05176
05177
05178
05179
05180
05181
05182
05183
05184
05185
05186
05187
05188
05189
05190 {
05191 #ifdef OS_WINNT
05192
05193 HANDLE hConsole;
05194 COORD coordScreen = { 0, 0 };
05195 BOOL bSuccess;
05196 DWORD cCharsWritten;
05197 CONSOLE_SCREEN_BUFFER_INFO csbi;
05198 DWORD dwConSize;
05199
05200 hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
05201
05202
05203 bSuccess = GetConsoleScreenBufferInfo(hConsole, &csbi);
05204 dwConSize = csbi.dwSize.X * csbi.dwSize.Y;
05205
05206
05207 bSuccess = FillConsoleOutputCharacter(hConsole, (TCHAR) ' ',
05208 dwConSize, coordScreen, &cCharsWritten);
05209
05210
05211 bSuccess = SetConsoleCursorPosition(hConsole, coordScreen);
05212 return;
05213
05214 #endif
05215 #if defined(OS_UNIX) || defined(OS_VXWORKS) || defined(OS_VMS)
05216 printf("\033[2J");
05217 #endif
05218 #ifdef OS_MSDOS
05219 clrscr();
05220 #endif
05221 }
05222
05223
05224 void ss_set_screen_size(int x, int y)
05225
05226
05227
05228
05229
05230
05231
05232
05233
05234
05235
05236
05237
05238
05239
05240
05241 {
05242 #ifdef OS_WINNT
05243
05244 HANDLE hConsole;
05245 COORD coordSize;
05246
05247 coordSize.X = (short) x;
05248 coordSize.Y = (short) y;
05249 hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
05250 SetConsoleScreenBufferSize(hConsole, coordSize);
05251
05252 #else
05253 int i;
05254 i = x;
05255 i = y;
05256 #endif
05257 }
05258
05259
05260 void ss_printf(INT x, INT y, const char *format, ...)
05261
05262
05263
05264
05265
05266
05267
05268
05269
05270
05271
05272
05273
05274
05275
05276
05277
05278
05279
05280
05281 {
05282 char str[256];
05283 va_list argptr;
05284
05285 va_start(argptr, format);
05286 vsprintf(str, (char *) format, argptr);
05287 va_end(argptr);
05288
05289 #ifdef OS_WINNT
05290 {
05291 HANDLE hConsole;
05292 COORD dwWriteCoord;
05293 DWORD cCharsWritten;
05294
05295 hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
05296
05297 dwWriteCoord.X = (short) x;
05298 dwWriteCoord.Y = (short) y;
05299
05300 WriteConsoleOutputCharacter(hConsole, str, strlen(str),
05301 dwWriteCoord, &cCharsWritten);
05302 }
05303
05304 #endif
05305
05306 #if defined(OS_UNIX) || defined(OS_VXWORKS) || defined(OS_VMS)
05307 printf("\033[%1d;%1d;H", y + 1, x + 1);
05308 printf(str);
05309 fflush(stdout);
05310 #endif
05311
05312 #ifdef OS_MSDOS
05313 gotoxy(x + 1, y + 1);
05314 cputs(str);
05315 #endif
05316 }
05317
05318
05319 char *ss_getpass(char *prompt)
05320
05321
05322
05323
05324
05325
05326
05327
05328
05329
05330
05331
05332
05333
05334
05335
05336 {
05337 static char password[32];
05338
05339 printf(prompt);
05340 memset(password, 0, sizeof(password));
05341
05342 #ifdef OS_UNIX
05343 return (char *) getpass("");
05344 #elif defined(OS_WINNT)
05345 {
05346 HANDLE hConsole;
05347 DWORD nCharsRead;
05348
05349 hConsole = GetStdHandle(STD_INPUT_HANDLE);
05350 SetConsoleMode(hConsole, ENABLE_LINE_INPUT);
05351 ReadConsole(hConsole, password, sizeof(password), &nCharsRead, NULL);
05352 SetConsoleMode(hConsole, ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT |
05353 ENABLE_PROCESSED_INPUT | ENABLE_MOUSE_INPUT);
05354 printf("\n");
05355
05356 if (password[strlen(password) - 1] == '\r')
05357 password[strlen(password) - 1] = 0;
05358
05359 return password;
05360 }
05361 #elif defined(OS_MSDOS)
05362 {
05363 char c, *ptr;
05364
05365 ptr = password;
05366 while ((c = getchar()) != EOF && c != '\n')
05367 *ptr++ = c;
05368 *ptr = 0;
05369
05370 printf("\n");
05371 return password;
05372 }
05373 #else
05374 {
05375 ss_gets(password, 32);
05376 return password;
05377 }
05378 #endif
05379 }
05380
05381
05382 INT ss_getchar(BOOL reset)
05383
05384
05385
05386
05387
05388
05389
05390
05391
05392
05393
05394
05395
05396
05397
05398
05399
05400
05401
05402 {
05403 #ifdef OS_UNIX
05404
05405 static BOOL init = FALSE;
05406 static struct termios save_termios;
05407 struct termios buf;
05408 int i, fd;
05409 char c[3];
05410
05411 if (_daemon_flag)
05412 return 0;
05413
05414 fd = fileno(stdin);
05415
05416 if (reset) {
05417 if (init)
05418 tcsetattr(fd, TCSAFLUSH, &save_termios);
05419 init = FALSE;
05420 return 0;
05421 }
05422
05423 if (!init) {
05424 tcgetattr(fd, &save_termios);
05425 memcpy(&buf, &save_termios, sizeof(buf));
05426
05427 buf.c_lflag &= ~(ECHO | ICANON | IEXTEN);
05428
05429 buf.c_iflag &= ~(ICRNL | INPCK | ISTRIP | IXON);
05430
05431 buf.c_cflag &= ~(CSIZE | PARENB);
05432 buf.c_cflag |= CS8;
05433
05434 buf.c_cc[VMIN] = 0;
05435 buf.c_cc[VTIME] = 0;
05436
05437 tcsetattr(fd, TCSAFLUSH, &buf);
05438 init = TRUE;
05439 }
05440
05441 memset(c, 0, 3);
05442 i = read(fd, c, 1);
05443
05444 if (i == 0)
05445 return 0;
05446
05447
05448 if (c[0] == 27) {
05449 i = read(fd, c, 2);
05450 if (i == 0)
05451 return 27;
05452
05453
05454 if (c[1] < 65)
05455 read(fd, c, 1);
05456
05457
05458 switch (c[1]) {
05459 case 49:
05460 return CH_HOME;
05461 case 50:
05462 return CH_INSERT;
05463 case 51:
05464 return CH_DELETE;
05465 case 52:
05466 return CH_END;
05467 case 53:
05468 return CH_PUP;
05469 case 54:
05470 return CH_PDOWN;
05471 case 65:
05472 return CH_UP;
05473 case 66:
05474 return CH_DOWN;
05475 case 67:
05476 return CH_RIGHT;
05477 case 68:
05478 return CH_LEFT;
05479 }
05480 }
05481
05482
05483 if (c[0] == 127)
05484 return CH_BS;
05485
05486 return c[0];
05487
05488 #elif defined(OS_WINNT)
05489
05490 static BOOL init = FALSE;
05491 static INT repeat_count = 0;
05492 static INT repeat_char;
05493 HANDLE hConsole;
05494 DWORD nCharsRead;
05495 INPUT_RECORD ir;
05496 OSVERSIONINFO vi;
05497
05498
05499 vi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
05500 GetVersionEx(&vi);
05501
05502 if (vi.dwPlatformId != VER_PLATFORM_WIN32_NT) {
05503
05504 int c;
05505
05506 if (!kbhit())
05507 return 0;
05508
05509 c = getch();
05510 if (c == 224) {
05511 c = getch();
05512 switch (c) {
05513 case 71:
05514 return CH_HOME;
05515 case 72:
05516 return CH_UP;
05517 case 73:
05518 return CH_PUP;
05519 case 75:
05520 return CH_LEFT;
05521 case 77:
05522 return CH_RIGHT;
05523 case 79:
05524 return CH_END;
05525 case 80:
05526 return CH_DOWN;
05527 case 81:
05528 return CH_PDOWN;
05529 case 82:
05530 return CH_INSERT;
05531 case 83:
05532 return CH_DELETE;
05533 }
05534 }
05535 return c;
05536 }
05537
05538 hConsole = GetStdHandle(STD_INPUT_HANDLE);
05539
05540 if (reset) {
05541 SetConsoleMode(hConsole, ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT |
05542 ENABLE_PROCESSED_INPUT | ENABLE_MOUSE_INPUT);
05543 init = FALSE;
05544 return 0;
05545 }
05546
05547 if (!init) {
05548 SetConsoleMode(hConsole, ENABLE_PROCESSED_INPUT);
05549 init = TRUE;
05550 }
05551
05552 if (repeat_count) {
05553 repeat_count--;
05554 return repeat_char;
05555 }
05556
05557 PeekConsoleInput(hConsole, &ir, 1, &nCharsRead);
05558
05559 if (nCharsRead == 0)
05560 return 0;
05561
05562 ReadConsoleInput(hConsole, &ir, 1, &nCharsRead);
05563
05564 if (ir.EventType != KEY_EVENT)
05565 return ss_getchar(0);
05566
05567 if (!ir.Event.KeyEvent.bKeyDown)
05568 return ss_getchar(0);
05569
05570 if (ir.Event.KeyEvent.wRepeatCount > 1) {
05571 repeat_count = ir.Event.KeyEvent.wRepeatCount - 1;
05572 repeat_char = ir.Event.KeyEvent.uChar.AsciiChar;
05573 return repeat_char;
05574 }
05575
05576 if (ir.Event.KeyEvent.uChar.AsciiChar)
05577 return ir.Event.KeyEvent.uChar.AsciiChar;
05578
05579 if (ir.Event.KeyEvent.dwControlKeyState & (ENHANCED_KEY)) {
05580 switch (ir.Event.KeyEvent.wVirtualKeyCode) {
05581 case 33:
05582 return CH_PUP;
05583 case 34:
05584 return CH_PDOWN;
05585 case 35:
05586 return CH_END;
05587 case 36:
05588 return CH_HOME;
05589 case 37:
05590 return CH_LEFT;
05591 case 38:
05592 return CH_UP;
05593 case 39:
05594 return CH_RIGHT;
05595 case 40:
05596 return CH_DOWN;
05597 case 45:
05598 return CH_INSERT;
05599 case 46:
05600 return CH_DELETE;
05601 }
05602
05603 return ir.Event.KeyEvent.wVirtualKeyCode;
05604 }
05605
05606 return ss_getchar(0);
05607
05608 #elif defined(OS_MSDOS)
05609
05610 int c;
05611
05612 if (!kbhit())
05613 return 0;
05614
05615 c = getch();
05616 if (!c) {
05617 c = getch();
05618 switch (c) {
05619 case 71:
05620 return CH_HOME;
05621 case 72:
05622 return CH_UP;
05623 case 73:
05624 return CH_PUP;
05625 case 75:
05626 return CH_LEFT;
05627 case 77:
05628 return CH_RIGHT;
05629 case 79:
05630 return CH_END;
05631 case 80:
05632 return CH_DOWN;
05633 case 81:
05634 return CH_PDOWN;
05635 case 82:
05636 return CH_INSERT;
05637 case 83:
05638 return CH_DELETE;
05639 }
05640 }
05641 return c;
05642
05643 #else
05644 return -1;
05645 #endif
05646 }
05647
05648
05649 char *ss_gets(char *string, int size)
05650
05651
05652
05653
05654
05655
05656
05657
05658
05659
05660
05661
05662
05663
05664
05665
05666
05667
05668 {
05669 char *p;
05670
05671 do {
05672 p = fgets(string, size, stdin);
05673 } while (p == NULL);
05674
05675
05676 if (strlen(p) > 0 && p[strlen(p) - 1] == '\n')
05677 p[strlen(p) - 1] = 0;
05678
05679 return p;
05680 }
05681
05682
05683
05684
05685
05686
05687
05688
05689
05690 INT ss_directio_give_port(INT start, INT end)
05691 {
05692 #ifdef OS_WINNT
05693
05694
05695
05696 OSVERSIONINFO vi;
05697 HANDLE hdio = 0;
05698 DWORD buffer[] = { 6, 0, 0, 0 };
05699 DWORD size;
05700
05701 vi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
05702 GetVersionEx(&vi);
05703
05704
05705 if (vi.dwPlatformId == VER_PLATFORM_WIN32_NT) {
05706 hdio =
05707 CreateFile("\\\\.\\directio", GENERIC_READ, FILE_SHARE_READ,
05708 NULL, OPEN_EXISTING, 0, NULL);
05709 if (hdio == INVALID_HANDLE_VALUE) {
05710 printf("hyt1331.c: Cannot access IO ports (No DirectIO driver installed)\n");
05711 return -1;
05712 }
05713
05714
05715 buffer[1] = start;
05716 buffer[2] = end;
05717 if (!DeviceIoControl
05718 (hdio, (DWORD) 0x9c406000, &buffer, sizeof(buffer), NULL, 0, &size, NULL))
05719 return -1;
05720 }
05721
05722 return SS_SUCCESS;
05723 #else
05724 int i;
05725 i = start;
05726 i = end;
05727 return SS_SUCCESS;
05728 #endif
05729 }
05730
05731
05732 INT ss_directio_lock_port(INT start, INT end)
05733 {
05734 #ifdef OS_WINNT
05735
05736
05737
05738 OSVERSIONINFO vi;
05739 HANDLE hdio;
05740 DWORD buffer[] = { 7, 0, 0, 0 };
05741 DWORD size;
05742
05743 vi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
05744 GetVersionEx(&vi);
05745
05746
05747 if (vi.dwPlatformId == VER_PLATFORM_WIN32_NT) {
05748 hdio =
05749 CreateFile("\\\\.\\directio", GENERIC_READ, FILE_SHARE_READ,
05750 NULL, OPEN_EXISTING, 0, NULL);
05751 if (hdio == INVALID_HANDLE_VALUE) {
05752 printf("hyt1331.c: Cannot access IO ports (No DirectIO driver installed)\n");
05753 return -1;
05754 }
05755
05756
05757 buffer[1] = start;
05758 buffer[2] = end;
05759 if (!DeviceIoControl
05760 (hdio, (DWORD) 0x9c406000, &buffer, sizeof(buffer), NULL, 0, &size, NULL))
05761 return -1;
05762 }
05763
05764 return SS_SUCCESS;
05765 #else
05766 int i;
05767 i = start;
05768 i = end;
05769 return SS_SUCCESS;
05770 #endif
05771 }
05772
05773
05774
05775
05776
05777
05778
05779
05780
05781 INT ss_syslog(const char *message)
05782
05783
05784
05785
05786
05787
05788
05789
05790
05791
05792
05793
05794
05795
05796
05797
05798 {
05799 #ifdef OS_UNIX
05800 static BOOL init = FALSE;
05801
05802 if (!init) {
05803 #ifdef OS_ULTRIX
05804 openlog("MIDAS", LOG_PID);
05805 #else
05806 openlog("MIDAS", LOG_PID, LOG_USER);
05807 #endif
05808 init = TRUE;
05809 }
05810
05811 syslog(LOG_DEBUG, message);
05812 return SS_SUCCESS;
05813 #elif defined(OS_WINNT)
05814
05815
05816
05817
05818
05819
05820
05821
05822
05823
05824
05825
05826
05827
05828
05829
05830
05831
05832
05833
05834
05835
05836
05837
05838
05839
05840
05841
05842
05843
05844 return SS_SUCCESS;
05845
05846 #else
05847
05848 return SS_SUCCESS;
05849
05850 #endif
05851 }
05852
05853
05854
05855
05856
05857
05858
05859
05860 #define bin_to_ascii(c) ((c)>=38?((c)-38+'a'):(c)>=12?((c)-12+'A'):(c)+'.')
05861
05862 char *ss_crypt(char *buf, char *salt)
05863
05864
05865
05866
05867
05868
05869
05870
05871
05872
05873
05874
05875
05876
05877
05878
05879
05880
05881
05882 {
05883 int i, seed;
05884 static char enc_pw[13];
05885
05886 memset(enc_pw, 0, sizeof(enc_pw));
05887 enc_pw[0] = salt[0];
05888 enc_pw[1] = salt[1];
05889
05890 for (i = 0; i < 8 && buf[i]; i++)
05891 enc_pw[i + 2] = buf[i];
05892 for (; i < 8; i++)
05893 enc_pw[i + 2] = 0;
05894
05895 seed = 123;
05896 for (i = 2; i < 13; i++) {
05897 seed = 5 * seed + 27 + enc_pw[i];
05898 enc_pw[i] = (char) bin_to_ascii(seed & 0x3F);
05899 }
05900
05901 return enc_pw;
05902 }
05903
05904
05905
05906
05907
05908
05909
05910
05911 double ss_nan()
05912 {
05913 double nan;
05914
05915 nan = 0;
05916 nan = 0 / nan;
05917 return nan;
05918 }
05919
05920 #ifdef OS_WINNT
05921 #include <float.h>
05922 #ifndef isnan
05923 #define isnan(x) _isnan(x)
05924 #endif
05925 #elif defined(OS_LINUX)
05926 #include <math.h>
05927 #endif
05928
05929 int ss_isnan(double x)
05930 {
05931 return isnan(x);
05932 }
05933
05934
05935 #endif
05936
05937
05938