1 // SoftEther UT-VPN SourceCode
\r
3 // Copyright (C) 2004-2010 SoftEther Corporation.
\r
4 // Copyright (C) 2004-2010 University of Tsukuba, Japan.
\r
5 // Copyright (C) 2003-2010 Daiyuu Nobori.
\r
6 // All Rights Reserved.
\r
8 // http://utvpn.tsukuba.ac.jp/
\r
10 // This program is free software; you can redistribute it and/or
\r
11 // modify it under the terms of the GNU General Public License
\r
12 // version 2 as published by the Free Software Foundation.
\r
14 // This program is distributed in the hope that it will be useful,
\r
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
17 // GNU General Public License for more details.
\r
19 // You should have received a copy of the GNU General Public License version 2
\r
20 // along with this program; if not, write to the Free Software
\r
21 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
\r
23 // このファイルは GPL バージョン 2 ライセンスで公開されています。
\r
24 // 誰でもこのファイルの内容を複製、改変したり、改変したバージョンを再配布
\r
25 // することができます。ただし、原著作物を改変した場合は、原著作物の著作権表示
\r
26 // を除去することはできません。改変した著作物を配布する場合は、改変実施者の
\r
27 // 著作権表示を原著作物の著作権表示に付随して記載するようにしてください。
\r
29 // この SoftEther UT-VPN オープンソース・プロジェクトは、日本国の
\r
30 // ソフトイーサ株式会社 (SoftEther Corporation, http://www.softether.co.jp/ )
\r
31 // および筑波大学 (University of Tsukuba, http://www.tsukuba.ac.jp/ ) によって
\r
33 // 本プログラムの配布者は、本プログラムを、業としての利用以外のため、
\r
34 // および、試験または研究のために利用が行われることを想定して配布
\r
36 // SoftEther UT-VPN プロジェクトの Web サイトは http://utvpn.tsukuba.ac.jp/ に
\r
38 // 本ソフトウェアの不具合の修正、機能改良、セキュリティホールの修復などのコード
\r
39 // の改変を行った場合で、その成果物を SoftEther UT-VPN プロジェクトに提出して
\r
40 // いただける場合は、 http://utvpn.tsukuba.ac.jp/ までソースコードを送付して
\r
41 // ください。SoftEther UT-VPN プロジェクトの本体リリースまたはブランチリリース
\r
44 // GPL に基づいて原著作物が提供される本ソフトウェアの改良版を配布、販売する
\r
45 // 場合は、そのソースコードを GPL に基づいて誰にでも開示する義務が生じます。
\r
47 // 本ソフトウェアに関連する著作権、特許権、商標権はソフトイーサ株式会社
\r
48 // (SoftEther Corporation) およびその他の著作権保持者が保有しています。
\r
49 // ソフトイーサ株式会社等はこれらの権利を放棄していません。本ソフトウェアの
\r
50 // 二次著作物を配布、販売する場合は、これらの権利を侵害しないようにご注意
\r
53 // お願い: どのような通信ソフトウェアにも通常は必ず未発見の
\r
54 // セキュリティホールが潜んでいます。本ソースコードをご覧いただいた結果、
\r
55 // UT-VPN にセキュリティホールを発見された場合は、当該セキュリティホールの
\r
56 // 情報を不特定多数に開示される前に、必ず、ソフトイーサ株式会社
\r
57 // および脆弱性情報の届出を受け付ける公的機関まで通報いただき、
\r
58 // 公益保護にご協力いただきますようお願い申し上げます。
\r
60 // ソフトイーサ株式会社は、当該セキュリティホールについて迅速に対処を
\r
61 // 行い、UT-VPN および UT-VPN に関連するソフトウェアのユーザー・顧客
\r
64 // ソフトイーサへの届出先: http://www.softether.co.jp/jp/contact/
\r
65 // 日本国内の脆弱性情報届出受付公的機関:
\r
67 // http://www.ipa.go.jp/security/vuln/report/
\r
69 // 上記各事項について不明な点は、ソフトイーサ株式会社までご連絡ください。
\r
70 // 連絡先: http://www.softether.co.jp/jp/contact/
\r
72 // -----------------------------------------------
\r
75 // 新規リリース by SoftEther
\r
76 // -----------------------------------------------
\r
90 #include <Mayaqua/Mayaqua.h>
\r
92 // MacOS X 用の struct statfs
\r
94 typedef struct fsid { int32_t val[2]; } fsid_t;
\r
96 short f_otype; /* TEMPORARY SHADOW COPY OF f_type */
\r
97 short f_oflags; /* TEMPORARY SHADOW COPY OF f_flags */
\r
98 long f_bsize; /* fundamental file system block size */
\r
99 long f_iosize; /* optimal transfer block size */
\r
100 long f_blocks; /* total data blocks in file system */
\r
101 long f_bfree; /* free blocks in fs */
\r
102 long f_bavail; /* free blocks avail to non-superuser */
\r
103 long f_files; /* total file nodes in file system */
\r
104 long f_ffree; /* free file nodes in fs */
\r
105 fsid_t f_fsid; /* file system id */
\r
106 uid_t f_owner; /* user that mounted the filesystem */
\r
107 short f_reserved1; /* spare for later */
\r
108 short f_type; /* type of filesystem */
\r
109 long f_flags; /* copy of mount exported flags */
\r
110 long f_reserved2[2]; /* reserved for future use */
\r
111 char f_fstypename[15]; /* fs type name */
\r
112 char f_mntonname[90]; /* directory on which mounted */
\r
113 char f_mntfromname[90];/* mounted filesystem */
\r
115 #endif // UNIX_MACOS
\r
117 // Solaris 用の scandir() 関数
\r
118 #ifdef UNIX_SOLARIS
\r
119 #define scandir local_scandir
\r
120 #define alphasort local_alphasort
\r
122 /*******************************************
\r
123 * Copyright Free の互換ルーチン (local_scandir)
\r
124 * コピー元: http://www005.upp.so-net.ne.jp/yoga/compile.html
\r
125 *******************************************/
\r
127 int local_scandir(const char *dir, struct dirent ***namelist,
\r
128 int (*select)(const struct dirent *),
\r
129 int (*compar)(const struct dirent **, const struct dirent **))
\r
132 struct dirent *entry;
\r
136 if ((d=opendir(dir)) == NULL)
\r
140 while ((entry=readdir(d)) != NULL)
\r
142 if (select == NULL || (select != NULL && (*select)(entry)))
\r
144 *namelist=(struct dirent **)realloc((void *)(*namelist),
\r
145 (size_t)((i+1)*sizeof(struct dirent *)));
\r
146 if (*namelist == NULL) return(-1);
\r
147 entrysize=sizeof(struct dirent)-sizeof(entry->d_name)+strlen(entry->d_name)+1;
\r
148 (*namelist)[i]=(struct dirent *)malloc(entrysize);
\r
149 if ((*namelist)[i] == NULL) return(-1);
\r
150 memcpy((*namelist)[i], entry, entrysize);
\r
154 if (closedir(d)) return(-1);
\r
155 if (i == 0) return(-1);
\r
156 if (compar != NULL)
\r
157 qsort((void *)(*namelist), (size_t)i, sizeof(struct dirent *), compar);
\r
162 int local_alphasort(const struct dirent **a, const struct dirent **b)
\r
164 return(strcmp((*a)->d_name, (*b)->d_name));
\r
168 #endif // UNIX_SOLARIS
\r
171 typedef struct UNIXTHREAD
\r
178 typedef struct UNIXTHREADSTARTUPINFO
\r
180 THREAD_PROC *thread_proc;
\r
183 } UNIXTHREADSTARTUPINFO;
\r
185 // UNIX 用スレッド関数プロトタイプ
\r
186 void *UnixDefaultThreadProc(void *param);
\r
189 static pid_t current_process_id = 0;
\r
191 // UNIX 用ファイル I/O データ
\r
192 typedef struct UNIXIO
\r
198 // UNIX 用ロックファイルデータ
\r
199 typedef struct UNIXLOCKFILE
\r
201 char FileName[MAX_SIZE];
\r
206 typedef struct UNIXEVENT
\r
208 pthread_mutex_t mutex;
\r
209 pthread_cond_t cond;
\r
213 static pthread_mutex_t get_time_lock;
\r
214 static pthread_mutex_t malloc_lock;
\r
215 static bool high_process = false;
\r
217 static bool unix_svc_terminate = false;
\r
218 static int solaris_sleep_p1 = -1, solaris_sleep_p2 = -1;
\r
221 OS_DISPATCH_TABLE *UnixGetDispatchTable()
\r
223 static OS_DISPATCH_TABLE t =
\r
265 UnixGetCallStackSymbolInfo,
\r
275 UnixSetHighPriority,
\r
276 UnixRestorePriority,
\r
277 UnixNewSingleInstance,
\r
278 UnixFreeSingleInstance,
\r
286 // Solaris 用 Sleep の初期化
\r
287 void UnixInitSolarisSleep()
\r
289 char tmp[MAX_SIZE];
\r
291 UnixNewPipe(&solaris_sleep_p1, &solaris_sleep_p2);
\r
292 read(solaris_sleep_p1, tmp, sizeof(tmp));
\r
295 // Solaris 用 Sleep の解放
\r
296 void UnixFreeSolarisSleep()
\r
298 UnixDeletePipe(solaris_sleep_p1, solaris_sleep_p2);
\r
299 solaris_sleep_p1 = -1;
\r
300 solaris_sleep_p2 = -1;
\r
304 void UnixSolarisSleep(UINT msec)
\r
308 memset(&p, 0, sizeof(p));
\r
309 p.fd = solaris_sleep_p1;
\r
312 poll(&p, 1, msec == INFINITE ? -1 : (int)msec);
\r
316 bool UnixGetDiskFreeW(wchar_t *path, UINT64 *free_size, UINT64 *used_size, UINT64 *total_size)
\r
318 char *path_a = CopyUniToStr(path);
\r
321 ret = UnixGetDiskFree(path_a, free_size, used_size, total_size);
\r
327 bool UnixGetDiskFree(char *path, UINT64 *free_size, UINT64 *used_size, UINT64 *total_size)
\r
329 char tmp[MAX_PATH];
\r
337 NormalizePath(tmp, sizeof(tmp), path);
\r
339 while ((ret = UnixGetDiskFreeMain(tmp, free_size, used_size, total_size)) == false)
\r
341 if (StrCmpi(tmp, "/") == 0)
\r
346 GetDirNameFromFilePath(tmp, sizeof(tmp), tmp);
\r
351 bool UnixGetDiskFreeMain(char *path, UINT64 *free_size, UINT64 *used_size, UINT64 *total_size)
\r
353 #ifndef USE_STATVFS
\r
355 char tmp[MAX_PATH];
\r
356 UINT64 v1 = 0, v2 = 0;
\r
364 NormalizePath(tmp, sizeof(tmp), path);
\r
366 Zero(&st, sizeof(st));
\r
367 if (statfs(tmp, &st) == 0)
\r
369 v1 = (UINT64)st.f_bsize * (UINT64)st.f_bavail;
\r
370 v2 = (UINT64)st.f_bsize * (UINT64)st.f_blocks;
\r
374 if (free_size != NULL)
\r
379 if (total_size != NULL)
\r
384 if (used_size != NULL)
\r
386 *used_size = v2 - v1;
\r
390 #else // USE_STATVFS
\r
392 char tmp[MAX_PATH];
\r
393 UINT64 v1 = 0, v2 = 0;
\r
401 NormalizePath(tmp, sizeof(tmp), path);
\r
403 Zero(&st, sizeof(st));
\r
405 if (statvfs(tmp, &st) == 0)
\r
407 v1 = (UINT64)st.f_bsize * (UINT64)st.f_bavail;
\r
408 v2 = (UINT64)st.f_bsize * (UINT64)st.f_blocks;
\r
412 if (free_size != NULL)
\r
417 if (total_size != NULL)
\r
422 if (used_size != NULL)
\r
424 *used_size = v2 - v1;
\r
428 #endif // USE_STATVFS
\r
432 DIRLIST *UnixEnumDirEx(char *dirname, COMPARE *compare)
\r
434 char tmp[MAX_PATH];
\r
440 if (dirname == NULL)
\r
445 o = NewListFast(compare);
\r
447 NormalizePath(tmp, sizeof(tmp), dirname);
\r
449 if (StrLen(tmp) >= 1 && tmp[StrLen(tmp) - 1] != '/')
\r
451 StrCat(tmp, sizeof(tmp), "/");
\r
455 n = scandir(tmp, &e, 0, alphasort);
\r
457 if (StrLen(tmp) >= 1 && tmp[StrLen(tmp) - 1] == '/')
\r
459 tmp[StrLen(tmp) - 1] = 0;
\r
462 if (n >= 0 && e != NULL)
\r
466 for (i = 0;i < (UINT)n;i++)
\r
468 char *filename = e[i]->d_name;
\r
470 if (filename != NULL)
\r
472 if (StrCmpi(filename, "..") != 0 && StrCmpi(filename, ".") != 0)
\r
474 char fullpath[MAX_PATH];
\r
476 Format(fullpath, sizeof(fullpath), "%s/%s", tmp, filename);
\r
478 Zero(&st, sizeof(st));
\r
480 if (stat(fullpath, &st) == 0)
\r
482 DIRENT *f = ZeroMalloc(sizeof(DIRENT));
\r
485 f->Folder = S_ISDIR(st.st_mode) ? true : false;
\r
486 f->FileName = CopyStr(filename);
\r
487 f->FileNameW = CopyUtfToUni(f->FileName);
\r
489 Zero(&t, sizeof(t));
\r
490 TimeToSystem(&t, st.st_ctime);
\r
491 f->CreateDate = LocalToSystem64(SystemToUINT64(&t));
\r
493 Zero(&t, sizeof(t));
\r
494 TimeToSystem(&t, st.st_mtime);
\r
495 f->UpdateDate = LocalToSystem64(SystemToUINT64(&t));
\r
497 if (f->Folder == false)
\r
499 f->FileSize = st.st_size;
\r
515 d = ZeroMalloc(sizeof(DIRLIST));
\r
516 d->NumFiles = LIST_NUM(o);
\r
517 d->File = ToArray(o);
\r
523 DIRLIST *UnixEnumDirExW(wchar_t *dirname, COMPARE *compare)
\r
525 char *dirname_a = CopyUniToUtf(dirname);
\r
528 ret = UnixEnumDirEx(dirname_a, compare);
\r
535 // 指定したファイルの実行権限をチェックする
\r
536 bool UnixCheckExecAccess(char *name)
\r
544 if (access(name, X_OK) == 0)
\r
551 bool UnixCheckExecAccessW(wchar_t *name)
\r
561 name_a = CopyUniToUtf(name);
\r
563 ret = UnixCheckExecAccess(name_a);
\r
571 void UnixSetThreadPriorityRealtime()
\r
573 struct sched_param p;
\r
574 Zero(&p, sizeof(p));
\r
575 p.sched_priority = 255;
\r
576 pthread_setschedparam(pthread_self(), SCHED_RR, &p);
\r
580 void UnixSetThreadPriorityLow()
\r
582 struct sched_param p;
\r
583 Zero(&p, sizeof(p));
\r
584 p.sched_priority = 32;
\r
585 pthread_setschedparam(pthread_self(), SCHED_OTHER, &p);
\r
589 void UnixSetThreadPriorityHigh()
\r
591 struct sched_param p;
\r
592 Zero(&p, sizeof(p));
\r
593 p.sched_priority = 127;
\r
594 pthread_setschedparam(pthread_self(), SCHED_RR, &p);
\r
597 // スレッドの優先順位をアイドルにする
\r
598 void UnixSetThreadPriorityIdle()
\r
600 struct sched_param p;
\r
601 Zero(&p, sizeof(p));
\r
602 p.sched_priority = 1;
\r
603 pthread_setschedparam(pthread_self(), SCHED_OTHER, &p);
\r
607 void UnixRestoreThreadPriority()
\r
609 struct sched_param p;
\r
610 Zero(&p, sizeof(p));
\r
611 p.sched_priority = 64;
\r
612 pthread_setschedparam(pthread_self(), SCHED_OTHER, &p);
\r
616 void UnixGetCurrentDir(char *dir, UINT size)
\r
626 void UnixGetCurrentDirW(wchar_t *dir, UINT size)
\r
628 char dir_a[MAX_PATH];
\r
630 UnixGetCurrentDir(dir_a, sizeof(dir_a));
\r
632 UtfToUni(dir, size, dir_a);
\r
638 #ifdef UNIX_SOLARIS
\r
639 UnixSolarisSleep(1);
\r
646 void UnixGetMemInfo(MEMINFO *info)
\r
655 Zero(info, sizeof(MEMINFO));
\r
659 void UnixFreeSingleInstance(void *data)
\r
669 o = (UNIXLOCKFILE *)data;
\r
671 Zero(&lock, sizeof(lock));
\r
672 lock.l_type = F_UNLCK;
\r
673 lock.l_whence = SEEK_SET;
\r
675 fcntl(o->fd, F_SETLK, &lock);
\r
678 remove(o->FileName);
\r
684 void *UnixNewSingleInstance(char *instance_name)
\r
687 char tmp[MAX_SIZE];
\r
688 char name[MAX_SIZE];
\r
689 char dir[MAX_PATH];
\r
693 if (instance_name == NULL)
\r
695 GetExeName(tmp, sizeof(tmp));
\r
696 HashInstanceName(tmp, sizeof(tmp), tmp);
\r
700 StrCpy(tmp, sizeof(tmp), instance_name);
\r
703 GetExeDir(dir, sizeof(dir));
\r
706 Format(name, sizeof(name), "%s/.%s", dir, tmp);
\r
708 fd = open(name, O_WRONLY);
\r
711 fd = creat(name, 0600);
\r
715 Format(tmp, sizeof(tmp), "Unable to create %s.", name);
\r
721 Zero(&lock, sizeof(lock));
\r
722 lock.l_type = F_WRLCK;
\r
723 lock.l_whence = SEEK_SET;
\r
725 if (fcntl(fd, F_SETLK, &lock) == -1)
\r
731 ret = ZeroMalloc(sizeof(UNIXLOCKFILE));
\r
733 StrCpy(ret->FileName, sizeof(ret->FileName), name);
\r
734 return (void *)ret;
\r
739 void UnixSetHighPriority()
\r
741 if (high_process == false)
\r
743 UINT pid = getpid();
\r
744 UINT pgid = getpgid(pid);
\r
746 high_process = true;
\r
749 setpriority(PRIO_PROCESS, pid, -20);
\r
750 setpriority(PRIO_PGRP, pgid, -20);
\r
755 void UnixRestorePriority()
\r
757 if (high_process != false)
\r
759 high_process = false;
\r
765 char *UnixGetProductId()
\r
767 return CopyStr("--");
\r
771 void UnixAlertW(wchar_t *msg, wchar_t *caption)
\r
773 char *msg8 = CopyUniToUtf(msg);
\r
774 char *caption8 = CopyUniToUtf(caption);
\r
776 UnixAlert(msg8, caption8);
\r
781 void UnixAlert(char *msg, char *caption)
\r
784 "-- Alert: %s --\n%s\n";
\r
790 if (caption == NULL)
\r
792 caption = "SoftEther UT-VPN Kernel";
\r
795 printf(tag, caption, msg);
\r
799 void UnixGetOsInfo(OS_INFO *info)
\r
807 Zero(info, sizeof(OS_INFO));
\r
808 info->OsType = OSTYPE_UNIX_UNKNOWN;
\r
810 #ifdef UNIX_SOLARIS
\r
811 info->OsType = OSTYPE_SOLARIS;
\r
812 #endif // UNIX_SOLARIS
\r
815 info->OsType = OSTYPE_CYGWIN;
\r
816 #endif // UNIX_CYGWIN
\r
819 info->OsType = OSTYPE_MACOS_X;
\r
820 #endif // UNIX_MACOS
\r
823 info->OsType = OSTYPE_BSD;
\r
827 info->OsType = OSTYPE_LINUX;
\r
828 #endif // UNIX_LINUX
\r
830 info->OsServicePack = 0;
\r
832 if (info->OsType != OSTYPE_LINUX)
\r
834 info->OsSystemName = CopyStr("UNIX");
\r
835 info->OsProductName = CopyStr("UNIX");
\r
839 info->OsSystemName = CopyStr("Linux");
\r
840 info->OsProductName = CopyStr("Linux");
\r
843 if (info->OsType == OSTYPE_LINUX)
\r
845 // Linux の場合 ディストリビューション名を取得する
\r
847 b = ReadDump("/etc/redhat-release");
\r
850 info->OsVersion = CfgReadNextLine(b);
\r
851 info->OsVendorName = CopyStr("Red Hat, Inc.");
\r
856 b = ReadDump("/etc/turbolinux-release");
\r
859 info->OsVersion = CfgReadNextLine(b);
\r
860 info->OsVendorName = CopyStr("Turbolinux, Inc.");
\r
865 info->OsVersion = CopyStr("Unknown Liunx Version");
\r
866 info->OsVendorName = CopyStr("Unknown Vendor");
\r
870 info->KernelName = CopyStr("Linux Kernel");
\r
872 b = ReadDump("/proc/sys/kernel/osrelease");
\r
875 info->KernelVersion = CfgReadNextLine(b);
\r
880 info->KernelVersion = CopyStr("Unknown Version");
\r
886 info->OsProductName = CopyStr(OsTypeToStr(info->OsType));
\r
887 info->OsVersion = CopyStr("Unknown Version");
\r
888 info->KernelName = CopyStr(OsTypeToStr(info->OsType));
\r
889 info->KernelVersion = CopyStr("Unknown Version");
\r
893 // 現在の OS が SoftEther UT-VPN Kernel によってサポートされているかどうか調べる
\r
894 bool UnixIsSupportedOs()
\r
896 // すべての起動可能な UNIX OS をサポートしている
\r
901 bool UnixRunW(wchar_t *filename, wchar_t *arg, bool hide, bool wait)
\r
903 char *filename8 = CopyUniToUtf(filename);
\r
904 char *arg8 = CopyUniToUtf(arg);
\r
905 bool ret = UnixRun(filename8, arg8, hide, wait);
\r
912 bool UnixRun(char *filename, char *arg, bool hide, bool wait)
\r
917 if (filename == NULL)
\r
936 Print("", filename, arg);
\r
944 t = ParseToken(arg, " ");
\r
954 num_args = t->NumTokens + 2;
\r
955 args = ZeroMalloc(sizeof(char *) * num_args);
\r
956 args[0] = filename;
\r
957 for (i = 1;i < num_args - 1;i++)
\r
959 args[i] = t->Token[i - 1];
\r
961 execvp(filename, args);
\r
968 pid_t pid = (pid_t)ret;
\r
974 if (waitpid(pid, &status, 0) == -1)
\r
979 if (WEXITSTATUS(status) == 0)
\r
994 void UnixDaemon(bool debug_mode)
\r
1001 signal(SIGHUP, SIG_IGN);
\r
1012 else if (ret == 0)
\r
1014 // 子プロセス用に新しいセッションを作成する
\r
1021 signal(SIGHUP, SIG_IGN);
\r
1031 void UnixCloseIO()
\r
1033 static bool close_io_first = false;
\r
1036 if (close_io_first)
\r
1045 open("/dev/null", O_RDWR);
\r
1048 close_io_first = false;
\r
1053 bool UnixFileRenameW(wchar_t *old_name, wchar_t *new_name)
\r
1055 char *old_name8 = CopyUniToUtf(old_name);
\r
1056 char *new_name8 = CopyUniToUtf(new_name);
\r
1057 bool ret = UnixFileRename(old_name8, new_name8);
\r
1064 bool UnixFileRename(char *old_name, char *new_name)
\r
1067 if (old_name == NULL || new_name == NULL)
\r
1072 if (rename(old_name, new_name) != 0)
\r
1081 CALLSTACK_DATA *UnixGetCallStack()
\r
1083 // Win32 以外ではサポートされていない
\r
1087 // コールスタックからシンボル情報を取得
\r
1088 bool UnixGetCallStackSymbolInfo(CALLSTACK_DATA *s)
\r
1090 // Win32 以外ではサポートされていない
\r
1095 bool UnixDeleteDirW(wchar_t *name)
\r
1097 char *name8 = CopyUniToUtf(name);
\r
1098 bool ret = UnixDeleteDir(name8);
\r
1104 bool UnixDeleteDir(char *name)
\r
1112 if (rmdir(name) != 0)
\r
1121 bool UnixMakeDirW(wchar_t *name)
\r
1123 char *name8 = CopyUniToUtf(name);
\r
1124 bool ret = UnixMakeDir(name8);
\r
1130 bool UnixMakeDir(char *name)
\r
1138 if (mkdir(name, 0700) != 0)
\r
1147 bool UnixFileDeleteW(wchar_t *name)
\r
1150 char *name8 = CopyUniToUtf(name);
\r
1152 ret = UnixFileDelete(name8);
\r
1158 bool UnixFileDelete(char *name)
\r
1166 if (remove(name) != 0)
\r
1175 bool UnixFileSeek(void *pData, UINT mode, int offset)
\r
1180 if (pData == NULL)
\r
1184 if (mode != FILE_BEGIN && mode != FILE_END && mode != FILE_CURRENT)
\r
1189 p = (UNIXIO *)pData;
\r
1191 ret = lseek(p->fd, offset, mode);
\r
1202 UINT64 UnixFileSize(void *pData)
\r
1207 if (pData == NULL)
\r
1212 p = (UNIXIO *)pData;
\r
1214 if (fstat(p->fd, &st) != 0)
\r
1219 return (UINT64)st.st_size;
\r
1223 bool UnixFileWrite(void *pData, void *buf, UINT size)
\r
1228 if (pData == NULL || buf == NULL || size == 0)
\r
1233 p = (UNIXIO *)pData;
\r
1235 ret = write(p->fd, buf, size);
\r
1245 bool UnixFileRead(void *pData, void *buf, UINT size)
\r
1250 if (pData == NULL || buf == NULL || size == 0)
\r
1255 p = (UNIXIO *)pData;
\r
1257 ret = read(p->fd, buf, size);
\r
1267 void UnixFileFlush(void *pData)
\r
1272 if (pData == NULL)
\r
1277 p = (UNIXIO *)pData;
\r
1279 write_mode = p->write_mode;
\r
1288 void UnixFileClose(void *pData, bool no_flush)
\r
1293 if (pData == NULL)
\r
1298 p = (UNIXIO *)pData;
\r
1300 write_mode = p->write_mode;
\r
1302 if (write_mode && no_flush == false)
\r
1309 UnixMemoryFree(p);
\r
1318 void *UnixFileCreateW(wchar_t *name)
\r
1321 char *name8 = CopyUniToUtf(name);
\r
1323 ret = UnixFileCreate(name8);
\r
1329 void *UnixFileCreate(char *name)
\r
1339 fd = creat(name, 0600);
\r
1346 p = UnixMemoryAlloc(sizeof(UNIXIO));
\r
1348 p->write_mode = true;
\r
1354 void *UnixFileOpenW(wchar_t *name, bool write_mode, bool read_lock)
\r
1356 char *name8 = CopyUniToUtf(name);
\r
1359 ret = UnixFileOpen(name8, write_mode, read_lock);
\r
1365 void *UnixFileOpen(char *name, bool write_mode, bool read_lock)
\r
1376 if (write_mode == false)
\r
1386 fd = open(name, mode);
\r
1393 p = UnixMemoryAlloc(sizeof(UNIXIO));
\r
1395 p->write_mode = write_mode;
\r
1401 UINT UnixThreadId()
\r
1405 ret = (UINT)pthread_self();
\r
1411 void *UnixDefaultThreadProc(void *param)
\r
1414 UNIXTHREADSTARTUPINFO *info = (UNIXTHREADSTARTUPINFO *)param;
\r
1420 ut = (UNIXTHREAD *)info->thread->pData;
\r
1423 info->thread_proc(info->thread, info->param);
\r
1426 ut->finished = true;
\r
1429 ReleaseThread(info->thread);
\r
1431 UnixMemoryFree(info);
\r
1433 FreeOpenSSLThreadState();
\r
1439 void UnixFreeThread(THREAD *t)
\r
1448 UnixMemoryFree(t->pData);
\r
1452 bool UnixWaitThread(THREAD *t)
\r
1455 void *retcode = NULL;
\r
1461 ut = (UNIXTHREAD *)t->pData;
\r
1467 pthread_join(ut->thread, &retcode);
\r
1473 bool UnixInitThread(THREAD *t)
\r
1476 UNIXTHREADSTARTUPINFO *info;
\r
1477 pthread_attr_t attr;
\r
1479 if (t == NULL || t->thread_proc == NULL)
\r
1485 ut = UnixMemoryAlloc(sizeof(UNIXTHREAD));
\r
1486 Zero(ut, sizeof(UNIXTHREAD));
\r
1489 info = UnixMemoryAlloc(sizeof(UNIXTHREADSTARTUPINFO));
\r
1490 Zero(info, sizeof(UNIXTHREADSTARTUPINFO));
\r
1491 info->param = t->param;
\r
1492 info->thread_proc = t->thread_proc;
\r
1497 pthread_attr_init(&attr);
\r
1498 pthread_attr_setstacksize(&attr, UNIX_THREAD_STACK_SIZE);
\r
1500 t->pData = (void *)ut;
\r
1502 if (pthread_create(&ut->thread, &attr, UnixDefaultThreadProc, info) != 0)
\r
1507 UnixMemoryFree(ut);
\r
1508 UnixMemoryFree(info);
\r
1509 pthread_attr_destroy(&attr);
\r
1513 pthread_attr_destroy(&attr);
\r
1519 void UnixFreeEvent(EVENT *event)
\r
1521 UNIXEVENT *ue = (UNIXEVENT *)event->pData;
\r
1527 pthread_cond_destroy(&ue->cond);
\r
1528 pthread_mutex_destroy(&ue->mutex);
\r
1530 UnixMemoryFree(ue);
\r
1534 bool UnixWaitEvent(EVENT *event, UINT timeout)
\r
1536 UNIXEVENT *ue = (UNIXEVENT *)event->pData;
\r
1537 struct timeval now;
\r
1538 struct timespec to;
\r
1545 pthread_mutex_lock(&ue->mutex);
\r
1546 gettimeofday(&now, NULL);
\r
1547 to.tv_sec = now.tv_sec + timeout / 1000;
\r
1548 to.tv_nsec = now.tv_usec * 1000 + (timeout % 1000) * 1000 * 1000;
\r
1549 if ((to.tv_nsec / 1000000000) >= 1)
\r
1551 to.tv_sec += to.tv_nsec / 1000000000;
\r
1552 to.tv_nsec = to.tv_nsec % 1000000000;
\r
1557 while (ue->signal == false)
\r
1559 if (timeout != INFINITE)
\r
1561 if (pthread_cond_timedwait(&ue->cond, &ue->mutex, &to))
\r
1569 pthread_cond_wait(&ue->cond, &ue->mutex);
\r
1572 ue->signal = false;
\r
1574 pthread_mutex_unlock(&ue->mutex);
\r
1580 void UnixResetEvent(EVENT *event)
\r
1582 UNIXEVENT *ue = (UNIXEVENT *)event->pData;
\r
1588 pthread_mutex_lock(&ue->mutex);
\r
1589 ue->signal = false;
\r
1590 pthread_cond_signal(&ue->cond);
\r
1591 pthread_mutex_unlock(&ue->mutex);
\r
1595 void UnixSetEvent(EVENT *event)
\r
1597 UNIXEVENT *ue = (UNIXEVENT *)event->pData;
\r
1603 pthread_mutex_lock(&ue->mutex);
\r
1604 ue->signal = true;
\r
1605 pthread_cond_signal(&ue->cond);
\r
1606 pthread_mutex_unlock(&ue->mutex);
\r
1610 void UnixInitEvent(EVENT *event)
\r
1612 UNIXEVENT *ue = UnixMemoryAlloc(sizeof(UNIXEVENT));
\r
1614 Zero(ue, sizeof(UNIXEVENT));
\r
1616 pthread_cond_init(&ue->cond, NULL);
\r
1617 pthread_mutex_init(&ue->mutex, NULL);
\r
1618 ue->signal = false;
\r
1620 event->pData = (void *)ue;
\r
1624 void UnixDeleteLock(LOCK *lock)
\r
1626 pthread_mutex_t *mutex;
\r
1627 // Ready フラグを安全に解除する
\r
1629 lock->Ready = false;
\r
1630 UnixUnlockEx(lock, true);
\r
1633 mutex = (pthread_mutex_t *)lock->pData;
\r
1634 pthread_mutex_destroy(mutex);
\r
1637 UnixMemoryFree(mutex);
\r
1638 UnixMemoryFree(lock);
\r
1642 void UnixUnlock(LOCK *lock)
\r
1644 UnixUnlockEx(lock, false);
\r
1646 void UnixUnlockEx(LOCK *lock, bool inner)
\r
1648 pthread_mutex_t *mutex;
\r
1649 if (lock->Ready == false && inner == false)
\r
1654 mutex = (pthread_mutex_t *)lock->pData;
\r
1656 if ((--lock->locked_count) > 0)
\r
1661 lock->thread_id = INFINITE;
\r
1663 pthread_mutex_unlock(mutex);
\r
1669 bool UnixLock(LOCK *lock)
\r
1671 pthread_mutex_t *mutex;
\r
1672 UINT thread_id = UnixThreadId();
\r
1673 if (lock->Ready == false)
\r
1679 if (lock->thread_id == thread_id)
\r
1681 lock->locked_count++;
\r
1685 mutex = (pthread_mutex_t *)lock->pData;
\r
1687 pthread_mutex_lock(mutex);
\r
1689 lock->thread_id = thread_id;
\r
1690 lock->locked_count++;
\r
1696 LOCK *UnixNewLock()
\r
1698 pthread_mutex_t *mutex;
\r
1700 LOCK *lock = UnixMemoryAlloc(sizeof(LOCK));
\r
1703 mutex = UnixMemoryAlloc(sizeof(pthread_mutex_t));
\r
1706 pthread_mutex_init(mutex, NULL);
\r
1708 lock->pData = (void *)mutex;
\r
1709 lock->Ready = true;
\r
1711 lock->thread_id = INFINITE;
\r
1712 lock->locked_count = 0;
\r
1718 void UnixSleep(UINT time)
\r
1720 UINT sec = 0, millisec = 0;
\r
1727 if (time == INFINITE)
\r
1732 #ifdef UNIX_SOLARIS
\r
1733 UnixSolarisSleep(time);
\r
1740 #ifdef UNIX_SOLARIS
\r
1741 UnixSolarisSleep(time);
\r
1745 sec = time / 1000;
\r
1746 millisec = time % 1000;
\r
1752 if (millisec != 0)
\r
1754 usleep(millisec * 1000);
\r
1760 void UnixDec32(UINT *value)
\r
1762 if (value != NULL)
\r
1769 void UnixInc32(UINT *value)
\r
1771 if (value != NULL)
\r
1778 void UnixGetSystemTime(SYSTEMTIME *system_time)
\r
1782 struct timeval tv;
\r
1783 struct timezone tz;
\r
1785 if (system_time == NULL)
\r
1790 pthread_mutex_lock(&get_time_lock);
\r
1792 Zero(system_time, sizeof(SYSTEMTIME));
\r
1793 Zero(&tv, sizeof(tv));
\r
1794 Zero(&tz, sizeof(tz));
\r
1798 gmtime_r(&now, &tm);
\r
1800 TmToSystem(system_time, &tm);
\r
1802 gettimeofday(&tv, &tz);
\r
1804 system_time->wMilliseconds = tv.tv_usec / 1000;
\r
1806 pthread_mutex_unlock(&get_time_lock);
\r
1809 // システムタイマの取得 (64bit)
\r
1810 UINT64 UnixGetTick64()
\r
1812 #if defined(OS_WIN32) || defined(CLOCK_REALTIME) || defined(CLOCK_MONOTONIC) || defined(CLOCK_HIGHRES)
\r
1814 struct timespec t;
\r
1816 static bool akirame = false;
\r
1820 return TickRealtimeManual();
\r
1823 Zero(&t, sizeof(t));
\r
1825 // システムの起動時刻を取得する関数
\r
1826 // システムによって実装が異なるので注意
\r
1827 #ifdef CLOCK_HIGHRES
\r
1828 clock_gettime(CLOCK_HIGHRES, &t);
\r
1829 #else // CLOCK_HIGHRES
\r
1830 #ifdef CLOCK_MONOTONIC
\r
1831 clock_gettime(CLOCK_MONOTONIC, &t);
\r
1832 #else // CLOCK_MONOTONIC
\r
1833 clock_gettime(CLOCK_REALTIME, &t);
\r
1834 #endif // CLOCK_MONOTONIC
\r
1835 #endif // CLOCK_HIGHRES
\r
1837 ret = (UINT64)t.tv_sec * 1000LL + (UINT64)t.tv_nsec / 1000000LL;
\r
1839 if (akirame == false && ret == 0)
\r
1841 ret = TickRealtimeManual();
\r
1849 return TickRealtimeManual();
\r
1855 UINT UnixGetTick()
\r
1857 return (UINT)UnixGetTick64();
\r
1861 void *UnixMemoryAlloc(UINT size)
\r
1864 pthread_mutex_lock(&malloc_lock);
\r
1866 pthread_mutex_unlock(&malloc_lock);
\r
1871 void *UnixMemoryReAlloc(void *addr, UINT size)
\r
1874 pthread_mutex_lock(&malloc_lock);
\r
1875 r = realloc(addr, size);
\r
1876 pthread_mutex_unlock(&malloc_lock);
\r
1881 void UnixMemoryFree(void *addr)
\r
1883 pthread_mutex_lock(&malloc_lock);
\r
1885 pthread_mutex_unlock(&malloc_lock);
\r
1889 void UnixSigChldHandler(int sig)
\r
1892 while (waitpid(-1, NULL, WNOHANG) > 0);
\r
1893 signal(SIGCHLD, UnixSigChldHandler);
\r
1896 // UNIX 用ライブラリの初期化
\r
1901 UnixInitSolarisSleep();
\r
1904 pthread_mutex_init(&get_time_lock, NULL);
\r
1905 pthread_mutex_init(&malloc_lock, NULL);
\r
1908 current_process_id = getpid();
\r
1910 #ifdef RLIMIT_CORE
\r
1911 UnixSetResourceLimit(RLIMIT_CORE, UNIX_MAX_MEMORY);
\r
1912 #endif // RLIMIT_CORE
\r
1914 #ifdef RLIMIT_DATA
\r
1915 UnixSetResourceLimit(RLIMIT_DATA, UNIX_MAX_MEMORY);
\r
1916 #endif // RLIMIT_DATA
\r
1918 #ifdef RLIMIT_NOFILE
\r
1919 UnixSetResourceLimit(RLIMIT_NOFILE, UNIX_MAX_FD);
\r
1920 #endif // RLIMIT_NOFILE
\r
1922 #ifdef RLIMIT_STACK
\r
1923 // UnixSetResourceLimit(RLIMIT_STACK, UNIX_MAX_MEMORY);
\r
1924 #endif // RLIMIT_STACK
\r
1927 UnixSetResourceLimit(RLIMIT_RSS, UNIX_MAX_MEMORY);
\r
1928 #endif // RLIMIT_RSS
\r
1930 #ifdef RLIMIT_LOCKS
\r
1931 UnixSetResourceLimit(RLIMIT_LOCKS, UNIX_MAX_LOCKS);
\r
1932 #endif // RLIMIT_LOCKS
\r
1934 #ifdef RLIMIT_MEMLOCK
\r
1935 UnixSetResourceLimit(RLIMIT_MEMLOCK, UNIX_MAX_MEMORY);
\r
1936 #endif // RLIMIT_MEMLOCK
\r
1938 #ifdef RLIMIT_NPROC
\r
1939 UnixSetResourceLimit(RLIMIT_NPROC, UNIX_MAX_CHILD_PROCESSES);
\r
1940 #endif // RLIMIT_NPROC
\r
1942 // proc ファイルシステムの threads-max に値を書き込む
\r
1943 o = UnixFileCreate("/proc/sys/kernel/threads-max");
\r
1947 sprintf(tmp, "%u\n", UNIX_LINUX_MAX_THREADS);
\r
1948 UnixFileWrite(o, tmp, strlen(tmp));
\r
1949 UnixFileClose(o, false);
\r
1953 signal(SIGPIPE, SIG_IGN);
\r
1954 signal(SIGALRM, SIG_IGN);
\r
1957 signal(64, SIG_IGN);
\r
1958 #endif // UNIX_BSD
\r
1961 signal(SIGXFSZ, SIG_IGN);
\r
1964 // 子プロセス回収用シグナルハンドラの設定
\r
1965 signal(SIGCHLD, UnixSigChldHandler);
\r
1971 UnixFreeSolarisSleep();
\r
1973 current_process_id = 0;
\r
1975 pthread_mutex_destroy(&get_time_lock);
\r
1978 // 占有することができる資源の上限値を調整
\r
1979 void UnixSetResourceLimit(UINT id, UINT value)
\r
1984 Zero(&t, sizeof(t));
\r
1985 getrlimit(id, &t);
\r
1987 hard_limit = t.rlim_max;
\r
1989 Zero(&t, sizeof(t));
\r
1990 t.rlim_cur = MIN(value, hard_limit);
\r
1991 t.rlim_max = hard_limit;
\r
1992 setrlimit(id, &t);
\r
1994 Zero(&t, sizeof(t));
\r
1995 t.rlim_cur = value;
\r
1996 t.rlim_max = value;
\r
1997 setrlimit(id, &t);
\r
2001 void UnixGenPidFileName(char *name, UINT size)
\r
2003 char exe_name[MAX_PATH];
\r
2004 UCHAR hash[MD5_SIZE];
\r
2006 char dir[MAX_PATH];
\r
2013 GetExeDir(dir, sizeof(dir));
\r
2015 GetExeName(exe_name, sizeof(exe_name));
\r
2016 StrCat(exe_name, sizeof(exe_name), ":pid_hash");
\r
2017 StrUpper(exe_name);
\r
2019 Hash(hash, exe_name, StrLen(exe_name), false);
\r
2020 BinToStr(tmp1, sizeof(tmp1), hash, sizeof(hash));
\r
2022 Format(name, size, "%s/.pid_%s", dir, tmp1);
\r
2026 void UnixDeletePidFile()
\r
2028 char tmp[MAX_PATH];
\r
2030 UnixGenPidFileName(tmp, sizeof(tmp));
\r
2032 UnixFileDelete(tmp);
\r
2036 void UnixWritePidFile(UINT pid)
\r
2038 char tmp[MAX_PATH];
\r
2042 UnixGenPidFileName(tmp, sizeof(tmp));
\r
2043 Format(tmp2, sizeof(tmp2), "%u\n", pid);
\r
2045 o = FileCreate(tmp);
\r
2048 FileWrite(o, tmp2, StrLen(tmp2));
\r
2054 UINT UnixReadPidFile()
\r
2056 char tmp[MAX_PATH];
\r
2059 UnixGenPidFileName(tmp, sizeof(tmp));
\r
2061 buf = ReadDump(tmp);
\r
2067 Zero(tmp, sizeof(tmp));
\r
2068 Copy(tmp, buf->Buf, MIN(buf->Size, sizeof(tmp)));
\r
2071 return ToInt(tmp);
\r
2075 void UnixStartService(char *name)
\r
2077 char *svc_name, *svc_title;
\r
2080 char exe[MAX_PATH];
\r
2087 GetExeName(exe, sizeof(exe));
\r
2089 Format(tmp, sizeof(tmp), SVC_NAME, name);
\r
2090 svc_name = _SS(tmp);
\r
2091 Format(tmp, sizeof(tmp), SVC_TITLE, name);
\r
2092 svc_title = _SS(tmp);
\r
2094 // すでにサービスが起動していないかどうか調べる
\r
2095 inst = NewSingleInstance(NULL);
\r
2099 UniPrint(_UU("UNIX_SVC_ALREADY_START"), svc_title, svc_name);
\r
2105 UniPrint(_UU("UNIX_SVC_STARTED"), svc_title);
\r
2106 FreeSingleInstance(inst);
\r
2112 UniPrint(_UU("UNIX_SVC_ERROR_FORK"), svc_title);
\r
2119 char *param = UNIX_SVC_ARG_EXEC_SVC;
\r
2125 signal(SIGHUP, SIG_IGN);
\r
2128 args = ZeroMalloc(sizeof(char *) * 3);
\r
2133 execvp(exe, args);
\r
2138 // 子プロセス番号をファイルに書き込まない
\r
2139 // UnixWritePidFile(pid);
\r
2146 void UnixStopService(char *name)
\r
2148 char *svc_name, *svc_title;
\r
2151 char exe[MAX_PATH];
\r
2159 GetExeName(exe, sizeof(exe));
\r
2161 Format(tmp, sizeof(tmp), SVC_NAME, name);
\r
2162 svc_name = _SS(tmp);
\r
2163 Format(tmp, sizeof(tmp), SVC_TITLE, name);
\r
2164 svc_title = _SS(tmp);
\r
2166 inst = NewSingleInstance(NULL);
\r
2167 pid = UnixReadPidFile();
\r
2168 if (inst != NULL || pid == 0)
\r
2171 UniPrint(_UU("UNIX_SVC_NOT_STARTED"), svc_title, svc_name);
\r
2178 UniPrint(_UU("UNIX_SVC_STOPPING"), svc_title);
\r
2181 kill(pid, SIGTERM);
\r
2182 if (UnixWaitProcessEx(pid, UNIX_SERVICE_STOP_TIMEOUT_2))
\r
2184 UniPrint(_UU("UNIX_SVC_STOPPED"), svc_title);
\r
2188 UniPrint(_UU("UNIX_SVC_STOP_FAILED"), svc_title);
\r
2192 FreeSingleInstance(inst);
\r
2195 // プロセスへの停止シグナルのハンドラ
\r
2196 void UnixSigTermHandler(int signum)
\r
2198 if (signum == SIGTERM)
\r
2200 unix_svc_terminate = true;
\r
2205 void UnixStopThread(THREAD *t, void *param)
\r
2207 SERVICE_FUNCTION *stop = (SERVICE_FUNCTION *)param;
\r
2209 if (t == NULL || param == NULL)
\r
2218 void UnixExecService(char *name, SERVICE_FUNCTION *start, SERVICE_FUNCTION *stop)
\r
2220 char *svc_name, *svc_title;
\r
2223 UINT yobi_size = 1024 * 128;
\r
2224 void *yobi1, *yobi2;
\r
2226 if (start == NULL || stop == NULL || name == NULL)
\r
2231 Format(tmp, sizeof(tmp), SVC_NAME, name);
\r
2232 svc_name = _SS(tmp);
\r
2233 Format(tmp, sizeof(tmp), SVC_TITLE, name);
\r
2234 svc_title = _SS(tmp);
\r
2236 inst = NewSingleInstance(NULL);
\r
2241 yobi1 = ZeroMalloc(yobi_size);
\r
2242 yobi2 = ZeroMalloc(yobi_size);
\r
2245 UnixWritePidFile(getpid());
\r
2249 // 起動完了 別のプロセスから SIGTERM が送られてくるのを待つ
\r
2250 signal(SIGTERM, &UnixSigTermHandler);
\r
2251 while (unix_svc_terminate == false)
\r
2258 t = NewThread(UnixStopThread, stop);
\r
2259 if (t == NULL || (WaitThread(t, UNIX_SERVICE_STOP_TIMEOUT_1) == false))
\r
2261 // 停止用スレッドの作成に失敗したか、タイムアウトした場合は
\r
2264 FreeSingleInstance(inst);
\r
2265 UnixDeletePidFile();
\r
2271 UnixDeletePidFile();
\r
2273 FreeSingleInstance(inst);
\r
2279 // 指定した pid のプロセスが存在するかどうか取得する
\r
2280 bool UnixIsProcess(UINT pid)
\r
2282 if (getsid((pid_t)pid) == -1)
\r
2290 // 指定したプロセスの終了を待機する
\r
2291 bool UnixWaitProcessEx(UINT pid, UINT timeout)
\r
2293 UINT64 start_tick = Tick64();
\r
2294 UINT64 end_tick = start_tick + (UINT64)timeout;
\r
2295 if (timeout == INFINITE)
\r
2299 while (UnixIsProcess(pid))
\r
2301 if (end_tick != 0)
\r
2303 if (end_tick < Tick64())
\r
2312 void UnixWaitProcess(UINT pid)
\r
2314 UnixWaitProcessEx(pid, INFINITE);
\r
2318 void UnixUsage(char *name)
\r
2320 char *svc_name, *svc_title;
\r
2328 Format(tmp, sizeof(tmp), SVC_NAME, name);
\r
2329 svc_name = _SS(tmp);
\r
2330 Format(tmp, sizeof(tmp), SVC_TITLE, name);
\r
2331 svc_title = _SS(tmp);
\r
2333 UniPrint(_UU("UNIX_SVC_HELP"), svc_title, svc_name, svc_name, svc_title, svc_name, svc_title);
\r
2336 // UNIX サービスのメイン関数
\r
2337 UINT UnixService(int argc, char *argv[], char *name, SERVICE_FUNCTION *start, SERVICE_FUNCTION *stop)
\r
2340 if (name == NULL || start == NULL || stop == NULL)
\r
2345 if (argc >= 2 && StrCmpi(argv[1], UNIX_SVC_ARG_EXEC_SVC) == 0)
\r
2349 // もし子プロセスが正しく終了しなかった場合は再起動する
\r
2353 if ((int)pid != -1)
\r
2358 UnixServiceMain(argc, argv, name, start, stop);
\r
2362 int status = 0, ret;
\r
2365 ret = waitpid(pid, &status, 0);
\r
2367 if (WIFEXITED(status) == 0)
\r
2371 goto RESTART_PROCESS;
\r
2379 UnixServiceMain(argc, argv, name, start, stop);
\r
2384 void UnixServiceMain(int argc, char *argv[], char *name, SERVICE_FUNCTION *start, SERVICE_FUNCTION *stop)
\r
2388 InitMayaqua(false, false, argc, argv);
\r
2392 if (StrCmpi(argv[1], UNIX_SVC_ARG_START) == 0)
\r
2394 mode = UNIX_SVC_MODE_START;
\r
2396 if (StrCmpi(argv[1], UNIX_SVC_ARG_STOP) == 0)
\r
2398 mode = UNIX_SVC_MODE_STOP;
\r
2400 if (StrCmpi(argv[1], UNIX_SVC_ARG_EXEC_SVC) == 0)
\r
2402 mode = UNIX_SVC_MODE_EXEC_SVC;
\r
2404 if (StrCmpi(argv[1], UNIX_ARG_EXIT) == 0)
\r
2406 mode = UNIX_SVC_MODE_EXIT;
\r
2412 case UNIX_SVC_MODE_EXIT:
\r
2415 case UNIX_SVC_MODE_START:
\r
2416 UnixStartService(name);
\r
2419 case UNIX_SVC_MODE_STOP:
\r
2420 UnixStopService(name);
\r
2423 case UNIX_SVC_MODE_EXEC_SVC:
\r
2424 UnixExecService(name, start, stop);
\r