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