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