source: lab.git/Dev/utvpn/utvpn-unix-v101-7101-public/src/Mayaqua/Unix.c

Last change on this file was a1bae3e, checked in by mitty <mitty@…>, 12 years ago
  • copy vendor drop to trunk

git-svn-id: https://lab.mitty.jp/svn/lab/trunk@147 7d2118f6-f56c-43e7-95a2-4bb3031d96e7

  • Property mode set to 100644
File size: 48.0 KB
Line 
1// SoftEther UT-VPN SourceCode
2//
3// Copyright (C) 2004-2010 SoftEther Corporation.
4// Copyright (C) 2004-2010 University of Tsukuba, Japan.
5// Copyright (C) 2003-2010 Daiyuu Nobori.
6// All Rights Reserved.
7//
8// http://utvpn.tsukuba.ac.jp/
9//
10// This program is free software; you can redistribute it and/or
11// modify it under the terms of the GNU General Public License
12// version 2 as published by the Free Software Foundation.
13//
14// This program is distributed in the hope that it will be useful,
15// but WITHOUT ANY WARRANTY; without even the implied warranty of
16// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17// GNU General Public License for more details.
18//
19// You should have received a copy of the GNU General Public License version 2
20// along with this program; if not, write to the Free Software
21// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22//
23// このファイルは GPL バージョン 2 ライセンスで公開されています。
24// 誰でもこのファイルの内容を複製、改変したり、改変したバージョンを再配布
25// することができます。ただし、原著作物を改変した場合は、原著作物の著作権表示
26// を除去することはできません。改変した著作物を配布する場合は、改変実施者の
27// 著作権表示を原著作物の著作権表示に付随して記載するようにしてください。
28//
29// この SoftEther UT-VPN オープンソース・プロジェクトは、日本国の
30// ソフトイーサ株式会社 (SoftEther Corporation, http://www.softether.co.jp/ )
31// および筑波大学 (University of Tsukuba, http://www.tsukuba.ac.jp/ ) によって
32// ホストされています。
33// 本プログラムの配布者は、本プログラムを、業としての利用以外のため、
34// および、試験または研究のために利用が行われることを想定して配布
35// しています。
36// SoftEther UT-VPN プロジェクトの Web サイトは http://utvpn.tsukuba.ac.jp/ に
37// あります。
38// 本ソフトウェアの不具合の修正、機能改良、セキュリティホールの修復などのコード
39// の改変を行った場合で、その成果物を SoftEther UT-VPN プロジェクトに提出して
40// いただける場合は、 http://utvpn.tsukuba.ac.jp/ までソースコードを送付して
41// ください。SoftEther UT-VPN プロジェクトの本体リリースまたはブランチリリース
42// に組み込みさせていただきます。
43//
44// GPL に基づいて原著作物が提供される本ソフトウェアの改良版を配布、販売する
45// 場合は、そのソースコードを GPL に基づいて誰にでも開示する義務が生じます。
46//
47// 本ソフトウェアに関連する著作権、特許権、商標権はソフトイーサ株式会社
48// (SoftEther Corporation) およびその他の著作権保持者が保有しています。
49// ソフトイーサ株式会社等はこれらの権利を放棄していません。本ソフトウェアの
50// 二次著作物を配布、販売する場合は、これらの権利を侵害しないようにご注意
51// ください。
52//
53// お願い: どのような通信ソフトウェアにも通常は必ず未発見の
54// セキュリティホールが潜んでいます。本ソースコードをご覧いただいた結果、
55// UT-VPN にセキュリティホールを発見された場合は、当該セキュリティホールの
56// 情報を不特定多数に開示される前に、必ず、ソフトイーサ株式会社
57// および脆弱性情報の届出を受け付ける公的機関まで通報いただき、
58// 公益保護にご協力いただきますようお願い申し上げます。
59//
60// ソフトイーサ株式会社は、当該セキュリティホールについて迅速に対処を
61// 行い、UT-VPN および UT-VPN に関連するソフトウェアのユーザー・顧客
62// を保護するための努力を行います。
63//
64// ソフトイーサへの届出先: http://www.softether.co.jp/jp/contact/
65// 日本国内の脆弱性情報届出受付公的機関:
66//         独立行政法人 情報処理推進機構
67//         http://www.ipa.go.jp/security/vuln/report/
68//
69// 上記各事項について不明な点は、ソフトイーサ株式会社までご連絡ください。
70// 連絡先: http://www.softether.co.jp/jp/contact/
71
72// -----------------------------------------------
73// [ChangeLog]
74// 2010.05.20
75//  新規リリース by SoftEther
76// -----------------------------------------------
77
78// Unix.c
79// UNIX 依存コード
80
81#ifdef  UNIX
82
83#include <stdio.h>
84#include <stdlib.h>
85#include <string.h>
86#include <wchar.h>
87#include <stdarg.h>
88#include <time.h>
89#include <errno.h>
90#include <Mayaqua/Mayaqua.h>
91
92// MacOS X 用の struct statfs
93#ifdef  UNIX_MACOS
94typedef struct fsid { int32_t val[2]; } fsid_t;
95struct statfs {
96        short   f_otype;                /* TEMPORARY SHADOW COPY OF f_type */
97        short   f_oflags;               /* TEMPORARY SHADOW COPY OF f_flags */
98        long    f_bsize;                /* fundamental file system block size */
99        long    f_iosize;               /* optimal transfer block size */
100        long    f_blocks;               /* total data blocks in file system */
101        long    f_bfree;                /* free blocks in fs */
102        long    f_bavail;               /* free blocks avail to non-superuser */
103        long    f_files;                /* total file nodes in file system */
104        long    f_ffree;                /* free file nodes in fs */
105        fsid_t  f_fsid;                 /* file system id */
106        uid_t   f_owner;                /* user that mounted the filesystem */
107        short   f_reserved1;    /* spare for later */
108        short   f_type;                 /* type of filesystem */
109    long        f_flags;                /* copy of mount exported flags */
110        long    f_reserved2[2]; /* reserved for future use */
111        char    f_fstypename[15]; /* fs type name */
112        char    f_mntonname[90];  /* directory on which mounted */
113        char    f_mntfromname[90];/* mounted filesystem */
114};
115#endif  // UNIX_MACOS
116
117// Solaris 用の scandir() 関数
118#ifdef  UNIX_SOLARIS
119#define scandir local_scandir
120#define alphasort local_alphasort
121
122/*******************************************
123 * Copyright Free の互換ルーチン (local_scandir)
124 * コピー元: http://www005.upp.so-net.ne.jp/yoga/compile.html
125 *******************************************/
126
127int local_scandir(const char *dir, struct dirent ***namelist,
128            int (*select)(const struct dirent *),
129            int (*compar)(const struct dirent **, const struct dirent **))
130{
131  DIR *d;
132  struct dirent *entry;
133  register int i=0;
134  size_t entrysize;
135
136  if ((d=opendir(dir)) == NULL)
137     return(-1);
138
139  *namelist=NULL;
140  while ((entry=readdir(d)) != NULL)
141  {
142    if (select == NULL || (select != NULL && (*select)(entry)))
143    {
144      *namelist=(struct dirent **)realloc((void *)(*namelist),
145                 (size_t)((i+1)*sizeof(struct dirent *)));
146    if (*namelist == NULL) return(-1);
147    entrysize=sizeof(struct dirent)-sizeof(entry->d_name)+strlen(entry->d_name)+1;
148    (*namelist)[i]=(struct dirent *)malloc(entrysize);
149    if ((*namelist)[i] == NULL) return(-1);
150    memcpy((*namelist)[i], entry, entrysize);
151    i++;
152    }
153  }
154  if (closedir(d)) return(-1);
155  if (i == 0) return(-1);
156  if (compar != NULL)
157    qsort((void *)(*namelist), (size_t)i, sizeof(struct dirent *), compar);
158   
159  return(i);
160}
161
162int local_alphasort(const struct dirent **a, const struct dirent **b)
163{
164  return(strcmp((*a)->d_name, (*b)->d_name));
165}
166
167
168#endif  // UNIX_SOLARIS
169
170// UNIX 用スレッドデータ
171typedef struct UNIXTHREAD
172{
173    pthread_t thread;
174    bool finished;
175} UNIXTHREAD;
176
177// UNIX 用スレッド起動情報
178typedef struct UNIXTHREADSTARTUPINFO
179{
180    THREAD_PROC *thread_proc;
181    void *param;
182    THREAD *thread;
183} UNIXTHREADSTARTUPINFO;
184
185// UNIX 用スレッド関数プロトタイプ
186void *UnixDefaultThreadProc(void *param);
187
188// 現在のプロセス ID
189static pid_t current_process_id = 0;
190
191// UNIX 用ファイル I/O データ
192typedef struct UNIXIO
193{
194    int fd;
195    bool write_mode;
196} UNIXIO;
197
198// UNIX 用ロックファイルデータ
199typedef struct UNIXLOCKFILE
200{
201    char FileName[MAX_SIZE];
202    int fd;
203} UNIXLOCKFILE;
204
205// UNIX 用イベントデータ
206typedef struct UNIXEVENT
207{
208    pthread_mutex_t mutex;
209    pthread_cond_t cond;
210    bool signal;
211} UNIXEVENT;
212
213static pthread_mutex_t get_time_lock;
214static pthread_mutex_t malloc_lock;
215static bool high_process = false;
216
217static bool unix_svc_terminate = false;
218static int solaris_sleep_p1 = -1, solaris_sleep_p2 = -1;
219
220// ディスパッチテーブルの作成
221OS_DISPATCH_TABLE *UnixGetDispatchTable()
222{
223    static OS_DISPATCH_TABLE t =
224    {
225        UnixInit,
226        UnixFree,
227        UnixMemoryAlloc,
228        UnixMemoryReAlloc,
229        UnixMemoryFree,
230        UnixGetTick,
231        UnixGetSystemTime,
232        UnixInc32,
233        UnixDec32,
234        UnixSleep,
235        UnixNewLock,
236        UnixLock,
237        UnixUnlock,
238        UnixDeleteLock,
239        UnixInitEvent,
240        UnixSetEvent,
241        UnixResetEvent,
242        UnixWaitEvent,
243        UnixFreeEvent,
244        UnixWaitThread,
245        UnixFreeThread,
246        UnixInitThread,
247        UnixThreadId,
248        UnixFileOpen,
249        UnixFileOpenW,
250        UnixFileCreate,
251        UnixFileCreateW,
252        UnixFileWrite,
253        UnixFileRead,
254        UnixFileClose,
255        UnixFileFlush,
256        UnixFileSize,
257        UnixFileSeek,
258        UnixFileDelete,
259        UnixFileDeleteW,
260        UnixMakeDir,
261        UnixMakeDirW,
262        UnixDeleteDir,
263        UnixDeleteDirW,
264        UnixGetCallStack,
265        UnixGetCallStackSymbolInfo,
266        UnixFileRename,
267        UnixFileRenameW,
268        UnixRun,
269        UnixRunW,
270        UnixIsSupportedOs,
271        UnixGetOsInfo,
272        UnixAlert,
273        UnixAlertW,
274        UnixGetProductId,
275        UnixSetHighPriority,
276        UnixRestorePriority,
277        UnixNewSingleInstance,
278        UnixFreeSingleInstance,
279        UnixGetMemInfo,
280        UnixYield,
281    };
282
283    return &t;
284}
285
286// Solaris 用 Sleep の初期化
287void UnixInitSolarisSleep()
288{
289    char tmp[MAX_SIZE];
290
291    UnixNewPipe(&solaris_sleep_p1, &solaris_sleep_p2);
292    read(solaris_sleep_p1, tmp, sizeof(tmp));
293}
294
295// Solaris 用 Sleep の解放
296void UnixFreeSolarisSleep()
297{
298    UnixDeletePipe(solaris_sleep_p1, solaris_sleep_p2);
299    solaris_sleep_p1 = -1;
300    solaris_sleep_p2 = -1;
301}
302
303// Solaris 用 Sleep
304void UnixSolarisSleep(UINT msec)
305{
306    struct pollfd p;
307
308    memset(&p, 0, sizeof(p));
309    p.fd = solaris_sleep_p1;
310    p.events = POLLIN;
311
312    poll(&p, 1, msec == INFINITE ? -1 : (int)msec);
313}
314
315// ディスクの空き容量を取得する
316bool UnixGetDiskFreeW(wchar_t *path, UINT64 *free_size, UINT64 *used_size, UINT64 *total_size)
317{
318    char *path_a = CopyUniToStr(path);
319    bool ret;
320
321    ret = UnixGetDiskFree(path_a, free_size, used_size, total_size);
322
323    Free(path_a);
324
325    return ret;
326}
327bool UnixGetDiskFree(char *path, UINT64 *free_size, UINT64 *used_size, UINT64 *total_size)
328{
329    char tmp[MAX_PATH];
330    bool ret = false;
331    // 引数チェック
332    if (path == NULL)
333    {
334        return false;
335    }
336
337    NormalizePath(tmp, sizeof(tmp), path);
338
339    while ((ret = UnixGetDiskFreeMain(tmp, free_size, used_size, total_size)) == false)
340    {
341        if (StrCmpi(tmp, "/") == 0)
342        {
343            break;
344        }
345
346        GetDirNameFromFilePath(tmp, sizeof(tmp), tmp);
347    }
348
349    return ret;
350}
351bool UnixGetDiskFreeMain(char *path, UINT64 *free_size, UINT64 *used_size, UINT64 *total_size)
352{
353#ifndef USE_STATVFS
354    struct statfs st;
355    char tmp[MAX_PATH];
356    UINT64 v1 = 0, v2 = 0;
357    bool ret = false;
358    // 引数チェック
359    if (path == NULL)
360    {
361        return false;
362    }
363
364    NormalizePath(tmp, sizeof(tmp), path);
365
366    Zero(&st, sizeof(st));
367    if (statfs(tmp, &st) == 0)
368    {
369        v1 = (UINT64)st.f_bsize * (UINT64)st.f_bavail;
370        v2 = (UINT64)st.f_bsize * (UINT64)st.f_blocks;
371        ret = true;
372    }
373
374    if (free_size != NULL)
375    {
376        *free_size = v1;
377    }
378
379    if (total_size != NULL)
380    {
381        *total_size = v2;
382    }
383
384    if (used_size != NULL)
385    {
386        *used_size = v2 - v1;
387    }
388
389    return ret;
390#else   // USE_STATVFS
391    struct statvfs st;
392    char tmp[MAX_PATH];
393    UINT64 v1 = 0, v2 = 0;
394    bool ret = false;
395    // 引数チェック
396    if (path == NULL)
397    {
398        return false;
399    }
400
401    NormalizePath(tmp, sizeof(tmp), path);
402
403    Zero(&st, sizeof(st));
404
405    if (statvfs(tmp, &st) == 0)
406    {
407        v1 = (UINT64)st.f_bsize * (UINT64)st.f_bavail;
408        v2 = (UINT64)st.f_bsize * (UINT64)st.f_blocks;
409        ret = true;
410    }
411
412    if (free_size != NULL)
413    {
414        *free_size = v1;
415    }
416
417    if (total_size != NULL)
418    {
419        *total_size = v2;
420    }
421
422    if (used_size != NULL)
423    {
424        *used_size = v2 - v1;
425    }
426
427    return ret;
428#endif  // USE_STATVFS
429}
430
431// ディレクトリ列挙
432DIRLIST *UnixEnumDirEx(char *dirname, COMPARE *compare)
433{
434    char tmp[MAX_PATH];
435    DIRLIST *d;
436    int n;
437    struct dirent **e;
438    LIST *o;
439    // 引数チェック
440    if (dirname == NULL)
441    {
442        return NULL;
443    }
444
445    o = NewListFast(compare);
446
447    NormalizePath(tmp, sizeof(tmp), dirname);
448
449    if (StrLen(tmp) >= 1 && tmp[StrLen(tmp) - 1] != '/')
450    {
451        StrCat(tmp, sizeof(tmp), "/");
452    }
453
454    e = NULL;
455    n = scandir(tmp, &e, 0, alphasort);
456
457    if (StrLen(tmp) >= 1 && tmp[StrLen(tmp) - 1] == '/')
458    {
459        tmp[StrLen(tmp) - 1] = 0;
460    }
461
462    if (n >= 0 && e != NULL)
463    {
464        UINT i;
465
466        for (i = 0;i < (UINT)n;i++)
467        {
468            char *filename = e[i]->d_name;
469
470            if (filename != NULL)
471            {
472                if (StrCmpi(filename, "..") != 0 && StrCmpi(filename, ".") != 0)
473                {
474                    char fullpath[MAX_PATH];
475                    struct stat st;
476                    Format(fullpath, sizeof(fullpath), "%s/%s", tmp, filename);
477
478                    Zero(&st, sizeof(st));
479
480                    if (stat(fullpath, &st) == 0)
481                    {
482                        DIRENT *f = ZeroMalloc(sizeof(DIRENT));
483                        SYSTEMTIME t;
484
485                        f->Folder = S_ISDIR(st.st_mode) ? true : false;
486                        f->FileName = CopyStr(filename);
487                        f->FileNameW = CopyUtfToUni(f->FileName);
488
489                        Zero(&t, sizeof(t));
490                        TimeToSystem(&t, st.st_ctime);
491                        f->CreateDate = LocalToSystem64(SystemToUINT64(&t));
492
493                        Zero(&t, sizeof(t));
494                        TimeToSystem(&t, st.st_mtime);
495                        f->UpdateDate = LocalToSystem64(SystemToUINT64(&t));
496
497                        if (f->Folder == false)
498                        {
499                            f->FileSize = st.st_size;
500                        }
501
502                        Add(o, f);
503                    }
504                }
505            }
506
507            free(e[i]);
508        }
509
510        free(e);
511    }
512
513    Sort(o);
514
515    d = ZeroMalloc(sizeof(DIRLIST));
516    d->NumFiles = LIST_NUM(o);
517    d->File = ToArray(o);
518
519    ReleaseList(o);
520
521    return d;
522}
523DIRLIST *UnixEnumDirExW(wchar_t *dirname, COMPARE *compare)
524{
525    char *dirname_a = CopyUniToUtf(dirname);
526    DIRLIST *ret;
527
528    ret = UnixEnumDirEx(dirname_a, compare);
529
530    Free(dirname_a);
531
532    return ret;
533}
534
535// 指定したファイルの実行権限をチェックする
536bool UnixCheckExecAccess(char *name)
537{
538    // 引数チェック
539    if (name == NULL)
540    {
541        return false;
542    }
543
544    if (access(name, X_OK) == 0)
545    {
546        return true;
547    }
548
549    return false;
550}
551bool UnixCheckExecAccessW(wchar_t *name)
552{
553    char *name_a;
554    bool ret;
555    // 引数チェック
556    if (name == NULL)
557    {
558        return false;
559    }
560
561    name_a = CopyUniToUtf(name);
562
563    ret = UnixCheckExecAccess(name_a);
564
565    Free(name_a);
566
567    return ret;
568}
569
570// スレッドの優先順位を最高にする
571void UnixSetThreadPriorityRealtime()
572{
573    struct sched_param p;
574    Zero(&p, sizeof(p));
575    p.sched_priority = 255;
576    pthread_setschedparam(pthread_self(), SCHED_RR, &p);
577}
578
579// スレッドの優先順位を低くする
580void UnixSetThreadPriorityLow()
581{
582    struct sched_param p;
583    Zero(&p, sizeof(p));
584    p.sched_priority = 32;
585    pthread_setschedparam(pthread_self(), SCHED_OTHER, &p);
586}
587
588// スレッドの優先順位を高くする
589void UnixSetThreadPriorityHigh()
590{
591    struct sched_param p;
592    Zero(&p, sizeof(p));
593    p.sched_priority = 127;
594    pthread_setschedparam(pthread_self(), SCHED_RR, &p);
595}
596
597// スレッドの優先順位をアイドルにする
598void UnixSetThreadPriorityIdle()
599{
600    struct sched_param p;
601    Zero(&p, sizeof(p));
602    p.sched_priority = 1;
603    pthread_setschedparam(pthread_self(), SCHED_OTHER, &p);
604}
605
606// スレッドの優先順位を標準に戻す
607void UnixRestoreThreadPriority()
608{
609    struct sched_param p;
610    Zero(&p, sizeof(p));
611    p.sched_priority = 64;
612    pthread_setschedparam(pthread_self(), SCHED_OTHER, &p);
613}
614
615// 現在のディレクトリの取得
616void UnixGetCurrentDir(char *dir, UINT size)
617{
618    // 引数チェック
619    if (dir == NULL)
620    {
621        return;
622    }
623
624    getcwd(dir, size);
625}
626void UnixGetCurrentDirW(wchar_t *dir, UINT size)
627{
628    char dir_a[MAX_PATH];
629
630    UnixGetCurrentDir(dir_a, sizeof(dir_a));
631
632    UtfToUni(dir, size, dir_a);
633}
634
635// イールド
636void UnixYield()
637{
638#ifdef UNIX_SOLARIS
639    UnixSolarisSleep(1);
640#else
641    sleep(1);
642#endif
643}
644
645// メモリ情報の取得
646void UnixGetMemInfo(MEMINFO *info)
647{
648    // 引数チェック
649    if (info == NULL)
650    {
651        return;
652    }
653
654    // 知らん!!
655    Zero(info, sizeof(MEMINFO));
656}
657
658// シングルインスタンスの解放
659void UnixFreeSingleInstance(void *data)
660{
661    UNIXLOCKFILE *o;
662    struct flock lock;
663    // 引数チェック
664    if (data == NULL)
665    {
666        return;
667    }
668
669    o = (UNIXLOCKFILE *)data;
670
671    Zero(&lock, sizeof(lock));
672    lock.l_type = F_UNLCK;
673    lock.l_whence = SEEK_SET;
674
675    fcntl(o->fd, F_SETLK, &lock);
676    close(o->fd);
677
678    remove(o->FileName);
679
680    Free(data);
681}
682
683// シングルインスタンスの作成
684void *UnixNewSingleInstance(char *instance_name)
685{
686    UNIXLOCKFILE *ret;
687    char tmp[MAX_SIZE];
688    char name[MAX_SIZE];
689    char dir[MAX_PATH];
690    int fd;
691    struct flock lock;
692    // 引数チェック
693    if (instance_name == NULL)
694    {
695        GetExeName(tmp, sizeof(tmp));
696        HashInstanceName(tmp, sizeof(tmp), tmp);
697    }
698    else
699    {
700        StrCpy(tmp, sizeof(tmp), instance_name);
701    }
702
703    GetExeDir(dir, sizeof(dir));
704
705    // ファイル名の生成
706    Format(name, sizeof(name), "%s/.%s", dir, tmp);
707
708    fd = open(name, O_WRONLY);
709    if (fd == -1)
710    {
711        fd = creat(name, 0600);
712    }
713    if (fd == -1)
714    {
715        Format(tmp, sizeof(tmp), "Unable to create %s.", name);
716        Alert(tmp, NULL);
717        exit(0);
718        return NULL;
719    }
720
721    Zero(&lock, sizeof(lock));
722    lock.l_type = F_WRLCK;
723    lock.l_whence = SEEK_SET;
724
725    if (fcntl(fd, F_SETLK, &lock) == -1)
726    {
727        return NULL;
728    }
729    else
730    {
731        ret = ZeroMalloc(sizeof(UNIXLOCKFILE));
732        ret->fd = fd;
733        StrCpy(ret->FileName, sizeof(ret->FileName), name);
734        return (void *)ret;
735    }
736}
737
738// プロセスの優先順位を上げる
739void UnixSetHighPriority()
740{
741    if (high_process == false)
742    {
743        UINT pid = getpid();
744        UINT pgid = getpgid(pid);
745
746        high_process = true;
747        nice(-20);
748
749        setpriority(PRIO_PROCESS, pid, -20);
750        setpriority(PRIO_PGRP, pgid, -20);
751    }
752}
753
754// プロセスの優先順位を戻す
755void UnixRestorePriority()
756{
757    if (high_process != false)
758    {
759        high_process = false;
760        nice(20);
761    }
762}
763
764// プロダクト ID を取得する
765char *UnixGetProductId()
766{
767    return CopyStr("--");
768}
769
770// アラートを表示する
771void UnixAlertW(wchar_t *msg, wchar_t *caption)
772{
773    char *msg8 = CopyUniToUtf(msg);
774    char *caption8 = CopyUniToUtf(caption);
775
776    UnixAlert(msg8, caption8);
777
778    Free(msg8);
779    Free(caption8);
780}
781void UnixAlert(char *msg, char *caption)
782{
783    char *tag =
784        "-- Alert: %s --\n%s\n";
785    // 引数チェック
786    if (msg == NULL)
787    {
788        msg = "Alert";
789    }
790    if (caption == NULL)
791    {
792        caption = "SoftEther UT-VPN Kernel";
793    }
794
795    printf(tag, caption, msg);
796}
797
798// 現在の OS の情報を取得する
799void UnixGetOsInfo(OS_INFO *info)
800{
801    // 引数チェック
802    if (info == NULL)
803    {
804        return;
805    }
806
807    Zero(info, sizeof(OS_INFO));
808    info->OsType = OSTYPE_UNIX_UNKNOWN;
809
810#ifdef  UNIX_SOLARIS
811    info->OsType = OSTYPE_SOLARIS;
812#endif  // UNIX_SOLARIS
813
814#ifdef  UNIX_CYGWIN
815    info->OsType = OSTYPE_CYGWIN;
816#endif  // UNIX_CYGWIN
817
818#ifdef  UNIX_MACOS
819    info->OsType = OSTYPE_MACOS_X;
820#endif  // UNIX_MACOS
821
822#ifdef  UNIX_BSD
823    info->OsType = OSTYPE_BSD;
824#endif  // UNIX_BSD
825
826#ifdef  UNIX_LINUX
827    info->OsType = OSTYPE_LINUX;
828#endif  // UNIX_LINUX
829
830    info->OsServicePack = 0;
831
832    if (info->OsType != OSTYPE_LINUX)
833    {
834        info->OsSystemName = CopyStr("UNIX");
835        info->OsProductName = CopyStr("UNIX");
836    }
837    else
838    {
839        info->OsSystemName = CopyStr("Linux");
840        info->OsProductName = CopyStr("Linux");
841    }
842
843    if (info->OsType == OSTYPE_LINUX)
844    {
845        // Linux の場合 ディストリビューション名を取得する
846        BUF *b;
847        b = ReadDump("/etc/redhat-release");
848        if (b != NULL)
849        {
850            info->OsVersion = CfgReadNextLine(b);
851            info->OsVendorName = CopyStr("Red Hat, Inc.");
852            FreeBuf(b);
853        }
854        else
855        {
856            b = ReadDump("/etc/turbolinux-release");
857            if (b != NULL)
858            {
859                info->OsVersion = CfgReadNextLine(b);
860                info->OsVendorName = CopyStr("Turbolinux, Inc.");
861                FreeBuf(b);
862            }
863            else
864            {
865                info->OsVersion = CopyStr("Unknown Liunx Version");
866                info->OsVendorName = CopyStr("Unknown Vendor");
867            }
868        }
869
870        info->KernelName = CopyStr("Linux Kernel");
871
872        b = ReadDump("/proc/sys/kernel/osrelease");
873        if (b != NULL)
874        {
875            info->KernelVersion = CfgReadNextLine(b);
876            FreeBuf(b);
877        }
878        else
879        {
880            info->KernelVersion = CopyStr("Unknown Version");
881        }
882    }
883    else
884    {
885        // その他の場合
886        info->OsProductName = CopyStr(OsTypeToStr(info->OsType));
887        info->OsVersion = CopyStr("Unknown Version");
888        info->KernelName = CopyStr(OsTypeToStr(info->OsType));
889        info->KernelVersion = CopyStr("Unknown Version");
890    }
891}
892
893// 現在の OS が SoftEther UT-VPN Kernel によってサポートされているかどうか調べる
894bool UnixIsSupportedOs()
895{
896    // すべての起動可能な UNIX OS をサポートしている
897    return true;
898}
899
900// 指定したコマンドを実行する
901bool UnixRunW(wchar_t *filename, wchar_t *arg, bool hide, bool wait)
902{
903    char *filename8 = CopyUniToUtf(filename);
904    char *arg8 = CopyUniToUtf(arg);
905    bool ret = UnixRun(filename8, arg8, hide, wait);
906
907    Free(filename8);
908    Free(arg8);
909
910    return ret;
911}
912bool UnixRun(char *filename, char *arg, bool hide, bool wait)
913{
914    TOKEN_LIST *t;
915    UINT ret;
916    // 引数チェック
917    if (filename == NULL)
918    {
919        return false;
920    }
921    if (arg == NULL)
922    {
923        arg = "";
924    }
925
926    // 子プロセス作成
927    ret = fork();
928    if (ret == -1)
929    {
930        // 子プロセス作成失敗
931        return false;
932    }
933
934    if (ret == 0)
935    {
936        Print("", filename, arg);
937        // 子プロセス
938        if (hide)
939        {
940            // 標準入出力を閉じる
941            UnixCloseIO();
942        }
943
944        t = ParseToken(arg, " ");
945        if (t == NULL)
946        {
947            AbortExit();
948        }
949        else
950        {
951            char **args;
952            UINT num_args;
953            UINT i;
954            num_args = t->NumTokens + 2;
955            args = ZeroMalloc(sizeof(char *) * num_args);
956            args[0] = filename;
957            for (i = 1;i < num_args - 1;i++)
958            {
959                args[i] = t->Token[i - 1];
960            }
961            execvp(filename, args);
962            AbortExit();
963        }
964    }
965    else
966    {
967        // 親プロセス
968        pid_t pid = (pid_t)ret;
969
970        if (wait)
971        {
972            int status = 0;
973            // 子プロセスの終了を待機する
974            if (waitpid(pid, &status, 0) == -1)
975            {
976                return false;
977            }
978
979            if (WEXITSTATUS(status) == 0)
980            {
981                return true;
982            }
983            else
984            {
985                return false;
986            }
987        }
988
989        return true;
990    }
991}
992
993// デーモンの初期化
994void UnixDaemon(bool debug_mode)
995{
996    UINT ret;
997
998    if (debug_mode)
999    {
1000        // デバッグモード
1001        signal(SIGHUP, SIG_IGN);
1002        return;
1003    }
1004
1005    ret = fork();
1006
1007    if (ret == -1)
1008    {
1009        // エラー
1010        return;
1011    }
1012    else if (ret == 0)
1013    {
1014        // 子プロセス用に新しいセッションを作成する
1015        setsid();
1016
1017        // 標準入出力をクローズする
1018        UnixCloseIO();
1019
1020        // 不要なシグナルを停止する
1021        signal(SIGHUP, SIG_IGN);
1022    }
1023    else
1024    {
1025        // 親プロセスを終了する
1026        exit(0);
1027    }
1028}
1029
1030// 標準入出力をクローズする
1031void UnixCloseIO()
1032{
1033    static bool close_io_first = false;
1034
1035    // 1 回しか実行できない
1036    if (close_io_first)
1037    {
1038        return;
1039    }
1040    else
1041    {
1042        close(0);
1043        close(1);
1044        close(2);
1045        open("/dev/null", O_RDWR);
1046        dup2(0, 1);
1047        dup2(0, 2);
1048        close_io_first = false;
1049    }
1050}
1051
1052// ファイル名を変更する
1053bool UnixFileRenameW(wchar_t *old_name, wchar_t *new_name)
1054{
1055    char *old_name8 = CopyUniToUtf(old_name);
1056    char *new_name8 = CopyUniToUtf(new_name);
1057    bool ret = UnixFileRename(old_name8, new_name8);
1058
1059    Free(old_name8);
1060    Free(new_name8);
1061
1062    return ret;
1063}
1064bool UnixFileRename(char *old_name, char *new_name)
1065{
1066    // 引数チェック
1067    if (old_name == NULL || new_name == NULL)
1068    {
1069        return false;
1070    }
1071
1072    if (rename(old_name, new_name) != 0)
1073    {
1074        return false;
1075    }
1076
1077    return true;
1078}
1079
1080// コールスタックを取得する
1081CALLSTACK_DATA *UnixGetCallStack()
1082{
1083    // Win32 以外ではサポートされていない
1084    return NULL;
1085}
1086
1087// コールスタックからシンボル情報を取得
1088bool UnixGetCallStackSymbolInfo(CALLSTACK_DATA *s)
1089{
1090    // Win32 以外ではサポートされていない
1091    return false;
1092}
1093
1094// ディレクトリを削除する
1095bool UnixDeleteDirW(wchar_t *name)
1096{
1097    char *name8 = CopyUniToUtf(name);
1098    bool ret = UnixDeleteDir(name8);
1099
1100    Free(name8);
1101
1102    return ret;
1103}
1104bool UnixDeleteDir(char *name)
1105{
1106    // 引数チェック
1107    if (name == NULL)
1108    {
1109        return false;
1110    }
1111
1112    if (rmdir(name) != 0)
1113    {
1114        return false;
1115    }
1116
1117    return true;
1118}
1119
1120// ディレクトリを作成する
1121bool UnixMakeDirW(wchar_t *name)
1122{
1123    char *name8 = CopyUniToUtf(name);
1124    bool ret = UnixMakeDir(name8);
1125
1126    Free(name8);
1127
1128    return ret;
1129}
1130bool UnixMakeDir(char *name)
1131{
1132    // 引数チェック
1133    if (name == NULL)
1134    {
1135        return false;
1136    }
1137
1138    if (mkdir(name, 0700) != 0)
1139    {
1140        return false;
1141    }
1142
1143    return true;
1144}
1145
1146// ファイルを削除する
1147bool UnixFileDeleteW(wchar_t *name)
1148{
1149    bool ret;
1150    char *name8 = CopyUniToUtf(name);
1151
1152    ret = UnixFileDelete(name8);
1153
1154    Free(name8);
1155
1156    return ret;
1157}
1158bool UnixFileDelete(char *name)
1159{
1160    // 引数チェック
1161    if (name == NULL)
1162    {
1163        return false;
1164    }
1165
1166    if (remove(name) != 0)
1167    {
1168        return false;
1169    }
1170
1171    return true;
1172}
1173
1174// ファイルをシークする
1175bool UnixFileSeek(void *pData, UINT mode, int offset)
1176{
1177    UNIXIO *p;
1178    UINT ret;
1179    // 引数チェック
1180    if (pData == NULL)
1181    {
1182        return 0;
1183    }
1184    if (mode != FILE_BEGIN && mode != FILE_END && mode != FILE_CURRENT)
1185    {
1186        return false;
1187    }
1188
1189    p = (UNIXIO *)pData;
1190
1191    ret = lseek(p->fd, offset, mode);
1192
1193    if (ret == -1)
1194    {
1195        return false;
1196    }
1197
1198    return true;
1199}
1200
1201// ファイルサイズを取得する
1202UINT64 UnixFileSize(void *pData)
1203{
1204    struct stat st;
1205    UNIXIO *p;
1206    // 引数チェック
1207    if (pData == NULL)
1208    {
1209        return 0;
1210    }
1211
1212    p = (UNIXIO *)pData;
1213
1214    if (fstat(p->fd, &st) != 0)
1215    {
1216        return 0;
1217    }
1218
1219    return (UINT64)st.st_size;
1220}
1221
1222// ファイルに書き込む
1223bool UnixFileWrite(void *pData, void *buf, UINT size)
1224{
1225    UNIXIO *p;
1226    UINT ret;
1227    // 引数チェック
1228    if (pData == NULL || buf == NULL || size == 0)
1229    {
1230        return false;
1231    }
1232
1233    p = (UNIXIO *)pData;
1234
1235    ret = write(p->fd, buf, size);
1236    if (ret != size)
1237    {
1238        return false;
1239    }
1240
1241    return true;
1242}
1243
1244// ファイルから読み込む
1245bool UnixFileRead(void *pData, void *buf, UINT size)
1246{
1247    UNIXIO *p;
1248    UINT ret;
1249    // 引数チェック
1250    if (pData == NULL || buf == NULL || size == 0)
1251    {
1252        return false;
1253    }
1254
1255    p = (UNIXIO *)pData;
1256
1257    ret = read(p->fd, buf, size);
1258    if (ret != size)
1259    {
1260        return false;
1261    }
1262
1263    return true;
1264}
1265
1266// ファイルをフラッシュする
1267void UnixFileFlush(void *pData)
1268{
1269    UNIXIO *p;
1270    bool write_mode;
1271    // 引数チェック
1272    if (pData == NULL)
1273    {
1274        return;
1275    }
1276
1277    p = (UNIXIO *)pData;
1278
1279    write_mode = p->write_mode;
1280
1281    if (write_mode)
1282    {
1283        fsync(p->fd);
1284    }
1285}
1286
1287// ファイルを閉じる
1288void UnixFileClose(void *pData, bool no_flush)
1289{
1290    UNIXIO *p;
1291    bool write_mode;
1292    // 引数チェック
1293    if (pData == NULL)
1294    {
1295        return;
1296    }
1297
1298    p = (UNIXIO *)pData;
1299
1300    write_mode = p->write_mode;
1301
1302    if (write_mode && no_flush == false)
1303    {
1304        fsync(p->fd);
1305    }
1306
1307    close(p->fd);
1308
1309    UnixMemoryFree(p);
1310
1311    if (write_mode)
1312    {
1313        //sync();
1314    }
1315}
1316
1317// ファイルを作成する
1318void *UnixFileCreateW(wchar_t *name)
1319{
1320    void *ret;
1321    char *name8 = CopyUniToUtf(name);
1322
1323    ret = UnixFileCreate(name8);
1324
1325    Free(name8);
1326
1327    return ret;
1328}
1329void *UnixFileCreate(char *name)
1330{
1331    UNIXIO *p;
1332    int fd;
1333    // 引数チェック
1334    if (name == NULL)
1335    {
1336        return NULL;
1337    }
1338
1339    fd = creat(name, 0600);
1340    if (fd == -1)
1341    {
1342        return NULL;
1343    }
1344
1345    // メモリ確保
1346    p = UnixMemoryAlloc(sizeof(UNIXIO));
1347    p->fd = fd;
1348    p->write_mode = true;
1349
1350    return (void *)p;
1351}
1352
1353// ファイルを開く
1354void *UnixFileOpenW(wchar_t *name, bool write_mode, bool read_lock)
1355{
1356    char *name8 = CopyUniToUtf(name);
1357    void *ret;
1358
1359    ret = UnixFileOpen(name8, write_mode, read_lock);
1360
1361    Free(name8);
1362
1363    return ret;
1364}
1365void *UnixFileOpen(char *name, bool write_mode, bool read_lock)
1366{
1367    UNIXIO *p;
1368    int fd;
1369    int mode;
1370    // 引数チェック
1371    if (name == NULL)
1372    {
1373        return NULL;
1374    }
1375
1376    if (write_mode == false)
1377    {
1378        mode = O_RDONLY;
1379    }
1380    else
1381    {
1382        mode = O_RDWR;
1383    }
1384
1385    // ファイルを開く
1386    fd = open(name, mode);
1387    if (fd == -1)
1388    {
1389        return NULL;
1390    }
1391
1392    // メモリ確保
1393    p = UnixMemoryAlloc(sizeof(UNIXIO));
1394    p->fd = fd;
1395    p->write_mode = write_mode;
1396
1397    return (void *)p;
1398}
1399
1400// 現在のスレッド ID を返す
1401UINT UnixThreadId()
1402{
1403    UINT ret;
1404
1405    ret = (UINT)pthread_self();
1406
1407    return ret;
1408}
1409
1410// スレッド関数
1411void *UnixDefaultThreadProc(void *param)
1412{
1413    UNIXTHREAD *ut;
1414    UNIXTHREADSTARTUPINFO *info = (UNIXTHREADSTARTUPINFO *)param;
1415    if (info == NULL)
1416    {
1417        return 0;
1418    }
1419
1420    ut = (UNIXTHREAD *)info->thread->pData;
1421
1422    // スレッド関数の呼び出し
1423    info->thread_proc(info->thread, info->param);
1424
1425    // 終了フラグを立てる
1426    ut->finished = true;
1427
1428    // 参照の解放
1429    ReleaseThread(info->thread);
1430
1431    UnixMemoryFree(info);
1432
1433    FreeOpenSSLThreadState();
1434
1435    return 0;
1436}
1437
1438// スレッドの解放
1439void UnixFreeThread(THREAD *t)
1440{
1441    // 引数チェック
1442    if (t == NULL)
1443    {
1444        return;
1445    }
1446
1447    // メモリの解放
1448    UnixMemoryFree(t->pData);
1449}
1450
1451// スレッドの終了を待機
1452bool UnixWaitThread(THREAD *t)
1453{
1454    UNIXTHREAD *ut;
1455    void *retcode = NULL;
1456    // 引数チェック
1457    if (t == NULL)
1458    {
1459        return false;
1460    }
1461    ut = (UNIXTHREAD *)t->pData;
1462    if (ut == NULL)
1463    {
1464        return false;
1465    }
1466
1467    pthread_join(ut->thread, &retcode);
1468
1469    return true;
1470}
1471
1472// スレッドの初期化
1473bool UnixInitThread(THREAD *t)
1474{
1475    UNIXTHREAD *ut;
1476    UNIXTHREADSTARTUPINFO *info;
1477    pthread_attr_t attr;
1478    // 引数チェック
1479    if (t == NULL || t->thread_proc == NULL)
1480    {
1481        return false;
1482    }
1483
1484    // スレッドデータ作成
1485    ut = UnixMemoryAlloc(sizeof(UNIXTHREAD));
1486    Zero(ut, sizeof(UNIXTHREAD));
1487
1488    // 起動情報作成
1489    info = UnixMemoryAlloc(sizeof(UNIXTHREADSTARTUPINFO));
1490    Zero(info, sizeof(UNIXTHREADSTARTUPINFO));
1491    info->param = t->param;
1492    info->thread_proc = t->thread_proc;
1493    info->thread = t;
1494    AddRef(t->ref);
1495
1496    // スレッド作成
1497    pthread_attr_init(&attr);
1498    pthread_attr_setstacksize(&attr, UNIX_THREAD_STACK_SIZE);
1499
1500    t->pData = (void *)ut;
1501
1502    if (pthread_create(&ut->thread, &attr, UnixDefaultThreadProc, info) != 0)
1503    {
1504        // エラー発生
1505        t->pData = NULL;
1506        Release(t->ref);
1507        UnixMemoryFree(ut);
1508        UnixMemoryFree(info);
1509        pthread_attr_destroy(&attr);
1510        return false;
1511    }
1512
1513    pthread_attr_destroy(&attr);
1514
1515    return true;
1516}
1517
1518// イベントの解放
1519void UnixFreeEvent(EVENT *event)
1520{
1521    UNIXEVENT *ue = (UNIXEVENT *)event->pData;
1522    if (ue == NULL)
1523    {
1524        return;
1525    }
1526
1527    pthread_cond_destroy(&ue->cond);
1528    pthread_mutex_destroy(&ue->mutex);
1529
1530    UnixMemoryFree(ue);
1531}
1532
1533// イベントの待機
1534bool UnixWaitEvent(EVENT *event, UINT timeout)
1535{
1536    UNIXEVENT *ue = (UNIXEVENT *)event->pData;
1537    struct timeval now;
1538    struct timespec to;
1539    bool ret;
1540    if (ue == NULL)
1541    {
1542        return false;
1543    }
1544
1545    pthread_mutex_lock(&ue->mutex);
1546    gettimeofday(&now, NULL);
1547    to.tv_sec = now.tv_sec + timeout / 1000;
1548    to.tv_nsec = now.tv_usec * 1000 + (timeout % 1000) * 1000 * 1000;
1549    if ((to.tv_nsec / 1000000000) >= 1)
1550    {
1551        to.tv_sec += to.tv_nsec / 1000000000;
1552        to.tv_nsec = to.tv_nsec % 1000000000;
1553    }
1554
1555    ret = true;
1556
1557    while (ue->signal == false)
1558    {
1559        if (timeout != INFINITE)
1560        {
1561            if (pthread_cond_timedwait(&ue->cond, &ue->mutex, &to))
1562            {
1563                ret = false;
1564                break;
1565            }
1566        }
1567        else
1568        {
1569            pthread_cond_wait(&ue->cond, &ue->mutex);
1570        }
1571    }
1572    ue->signal = false;
1573
1574    pthread_mutex_unlock(&ue->mutex);
1575
1576    return ret;
1577}
1578
1579// イベントのリセット
1580void UnixResetEvent(EVENT *event)
1581{
1582    UNIXEVENT *ue = (UNIXEVENT *)event->pData;
1583    if (ue == NULL)
1584    {
1585        return;
1586    }
1587
1588    pthread_mutex_lock(&ue->mutex);
1589    ue->signal = false;
1590    pthread_cond_signal(&ue->cond);
1591    pthread_mutex_unlock(&ue->mutex);
1592}
1593
1594// イベントのセット
1595void UnixSetEvent(EVENT *event)
1596{
1597    UNIXEVENT *ue = (UNIXEVENT *)event->pData;
1598    if (ue == NULL)
1599    {
1600        return;
1601    }
1602
1603    pthread_mutex_lock(&ue->mutex);
1604    ue->signal = true;
1605    pthread_cond_signal(&ue->cond);
1606    pthread_mutex_unlock(&ue->mutex);
1607}
1608
1609// イベントの初期化
1610void UnixInitEvent(EVENT *event)
1611{
1612    UNIXEVENT *ue = UnixMemoryAlloc(sizeof(UNIXEVENT));
1613
1614    Zero(ue, sizeof(UNIXEVENT));
1615
1616    pthread_cond_init(&ue->cond, NULL);
1617    pthread_mutex_init(&ue->mutex, NULL);
1618    ue->signal = false;
1619
1620    event->pData = (void *)ue;
1621}
1622
1623// ロックの削除
1624void UnixDeleteLock(LOCK *lock)
1625{
1626    pthread_mutex_t *mutex;
1627    // Ready フラグを安全に解除する
1628    UnixLock(lock);
1629    lock->Ready = false;
1630    UnixUnlockEx(lock, true);
1631
1632    // mutex の削除
1633    mutex = (pthread_mutex_t *)lock->pData;
1634    pthread_mutex_destroy(mutex);
1635
1636    // メモリ解放
1637    UnixMemoryFree(mutex);
1638    UnixMemoryFree(lock);
1639}
1640
1641// ロック解除
1642void UnixUnlock(LOCK *lock)
1643{
1644    UnixUnlockEx(lock, false);
1645}
1646void UnixUnlockEx(LOCK *lock, bool inner)
1647{
1648    pthread_mutex_t *mutex;
1649    if (lock->Ready == false && inner == false)
1650    {
1651        // 状態が不正
1652        return;
1653    }
1654    mutex = (pthread_mutex_t *)lock->pData;
1655
1656    if ((--lock->locked_count) > 0)
1657    {
1658        return;
1659    }
1660
1661    lock->thread_id = INFINITE;
1662
1663    pthread_mutex_unlock(mutex);
1664
1665    return;
1666}
1667
1668// ロック
1669bool UnixLock(LOCK *lock)
1670{
1671    pthread_mutex_t *mutex;
1672    UINT thread_id = UnixThreadId();
1673    if (lock->Ready == false)
1674    {
1675        // 状態が不正
1676        return false;
1677    }
1678
1679    if (lock->thread_id == thread_id)
1680    {
1681        lock->locked_count++;
1682        return true;
1683    }
1684
1685    mutex = (pthread_mutex_t *)lock->pData;
1686
1687    pthread_mutex_lock(mutex);
1688
1689    lock->thread_id = thread_id;
1690    lock->locked_count++;
1691
1692    return true;
1693}
1694
1695// 新しいロックの作成
1696LOCK *UnixNewLock()
1697{
1698    pthread_mutex_t *mutex;
1699    // メモリ確保
1700    LOCK *lock = UnixMemoryAlloc(sizeof(LOCK));
1701
1702    // mutex 作成
1703    mutex = UnixMemoryAlloc(sizeof(pthread_mutex_t));
1704
1705    // mutex 初期化
1706    pthread_mutex_init(mutex, NULL);
1707
1708    lock->pData = (void *)mutex;
1709    lock->Ready = true;
1710
1711    lock->thread_id = INFINITE;
1712    lock->locked_count = 0;
1713
1714    return lock;
1715}
1716
1717// スリープ
1718void UnixSleep(UINT time)
1719{
1720    UINT sec = 0, millisec = 0;
1721    // 引数チェック
1722    if (time == 0)
1723    {
1724        return;
1725    }
1726
1727    if (time == INFINITE)
1728    {
1729        // 無限に待機する
1730        while (true)
1731        {
1732#ifdef UNIX_SOLARIS
1733            UnixSolarisSleep(time);
1734#else
1735            sleep(1000000);
1736#endif
1737        }
1738    }
1739
1740#ifdef UNIX_SOLARIS
1741    UnixSolarisSleep(time);
1742#else
1743
1744    // 桁あふれ防止
1745    sec = time / 1000;
1746    millisec = time % 1000;
1747
1748    if (sec != 0)
1749    {
1750        sleep(sec);
1751    }
1752    if (millisec != 0)
1753    {
1754        usleep(millisec * 1000);
1755    }
1756#endif
1757}
1758
1759// デクリメント
1760void UnixDec32(UINT *value)
1761{
1762    if (value != NULL)
1763    {
1764        (*value)--;
1765    }
1766}
1767
1768// インクリメント
1769void UnixInc32(UINT *value)
1770{
1771    if (value != NULL)
1772    {
1773        (*value)++;
1774    }
1775}
1776
1777// システム時刻の取得
1778void UnixGetSystemTime(SYSTEMTIME *system_time)
1779{
1780    time_t now = 0;
1781    struct tm tm;
1782    struct timeval tv;
1783    struct timezone tz;
1784    // 引数チェック
1785    if (system_time == NULL)
1786    {
1787        return;
1788    }
1789
1790    pthread_mutex_lock(&get_time_lock);
1791
1792    Zero(system_time, sizeof(SYSTEMTIME));
1793    Zero(&tv, sizeof(tv));
1794    Zero(&tz, sizeof(tz));
1795
1796    time(&now);
1797
1798    gmtime_r(&now, &tm);
1799
1800    TmToSystem(system_time, &tm);
1801
1802    gettimeofday(&tv, &tz);
1803
1804    system_time->wMilliseconds = tv.tv_usec / 1000;
1805
1806    pthread_mutex_unlock(&get_time_lock);
1807}
1808
1809// システムタイマの取得 (64bit)
1810UINT64 UnixGetTick64()
1811{
1812#if defined(OS_WIN32) || defined(CLOCK_REALTIME) || defined(CLOCK_MONOTONIC) || defined(CLOCK_HIGHRES)
1813
1814    struct timespec t;
1815    UINT64 ret;
1816    static bool akirame = false;
1817
1818    if (akirame)
1819    {
1820        return TickRealtimeManual();
1821    }
1822
1823    Zero(&t, sizeof(t));
1824
1825    // システムの起動時刻を取得する関数
1826    // システムによって実装が異なるので注意
1827#ifdef  CLOCK_HIGHRES
1828    clock_gettime(CLOCK_HIGHRES, &t);
1829#else   // CLOCK_HIGHRES
1830#ifdef  CLOCK_MONOTONIC
1831    clock_gettime(CLOCK_MONOTONIC, &t);
1832#else   // CLOCK_MONOTONIC
1833    clock_gettime(CLOCK_REALTIME, &t);
1834#endif  // CLOCK_MONOTONIC
1835#endif  // CLOCK_HIGHRES
1836
1837    ret = (UINT64)t.tv_sec * 1000LL + (UINT64)t.tv_nsec / 1000000LL;
1838
1839    if (akirame == false && ret == 0)
1840    {
1841        ret = TickRealtimeManual();
1842        akirame = true;
1843    }
1844
1845    return ret;
1846
1847#else
1848
1849    return TickRealtimeManual();
1850
1851#endif
1852}
1853
1854// システムタイマの取得
1855UINT UnixGetTick()
1856{
1857    return (UINT)UnixGetTick64();
1858}
1859
1860// メモリの確保
1861void *UnixMemoryAlloc(UINT size)
1862{
1863    void *r;
1864    pthread_mutex_lock(&malloc_lock);
1865    r = malloc(size);
1866    pthread_mutex_unlock(&malloc_lock);
1867    return r;
1868}
1869
1870// メモリの再確保
1871void *UnixMemoryReAlloc(void *addr, UINT size)
1872{
1873    void *r;
1874    pthread_mutex_lock(&malloc_lock);
1875    r = realloc(addr, size);
1876    pthread_mutex_unlock(&malloc_lock);
1877    return r;
1878}
1879
1880// メモリの解放
1881void UnixMemoryFree(void *addr)
1882{
1883    pthread_mutex_lock(&malloc_lock);
1884    free(addr);
1885    pthread_mutex_unlock(&malloc_lock);
1886}
1887
1888// SIGCHLD ハンドラ
1889void UnixSigChldHandler(int sig)
1890{
1891    // ゾンビプロセスの回収
1892    while (waitpid(-1, NULL, WNOHANG) > 0);
1893    signal(SIGCHLD, UnixSigChldHandler);
1894}
1895
1896// UNIX 用ライブラリの初期化
1897void UnixInit()
1898{
1899    UNIXIO *o;
1900
1901    UnixInitSolarisSleep();
1902
1903    // グローバルロック
1904    pthread_mutex_init(&get_time_lock, NULL);
1905    pthread_mutex_init(&malloc_lock, NULL);
1906
1907    // プロセス ID の取得
1908    current_process_id = getpid();
1909
1910#ifdef  RLIMIT_CORE
1911    UnixSetResourceLimit(RLIMIT_CORE, UNIX_MAX_MEMORY);
1912#endif  // RLIMIT_CORE
1913
1914#ifdef  RLIMIT_DATA
1915    UnixSetResourceLimit(RLIMIT_DATA, UNIX_MAX_MEMORY);
1916#endif  // RLIMIT_DATA
1917
1918#ifdef  RLIMIT_NOFILE
1919    UnixSetResourceLimit(RLIMIT_NOFILE, UNIX_MAX_FD);
1920#endif  // RLIMIT_NOFILE
1921
1922#ifdef  RLIMIT_STACK
1923//  UnixSetResourceLimit(RLIMIT_STACK, UNIX_MAX_MEMORY);
1924#endif  // RLIMIT_STACK
1925
1926#ifdef  RLIMIT_RSS
1927    UnixSetResourceLimit(RLIMIT_RSS, UNIX_MAX_MEMORY);
1928#endif  // RLIMIT_RSS
1929
1930#ifdef  RLIMIT_LOCKS
1931    UnixSetResourceLimit(RLIMIT_LOCKS, UNIX_MAX_LOCKS);
1932#endif  // RLIMIT_LOCKS
1933
1934#ifdef  RLIMIT_MEMLOCK
1935    UnixSetResourceLimit(RLIMIT_MEMLOCK, UNIX_MAX_MEMORY);
1936#endif  // RLIMIT_MEMLOCK
1937
1938#ifdef  RLIMIT_NPROC
1939    UnixSetResourceLimit(RLIMIT_NPROC, UNIX_MAX_CHILD_PROCESSES);
1940#endif  // RLIMIT_NPROC
1941
1942    // proc ファイルシステムの threads-max に値を書き込む
1943    o = UnixFileCreate("/proc/sys/kernel/threads-max");
1944    if (o != NULL)
1945    {
1946        char tmp[128];
1947        sprintf(tmp, "%u\n", UNIX_LINUX_MAX_THREADS);
1948        UnixFileWrite(o, tmp, strlen(tmp));
1949        UnixFileClose(o, false);
1950    }
1951
1952    // 無視するシグナルを設定
1953    signal(SIGPIPE, SIG_IGN);
1954    signal(SIGALRM, SIG_IGN);
1955
1956#ifdef  UNIX_BSD
1957    signal(64, SIG_IGN);
1958#endif  // UNIX_BSD
1959
1960#ifdef  SIGXFSZ
1961    signal(SIGXFSZ, SIG_IGN);
1962#endif  // SIGXFSZ
1963
1964    // 子プロセス回収用シグナルハンドラの設定
1965    signal(SIGCHLD, UnixSigChldHandler);
1966}
1967
1968// UNIX 用ライブラリの解放
1969void UnixFree()
1970{
1971    UnixFreeSolarisSleep();
1972
1973    current_process_id = 0;
1974
1975    pthread_mutex_destroy(&get_time_lock);
1976}
1977
1978// 占有することができる資源の上限値を調整
1979void UnixSetResourceLimit(UINT id, UINT value)
1980{
1981    struct rlimit t;
1982    UINT hard_limit;
1983
1984    Zero(&t, sizeof(t));
1985    getrlimit(id, &t);
1986
1987    hard_limit = t.rlim_max;
1988
1989    Zero(&t, sizeof(t));
1990    t.rlim_cur = MIN(value, hard_limit);
1991    t.rlim_max = hard_limit;
1992    setrlimit(id, &t);
1993
1994    Zero(&t, sizeof(t));
1995    t.rlim_cur = value;
1996    t.rlim_max = value;
1997    setrlimit(id, &t);
1998}
1999
2000// PID ファイル名を生成する
2001void UnixGenPidFileName(char *name, UINT size)
2002{
2003    char exe_name[MAX_PATH];
2004    UCHAR hash[MD5_SIZE];
2005    char tmp1[64];
2006    char dir[MAX_PATH];
2007    // 引数チェック
2008    if (name == NULL)
2009    {
2010        return;
2011    }
2012
2013    GetExeDir(dir, sizeof(dir));
2014
2015    GetExeName(exe_name, sizeof(exe_name));
2016    StrCat(exe_name, sizeof(exe_name), ":pid_hash");
2017    StrUpper(exe_name);
2018
2019    Hash(hash, exe_name, StrLen(exe_name), false);
2020    BinToStr(tmp1, sizeof(tmp1), hash, sizeof(hash));
2021
2022    Format(name, size, "%s/.pid_%s", dir, tmp1);
2023}
2024
2025// PID ファイルを削除する
2026void UnixDeletePidFile()
2027{
2028    char tmp[MAX_PATH];
2029
2030    UnixGenPidFileName(tmp, sizeof(tmp));
2031
2032    UnixFileDelete(tmp);
2033}
2034
2035// PID ファイルに書き込む
2036void UnixWritePidFile(UINT pid)
2037{
2038    char tmp[MAX_PATH];
2039    char tmp2[64];
2040    IO *o;
2041
2042    UnixGenPidFileName(tmp, sizeof(tmp));
2043    Format(tmp2, sizeof(tmp2), "%u\n", pid);
2044
2045    o = FileCreate(tmp);
2046    if (o != NULL)
2047    {
2048        FileWrite(o, tmp2, StrLen(tmp2));
2049        FileClose(o);
2050    }
2051}
2052
2053// PID ファイルを読み込む
2054UINT UnixReadPidFile()
2055{
2056    char tmp[MAX_PATH];
2057    BUF *buf;
2058
2059    UnixGenPidFileName(tmp, sizeof(tmp));
2060
2061    buf = ReadDump(tmp);
2062    if (buf == NULL)
2063    {
2064        return 0;
2065    }
2066
2067    Zero(tmp, sizeof(tmp));
2068    Copy(tmp, buf->Buf, MIN(buf->Size, sizeof(tmp)));
2069    FreeBuf(buf);
2070
2071    return ToInt(tmp);
2072}
2073
2074// サービスの開始
2075void UnixStartService(char *name)
2076{
2077    char *svc_name, *svc_title;
2078    char tmp[128];
2079    INSTANCE *inst;
2080    char exe[MAX_PATH];
2081    // 引数チェック
2082    if (name == NULL)
2083    {
2084        return;
2085    }
2086
2087    GetExeName(exe, sizeof(exe));
2088
2089    Format(tmp, sizeof(tmp), SVC_NAME, name);
2090    svc_name = _SS(tmp);
2091    Format(tmp, sizeof(tmp), SVC_TITLE, name);
2092    svc_title = _SS(tmp);
2093
2094    // すでにサービスが起動していないかどうか調べる
2095    inst = NewSingleInstance(NULL);
2096    if (inst == NULL)
2097    {
2098        // すでにサービスが起動している
2099        UniPrint(_UU("UNIX_SVC_ALREADY_START"), svc_title, svc_name);
2100    }
2101    else
2102    {
2103        int pid;
2104        // サービスの起動を開始する
2105        UniPrint(_UU("UNIX_SVC_STARTED"), svc_title);
2106        FreeSingleInstance(inst);
2107
2108        // 子プロセスを作成する
2109        pid = fork();
2110        if (pid == -1)
2111        {
2112            UniPrint(_UU("UNIX_SVC_ERROR_FORK"), svc_title);
2113        }
2114        else
2115        {
2116            if (pid == 0)
2117            {
2118                // 子プロセス
2119                char *param = UNIX_SVC_ARG_EXEC_SVC;
2120                char **args;
2121
2122                // デーモン化する
2123                setsid();
2124                UnixCloseIO();
2125                signal(SIGHUP, SIG_IGN);
2126
2127                // 引数を準備
2128                args = ZeroMalloc(sizeof(char *) * 3);
2129                args[0] = exe;
2130                args[1] = param;
2131                args[2] = NULL;
2132
2133                execvp(exe, args);
2134                AbortExit();
2135            }
2136            else
2137            {
2138                // 子プロセス番号をファイルに書き込まない
2139//              UnixWritePidFile(pid);
2140            }
2141        }
2142    }
2143}
2144
2145// サービスの停止
2146void UnixStopService(char *name)
2147{
2148    char *svc_name, *svc_title;
2149    char tmp[128];
2150    INSTANCE *inst;
2151    char exe[MAX_PATH];
2152    UINT pid;
2153    // 引数チェック
2154    if (name == NULL)
2155    {
2156        return;
2157    }
2158
2159    GetExeName(exe, sizeof(exe));
2160
2161    Format(tmp, sizeof(tmp), SVC_NAME, name);
2162    svc_name = _SS(tmp);
2163    Format(tmp, sizeof(tmp), SVC_TITLE, name);
2164    svc_title = _SS(tmp);
2165
2166    inst = NewSingleInstance(NULL);
2167    pid = UnixReadPidFile();
2168    if (inst != NULL || pid == 0)
2169    {
2170        // まだサービスが起動していない
2171        UniPrint(_UU("UNIX_SVC_NOT_STARTED"), svc_title, svc_name);
2172    }
2173    else
2174    {
2175        int status;
2176
2177        // サービスを停止する
2178        UniPrint(_UU("UNIX_SVC_STOPPING"), svc_title);
2179
2180        // プロセスを終了する
2181        kill(pid, SIGTERM);
2182        if (UnixWaitProcessEx(pid, UNIX_SERVICE_STOP_TIMEOUT_2))
2183        {
2184            UniPrint(_UU("UNIX_SVC_STOPPED"), svc_title);
2185        }
2186        else
2187        {
2188            UniPrint(_UU("UNIX_SVC_STOP_FAILED"), svc_title);
2189        }
2190    }
2191
2192    FreeSingleInstance(inst);
2193}
2194
2195// プロセスへの停止シグナルのハンドラ
2196void UnixSigTermHandler(int signum)
2197{
2198    if (signum == SIGTERM)
2199    {
2200        unix_svc_terminate = true;
2201    }
2202}
2203
2204// サービス停止用スレッド
2205void UnixStopThread(THREAD *t, void *param)
2206{
2207    SERVICE_FUNCTION *stop = (SERVICE_FUNCTION *)param;
2208    // 引数チェック
2209    if (t == NULL || param == NULL)
2210    {
2211        return;
2212    }
2213
2214    stop();
2215}
2216
2217// サービスの内容の実行
2218void UnixExecService(char *name, SERVICE_FUNCTION *start, SERVICE_FUNCTION *stop)
2219{
2220    char *svc_name, *svc_title;
2221    char tmp[128];
2222    INSTANCE *inst;
2223    UINT yobi_size = 1024 * 128;
2224    void *yobi1, *yobi2;
2225    // 引数チェック
2226    if (start == NULL || stop == NULL || name == NULL)
2227    {
2228        return;
2229    }
2230
2231    Format(tmp, sizeof(tmp), SVC_NAME, name);
2232    svc_name = _SS(tmp);
2233    Format(tmp, sizeof(tmp), SVC_TITLE, name);
2234    svc_title = _SS(tmp);
2235
2236    inst = NewSingleInstance(NULL);
2237    if (inst != NULL)
2238    {
2239        THREAD *t;
2240
2241        yobi1 = ZeroMalloc(yobi_size);
2242        yobi2 = ZeroMalloc(yobi_size);
2243
2244        // 起動
2245        UnixWritePidFile(getpid());
2246
2247        start();
2248
2249        // 起動完了 別のプロセスから SIGTERM が送られてくるのを待つ
2250        signal(SIGTERM, &UnixSigTermHandler);
2251        while (unix_svc_terminate == false)
2252        {
2253            pause();
2254        }
2255
2256        // 停止
2257        Free(yobi1);
2258        t = NewThread(UnixStopThread, stop);
2259        if (t == NULL || (WaitThread(t, UNIX_SERVICE_STOP_TIMEOUT_1) == false))
2260        {
2261            // 停止用スレッドの作成に失敗したか、タイムアウトした場合は
2262            // 強制終了する
2263            Free(yobi2);
2264            FreeSingleInstance(inst);
2265            UnixDeletePidFile();
2266            _exit(0);
2267        }
2268        ReleaseThread(t);
2269
2270        // PID ファイルを削除
2271        UnixDeletePidFile();
2272
2273        FreeSingleInstance(inst);
2274
2275        Free(yobi2);
2276    }
2277}
2278
2279// 指定した pid のプロセスが存在するかどうか取得する
2280bool UnixIsProcess(UINT pid)
2281{
2282    if (getsid((pid_t)pid) == -1)
2283    {
2284        return false;
2285    }
2286
2287    return true;
2288}
2289
2290// 指定したプロセスの終了を待機する
2291bool UnixWaitProcessEx(UINT pid,  UINT timeout)
2292{
2293    UINT64 start_tick = Tick64();
2294    UINT64 end_tick = start_tick + (UINT64)timeout;
2295    if (timeout == INFINITE)
2296    {
2297        end_tick = 0;
2298    }
2299    while (UnixIsProcess(pid))
2300    {
2301        if (end_tick != 0)
2302        {
2303            if (end_tick < Tick64())
2304            {
2305                return false;
2306            }
2307        }
2308        SleepThread(100);
2309    }
2310    return true;
2311}
2312void UnixWaitProcess(UINT pid)
2313{
2314    UnixWaitProcessEx(pid, INFINITE);
2315}
2316
2317// 起動方法の説明
2318void UnixUsage(char *name)
2319{
2320    char *svc_name, *svc_title;
2321    char tmp[128];
2322    // 引数チェック
2323    if (name == NULL)
2324    {
2325        return;
2326    }
2327
2328    Format(tmp, sizeof(tmp), SVC_NAME, name);
2329    svc_name = _SS(tmp);
2330    Format(tmp, sizeof(tmp), SVC_TITLE, name);
2331    svc_title = _SS(tmp);
2332
2333    UniPrint(_UU("UNIX_SVC_HELP"), svc_title, svc_name, svc_name, svc_title, svc_name, svc_title);
2334}
2335
2336// UNIX サービスのメイン関数
2337UINT UnixService(int argc, char *argv[], char *name, SERVICE_FUNCTION *start, SERVICE_FUNCTION *stop)
2338{
2339    // 引数チェック
2340    if (name == NULL || start == NULL || stop == NULL)
2341    {
2342        return 0;
2343    }
2344
2345    if (argc >= 2 && StrCmpi(argv[1], UNIX_SVC_ARG_EXEC_SVC) == 0)
2346    {
2347        UINT pid;
2348        // 子プロセスを生成して開始する
2349        // もし子プロセスが正しく終了しなかった場合は再起動する
2350
2351RESTART_PROCESS:
2352        pid = fork();
2353        if ((int)pid != -1)
2354        {
2355            if (pid == 0)
2356            {
2357                // メイン処理の実行
2358                UnixServiceMain(argc, argv, name, start, stop);
2359            }
2360            else
2361            {
2362                int status = 0, ret;
2363
2364                // 子プロセスの終了を待機する
2365                ret = waitpid(pid, &status, 0);
2366
2367                if (WIFEXITED(status) == 0)
2368                {
2369                    // 異常終了した
2370                    UnixSleep(100);
2371                    goto RESTART_PROCESS;
2372                }
2373            }
2374        }
2375    }
2376    else
2377    {
2378        // 通常に開始する
2379        UnixServiceMain(argc, argv, name, start, stop);
2380    }
2381
2382    return 0;
2383}
2384void UnixServiceMain(int argc, char *argv[], char *name, SERVICE_FUNCTION *start, SERVICE_FUNCTION *stop)
2385{
2386    UINT mode = 0;
2387    // Mayaqua の開始
2388    InitMayaqua(false, false, argc, argv);
2389
2390    if (argc >= 2)
2391    {
2392        if (StrCmpi(argv[1], UNIX_SVC_ARG_START) == 0)
2393        {
2394            mode = UNIX_SVC_MODE_START;
2395        }
2396        if (StrCmpi(argv[1], UNIX_SVC_ARG_STOP) == 0)
2397        {
2398            mode = UNIX_SVC_MODE_STOP;
2399        }
2400        if (StrCmpi(argv[1], UNIX_SVC_ARG_EXEC_SVC) == 0)
2401        {
2402            mode = UNIX_SVC_MODE_EXEC_SVC;
2403        }
2404        if (StrCmpi(argv[1], UNIX_ARG_EXIT) == 0)
2405        {
2406            mode = UNIX_SVC_MODE_EXIT;
2407        }
2408    }
2409
2410    switch (mode)
2411    {
2412    case UNIX_SVC_MODE_EXIT:
2413        break;
2414
2415    case UNIX_SVC_MODE_START:
2416        UnixStartService(name);
2417        break;
2418
2419    case UNIX_SVC_MODE_STOP:
2420        UnixStopService(name);
2421        break;
2422
2423    case UNIX_SVC_MODE_EXEC_SVC:
2424        UnixExecService(name, start, stop);
2425        break;
2426
2427    default:
2428        UnixUsage(name);
2429        break;
2430    }
2431
2432    // Mayaquq の終了
2433    FreeMayaqua();
2434
2435    return;
2436}
2437
2438#endif  // UNIX
Note: See TracBrowser for help on using the repository browser.