G:/ScriptBasic/source/filesys.c

Go to the documentation of this file.
00001 /* 
00002 FILE:   filesys.c
00003 HEADER: filesys.h
00004 
00005 --GNU LGPL
00006 This library is free software; you can redistribute it and/or
00007 modify it under the terms of the GNU Lesser General Public
00008 License as published by the Free Software Foundation; either
00009 version 2.1 of the License, or (at your option) any later version.
00010 
00011 This library is distributed in the hope that it will be useful,
00012 but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014 Lesser General Public License for more details.
00015 
00016 You should have received a copy of the GNU Lesser General Public
00017 License along with this library; if not, write to the Free Software
00018 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019 
00020 TO_HEADER:
00021 
00022 #ifdef WIN32
00023 #include <windows.h>
00024 #include <winbase.h>
00025 #ifndef _WIN32_WCE
00026 #include <io.h>
00027 #include <direct.h>
00028 #include <lm.h>
00029 #include <lmaccess.h>
00030 #endif
00031 #else
00032 #ifdef _WIN32_WCE
00033 #include <windows.h>
00034 #include <winbase.h>
00035 #include <io.h>
00036 #include <direct.h>
00037 #include <lm.h>
00038 #include <lmaccess.h>
00039 #else
00040 #ifdef __MACOS__
00041 #include <unistd.h>
00042 #include <dirent.h>
00043 #else
00044 #include <sys/file.h>
00045 #include <sys/types.h>
00046 #include <sys/wait.h>
00047 #include <unistd.h>
00048 #include <dirent.h>
00049 #include <pwd.h>
00050 #include <netdb.h>
00051 #include <netinet/in.h>
00052 #include <pthread.h>
00053 #endif
00054 #ifndef TYPE_SOCKET
00055 typedef int SOCKET;
00056 #endif
00057 #endif
00058 #endif
00059 
00060 #ifndef LOCK_SH
00061 #define LOCK_SH 1
00062 #endif
00063 
00064 #ifndef LOCK_EX
00065 #define LOCK_EX 2
00066 #endif
00067 
00068 #ifndef LOCK_NB
00069 #define LOCK_NB 4
00070 #endif
00071 
00072 #ifndef LOCK_UN
00073 #define LOCK_UN 8
00074 #endif
00075 
00076 
00077 */
00078 
00079 #ifdef _WIN32_WCE
00080 #else
00081 #include <fcntl.h>
00082 #ifndef __MACOS__
00083 #include <sys/types.h>
00084 #include <sys/stat.h>
00085 #endif
00086 #include <errno.h>
00087 #endif
00088 #include <stdio.h>
00089 #include <string.h>
00090 #include <ctype.h>
00091 
00092 #ifdef WIN32
00093 #ifndef _WIN32_WCE
00094 #include <winsock2.h>
00095 #include <aclapi.h>
00096 #endif
00097 #define SHUT_RDWR SD_BOTH
00098 #else
00099 #ifndef __MACOS__
00100 #include <sys/socket.h>
00101 #endif
00102 #include <utime.h>
00103 #include <signal.h>
00104 #ifndef SHUT_RDWR
00105 #define SHUT_RDWR 2
00106 #endif
00107 #ifndef SD_BOTH
00108 #define SD_BOTH 2
00109 #endif
00110 #endif
00111 
00112 #ifdef vms
00113 #ifndef VMS
00114 #define VMS
00115 #endif
00116 #endif
00117 
00118 #include "filesys.h"
00119 #include "errcodes.h"
00120 /*POD
00121 @c Handling system specific file operations
00122 =abstract
00123 The file T<filesys.h> contains file handling primitive functions. The reason for this module
00124 is to have all system specific file handling functions to be separated in a single file.
00125 All other modules use these functions that behave the same on Win32 platform as well as on UNIX.
00126 =end
00127 These functions are to be used by other parts of the program. They implement system
00128 specific operations, and other levels need not care about these system specific stuff.
00129 
00130 The function names are prefixed usually with T<file_>, some are prefixed with T<sys_>.
00131 
00132 =toc
00133 
00134 CUT*/
00135 
00136 /*POD
00137 =H file_fopen
00138 @c Open a file
00139 
00140 This is same as fopen.
00141 
00142 VMS has some specialities when writing a file.
00143 
00144 /*FUNCTION*/
00145 FILE *file_fopen(
00146   char *pszFileName,
00147   char *pszOpenMode
00148   ){
00149 /*noverbatim
00150 CUT*/
00151 #ifdef VMS
00152 /* it is presented here to ease porting to VMS, but it was never tested. */
00153   if( *pszOpenMode == "w" )
00154     return fopen(pszFileName,pszOpenMode,"rat=cr","rfm=var");
00155   else
00156     return fopen(pszFileName,pszOpenMode);
00157 #else
00158 
00159   return fopen(pszFileName,pszOpenMode);
00160 #endif
00161   }
00162 
00163 
00164 /*POD
00165 =H file_fclose
00166 @c Close a file
00167 
00168 This is same as fclose. Nothing special. This is just a placeholder.
00169 
00170 /*FUNCTION*/
00171 void file_fclose(FILE *fp
00172   ){
00173 /*noverbatim
00174 CUT*/
00175   fclose(fp);
00176   }
00177 
00178 /*POD
00179 =H file_size
00180 @c return the size of a file
00181 
00182 /*FUNCTION*/
00183 long file_size(char *pszFileName
00184   ){
00185 /*noverbatim
00186 CUT*/
00187   struct stat buf;
00188   int LastChar,i,st;
00189 
00190   i = strlen(pszFileName);
00191   if( i == 0 )return 0;
00192 #ifdef __MACOS__
00193   st = stat(pszFileName,&buf);
00194 #else
00195   i--;
00196   LastChar = pszFileName[i];
00197   if( LastChar == '/' )pszFileName[i] = (char)0;
00198   st = stat(pszFileName,&buf);
00199   if( LastChar == '/' )pszFileName[i] = LastChar;
00200 #endif
00201   if( st == -1 )return 0;
00202   return buf.st_size;
00203   }
00204 
00205 #ifdef WIN32
00206 /* This is a Windows specific routine that converts normal UNIX
00207    time value (seconds since the epoch) to Windows FILETIME structure
00208 */
00209 #define MSEPOCH 116444736000000000L
00210 static void Utime2Filetime(long lTime,
00211                            PFILETIME pFileTime){
00212   union myuft {
00213     LONGLONG llTime;
00214     FILETIME FT;
00215     } *p;
00216 
00217   p = (union myuft *)pFileTime;
00218   p->llTime = lTime;
00219   p->llTime *= 10000000; /* convert from seconds to 100nsecs */
00220   /* This is the file time value of January 1, 1970. 00:00 */
00221   p->llTime += MSEPOCH;
00222   return;
00223   }
00224 
00225 static void Filetime2Utime(long *plTime,
00226                            PFILETIME pFileTime){
00227   LONGLONG llTime;
00228 
00229   memcpy(&llTime,pFileTime,sizeof(llTime));
00230 
00231   /* This is the file time value of January 1, 1970. 00:00 */
00232   llTime -= MSEPOCH;
00233 
00234   llTime /= 10000000; /* convert from 100nsecs to seconds */
00235   *plTime = (long)llTime;
00236   return;
00237   }
00238 #endif
00239 
00240 /*POD
00241 =H file_time_accessed
00242 @c return the time the file was last accessed
00243 
00244 /*FUNCTION*/
00245 long file_time_accessed(char *pszFileName
00246   ){
00247 /*noverbatim
00248 CUT*/
00249 #ifdef WIN32
00250   FILETIME FileTime;
00251   long lTime;
00252   HANDLE hFile;
00253   int LastChar,i;
00254 
00255   i = strlen(pszFileName);
00256   if( i == 0 )return 0;
00257   i--;
00258   LastChar = pszFileName[i];
00259   if( LastChar == '/' || LastChar == '\\' )pszFileName[i] = (char)0;
00260   hFile = CreateFile(pszFileName,GENERIC_READ,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
00261   if( LastChar == '/' || LastChar == '\\' )pszFileName[i] = LastChar;
00262 
00263   if( hFile == INVALID_HANDLE_VALUE )return 0;
00264   if( !GetFileTime(hFile,NULL,&FileTime,NULL) ){
00265     CloseHandle(hFile);
00266     return 0;
00267     }
00268   CloseHandle(hFile);
00269   Filetime2Utime(&lTime,&FileTime);
00270   return lTime;
00271 
00272 #else
00273   struct stat buf;
00274   int LastChar,i,st;
00275 
00276   i = strlen(pszFileName);
00277   if( i == 0 )return 0;
00278 #ifdef __MACOS__
00279   st = stat(pszFileName,&buf);
00280 #else
00281   i--;
00282   LastChar = pszFileName[i];
00283   if( LastChar == '/' )pszFileName[i] = (char)0;
00284   st = stat(pszFileName,&buf);
00285   if( LastChar == '/' )pszFileName[i] = LastChar;
00286 #endif
00287   if( st == -1 )return 0;
00288   return buf.st_atime;
00289 #endif
00290   }
00291 
00292 /*POD
00293 =H file_time_modified
00294 @c return the time the file was modified
00295 
00296 /*FUNCTION*/
00297 long file_time_modified(char *pszFileName
00298   ){
00299 /*noverbatim
00300 CUT*/
00301 #ifdef WIN32
00302   FILETIME FileTime;
00303   unsigned long lTime;
00304   HANDLE hFile;
00305   SYSTEMTIME Syst;
00306   int LastChar,i;
00307 
00308   i = strlen(pszFileName);
00309   if( i == 0 )return 0;
00310   i--;
00311   LastChar = pszFileName[i];
00312   if( LastChar == '/' || LastChar == '\\' )pszFileName[i] = (char)0;
00313   hFile = CreateFile(pszFileName,GENERIC_READ,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
00314   if( LastChar == '/' || LastChar == '\\' )pszFileName[i] = LastChar;
00315 
00316   if( hFile == INVALID_HANDLE_VALUE )return 0;
00317   if( !GetFileTime(hFile,NULL,NULL,&FileTime) ){
00318     CloseHandle(hFile);
00319     return 0;
00320     }
00321   CloseHandle(hFile);
00322   FileTimeToSystemTime(&FileTime,&Syst);
00323   Filetime2Utime(&lTime,&FileTime);
00324   return lTime;
00325 
00326 #else
00327   struct stat buf;
00328   int LastChar,i,st;
00329 
00330   i = strlen(pszFileName);
00331   if( i == 0 )return 0;
00332 #ifdef __MACOS__
00333   st = stat(pszFileName,&buf);
00334 #else
00335   i--;
00336   LastChar = pszFileName[i];
00337   if( LastChar == '/' )pszFileName[i] = (char)0;
00338   st = stat(pszFileName,&buf);
00339   if( LastChar == '/' )pszFileName[i] = LastChar;
00340 #endif
00341   if( st == -1 )return 0;
00342   return buf.st_mtime;
00343 #endif
00344   }
00345 
00346 /*POD
00347 =H file_time_created
00348 @c return the time the file was created
00349 
00350 /*FUNCTION*/
00351 long file_time_created(char *pszFileName
00352   ){
00353 /*noverbatim
00354 CUT*/
00355 #ifdef WIN32
00356   FILETIME FileTime;
00357   long lTime;
00358   HANDLE hFile;
00359   int LastChar,i;
00360 
00361   i = strlen(pszFileName);
00362   if( i == 0 )return 0;
00363   i--;
00364   LastChar = pszFileName[i];
00365   if( LastChar == '/' || LastChar == '\\' )pszFileName[i] = (char)0;
00366   hFile = CreateFile(pszFileName,GENERIC_READ,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
00367   if( LastChar == '/' || LastChar == '\\' )pszFileName[i] = LastChar;
00368 
00369   if( hFile == INVALID_HANDLE_VALUE )return 0;
00370   if( !GetFileTime(hFile,&FileTime,NULL,NULL) ){
00371     CloseHandle(hFile);
00372     return 0;
00373     }
00374   CloseHandle(hFile);
00375   Filetime2Utime(&lTime,&FileTime);
00376   return lTime;
00377 
00378 #else
00379   struct stat buf;
00380   int LastChar,i,st;
00381 
00382   i = strlen(pszFileName);
00383   if( i == 0 )return 0;
00384 #ifdef __MACOS__
00385   st = stat(pszFileName,&buf);
00386 #else
00387   i--;
00388   LastChar = pszFileName[i];
00389   if( LastChar == '/' )pszFileName[i] = (char)0;
00390   st = stat(pszFileName,&buf);
00391   if( LastChar == '/' )pszFileName[i] = LastChar;
00392 #endif
00393   if( st == -1 )return 0;
00394   return buf.st_ctime;
00395 #endif
00396   }
00397 
00398 /*POD
00399 =H file_isdir
00400 @c return true if the file is a directory
00401 
00402 /*FUNCTION*/
00403 int file_isdir(char *pszFileName
00404   ){
00405 /*noverbatim
00406 CUT*/
00407   struct stat buf;
00408   int LastChar,i,st;
00409 
00410   i = strlen(pszFileName);
00411   if( i == 0 )return 0;
00412 #ifdef __MACOS__
00413   st = stat(pszFileName,&buf);
00414 #else
00415   i--;
00416   LastChar = pszFileName[i];
00417   if( LastChar == '/' || LastChar == '\\' )pszFileName[i] = (char)0;
00418   st = stat(pszFileName,&buf);
00419   if( LastChar == '/' || LastChar == '\\' )pszFileName[i] = LastChar;
00420 #endif
00421   if( st == -1 )return 0;
00422   return (buf.st_mode&S_IFDIR) ? -1 : 0;
00423   }
00424 
00425 /*POD
00426 =H file_isreg
00427 @c return true if the file is a regular file (not directory)
00428 
00429 /*FUNCTION*/
00430 int file_isreg(char *pszFileName
00431   ){
00432 /*noverbatim
00433 CUT*/
00434   struct stat buf;
00435   int LastChar,i,st;
00436 
00437   i = strlen(pszFileName);
00438   if( i == 0 )return 0;
00439 #ifdef __MACOS__
00440   st = stat(pszFileName,&buf);
00441 #else
00442   i--;
00443   LastChar = pszFileName[i];
00444   if( LastChar == '/' || LastChar == '\\' )pszFileName[i] = (char)0;
00445   st = stat(pszFileName,&buf);
00446   if( LastChar == '/' || LastChar == '\\' )pszFileName[i] = LastChar;
00447 #endif
00448   if( st == -1 )return 0;
00449   return (buf.st_mode&S_IFREG) ? -1 : 0;
00450   }
00451 
00452 /*POD
00453 =H file_exists
00454 @c return true if the file exists
00455 
00456 /*FUNCTION*/
00457 int file_exists(char *pszFileName
00458   ){
00459 /*noverbatim
00460 CUT*/
00461   struct stat buf;
00462   int LastChar,i,st;
00463 
00464   i = strlen(pszFileName);
00465   if( i == 0 )return 0;
00466 #ifdef __MACOS__
00467   st = stat(pszFileName,&buf);
00468 #else
00469   i--;
00470   LastChar = pszFileName[i];
00471   if( LastChar == '/' || LastChar == '\\' )pszFileName[i] = (char)0;
00472   st = stat(pszFileName,&buf);
00473   if( LastChar == '/' || LastChar == '\\' )pszFileName[i] = LastChar;
00474 #endif
00475   if( st == -1 )
00476     return 0;
00477   else
00478     return -1;
00479   }
00480 
00481 /*POD
00482 =H file_truncate
00483 @c truncate a file to a given length
00484 
00485 It return 0 on success and -1 on error.
00486 
00487 /*FUNCTION*/
00488 int file_truncate(FILE *fp,
00489                   long lNewFileSize
00490   ){
00491 /*noverbatim
00492 CUT*/
00493 #if (defined(WIN32) || defined(__MACOS__))
00494 #if BCC32
00495 #define _chsize chsize
00496 #endif
00497   return _chsize(_fileno(fp),lNewFileSize);
00498 #else
00499   return ftruncate(fileno(fp),lNewFileSize);
00500 #endif
00501   }
00502 
00503 /*POD
00504 =H file_fgetc
00505 @c Get a single character from a file
00506 
00507 Nothing special, it is just a placeholder.
00508 
00509 /*FUNCTION*/
00510 int file_fgetc(FILE *fp
00511   ){
00512 /*noverbatim
00513 CUT*/
00514   return fgetc(fp);
00515   }
00516 
00517 /*POD
00518 =H file_ferror
00519 @c ferror
00520 
00521 Nothing special, it is just a placeholder.
00522 
00523 /*FUNCTION*/
00524 int file_ferror(FILE *fp
00525   ){
00526 /*noverbatim
00527 CUT*/
00528   return ferror(fp);
00529   }
00530 
00531 /*POD
00532 =H file_fread
00533 @c fread
00534 
00535 Nothing special, it is just a placeholder.
00536 
00537 /*FUNCTION*/
00538 int file_fread(char *buf,
00539                int size,
00540                int count,
00541                FILE *fp
00542   ){
00543 /*noverbatim
00544 CUT*/
00545   return fread(buf,size,count,fp);
00546   }
00547 
00548 /*POD
00549 =H file_fwrite
00550 @c fwrite
00551 
00552 Nothing special, it is just a placeholder.
00553 
00554 /*FUNCTION*/
00555 int file_fwrite(char *buf,
00556                int size,
00557                int count,
00558                FILE *fp
00559   ){
00560 /*noverbatim
00561 CUT*/
00562   return fwrite(buf,size,count,fp);
00563   }
00564 
00565 /*POD
00566 =H file_fputc
00567 @c Get a single character from a file
00568 
00569 Nothing special, it is just a placeholder.
00570 
00571 /*FUNCTION*/
00572 int file_fputc(int c, FILE *fp
00573   ){
00574 /*noverbatim
00575 CUT*/
00576   return fputc(c,fp);
00577   }
00578 
00579 /*POD
00580 =H file_setmode
00581 @c Set the mode of a file stream to binary or to ASCII
00582 
00583 Nothing special, it is just a placeholder. On UNIX this is doing
00584 nothing transparently.
00585 
00586 /*FUNCTION*/
00587 void file_setmode(FILE *fp,
00588                   int mode
00589   ){
00590 /*noverbatim
00591 CUT*/
00592 #ifdef WIN32
00593 #if BCC32
00594 #define _setmode setmode
00595 #endif
00596   _setmode(_fileno(fp),mode);
00597 #endif
00598   return;
00599   }
00600 
00601 /*POD
00602 =H file_binmode
00603 @c Set a file stream to binary mode
00604 /*FUNCTION*/
00605 void file_binmode(FILE *fp
00606   ){
00607 /*noverbatim
00608 CUT*/
00609 #ifdef WIN32
00610   file_setmode(fp,_O_BINARY);
00611 #endif
00612   return;
00613   }
00614 
00615 /*POD
00616 =H file_textmode
00617 @c Set a file stream to text mode
00618 /*FUNCTION*/
00619 void file_textmode(FILE *fp
00620   ){
00621 /*noverbatim
00622 CUT*/
00623 #ifdef WIN32
00624   file_setmode(fp,_O_TEXT);
00625 #endif
00626   return;
00627   }
00628 
00629 /*POD
00630 =H file_flock
00631 @c Lock a file
00632 
00633 /*FUNCTION*/
00634 int file_flock(FILE *fp,
00635                int iLockType
00636   ){
00637 /*noverbatim
00638 CUT*/
00639 #define LK_LEN          0xffff0000
00640 #ifdef WIN32
00641 #define LK_ERR(f,i)     ((f) ? (i = 0) : 0 )
00642 
00643   OVERLAPPED o;
00644   int i = -1;
00645   HANDLE fh;
00646 
00647   fh = (HANDLE)_get_osfhandle(_fileno(fp));
00648   memset(&o, 0, sizeof(o));
00649 
00650   switch(iLockType) {
00651     case LOCK_SH:               /* shared lock */
00652       LK_ERR(LockFileEx(fh, 0, 0, LK_LEN, 0, &o),i);
00653       break;
00654     case LOCK_EX:               /* exclusive lock */
00655         LK_ERR(LockFileEx(fh, LOCKFILE_EXCLUSIVE_LOCK, 0, LK_LEN, 0, &o),i);
00656         break;
00657     case LOCK_SH|LOCK_NB:       /* non-blocking shared lock */
00658         LK_ERR(LockFileEx(fh, LOCKFILE_FAIL_IMMEDIATELY, 0, LK_LEN, 0, &o),i);
00659         break;
00660     case LOCK_EX|LOCK_NB:       /* non-blocking exclusive lock */
00661         LK_ERR(LockFileEx(fh,
00662                        LOCKFILE_EXCLUSIVE_LOCK|LOCKFILE_FAIL_IMMEDIATELY,
00663                        0, LK_LEN, 0, &o),i);
00664         break;
00665     case LOCK_UN:               /* unlock lock */
00666         LK_ERR(UnlockFileEx(fh, 0, LK_LEN, 0, &o),i);
00667         break;
00668   default:                      /* unknown */
00669         /*errno = EINVAL;*/
00670         break;
00671     }
00672     return i;
00673 #elif defined(__MACOS__)
00674   return 0;
00675 #else
00676 /*  return flock(fileno(fp),iLockType); */
00677   struct flock fl;
00678   int WaitOption;
00679 
00680   switch(iLockType) {
00681     case LOCK_SH:               /* shared lock */
00682       iLockType =  F_RDLCK;
00683       WaitOption = F_SETLKW;
00684       break;
00685     case LOCK_EX:               /* exclusive lock */
00686       iLockType = F_WRLCK;
00687       WaitOption = F_SETLKW;
00688       break;
00689     case LOCK_SH|LOCK_NB:       /* non-blocking shared lock */
00690       iLockType =  F_RDLCK;
00691       WaitOption = F_SETLK;
00692       break;
00693     case LOCK_EX|LOCK_NB:       /* non-blocking exclusive lock */
00694       iLockType = F_WRLCK;
00695       WaitOption = F_SETLK;
00696       break;
00697     case LOCK_UN:               /* unlock lock */
00698       iLockType = F_UNLCK;
00699       WaitOption = F_SETLKW;
00700       break;
00701     default:                    /* unknown */
00702       return -1;
00703     }
00704   fl.l_type   = iLockType;
00705   fl.l_whence = SEEK_SET;
00706   fl.l_start  = 0;
00707   fl.l_len    = LK_LEN;
00708 
00709   return fcntl( fileno( fp ), F_SETLKW , &fl );
00710 
00711 #endif
00712   }
00713 
00714 /*POD
00715 =H file_lock
00716 @c Lock a range of a file
00717 
00718 /*FUNCTION*/
00719 int file_lock(FILE *fp,
00720               int iLockType,
00721               long lStart,
00722               long lLength
00723   ){
00724 /*noverbatim
00725 CUT*/
00726 #ifdef WIN32
00727 #undef LK_ERR
00728 #undef LK_LEN
00729 #define LK_ERR(f,i)     return ((f) ? 0 : -1)
00730 #define LK_LEN          0xffff0000
00731 #define dwReserved 0L
00732   OVERLAPPED o;
00733   int i = -1;
00734   HANDLE fh;
00735 
00736   fh = (HANDLE)_get_osfhandle(_fileno(fp));
00737   memset(&o, 0, sizeof(o));
00738   o.Offset = (DWORD)lStart;
00739 
00740   switch(iLockType) {
00741     case LOCK_SH:               /* shared lock */
00742       LK_ERR(LockFileEx(fh, 0, dwReserved, lLength, 0, &o),i);
00743     case LOCK_EX:               /* exclusive lock */
00744             LK_ERR(LockFileEx(fh, LOCKFILE_EXCLUSIVE_LOCK, dwReserved, lLength, 0, &o),i);
00745     case LOCK_SH|LOCK_NB:       /* non-blocking shared lock */
00746             LK_ERR(LockFileEx(fh, LOCKFILE_FAIL_IMMEDIATELY, dwReserved, lLength, 0, &o),i);
00747     case LOCK_EX|LOCK_NB:       /* non-blocking exclusive lock */
00748             LK_ERR(LockFileEx(fh, LOCKFILE_EXCLUSIVE_LOCK|LOCKFILE_FAIL_IMMEDIATELY, dwReserved, lLength, 0, &o),i);
00749     case LOCK_UN:               /* unlock lock */
00750             LK_ERR(UnlockFileEx(fh, 0, lLength, 0, &o),i);
00751     default:                    /* unknown */
00752       return -1;
00753     }
00754 #elif defined(__MACOS__)
00755   return 0;
00756 #else
00757   struct flock fl;
00758   int WaitOption;
00759 
00760   switch(iLockType) {
00761     case LOCK_SH:               /* shared lock */
00762       iLockType =  F_RDLCK;
00763       WaitOption = F_SETLKW;
00764       break;
00765     case LOCK_EX:               /* exclusive lock */
00766       iLockType = F_WRLCK;
00767       WaitOption = F_SETLKW;
00768       break;
00769     case LOCK_SH|LOCK_NB:       /* non-blocking shared lock */
00770       iLockType =  F_RDLCK;
00771       WaitOption = F_SETLK;
00772       break;
00773     case LOCK_EX|LOCK_NB:       /* non-blocking exclusive lock */
00774       iLockType = F_WRLCK;
00775       WaitOption = F_SETLK;
00776       break;
00777     case LOCK_UN:               /* unlock lock */
00778       iLockType = F_UNLCK;
00779       WaitOption = F_SETLKW;
00780       break;
00781     default:                    /* unknown */
00782       return -1;
00783     }
00784   fl.l_type   = iLockType;
00785   fl.l_whence = SEEK_SET;
00786   fl.l_start  = lStart;
00787   fl.l_len    = lLength;
00788 
00789   return fcntl( fileno( fp ), F_SETLKW , &fl );
00790 #endif
00791   }
00792 
00793 /*POD
00794 =H file_feof
00795 @c Check end of file condition
00796 
00797 Nothing special, it is just a placeholder.
00798 
00799 /*FUNCTION*/
00800 int file_feof(FILE *fp
00801   ){
00802 /*noverbatim
00803 CUT*/
00804   return feof(fp);
00805   }
00806 
00807 /*POD
00808 =H file_mkdir
00809 @c Create a directory
00810 
00811 This is the usual UNIX mkdir function. The difference is that the access code is always 0777 on UNIX
00812 which means that the user, group and others can read, write and execute the directory. If the permission
00813 needed is different from that you have to call the T<file_chmod> function as soon as it becomes available.
00814 
00815 The argument of the function is the name of the desired directory.
00816 
00817 /*FUNCTION*/
00818 int file_mkdir(char *pszDirectoryName
00819   ){
00820 /*noverbatim
00821 CUT*/
00822   char *s;
00823 
00824 #ifndef __MACOS__
00825   for( s = pszDirectoryName ; *s ; s++ )if( *s == '\\' )*s= '/';
00826 #endif
00827 #ifdef WIN32
00828   return _mkdir(pszDirectoryName);
00829 #else
00830   return mkdir(pszDirectoryName,0777);
00831 #endif
00832   }
00833 
00834 /*POD
00835 =H file_rmdir
00836 @c Remove a directory
00837 
00838 This is the usual UNIX rmdir function.
00839 
00840 The argument of the function is the name of the directory to be deleted.
00841 
00842 /*FUNCTION*/
00843 int file_rmdir(char *pszDirectoryName
00844   ){
00845 /*noverbatim
00846 CUT*/
00847   char *s;
00848 
00849 #ifndef __MACOS__
00850   for( s = pszDirectoryName ; *s ; s++ )if( *s == '\\' )*s= '/';
00851 #endif
00852 #ifdef WIN32
00853   /* Note that there is no need to convert the / characters to \
00854      because / is a valid separator under Windows NT just as \ is.  */
00855   return _rmdir(pszDirectoryName);
00856 #else
00857   return rmdir(pszDirectoryName);
00858 #endif
00859   }
00860 
00861 /*POD
00862 =H file_remove
00863 @c Remove a file
00864 
00865 Nothing special, it is just a placeholder. This function performs the UNIX T<remove> functionality. This
00866 function also exists under WIN32, therefore this function is only a placeholder.
00867 
00868 /*FUNCTION*/
00869 int file_remove(char *pszFileName
00870   ){
00871 /*noverbatim
00872 CUT*/
00873   char *s;
00874 
00875 #ifndef __MACOS__
00876   for( s = pszFileName ; *s ; s++ )if( *s == '\\' )*s= '/';
00877 #endif
00878   return remove(pszFileName);
00879   }
00880 
00881 /* Note that the recursive calls can use the same file name buffer and
00882    still the different concurrently running threads use different buffers.
00883    This would NOT be the case if buffer is static inside the recursive function.
00884    We could use an auto buffer but that is waste of stack space.
00885 */
00886 #define MAX_FNLEN 1024
00887 int file_deltree_r(char * buffer){
00888   tDIR DirList;
00889   DIR*pDirList;
00890 
00891   struct dirent *pD;
00892   int dirlen;
00893 
00894   dirlen=strlen(buffer);
00895 #ifdef __MACOS__
00896   if( buffer[dirlen-1] != ':' ){
00897     dirlen++;
00898     if( dirlen >= MAX_FNLEN )return -1;
00899     strcpy(buffer+dirlen-1,":");
00900     }
00901 #else
00902   if( buffer[dirlen-1] != '/' ){
00903     dirlen++;
00904     if( dirlen >= MAX_FNLEN )return -1;
00905     strcpy(buffer+dirlen-1,"/");
00906     }
00907 #endif
00908   pDirList = file_opendir(buffer,&DirList);
00909   if( pDirList == NULL )return -1;
00910   while( pD = file_readdir(pDirList) ){
00911     /* skip . and .. directories */
00912     if( pD->d_name[0] == '.' && 
00913        ( pD->d_name[1] == (char)0 ||
00914          ( pD->d_name[1] == '.' && pD->d_name[2] == (char)0 ) ) )continue;
00915     if( dirlen+strlen(pD->d_name) >= MAX_FNLEN )return -1;
00916     strcpy(buffer+dirlen,pD->d_name);
00917     if( file_isdir(buffer) )
00918       file_deltree_r(buffer);
00919     else
00920       file_remove(buffer);
00921     }
00922   file_closedir(pDirList);
00923   dirlen--;
00924   buffer[dirlen] = (char)0;
00925   return file_rmdir(buffer);
00926   }
00927 
00928 /*POD
00929 =H file_deltree
00930 @c Delete a directory tree
00931 
00932 /*FUNCTION*/
00933 int file_deltree(char *pszDirectoryName
00934   ){
00935 /*noverbatim
00936 CUT*/
00937   char buffer[MAX_FNLEN];
00938 #ifndef __MACOS__
00939   char *s;
00940 
00941   for( s = pszDirectoryName ; *s ; s++ )if( *s == '\\' )*s= '/';
00942 #endif
00943   if( ! file_exists(pszDirectoryName) )return -1;
00944   if( ! file_isdir(pszDirectoryName) )return -1;
00945   /* does not fit into the buffer ? */
00946   if( strlen(pszDirectoryName) >= MAX_FNLEN )return -1;
00947 
00948   strcpy(buffer,pszDirectoryName);
00949   return file_deltree_r(buffer);
00950   }
00951 
00952 /*POD
00953 =H file_MakeDirectory
00954 
00955 This function is a bit out of the line of the other functions in this module. This function uses the
00956 T<file_mkdir> function to create a directory. The difference is that this function tries to create a
00957 directory recursively. For example you can create the directory
00958 
00959 T</usr/bin/scriba>
00960 
00961 with a simple call and the function will create the directories T</usr> if it did not exist, then 
00962 T</usr/bin> and finally T</usr/bin/scriba> The function fails if the directory can not be created
00963 because of access restrictions or because the directory path or a sub path already exists, and is not
00964 a directory.
00965 
00966 The argument of the function is the name of the desired directory.
00967 
00968 The function alters the argument replacing each \ character to /
00969 
00970 The argument may end with / since v1.0b30
00971 
00972 If the argument is a Windows full path including the drive letter, like
00973 'C:' the function tries to create the directory 'C:', which fails, but
00974 ignores this error because only the last creation in the line down the
00975 directory path is significant.
00976 
00977 In case of error, the argument may totally be destroyed.
00978 
00979 /*FUNCTION*/
00980 int file_MakeDirectory(char *pszDirectoryName
00981   ){
00982 /*noverbatim
00983 CUT*/
00984   char *s;
00985   int iDirNameLen,i,iResult;
00986 
00987 #ifndef __MACOS__
00988   for( s=pszDirectoryName ; *s ; s++ )
00989     if( *s == '\\' )*s = '/';
00990 #endif
00991   iDirNameLen = strlen(pszDirectoryName);
00992 
00993   i = 0;
00994   iResult = 0;
00995   while( i < iDirNameLen ){
00996 #ifdef __MACOS__
00997     while( pszDirectoryName[i] && pszDirectoryName[i] != ':' )i++;
00998 #else
00999     while( pszDirectoryName[i] && pszDirectoryName[i] != '/' )i++;
01000 #endif
01001     pszDirectoryName[i] = (char)0;
01002     if( file_exists(pszDirectoryName) ){
01003       if( ! file_isdir(pszDirectoryName) )
01004           return -1;/* the path exists and there is a non-directory sub-path in it*/
01005       else{
01006         iResult = 0;
01007 #ifdef __MACOS__
01008         if( i < iDirNameLen ) pszDirectoryName[i] = ':';
01009 #else
01010         if( i < iDirNameLen ) pszDirectoryName[i] = '/';
01011 #endif
01012         }
01013       }else{
01014       iResult = file_mkdir(pszDirectoryName);
01015 #ifdef __MACOS__
01016       if( i < iDirNameLen ) pszDirectoryName[i] = ':';
01017 #else
01018       if( i < iDirNameLen ) pszDirectoryName[i] = '/';
01019 #endif
01020       }
01021     i++;
01022     }
01023   return iResult;
01024   }
01025 
01026 
01027 /*
01028 TO_HEADER:
01029 #ifdef WIN32
01030 struct dirent {
01031   char d_name[MAX_PATH];
01032   };
01033 typedef struct _OpenDir {
01034   HANDLE hFindFile;
01035   WIN32_FIND_DATA FindFileData;
01036   struct dirent CurrentEntry;
01037   } DIR,tDIR;
01038 #else
01039 typedef unsigned char tDIR;
01040 #endif
01041 */
01042 
01043 /*POD
01044 =H file_opendir
01045 @c Open a directory for listing
01046 
01047 This function implements the T<opendir> function of UNIX. The difference between this implementation and
01048 the UNIX version is that this implementation requires a T<DIR> structure to be passed as an argument. The
01049 reason for this is that the Windows system calls do not allocate memory and pass return values in structures
01050 allocated by the caller. Because we did not want to implement memory allocation in these routines
01051 we followed the Windows like way.
01052 
01053 The first argument T<pszDirectoryName> is a ZCAR directory name to be scanned. The second argument is an
01054 allocated T<DIR> structure that has to be valid until the T<file_closedir> is called.
01055 
01056 The second parameter under UNIX is not used. However to be safe and portable to Win32 the parameter
01057 should be handled with care.
01058 /*FUNCTION*/
01059 DIR *file_opendir(char *pszDirectoryName,
01060                   tDIR *pDirectory
01061   ){
01062 /*noverbatim
01063 CUT*/
01064 #ifdef WIN32
01065   if( strlen(pszDirectoryName) >= MAX_PATH - 4 )return NULL;
01066   strcpy(pDirectory->CurrentEntry.d_name,pszDirectoryName);
01067   strcat(pDirectory->CurrentEntry.d_name,"/*.*");
01068   pDirectory->hFindFile = FindFirstFile(pDirectory->CurrentEntry.d_name,&(pDirectory->FindFileData));
01069   if( pDirectory->hFindFile == INVALID_HANDLE_VALUE )return NULL;
01070   return pDirectory;
01071 #else
01072   return opendir(pszDirectoryName);
01073 #endif
01074   }
01075 
01076 /*POD
01077 =H file_readdir
01078 @c Read next item from a directory
01079 
01080 This function is the implementation of the UNIX T<readdir>
01081 
01082 /*FUNCTION*/
01083 struct dirent *file_readdir(DIR *pDirectory
01084   ){
01085 /*noverbatim
01086 CUT*/
01087 #ifdef WIN32
01088   char *s;
01089 
01090   strcpy(pDirectory->CurrentEntry.d_name,pDirectory->FindFileData.cFileName);
01091   if( ! FindNextFile(pDirectory->hFindFile,&(pDirectory->FindFileData)) ){
01092     *(pDirectory->FindFileData.cFileName) = (char)0;
01093     }
01094   s = pDirectory->CurrentEntry.d_name;
01095   if( *s ){
01096     for( ; *s ; s++ )if( isupper(*s) )*s = tolower(*s);
01097     return &(pDirectory->CurrentEntry);
01098     }
01099   else
01100     return NULL;
01101 #else
01102   return readdir(pDirectory);
01103 #endif
01104   }
01105 
01106 /*POD
01107 =H file_closedir
01108 @c Close a directory opened for listing
01109 
01110 /*FUNCTION*/
01111 void file_closedir(DIR *pDirectory
01112   ){
01113 /*noverbatim
01114 CUT*/
01115 #ifdef WIN32
01116   FindClose(pDirectory->hFindFile);
01117 #else
01118   closedir(pDirectory);
01119 #endif
01120   return;
01121   }
01122 
01123 /*POD
01124 =H file_sleep
01125 @c Sleep the process
01126 
01127 /*FUNCTION*/
01128 void sys_sleep(long lSeconds
01129   ){
01130 /*noverbatim
01131 CUT*/
01132 #ifdef WIN32
01133   lSeconds *= 1000; /* convert to milliseconds */
01134   Sleep((DWORD)lSeconds);
01135 #else
01136   sleep(lSeconds);
01137 #endif
01138   }
01139 
01140 /*POD
01141 =H file_curdir
01142 @c Get the current working directory
01143 
01144 The first argument should point to a buffer having space for at least
01145 T<cbBuffer> characters. The function will copy the name of the current
01146 directory into this buffer. 
01147 
01148 Return value is zero on success. If the current directory can not be
01149 retrieved or the buffer is too short the return value is -1.
01150 /*FUNCTION*/
01151 int file_curdir(char *Buffer,
01152                 unsigned long cbBuffer
01153   ){
01154 /*noverbatim
01155 CUT*/
01156 #ifdef WIN32
01157   int i;
01158 
01159   i = GetCurrentDirectory(cbBuffer,Buffer);
01160   if( i == 0 )return -1;
01161   return 0;
01162 #else
01163   char *s;
01164 
01165   s = getcwd(Buffer,cbBuffer);
01166   if( s == NULL )return -1;
01167   return 0;
01168 #endif
01169   }
01170 
01171 /*POD
01172 =H file_chdir
01173 @c Change the current working direcory
01174 
01175 /*FUNCTION*/
01176 int file_chdir(char *Buffer
01177   ){
01178 /*noverbatim
01179 CUT*/
01180 #ifdef WIN32
01181   int i;
01182 
01183   i = SetCurrentDirectory(Buffer);
01184   if( i == 0 )return -1;
01185   return 0;
01186 #else
01187   int i;
01188 
01189   return chdir(Buffer);
01190 #endif
01191   }
01192 
01193 /* HERE WE HAVE SOME FUNCTIONS THAT ARE NEEDED TO IMPLEMENT CHOWN UNDERR WINDOWS NT
01194 
01195 The routine was written from the sources of the Windows NT command line utility chown
01196 of Alexander.Frink@Uni-Mainz.DE, at http://wwwthep.physik.uni-mainz.de/~frink/nt.html
01197 
01198 */
01199 #ifdef WIN32
01200 #define MAXNAMELEN 256
01201 
01202 #define toUnicode(FROM,TO)                     \
01203     MultiByteToWideChar(CP_OEMCP,              \
01204                         0,                     \
01205                         (char *)FROM,          \
01206                         strlen((char *)FROM)+1,\
01207                         TO,                    \
01208                         sizeof(TO))
01209 
01210 #define fromUnicode(FROM,TO)             \
01211     WideCharToMultiByte(CP_OEMCP,        \
01212                         0,               \
01213                         FROM,            \
01214                         -1,              \
01215                         TO,              \
01216                         sizeof(TO),      \
01217                         NULL,            \
01218                         NULL)
01219 
01220 #define SZ_SD_BUF   100
01221 
01222 
01223 BOOL 
01224 GetAccountSid( 
01225     LPTSTR SystemName, 
01226     LPTSTR AccountName, 
01227     PSID *Sid 
01228     ) 
01229 { 
01230     LPTSTR ReferencedDomain=NULL; 
01231     DWORD cbSid=128;    // initial allocation attempt 
01232     DWORD cchReferencedDomain=16; // initial allocation size 
01233     SID_NAME_USE peUse; 
01234     BOOL bSuccess=FALSE; // assume this function will fail 
01235 #if BCC32
01236     BOOL bLeave=FALSE;
01237 #define __finally if( bLeave )
01238 #define __leave {bLeave=TRUE; break;}
01239 #define __try do
01240 #define __end_try while(0);
01241 #else
01242 #define __end_try
01243 #endif 
01244     __try { 
01245  
01246     // 
01247     // initial memory allocations 
01248     // 
01249     *Sid = (PSID)HeapAlloc(GetProcessHeap(), 0, cbSid); 
01250  
01251     if(*Sid == NULL) __leave; 
01252  
01253     ReferencedDomain = (LPTSTR)HeapAlloc( 
01254                     GetProcessHeap(), 
01255                     0, 
01256                     cchReferencedDomain * sizeof(TCHAR) 
01257                     ); 
01258  
01259     if(ReferencedDomain == NULL) __leave; 
01260  
01261     // 
01262     // Obtain the SID of the specified account on the specified system. 
01263     // 
01264     while(!LookupAccountName( 
01265                     SystemName,         // machine to lookup account on 
01266                     AccountName,        // account to lookup 
01267                     *Sid,               // SID of interest 
01268                     &cbSid,             // size of SID 
01269                     ReferencedDomain,   // domain account was found on 
01270                     &cchReferencedDomain, 
01271                     &peUse 
01272                     )) { 
01273         if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { 
01274             // 
01275             // reallocate memory 
01276             // 
01277             *Sid = (PSID)HeapReAlloc( 
01278                         GetProcessHeap(), 
01279                         0, 
01280                         *Sid, 
01281                         cbSid 
01282                         ); 
01283             if(*Sid == NULL) __leave; 
01284  
01285             ReferencedDomain = (LPTSTR)HeapReAlloc( 
01286                         GetProcessHeap(), 
01287                         0, 
01288                         ReferencedDomain, 
01289                         cchReferencedDomain * sizeof(TCHAR) 
01290                         ); 
01291             if(ReferencedDomain == NULL) __leave; 
01292         } 
01293         else __leave; 
01294     } 
01295  
01296     // 
01297     // Indicate success. 
01298     // 
01299     bSuccess = TRUE; 
01300  
01301     } __end_try 
01302     __finally { 
01303  
01304     // 
01305     // Cleanup and indicate failure, if appropriate. 
01306     // 
01307  
01308     HeapFree(GetProcessHeap(), 0, ReferencedDomain); 
01309  
01310     if(!bSuccess) { 
01311         if(*Sid != NULL) { 
01312             HeapFree(GetProcessHeap(), 0, *Sid); 
01313             *Sid = NULL; 
01314         } 
01315     } 
01316  
01317     } // finally 
01318  
01319     return bSuccess; 
01320 } 
01321 
01322 BOOL 
01323 GetSid( 
01324     LPTSTR AccountName, 
01325     PSID *Sid 
01326     ) 
01327 {
01328 /*
01329 The NetGetDCName function is implemented in netapi32.dll This function is specific to Windows NT. If
01330 we create the exe file statically linking netapi32.lib then the exe can not start on Win95/98. This
01331 dynamic linking implemented in this code (since build14) allows Win95/98 to run the code, and get a
01332 trappable (on error goto works) error if the basic program wants to set the owner of a file, which
01333 is not available under Win95/98 anyway.
01334 
01335 Note that a multi-thread implementation of this code should also work fine. The different threads may
01336 load the dll multiple times, but that is not a problem. The function NetGetDCName has a single entry
01337 point and that is loaded into the static variable pNetGetDCName. After this has been set the first time
01338 it will not change later even during another thread updating this variable. It can happen that
01339 thread "A" sets the value of this variable, and half of the bytes are updated and other parts are not and at
01340 this moment thread "B" uses the variable to call the function it points to. But thread "B" should see the
01341 same address even in this case, because the update value is identical to the original.
01342 */
01343     typedef NET_API_STATUS (*tNetGetDCName)(LPWSTR,LPWSTR,LPBYTE *);
01344     static tNetGetDCName pNetGetDCName = NULL;
01345 #define NetGetDCName pNetGetDCName
01346 
01347     HINSTANCE Netapi32DllInstance;
01348     PBYTE wszDomainController;
01349     UCHAR szDomainController[MAXNAMELEN];
01350     UCHAR szDomain[MAXNAMELEN];
01351     WCHAR wszDomain[MAXNAMELEN];
01352     char *s,*p;
01353 
01354     /* if the account name is DOMAIN\USER the copy the DOMAIN into szDomain */
01355     s = AccountName;
01356     p = szDomain;
01357     while( *s && *s != '\\' ){
01358       *p++ = *s++;
01359       }
01360     if( *s ){
01361       *p = (char)0;
01362       AccountName = s+1; /* point after the \ to contain the USER */
01363       }
01364     else
01365       *szDomain = (char)0;
01366     if( *szDomain ) {
01367         toUnicode(szDomain,wszDomain);
01368         if( NetGetDCName == NULL ){
01369           if( (Netapi32DllInstance = LoadLibrary("netapi32")) != NULL ){
01370             NetGetDCName = (tNetGetDCName)GetProcAddress(Netapi32DllInstance,"NetGetDCName");
01371             }
01372           }
01373         if( NetGetDCName && NetGetDCName(NULL,wszDomain,&wszDomainController) != NERR_Success )return FALSE;
01374         fromUnicode((LPWSTR)wszDomainController,szDomainController);
01375         return GetAccountSid(szDomainController,
01376                              AccountName,
01377                              Sid);
01378     } else {
01379         return GetAccountSid(NULL,
01380                              AccountName,
01381                              Sid);
01382     }
01383 }
01384 
01385 BOOL SetPrivilege(
01386     HANDLE hToken,          // token handle (NULL: current process)
01387     LPCTSTR Privilege,      // Privilege to enable/disable
01388     BOOL bEnablePrivilege   // TRUE to enable.  FALSE to disable
01389     )
01390 {
01391     TOKEN_PRIVILEGES tp;
01392     LUID luid;
01393     TOKEN_PRIVILEGES tpPrevious;
01394     DWORD cbPrevious=sizeof(TOKEN_PRIVILEGES);
01395     BOOL CloseAtEnd=FALSE;
01396 
01397     //
01398     // Retrieve a handle of the access token
01399     //
01400     if (hToken==NULL) {
01401                 if (!OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY,&hToken))return FALSE;
01402         CloseAtEnd=TRUE;
01403         }
01404 
01405     if (!LookupPrivilegeValue( NULL, Privilege, &luid )) {
01406                 return FALSE;
01407         }
01408 
01409     //
01410     // first pass.  get current privilege setting
01411     //
01412     tp.PrivilegeCount           = 1;
01413     tp.Privileges[0].Luid       = luid;
01414     tp.Privileges[0].Attributes = 0;
01415 
01416     AdjustTokenPrivileges(
01417             hToken,
01418             FALSE,
01419             &tp,
01420             sizeof(TOKEN_PRIVILEGES),
01421             &tpPrevious,
01422             &cbPrevious
01423             );
01424 
01425     if (GetLastError() != ERROR_SUCCESS) {
01426                 return FALSE;
01427         }
01428 
01429     //
01430     // second pass.  set privilege based on previous setting
01431     //
01432     tpPrevious.PrivilegeCount       = 1;
01433     tpPrevious.Privileges[0].Luid   = luid;
01434 
01435     if(bEnablePrivilege) {
01436         tpPrevious.Privileges[0].Attributes |= (SE_PRIVILEGE_ENABLED);
01437     }
01438     else {
01439         tpPrevious.Privileges[0].Attributes ^= (SE_PRIVILEGE_ENABLED &
01440             tpPrevious.Privileges[0].Attributes);
01441     }
01442 
01443     AdjustTokenPrivileges(
01444             hToken,
01445             FALSE,
01446             &tpPrevious,
01447             cbPrevious,
01448             NULL,
01449             NULL
01450             );
01451 
01452     if (GetLastError() != ERROR_SUCCESS) {
01453                 return FALSE;
01454         }
01455 
01456     /* call CloseHandle or not ??? */
01457     if (CloseAtEnd) {
01458         CloseHandle(hToken);
01459     }
01460     
01461     return TRUE;
01462 }
01463 #endif //WIN32
01464 
01465 /*POD
01466 =H file_chown
01467 @c Change owner of a file
01468 
01469 This function implements the chown command of the UNIX operating system
01470 on UNIX and Windows NT. The first argument is the ZCHAR terminated
01471 file name. No wild card characters are allowed.
01472 
01473 The second argument is the name of the desired new user. The function
01474 sets the owner of the file to the specified user, and returns zero
01475 if the setting was succesful. If the setting fails the function returns
01476 an error code. The error codes are:
01477 
01478 COMMAND_ERROR_CHOWN_NOT_SUPPORTED
01479 COMMAND_ERROR_CHOWN_INVALID_USER
01480 COMMAND_ERROR_CHOWN_SET_OWNER
01481 
01482 /*FUNCTION*/
01483 int file_chown(char *pszFile,
01484                char *pszOwner
01485   ){
01486 /*noverbatim
01487 CUT*/
01488 #ifdef WIN32
01489   UCHAR                ucFileSDBuf[SZ_SD_BUF] = "";
01490   PSECURITY_DESCRIPTOR psdFileSDrel = (PSECURITY_DESCRIPTOR)&ucFileSDBuf;
01491   PSECURITY_DESCRIPTOR psdFileSDabs = NULL;
01492   PSID                 psidOwner;
01493 
01494   if (GetVersion() & 0x80000000)return COMMAND_ERROR_CHOWN_NOT_SUPPORTED;
01495 
01496   SetPrivilege(NULL,SE_TAKE_OWNERSHIP_NAME,TRUE);
01497   SetPrivilege(NULL,SE_RESTORE_NAME,TRUE);
01498   SetPrivilege(NULL,SE_BACKUP_NAME,TRUE);
01499   SetPrivilege(NULL,SE_CHANGE_NOTIFY_NAME,TRUE);
01500 
01501   if (!GetSid(pszOwner,&psidOwner))return COMMAND_ERROR_CHOWN_INVALID_USER;
01502 
01503   if( !InitializeSecurityDescriptor(psdFileSDrel, SECURITY_DESCRIPTOR_REVISION))
01504     return COMMAND_ERROR_CHOWN_SET_OWNER;
01505   if (!SetSecurityDescriptorOwner(psdFileSDrel,psidOwner, FALSE))
01506     return COMMAND_ERROR_CHOWN_SET_OWNER;
01507   if (!IsValidSecurityDescriptor(psdFileSDrel))
01508     return COMMAND_ERROR_CHOWN_SET_OWNER;
01509   if (!SetFileSecurity(pszFile,(SECURITY_INFORMATION)(OWNER_SECURITY_INFORMATION),psdFileSDrel))
01510     return COMMAND_ERROR_CHOWN_SET_OWNER;
01511 
01512   return 0;
01513 #elif defined(__MACOS__)
01514   /* Macintosh doesn't have file ownership */
01515   return 0;
01516 #else
01517   struct passwd *pasw;
01518 
01519   pasw = getpwnam(pszOwner);
01520   if( pasw == NULL )return COMMAND_ERROR_CHOWN_INVALID_USER;
01521   if( chown(pszFile,pasw->pw_uid,-1) )return COMMAND_ERROR_CHOWN_SET_OWNER;
01522 #endif
01523   }
01524 
01525 /*POD
01526 =H file_getowner
01527 @c Get the owner of a file
01528 
01529 /*FUNCTION*/
01530 int file_getowner(char *pszFileName,
01531                   char *pszOwnerBuffer,
01532                   long cbOwnerBuffer
01533  ){
01534 /*noverbatim
01535 CUT*/
01536 #ifdef WIN32
01537 #define UNAMEMAXSIZE 256
01538 
01539   PSID psid;
01540   PSECURITY_DESCRIPTOR ppSecurityDescriptor;
01541   DWORD cbName=UNAMEMAXSIZE;
01542   char Name[UNAMEMAXSIZE];
01543   char ReferencedDomainName[256];
01544   DWORD cbReferencedDomainName = 256;
01545   SID_NAME_USE peUse;
01546   int Result;
01547   
01548   Result =
01549   GetNamedSecurityInfo(pszFileName,
01550                        SE_FILE_OBJECT,
01551                        OWNER_SECURITY_INFORMATION,
01552                        &psid,
01553                        NULL, // sidGroup is not needed
01554                        NULL, // dACL is not needed
01555                        NULL, // sACL is not needed
01556                        &ppSecurityDescriptor);
01557 
01558   if( Result )return Result;
01559   
01560   Result = 
01561   LookupAccountSid(NULL,
01562                    psid,
01563                    Name,
01564                    &cbName ,
01565                    ReferencedDomainName,
01566                    &cbReferencedDomainName,
01567                    &peUse);
01568 
01569   LocalFree( ppSecurityDescriptor );
01570   if( Result ){
01571     if( (cbName=strlen(Name)) + 
01572         (cbReferencedDomainName=strlen(ReferencedDomainName)) +
01573                                                 2 <= (unsigned)cbOwnerBuffer ){
01574       if( cbReferencedDomainName ){
01575         strcpy(pszOwnerBuffer,ReferencedDomainName);
01576         strcat(pszOwnerBuffer,"\\");
01577         }else
01578         *pszOwnerBuffer = (char)0;
01579       strcat(pszOwnerBuffer,Name);
01580       }
01581     return 0;
01582     }
01583   return 1;
01584 #elif defined(__MACOS__)
01585   /* Macintosh doesn't have file ownership */
01586   char *owner = "Apple";
01587   
01588   if( strlen(owner) < cbOwnerBuffer ){
01589     strcpy(pszOwnerBuffer,owner);
01590     return 0;
01591     }
01592   return 1;
01593 #else
01594 
01595   struct stat FileState;
01596   struct passwd *pasw;
01597 
01598   if( stat(pszFileName,&FileState) )return 1;
01599 
01600   pasw = getpwuid(FileState.st_uid);
01601   if( strlen(pasw->pw_name) < cbOwnerBuffer ){
01602     strcpy(pszOwnerBuffer,pasw->pw_name);
01603     return 0;
01604     }
01605   return 1;
01606 
01607 #endif
01608   }
01609 
01610 
01611 #ifdef WIN32
01612 /*
01613 Open a file so that the file time can be set. In case the file is read only the
01614 function alters the file attributes so that the file is NOT read only anymore.
01615 When the file time is altered calling my_CloseHandle restores the file attributes
01616 */
01617 static HANDLE my_CreateFile(char *pszFile, int *fFlag){
01618   HANDLE hFile;
01619   DWORD attrib;
01620 
01621   *fFlag = 0; /* the attributes were not altered, attrib does not hold any value to restore */
01622   hFile = CreateFile(pszFile,
01623                      GENERIC_WRITE,
01624                      FILE_SHARE_READ | FILE_SHARE_WRITE,
01625                      NULL,
01626                      OPEN_EXISTING,
01627                      FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS,
01628                      0);
01629   if( hFile != INVALID_HANDLE_VALUE )return hFile;
01630 
01631   attrib = GetFileAttributes(pszFile);
01632   if( attrib & FILE_ATTRIBUTE_READONLY ){
01633     *fFlag = 1; /* remember that we have altered the attributes, has to be restored when closing the handle */
01634     /* remove the read only bit from the flags and ... */
01635     SetFileAttributes(pszFile,attrib & ~FILE_ATTRIBUTE_READONLY);
01636     /* ... try to open the file again */
01637     hFile = CreateFile(pszFile,
01638                        GENERIC_WRITE,
01639                        FILE_SHARE_READ | FILE_SHARE_WRITE,
01640                        NULL,
01641                        OPEN_EXISTING,
01642                        FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS,
01643                        0);
01644     /* the file is now opned ok */
01645     if( hFile != INVALID_HANDLE_VALUE )return hFile;
01646     /* if the file still cannot be opened, then reset the attributes to the original */
01647     SetFileAttributes(pszFile,attrib);
01648     *fFlag = 0;
01649     }
01650   return hFile;
01651   }
01652 
01653 /* Close the file handle that was opened by my_CreateFile to alter one of the time values of a file.
01654    If the read-only flag was cleared to make the code able to alter the file time then this flag is
01655    reset after the operation.
01656 */
01657 static void my_CloseHandle(HANDLE hFile, char *pszFile, int *fFlag){
01658   DWORD attrib;
01659 
01660   if( *fFlag ){
01661     /* this may be slower to retrieve the file attributes again, but it does not hurt in case somebody
01662        alters some other attribute in the mean time. */
01663     attrib = GetFileAttributes(pszFile);
01664     attrib |= FILE_ATTRIBUTE_READONLY;
01665     SetFileAttributes(pszFile,attrib);
01666     }
01667   CloseHandle(hFile);
01668   }
01669 #endif
01670 /*POD
01671 =H file_SetCreateTime
01672 @c Set the creation time of a file
01673 
01674 Note that this time value does not exist on UNIX and
01675 therefore calling this function under UNIX result error.
01676 
01677 The argument to the function is the file name and the desired time
01678 in number of seconds since the epoch. (January 1, 1970. 00:00)
01679 
01680 If the time was set the return value is zero. If there is an error the
01681 return value is the error code.
01682 /*FUNCTION*/
01683 int file_SetCreateTime(char *pszFile,
01684                        long lTime
01685   ){
01686 /*noverbatim
01687 CUT*/
01688 #ifdef WIN32
01689   FILETIME FileTime;
01690   HANDLE hFile;
01691   int fFlag;
01692 
01693   Utime2Filetime(lTime,&FileTime);
01694   hFile = my_CreateFile(pszFile,&fFlag);
01695   if( hFile == INVALID_HANDLE_VALUE )
01696     return COMMAND_ERROR_CREATIME_FAIL;
01697   if( !SetFileTime(hFile,&FileTime,NULL,NULL) ){
01698     my_CloseHandle(hFile,pszFile,&fFlag);
01699     return COMMAND_ERROR_CREATIME_FAIL;
01700     }
01701   my_CloseHandle(hFile,pszFile,&fFlag);
01702   return 0;
01703 #else
01704   return 0;
01705 #endif
01706   }
01707 
01708 /*POD
01709 =H file_SetModifyTime
01710 @c Set the modification time of a file
01711 
01712 The argument to the function is the file name and the desired time
01713 in number of seconds since the epoch. (January 1, 1970. 00:00)
01714 
01715 If the time was set the return value is zero. If there is an error the
01716 return value is the error code.
01717 /*FUNCTION*/
01718 int file_SetModifyTime(char *pszFile,
01719                        long lTime
01720   ){
01721 /*noverbatim
01722 CUT*/
01723 #ifdef WIN32
01724   FILETIME FileTime;
01725   HANDLE hFile;
01726   int fFlag;
01727 
01728   Utime2Filetime(lTime,&FileTime);
01729   hFile = my_CreateFile(pszFile,&fFlag);
01730   if( hFile == INVALID_HANDLE_VALUE )
01731     return COMMAND_ERROR_MODTIME_FAIL;
01732   if( !SetFileTime(hFile,NULL,NULL,&FileTime) ){
01733     my_CloseHandle(hFile,pszFile,&fFlag);
01734     return COMMAND_ERROR_MODTIME_FAIL;
01735     }
01736   my_CloseHandle(hFile,pszFile,&fFlag);
01737   return 0;
01738 #else
01739   struct utimbuf uTime;
01740 
01741   uTime.modtime = lTime;
01742   uTime.actime  = file_time_accessed(pszFile);
01743   if( utime(pszFile,&uTime) == -1 )return COMMAND_ERROR_MODTIME_FAIL;
01744   return 0;
01745 #endif
01746   }
01747 
01748 /*POD
01749 =H file_SetAccessTime
01750 @c Set the access time of a file
01751 
01752 The argument to the function is the file name and the desired time
01753 in number of seconds since the epoch. (January 1, 1970. 00:00)
01754 
01755 If the time was set the return value is zero. If there is an error the
01756 return value is the error code.
01757 /*FUNCTION*/
01758 int file_SetAccessTime(char *pszFile,
01759                        long lTime
01760   ){
01761 /*noverbatim
01762 CUT*/
01763 #ifdef WIN32
01764   FILETIME FileTime;
01765   HANDLE hFile;
01766   int fFlag;
01767 
01768   Utime2Filetime(lTime,&FileTime);
01769   hFile = my_CreateFile(pszFile,&fFlag);
01770   if( hFile == INVALID_HANDLE_VALUE )
01771     return COMMAND_ERROR_ACCTIM_FAIL;
01772   if( !SetFileTime(hFile,NULL,&FileTime,NULL) ){
01773     my_CloseHandle(hFile,pszFile,&fFlag);
01774     return COMMAND_ERROR_ACCTIM_FAIL;
01775     }
01776   my_CloseHandle(hFile,pszFile,&fFlag);
01777   return 0;
01778 #else
01779   struct utimbuf uTime;
01780 
01781   uTime.actime = lTime;
01782   uTime.modtime  = file_time_modified(pszFile);
01783   if( utime(pszFile,&uTime) == -1 )return COMMAND_ERROR_ACCTIM_FAIL;
01784   return 0;
01785 #endif
01786   }
01787 
01788 /* Initialize the Windows socket sub system to use the version 2.2 */
01789 #ifdef WIN32
01790 #define WIN32SOCKETINIT  WORD wVersionRequested; \
01791   WSADATA wsaData; int err; \
01792   wVersionRequested = MAKEWORD( 2, 2 ); \
01793   err = WSAStartup( wVersionRequested, &wsaData );\
01794   if ( err != 0 )return err;
01795 #else
01796 #define WIN32SOCKETINIT int err;
01797 #endif
01798 
01799 
01800 /*POD
01801 =H file_gethostname
01802 @c Get the name of the actual host
01803 
01804 This function gets the name of the host that runs the program.
01805 The result of the function is positive if no TCP/IP protocol is
01806 available on the machine or some error occured.
01807 
01808 In case of success the return value is zero.
01809 /*FUNCTION*/
01810 int file_gethostname(char *pszBuffer,
01811                      long cbBuffer
01812   ){
01813 /*noverbatim
01814 The first argument should point to the character buffer, and the second
01815 argument should hold the size of the buffer in bytes.
01816 CUT*/
01817 #ifndef __NO_SOCKETS__
01818   WIN32SOCKETINIT
01819 
01820   return gethostname(pszBuffer,(int)cbBuffer);
01821 #else
01822   return 1;
01823 #endif
01824   }
01825 
01826 /*POD
01827 =H file_gethost
01828 @c Get host by name or by address
01829 
01830 This function gets the T<struct hostent> entry for the given address.
01831 The address can be given as a FQDN or as an IP octet tuple, like
01832 www.digital.com or 16.193.48.55
01833 
01834 Optionally the address may contain a port number separated by : from
01835 the name or the IP number. The port number is simply ignored.
01836 
01837 /*FUNCTION*/
01838 int file_gethost(char *pszBuffer,
01839                  struct hostent *pHost
01840   ){
01841 /*noverbatim
01842 T<pszBuffer> should hold the name or the address of the target machine.
01843 This buffer is not altered during the function.
01844 
01845 T<pHost> should point to a buffer ready to hold the hostent information.
01846 
01847 Note that the structure T<hostent> contains pointers outside the structre.
01848 Those pointers are copied verbatim thus they point to the original content
01849 as returned by the underlying socket layer. This means that the values
01850 the T<hostent> structure points to should not be freed, altered and 
01851 the values needed later should be copied as soon as possible into a safe
01852 location before any other socket call is done.
01853 CUT*/
01854 #ifndef __NO_SOCKETS__
01855   int i,OctetCounter,IPnumber;
01856   unsigned char addr[4],*s;
01857   struct hostent *q;
01858   WIN32SOCKETINIT
01859 
01860   /* decide if the given string is a dd.dd.dd.dd IP number */
01861   IPnumber = 1; /* assume that it is an IP number when we start */
01862   addr[0] = 0;
01863   OctetCounter = 0;
01864   for( i = 0 ; pszBuffer[i] && pszBuffer[i] != ':' ; i++ ){
01865      if( pszBuffer[i] == '.' ){
01866        OctetCounter ++;
01867        if( OctetCounter > 3 ){
01868          IPnumber = 0; /* there are too many octets, there should be no more than four */
01869          break;        /* we will take care of IPng later */
01870          }
01871        addr[OctetCounter] = 0;
01872        continue;
01873        }
01874      if( ! isdigit(pszBuffer[i]) ){
01875        IPnumber = 0;/* if there is a non digit character it can not be IP number */
01876        while( pszBuffer[i] && pszBuffer[i] != ':' )i++;/* we need the colon by i */
01877        break;
01878        }
01879      addr[OctetCounter] = 10*addr[OctetCounter] + pszBuffer[i] - '0';
01880      }
01881 
01882   /* if there was nothing telling that this is not an IP number
01883      and we have found four octets total */
01884   if( IPnumber && OctetCounter == 3 ){
01885     q = gethostbyaddr(addr,4,AF_INET);
01886     if( q == NULL )return 1;
01887     memcpy(pHost,q,sizeof(struct hostent));
01888     return 0;
01889     }else{/* note that we can not modify pszBuffer even temporarily, because
01890              WindowsNT string constants are real constants and the process is
01891              not allowed to alter the string constants. */
01892     if( pszBuffer[i] ){
01893       s = (unsigned char *)malloc(i+2);
01894       if( s == NULL )return 1;
01895       memcpy(s,pszBuffer,i);
01896       s[i] = (char)0;
01897       q = gethostbyname(s);
01898       free(s);
01899       }else q = gethostbyname(pszBuffer);
01900     if( q == NULL )return 1;
01901     memcpy(pHost,q,sizeof(struct hostent));
01902     return 0;
01903     }
01904 #else
01905   return 1;
01906 #endif
01907   }
01908 
01909 /*POD
01910 =H file_tcpconnect
01911 @c Connect a socket to a server:port
01912 
01913 This function tries to connect to the remote port of a remote server.
01914 The first argument of the function should be a pointer to T<SOCKET>
01915 variable as defined in T<filesys.h> or in the Windows header files. The
01916 second argument is a string that contains the name of the remote host,
01917 or the IP number of the remote host and the desired port number following
01918 the name separated by a colon. For example T<index.hu:80> tries to connect
01919 to the http port of the server T<index.hu>. You can also write
01920 T<16.192.80.33:80> to get a connection. The function automatically recognizes
01921 IP numbers and host names. The socket is created automatically calling the
01922 system function T<socket>.
01923 
01924 If the function successfully connected to the remote server the return value
01925 is zero. Otherwise the return value is the error code.
01926 
01927 /*FUNCTION*/
01928 int file_tcpconnect(SOCKET *sClient,
01929                     char *pszRemoteSocket
01930   ){
01931 /*noverbatim
01932 CUT*/
01933 #ifndef __NO_SOCKETS__
01934   unsigned long iaddr,octet;
01935   unsigned int iPort,IPnumber,OctetCounter,i;
01936   struct sockaddr_in RemoteAddress;
01937   struct hostent RemoteMachine;
01938   static unsigned long pow[4] = { 1, 256 , 256*256, 256*256*256 };
01939   WIN32SOCKETINIT
01940   /* decide if the given string is a dd.dd.dd.dd:port IP number */
01941   IPnumber = 1; /* assume that it is an IP number when we start */
01942   iaddr = 0;
01943   octet = 0;
01944   OctetCounter = 0;
01945   for( i = 0 ; pszRemoteSocket[i]  ; i++ ){
01946      if( pszRemoteSocket[i] == '.' || pszRemoteSocket[i] == ':'){
01947        iaddr = iaddr + octet * pow[OctetCounter];
01948        octet = 0;
01949        OctetCounter ++;
01950        if( OctetCounter > 4 ){
01951          IPnumber = 0; /* there are too many octets, there should be no more than four */
01952          break;        /* we will take care of IPng later */
01953          }
01954        if( pszRemoteSocket[i] == ':')break;
01955        continue;
01956        }
01957      if( ! isdigit(pszRemoteSocket[i]) ){
01958        IPnumber = 0;/* if there is a non digit character it can not be IP number */
01959        while( pszRemoteSocket[i] && pszRemoteSocket[i] != ':' )i++;/* we need the colon by i */
01960        break;
01961        }
01962      octet = 10*octet + pszRemoteSocket[i] - '0';
01963      }
01964 
01965   while( pszRemoteSocket[i] && pszRemoteSocket[i] != ':' )i++;
01966   if( pszRemoteSocket[i] != ':' )return 1;
01967   i++;
01968   for( iPort = 0 ; pszRemoteSocket[i] ; i++ ){
01969     if( ! isdigit(pszRemoteSocket[i]) )return 1;
01970     iPort = 10*iPort + pszRemoteSocket[i] - '0';
01971     }
01972 
01973   /* if there was nothing telling that this is not an IP number
01974      and we have found four octets total */
01975   if( !IPnumber || OctetCounter != 4 ){
01976     if( err = file_gethost(pszRemoteSocket,&RemoteMachine) )return err;
01977     memcpy(&iaddr,RemoteMachine.h_addr,4);
01978     }
01979 #ifdef WIN32
01980   RemoteAddress.sin_addr.S_un.S_addr = iaddr;
01981 #else
01982   RemoteAddress.sin_addr.s_addr = iaddr;
01983 #endif
01984   RemoteAddress.sin_port = htons((unsigned short)iPort);
01985   RemoteAddress.sin_family = AF_INET;
01986   *sClient = socket(AF_INET,SOCK_STREAM,0);
01987   return connect((*sClient),(struct sockaddr *)&RemoteAddress,sizeof(RemoteAddress));
01988 #else
01989   return 1;
01990 #endif
01991   }
01992 
01993 /*POD
01994 =H file_tcpsend
01995 @c send bytes to remote server via socket
01996 
01997 /*FUNCTION*/
01998 int file_tcpsend(SOCKET sClient,
01999                  char *pszBuffer,
02000                  long cbBuffer,
02001                  int iFlags
02002   ){
02003 /*noverbatim
02004 CUT*/
02005 #ifndef __NO_SOCKETS__
02006   WIN32SOCKETINIT
02007 
02008   return send(sClient,pszBuffer,(int)cbBuffer,iFlags);
02009 #else
02010   return 1;
02011 #endif
02012   }
02013 
02014 /*POD
02015 =H file_tcprecv
02016 @c receive bytes from remote server via socket
02017 
02018 /*FUNCTION*/
02019 int file_tcprecv(SOCKET sClient,
02020                  char *pszBuffer,
02021                  long cbBuffer,
02022                  int iFlags
02023   ){
02024 /*noverbatim
02025 CUT*/
02026 #ifndef __NO_SOCKETS__
02027   WIN32SOCKETINIT
02028 
02029   return recv(sClient,pszBuffer,(int)cbBuffer,iFlags);
02030 #else
02031   return 1;
02032 #endif
02033   }
02034 
02035 /*POD
02036 =H file_tcpclose
02037 @c close a tcp connection
02038 
02039 /*FUNCTION*/
02040 int file_tcpclose(SOCKET sClient
02041   ){
02042 /*noverbatim
02043 CUT*/
02044 #ifndef __NO_SOCKETS__
02045   WIN32SOCKETINIT
02046 
02047   if( shutdown(sClient,SHUT_RDWR) )return 1;
02048 #ifdef WIN32
02049   closesocket(sClient);
02050 #else
02051   close(sClient);
02052 #endif
02053   return 0;
02054 #else
02055   return 1;
02056 #endif
02057   }
02058 
02059 /*POD
02060 =H file_killproc
02061 @c Kill a process
02062 
02063 
02064 This function kills a process identified by the process ID (PID).
02065 
02066 If the process is killed successfully the return value is zero, otherwise
02067 a positive value.
02068 /*FUNCTION*/
02069 int file_killproc(long pid
02070   ){
02071 /*noverbatim
02072 CUT*/
02073 #ifdef WIN32
02074   HANDLE hProcess;
02075 
02076   hProcess = OpenProcess(PROCESS_TERMINATE,0,(DWORD)pid);
02077   if( hProcess == NULL )return 1;
02078   if( TerminateProcess(hProcess,1) )return 0;
02079   return 1;
02080 #elif defined(__MACOS__)
02081   return 1;
02082 #else
02083   return kill( (pid_t)pid,9);
02084 #endif
02085   }
02086 
02087 /* Eric Young.
02088  * This version of crypt has been developed from my MIT compatable
02089  * DES library.
02090  * The library is available at pub/DES at ftp.psy.uq.oz.au
02091  * eay@psych.psy.uq.oz.au
02092  */
02093 
02094 typedef unsigned char des_cblock[8];
02095 
02096 typedef struct des_ks_struct
02097         {
02098         union   {
02099                 des_cblock _;
02100                 /* make sure things are correct size on machines with
02101                  * 8 byte longs */
02102                 unsigned long pad[2];
02103                 } ks;
02104 #define _       ks._
02105         } des_key_schedule[16];
02106 
02107 #define DES_KEY_SZ      (sizeof(des_cblock))
02108 #define DES_ENCRYPT     1
02109 #define DES_DECRYPT     0
02110 
02111 #define ITERATIONS 16
02112 #define HALF_ITERATIONS 8
02113 
02114 #define c2l(c,l)        (l =((unsigned long)(*((c)++)))    , \
02115                          l|=((unsigned long)(*((c)++)))<< 8, \
02116                          l|=((unsigned long)(*((c)++)))<<16, \
02117                          l|=((unsigned long)(*((c)++)))<<24)
02118 
02119 #define l2c(l,c)        (*((c)++)=(unsigned char)(((l)    )&0xff), \
02120                          *((c)++)=(unsigned char)(((l)>> 8)&0xff), \
02121                          *((c)++)=(unsigned char)(((l)>>16)&0xff), \
02122                          *((c)++)=(unsigned char)(((l)>>24)&0xff))
02123 
02124 static unsigned long SPtrans[8][64]={
02125 /* nibble 0 */
02126 0x00820200, 0x00020000, 0x80800000, 0x80820200,
02127 0x00800000, 0x80020200, 0x80020000, 0x80800000,
02128 0x80020200, 0x00820200, 0x00820000, 0x80000200,
02129 0x80800200, 0x00800000, 0x00000000, 0x80020000,
02130 0x00020000, 0x80000000, 0x00800200, 0x00020200,
02131 0x80820200, 0x00820000, 0x80000200, 0x00800200,
02132 0x80000000, 0x00000200, 0x00020200, 0x80820000,
02133 0x00000200, 0x80800200, 0x80820000, 0x00000000,
02134 0x00000000, 0x80820200, 0x00800200, 0x80020000,
02135 0x00820200, 0x00020000, 0x80000200, 0x00800200,
02136 0x80820000, 0x00000200, 0x00020200, 0x80800000,
02137 0x80020200, 0x80000000, 0x80800000, 0x00820000,
02138 0x80820200, 0x00020200, 0x00820000, 0x80800200,
02139 0x00800000, 0x80000200, 0x80020000, 0x00000000,
02140 0x00020000, 0x00800000, 0x80800200, 0x00820200,
02141 0x80000000, 0x80820000, 0x00000200, 0x80020200,
02142 /* nibble 1 */
02143 0x10042004, 0x00000000, 0x00042000, 0x10040000,
02144 0x10000004, 0x00002004, 0x10002000, 0x00042000,
02145 0x00002000, 0x10040004, 0x00000004, 0x10002000,
02146 0x00040004, 0x10042000, 0x10040000, 0x00000004,
02147 0x00040000, 0x10002004, 0x10040004, 0x00002000,
02148 0x00042004, 0x10000000, 0x00000000, 0x00040004,
02149 0x10002004, 0x00042004, 0x10042000, 0x10000004,
02150 0x10000000, 0x00040000, 0x00002004, 0x10042004,
02151 0x00040004, 0x10042000, 0x10002000, 0x00042004,
02152 0x10042004, 0x00040004, 0x10000004, 0x00000000,
02153 0x10000000, 0x00002004, 0x00040000, 0x10040004,
02154 0x00002000, 0x10000000, 0x00042004, 0x10002004,
02155 0x10042000, 0x00002000, 0x00000000, 0x10000004,
02156 0x00000004, 0x10042004, 0x00042000, 0x10040000,
02157 0x10040004, 0x00040000, 0x00002004, 0x10002000,
02158 0x10002004, 0x00000004, 0x10040000, 0x00042000,
02159 /* nibble 2 */
02160 0x41000000, 0x01010040, 0x00000040, 0x41000040,
02161 0x40010000, 0x01000000, 0x41000040, 0x00010040,
02162 0x01000040, 0x00010000, 0x01010000, 0x40000000,
02163 0x41010040, 0x40000040, 0x40000000, 0x41010000,
02164 0x00000000, 0x40010000, 0x01010040, 0x00000040,
02165 0x40000040, 0x41010040, 0x00010000, 0x41000000,
02166 0x41010000, 0x01000040, 0x40010040, 0x01010000,
02167 0x00010040, 0x00000000, 0x01000000, 0x40010040,
02168 0x01010040, 0x00000040, 0x40000000, 0x00010000,
02169 0x40000040, 0x40010000, 0x01010000, 0x41000040,
02170 0x00000000, 0x01010040, 0x00010040, 0x41010000,
02171 0x40010000, 0x01000000, 0x41010040, 0x40000000,
02172 0x40010040, 0x41000000, 0x01000000, 0x41010040,
02173 0x00010000, 0x01000040, 0x41000040, 0x00010040,
02174 0x01000040, 0x00000000, 0x41010000, 0x40000040,
02175 0x41000000, 0x40010040, 0x00000040, 0x01010000,
02176 /* nibble 3 */
02177 0x00100402, 0x04000400, 0x00000002, 0x04100402,
02178 0x00000000, 0x04100000, 0x04000402, 0x00100002,
02179 0x04100400, 0x04000002, 0x04000000, 0x00000402,
02180 0x04000002, 0x00100402, 0x00100000, 0x04000000,
02181 0x04100002, 0x00100400, 0x00000400, 0x00000002,
02182 0x00100400, 0x04000402, 0x04100000, 0x00000400,
02183 0x00000402, 0x00000000, 0x00100002, 0x04100400,
02184 0x04000400, 0x04100002, 0x04100402, 0x00100000,
02185 0x04100002, 0x00000402, 0x00100000, 0x04000002,
02186 0x00100400, 0x04000400, 0x00000002, 0x04100000,
02187 0x04000402, 0x00000000, 0x00000400, 0x00100002,
02188 0x00000000, 0x04100002, 0x04100400, 0x00000400,
02189 0x04000000, 0x04100402, 0x00100402, 0x00100000,
02190 0x04100402, 0x00000002, 0x04000400, 0x00100402,
02191 0x00100002, 0x00100400, 0x04100000, 0x04000402,
02192 0x00000402, 0x04000000, 0x04000002, 0x04100400,
02193 /* nibble 4 */
02194 0x02000000, 0x00004000, 0x00000100, 0x02004108,
02195 0x02004008, 0x02000100, 0x00004108, 0x02004000,
02196 0x00004000, 0x00000008, 0x02000008, 0x00004100,
02197 0x02000108, 0x02004008, 0x02004100, 0x00000000,
02198 0x00004100, 0x02000000, 0x00004008, 0x00000108,
02199 0x02000100, 0x00004108, 0x00000000, 0x02000008,
02200 0x00000008, 0x02000108, 0x02004108, 0x00004008,
02201 0x02004000, 0x00000100, 0x00000108, 0x02004100,
02202 0x02004100, 0x02000108, 0x00004008, 0x02004000,
02203 0x00004000, 0x00000008, 0x02000008, 0x02000100,
02204 0x02000000, 0x00004100, 0x02004108, 0x00000000,
02205 0x00004108, 0x02000000, 0x00000100, 0x00004008,
02206 0x02000108, 0x00000100, 0x00000000, 0x02004108,
02207 0x02004008, 0x02004100, 0x00000108, 0x00004000,
02208 0x00004100, 0x02004008, 0x02000100, 0x00000108,
02209 0x00000008, 0x00004108, 0x02004000, 0x02000008,
02210 /* nibble 5 */
02211 0x20000010, 0x00080010, 0x00000000, 0x20080800,
02212 0x00080010, 0x00000800, 0x20000810, 0x00080000,
02213 0x00000810, 0x20080810, 0x00080800, 0x20000000,
02214 0x20000800, 0x20000010, 0x20080000, 0x00080810,
02215 0x00080000, 0x20000810, 0x20080010, 0x00000000,
02216 0x00000800, 0x00000010, 0x20080800, 0x20080010,
02217 0x20080810, 0x20080000, 0x20000000, 0x00000810,
02218 0x00000010, 0x00080800, 0x00080810, 0x20000800,
02219 0x00000810, 0x20000000, 0x20000800, 0x00080810,
02220 0x20080800, 0x00080010, 0x00000000, 0x20000800,
02221 0x20000000, 0x00000800, 0x20080010, 0x00080000,
02222 0x00080010, 0x20080810, 0x00080800, 0x00000010,
02223 0x20080810, 0x00080800, 0x00080000, 0x20000810,
02224 0x20000010, 0x20080000, 0x00080810, 0x00000000,
02225 0x00000800, 0x20000010, 0x20000810, 0x20080800,
02226 0x20080000, 0x00000810, 0x00000010, 0x20080010,
02227 /* nibble 6 */
02228 0x00001000, 0x00000080, 0x00400080, 0x00400001,
02229 0x00401081, 0x00001001, 0x00001080, 0x00000000,
02230 0x00400000, 0x00400081, 0x00000081, 0x00401000,
02231 0x00000001, 0x00401080, 0x00401000, 0x00000081,
02232 0x00400081, 0x00001000, 0x00001001, 0x00401081,
02233 0x00000000, 0x00400080, 0x00400001, 0x00001080,
02234 0x00401001, 0x00001081, 0x00401080, 0x00000001,
02235 0x00001081, 0x00401001, 0x00000080, 0x00400000,
02236 0x00001081, 0x00401000, 0x00401001, 0x00000081,
02237 0x00001000, 0x00000080, 0x00400000, 0x00401001,
02238 0x00400081, 0x00001081, 0x00001080, 0x00000000,
02239 0x00000080, 0x00400001, 0x00000001, 0x00400080,
02240 0x00000000, 0x00400081, 0x00400080, 0x00001080,
02241 0x00000081, 0x00001000, 0x00401081, 0x00400000,
02242 0x00401080, 0x00000001, 0x00001001, 0x00401081,
02243 0x00400001, 0x00401080, 0x00401000, 0x00001001,
02244 /* nibble 7 */
02245 0x08200020, 0x08208000, 0x00008020, 0x00000000,
02246 0x08008000, 0x00200020, 0x08200000, 0x08208020,
02247 0x00000020, 0x08000000, 0x00208000, 0x00008020,
02248 0x00208020, 0x08008020, 0x08000020, 0x08200000,
02249 0x00008000, 0x00208020, 0x00200020, 0x08008000,
02250 0x08208020, 0x08000020, 0x00000000, 0x00208000,
02251 0x08000000, 0x00200000, 0x08008020, 0x08200020,
02252 0x00200000, 0x00008000, 0x08208000, 0x00000020,
02253 0x00200000, 0x00008000, 0x08000020, 0x08208020,
02254 0x00008020, 0x08000000, 0x00000000, 0x00208000,
02255 0x08200020, 0x08008020, 0x08008000, 0x00200020,
02256 0x08208000, 0x00000020, 0x00200020, 0x08008000,
02257 0x08208020, 0x00200000, 0x08200000, 0x08000020,
02258 0x00208000, 0x00008020, 0x08008020, 0x08200000,
02259 0x00000020, 0x08208000, 0x00208020, 0x00000000,
02260 0x08000000, 0x08200020, 0x00008000, 0x00208020};
02261 static unsigned long skb[8][64]={
02262 /* for C bits (numbered as per FIPS 46) 1 2 3 4 5 6 */
02263 0x00000000,0x00000010,0x20000000,0x20000010,
02264 0x00010000,0x00010010,0x20010000,0x20010010,
02265 0x00000800,0x00000810,0x20000800,0x20000810,
02266 0x00010800,0x00010810,0x20010800,0x20010810,
02267 0x00000020,0x00000030,0x20000020,0x20000030,
02268 0x00010020,0x00010030,0x20010020,0x20010030,
02269 0x00000820,0x00000830,0x20000820,0x20000830,
02270 0x00010820,0x00010830,0x20010820,0x20010830,
02271 0x00080000,0x00080010,0x20080000,0x20080010,
02272 0x00090000,0x00090010,0x20090000,0x20090010,
02273 0x00080800,0x00080810,0x20080800,0x20080810,
02274 0x00090800,0x00090810,0x20090800,0x20090810,
02275 0x00080020,0x00080030,0x20080020,0x20080030,
02276 0x00090020,0x00090030,0x20090020,0x20090030,
02277 0x00080820,0x00080830,0x20080820,0x20080830,
02278 0x00090820,0x00090830,0x20090820,0x20090830,
02279 /* for C bits (numbered as per FIPS 46) 7 8 10 11 12 13 */
02280 0x00000000,0x02000000,0x00002000,0x02002000,
02281 0x00200000,0x02200000,0x00202000,0x02202000,
02282 0x00000004,0x02000004,0x00002004,0x02002004,
02283 0x00200004,0x02200004,0x00202004,0x02202004,
02284 0x00000400,0x02000400,0x00002400,0x02002400,
02285 0x00200400,0x02200400,0x00202400,0x02202400,
02286 0x00000404,0x02000404,0x00002404,0x02002404,
02287 0x00200404,0x02200404,0x00202404,0x02202404,
02288 0x10000000,0x12000000,0x10002000,0x12002000,
02289 0x10200000,0x12200000,0x10202000,0x12202000,
02290 0x10000004,0x12000004,0x10002004,0x12002004,
02291 0x10200004,0x12200004,0x10202004,0x12202004,
02292 0x10000400,0x12000400,0x10002400,0x12002400,
02293 0x10200400,0x12200400,0x10202400,0x12202400,
02294 0x10000404,0x12000404,0x10002404,0x12002404,
02295 0x10200404,0x12200404,0x10202404,0x12202404,
02296 /* for C bits (numbered as per FIPS 46) 14 15 16 17 19 20 */
02297 0x00000000,0x00000001,0x00040000,0x00040001,
02298 0x01000000,0x01000001,0x01040000,0x01040001,
02299 0x00000002,0x00000003,0x00040002,0x00040003,
02300 0x01000002,0x01000003,0x01040002,0x01040003,
02301 0x00000200,0x00000201,0x00040200,0x00040201,
02302 0x01000200,0x01000201,0x01040200,0x01040201,
02303 0x00000202,0x00000203,0x00040202,0x00040203,
02304 0x01000202,0x01000203,0x01040202,0x01040203,
02305 0x08000000,0x08000001,0x08040000,0x08040001,
02306 0x09000000,0x09000001,0x09040000,0x09040001,
02307 0x08000002,0x08000003,0x08040002,0x08040003,
02308 0x09000002,0x09000003,0x09040002,0x09040003,
02309 0x08000200,0x08000201,0x08040200,0x08040201,
02310 0x09000200,0x09000201,0x09040200,0x09040201,
02311 0x08000202,0x08000203,0x08040202,0x08040203,
02312 0x09000202,0x09000203,0x09040202,0x09040203,
02313 /* for C bits (numbered as per FIPS 46) 21 23 24 26 27 28 */
02314 0x00000000,0x00100000,0x00000100,0x00100100,
02315 0x00000008,0x00100008,0x00000108,0x00100108,
02316 0x00001000,0x00101000,0x00001100,0x00101100,
02317 0x00001008,0x00101008,0x00001108,0x00101108,
02318 0x04000000,0x04100000,0x04000100,0x04100100,
02319 0x04000008,0x04100008,0x04000108,0x04100108,
02320 0x04001000,0x04101000,0x04001100,0x04101100,
02321 0x04001008,0x04101008,0x04001108,0x04101108,
02322 0x00020000,0x00120000,0x00020100,0x00120100,
02323 0x00020008,0x00120008,0x00020108,0x00120108,
02324 0x00021000,0x00121000,0x00021100,0x00121100,
02325 0x00021008,0x00121008,0x00021108,0x00121108,
02326 0x04020000,0x04120000,0x04020100,0x04120100,
02327 0x04020008,0x04120008,0x04020108,0x04120108,
02328 0x04021000,0x04121000,0x04021100,0x04121100,
02329 0x04021008,0x04121008,0x04021108,0x04121108,
02330 /* for D bits (numbered as per FIPS 46) 1 2 3 4 5 6 */
02331 0x00000000,0x10000000,0x00010000,0x10010000,
02332 0x00000004,0x10000004,0x00010004,0x10010004,
02333 0x20000000,0x30000000,0x20010000,0x30010000,
02334 0x20000004,0x30000004,0x20010004,0x30010004,
02335 0x00100000,0x10100000,0x00110000,0x10110000,
02336 0x00100004,0x10100004,0x00110004,0x10110004,
02337 0x20100000,0x30100000,0x20110000,0x30110000,
02338 0x20100004,0x30100004,0x20110004,0x30110004,
02339 0x00001000,0x10001000,0x00011000,0x10011000,
02340 0x00001004,0x10001004,0x00011004,0x10011004,
02341 0x20001000,0x30001000,0x20011000,0x30011000,
02342 0x20001004,0x30001004,0x20011004,0x30011004,
02343 0x00101000,0x10101000,0x00111000,0x10111000,
02344 0x00101004,0x10101004,0x00111004,0x10111004,
02345 0x20101000,0x30101000,0x20111000,0x30111000,
02346 0x20101004,0x30101004,0x20111004,0x30111004,
02347 /* for D bits (numbered as per FIPS 46) 8 9 11 12 13 14 */
02348 0x00000000,0x08000000,0x00000008,0x08000008,
02349 0x00000400,0x08000400,0x00000408,0x08000408,
02350 0x00020000,0x08020000,0x00020008,0x08020008,
02351 0x00020400,0x08020400,0x00020408,0x08020408,
02352 0x00000001,0x08000001,0x00000009,0x08000009,
02353 0x00000401,0x08000401,0x00000409,0x08000409,
02354 0x00020001,0x08020001,0x00020009,0x08020009,
02355 0x00020401,0x08020401,0x00020409,0x08020409,
02356 0x02000000,0x0A000000,0x02000008,0x0A000008,
02357 0x02000400,0x0A000400,0x02000408,0x0A000408,
02358 0x02020000,0x0A020000,0x02020008,0x0A020008,
02359 0x02020400,0x0A020400,0x02020408,0x0A020408,
02360 0x02000001,0x0A000001,0x02000009,0x0A000009,
02361 0x02000401,0x0A000401,0x02000409,0x0A000409,
02362 0x02020001,0x0A020001,0x02020009,0x0A020009,
02363 0x02020401,0x0A020401,0x02020409,0x0A020409,
02364 /* for D bits (numbered as per FIPS 46) 16 17 18 19 20 21 */
02365 0x00000000,0x00000100,0x00080000,0x00080100,
02366 0x01000000,0x01000100,0x01080000,0x01080100,
02367 0x00000010,0x00000110,0x00080010,0x00080110,
02368 0x01000010,0x01000110,0x01080010,0x01080110,
02369 0x00200000,0x00200100,0x00280000,0x00280100,
02370 0x01200000,0x01200100,0x01280000,0x01280100,
02371 0x00200010,0x00200110,0x00280010,0x00280110,
02372 0x01200010,0x01200110,0x01280010,0x01280110,
02373 0x00000200,0x00000300,0x00080200,0x00080300,
02374 0x01000200,0x01000300,0x01080200,0x01080300,
02375 0x00000210,0x00000310,0x00080210,0x00080310,
02376 0x01000210,0x01000310,0x01080210,0x01080310,
02377 0x00200200,0x00200300,0x00280200,0x00280300,
02378 0x01200200,0x01200300,0x01280200,0x01280300,
02379 0x00200210,0x00200310,0x00280210,0x00280310,
02380 0x01200210,0x01200310,0x01280210,0x01280310,
02381 /* for D bits (numbered as per FIPS 46) 22 23 24 25 27 28 */
02382 0x00000000,0x04000000,0x00040000,0x04040000,
02383 0x00000002,0x04000002,0x00040002,0x04040002,
02384 0x00002000,0x04002000,0x00042000,0x04042000,
02385 0x00002002,0x04002002,0x00042002,0x04042002,
02386 0x00000020,0x04000020,0x00040020,0x04040020,
02387 0x00000022,0x04000022,0x00040022,0x04040022,
02388 0x00002020,0x04002020,0x00042020,0x04042020,
02389 0x00002022,0x04002022,0x00042022,0x04042022,
02390 0x00000800,0x04000800,0x00040800,0x04040800,
02391 0x00000802,0x04000802,0x00040802,0x04040802,
02392 0x00002800,0x04002800,0x00042800,0x04042800,
02393 0x00002802,0x04002802,0x00042802,0x04042802,
02394 0x00000820,0x04000820,0x00040820,0x04040820,
02395 0x00000822,0x04000822,0x00040822,0x04040822,
02396 0x00002820,0x04002820,0x00042820,0x04042820,
02397 0x00002822,0x04002822,0x00042822,0x04042822,
02398 };
02399 
02400 /* See ecb_encrypt.c for a pseudo description of these macros. */
02401 #define PERM_OP(a,b,t,n,m) ((t)=((((a)>>(n))^(b))&(m)),\
02402         (b)^=(t),\
02403         (a)^=((t)<<(n)))
02404 
02405 #define HPERM_OP(a,t,n,m) ((t)=((((a)<<(16-(n)))^(a))&(m)),\
02406         (a)=(a)^(t)^(t>>(16-(n))))\
02407 
02408 static char shifts2[16]={0,0,1,1,1,1,1,1,0,1,1,1,1,1,1,0};
02409 
02410 static int body(
02411         unsigned long *out0,
02412         unsigned long *out1,
02413         des_key_schedule ks,
02414         unsigned long Eswap0,
02415         unsigned long Eswap1);
02416 
02417 static int
02418 des_set_key(des_cblock *key, des_key_schedule schedule)
02419         {
02420         register unsigned long c,d,t,s;
02421         register unsigned char *in;
02422         register unsigned long *k;
02423         register int i;
02424 
02425         k=(unsigned long *)schedule;
02426         in=(unsigned char *)key;
02427 
02428         c2l(in,c);
02429         c2l(in,d);
02430 
02431         /* I now do it in 47 simple operations :-)
02432          * Thanks to John Fletcher (john_fletcher@lccmail.ocf.llnl.gov)
02433          * for the inspiration. :-) */
02434         PERM_OP (d,c,t,4,0x0f0f0f0f);
02435         HPERM_OP(c,t,-2,0xcccc0000);
02436         HPERM_OP(d,t,-2,0xcccc0000);
02437         PERM_OP (d,c,t,1,0x55555555);
02438         PERM_OP (c,d,t,8,0x00ff00ff);
02439         PERM_OP (d,c,t,1,0x55555555);
02440         d=      (((d&0x000000ff)<<16)| (d&0x0000ff00)     |
02441                  ((d&0x00ff0000)>>16)|((c&0xf0000000)>>4));
02442         c&=0x0fffffff;
02443 
02444         for (i=0; i<ITERATIONS; i++)
02445                 {
02446                 if (shifts2[i])
02447                         { c=((c>>2)|(c<<26)); d=((d>>2)|(d<<26)); }
02448                 else
02449                         { c=((c>>1)|(c<<27)); d=((d>>1)|(d<<27)); }
02450                 c&=0x0fffffff;
02451                 d&=0x0fffffff;
02452                 /* could be a few less shifts but I am to lazy at this
02453                  * point in time to investigate */
02454                 s=      skb[0][ (c    )&0x3f                ]|
02455                         skb[1][((c>> 6)&0x03)|((c>> 7)&0x3c)]|
02456                         skb[2][((c>>13)&0x0f)|((c>>14)&0x30)]|
02457                         skb[3][((c>>20)&0x01)|((c>>21)&0x06) |
02458                                               ((c>>22)&0x38)];
02459                 t=      skb[4][ (d    )&0x3f                ]|
02460                         skb[5][((d>> 7)&0x03)|((d>> 8)&0x3c)]|
02461                         skb[6][ (d>>15)&0x3f                ]|
02462                         skb[7][((d>>21)&0x0f)|((d>>22)&0x30)];
02463 
02464                 /* table contained 0213 4657 */
02465                 *(k++)=((t<<16)|(s&0x0000ffff))&0xffffffff;
02466                 s=     ((s>>16)|(t&0xffff0000));
02467                 
02468                 s=(s<<4)|(s>>28);
02469                 *(k++)=s&0xffffffff;
02470                 }
02471         return(0);
02472         }
02473 
02474 /******************************************************************
02475  * modified stuff for crypt.
02476  ******************************************************************/
02477 
02478 /* The changes to this macro may help or hinder, depending on the
02479  * compiler and the achitecture.  gcc2 always seems to do well :-). 
02480  * Inspired by Dana How <how@isl.stanford.edu>
02481  * DO NOT use the alternative version on machines with 8 byte longs.
02482  */
02483 #ifdef ALT_ECB
02484 #define D_ENCRYPT(L,R,S) \
02485         v=(R^(R>>16)); \
02486         u=(v&E0); \
02487         v=(v&E1); \
02488         u=((u^(u<<16))^R^s[S  ])<<2; \
02489         t=(v^(v<<16))^R^s[S+1]; \
02490         t=(t>>2)|(t<<30); \
02491         L^= \
02492         *(unsigned long *)(des_SP+0x0100+((t    )&0xfc))+ \
02493         *(unsigned long *)(des_SP+0x0300+((t>> 8)&0xfc))+ \
02494         *(unsigned long *)(des_SP+0x0500+((t>>16)&0xfc))+ \
02495         *(unsigned long *)(des_SP+0x0700+((t>>24)&0xfc))+ \
02496         *(unsigned long *)(des_SP+       ((u    )&0xfc))+ \
02497         *(unsigned long *)(des_SP+0x0200+((u>> 8)&0xfc))+ \
02498         *(unsigned long *)(des_SP+0x0400+((u>>16)&0xfc))+ \
02499         *(unsigned long *)(des_SP+0x0600+((u>>24)&0xfc));
02500 #else /* original version */
02501 #define D_ENCRYPT(L,R,S)        \
02502         v=(R^(R>>16)); \
02503         u=(v&E0); \
02504         v=(v&E1); \
02505         u=(u^(u<<16))^R^s[S  ]; \
02506         t=(v^(v<<16))^R^s[S+1]; \
02507         t=(t>>4)|(t<<28); \
02508         L^=     SPtrans[1][(t    )&0x3f]| \
02509                 SPtrans[3][(t>> 8)&0x3f]| \
02510                 SPtrans[5][(t>>16)&0x3f]| \
02511                 SPtrans[7][(t>>24)&0x3f]| \
02512                 SPtrans[0][(u    )&0x3f]| \
02513                 SPtrans[2][(u>> 8)&0x3f]| \
02514                 SPtrans[4][(u>>16)&0x3f]| \
02515                 SPtrans[6][(u>>24)&0x3f];
02516 #endif
02517 
02518 unsigned char con_salt[128]={
02519 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
02520 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
02521 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
02522 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
02523 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
02524 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,
02525 0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
02526 0x0A,0x0B,0x05,0x06,0x07,0x08,0x09,0x0A,
02527 0x0B,0x0C,0x0D,0x0E,0x0F,0x10,0x11,0x12,
02528 0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,
02529 0x1B,0x1C,0x1D,0x1E,0x1F,0x20,0x21,0x22,
02530 0x23,0x24,0x25,0x20,0x21,0x22,0x23,0x24,
02531 0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,
02532 0x2D,0x2E,0x2F,0x30,0x31,0x32,0x33,0x34,
02533 0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,0x3C,
02534 0x3D,0x3E,0x3F,0x00,0x00,0x00,0x00,0x00,
02535 };
02536 
02537 unsigned char cov_2char[64]={
02538 0x2E,0x2F,0x30,0x31,0x32,0x33,0x34,0x35,
02539 0x36,0x37,0x38,0x39,0x41,0x42,0x43,0x44,
02540 0x45,0x46,0x47,0x48,0x49,0x4A,0x4B,0x4C,
02541 0x4D,0x4E,0x4F,0x50,0x51,0x52,0x53,0x54,
02542 0x55,0x56,0x57,0x58,0x59,0x5A,0x61,0x62,
02543 0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A,
02544 0x6B,0x6C,0x6D,0x6E,0x6F,0x70,0x71,0x72,
02545 0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A
02546 };
02547 
02548 /*POD
02549 =H file_fcrypt
02550 @c Calculate encrypted password
02551 
02552 This function implements the password encryption algorithm
02553 using the DES function. The first argument is the clear text
02554 password, the second argument is the two character salt value.
02555 This need not be zero terminated. The third argument should
02556 point to a 13 characters char array to get the encoded
02557 password. T<buff[13]> will contain the terminating zchar upon return.
02558 
02559 /*FUNCTION*/
02560 char *file_fcrypt(char *buf, char *salt, char *buff
02561   ){
02562 /*noverbatim
02563 CUT*/
02564         unsigned int i,j,x,y;
02565         unsigned long Eswap0=0,Eswap1=0;
02566         unsigned long out[2],ll;
02567         des_cblock key;
02568         des_key_schedule ks;
02569         unsigned char bb[9];
02570         unsigned char *b=bb;
02571         unsigned char c,u;
02572 
02573         /* eay 25/08/92
02574          * If you call crypt("pwd","*") as often happens when you
02575          * have * as the pwd field in /etc/passwd, the function
02576          * returns *\0XXXXXXXXX
02577          * The \0 makes the string look like * so the pwd "*" would
02578          * crypt to "*".  This was found when replacing the crypt in
02579          * our shared libraries.  People found that the disbled
02580          * accounts effectively had no passwd :-(. */
02581         x=buff[0]=((salt[0] == '\0')?'A':salt[0]);
02582         Eswap0=con_salt[x];
02583         x=buff[1]=((salt[1] == '\0')?'A':salt[1]);
02584         Eswap1=con_salt[x]<<4;
02585 
02586         for (i=0; i<8; i++)
02587                 {
02588                 c= *(buf++);
02589                 if (!c) break;
02590                 key[i]=(c<<1);
02591                 }
02592         for (; i<8; i++)
02593                 key[i]=0;
02594 
02595         des_set_key((des_cblock *)(key),ks);
02596         body(&out[0],&out[1],ks,Eswap0,Eswap1);
02597 
02598         ll=out[0]; l2c(ll,b);
02599         ll=out[1]; l2c(ll,b);
02600         y=0;
02601         u=0x80;
02602         bb[8]=0;
02603         for (i=2; i<13; i++)
02604                 {
02605                 c=0;
02606                 for (j=0; j<6; j++)
02607                         {
02608                         c<<=1;
02609                         if (bb[y] & u) c|=1;
02610                         u>>=1;
02611                         if (!u)
02612                                 {
02613                                 y++;
02614                                 u=0x80;
02615                                 }
02616                         }
02617                 buff[i]=cov_2char[c];
02618                 }
02619         buff[13]='\0';
02620         return buff;
02621         }
02622 
02623 static int 
02624 body(   unsigned long *out0,
02625         unsigned long *out1,
02626         des_key_schedule ks,
02627         unsigned long Eswap0,
02628         unsigned long Eswap1)
02629         {
02630         register unsigned long l,r,t,u,v;
02631 #ifdef ALT_ECB
02632         register unsigned char *des_SP=(unsigned char *)SPtrans;
02633 #endif
02634         register unsigned long *s;
02635         register int i,j;
02636         register unsigned long E0,E1;
02637 
02638         l=0;
02639         r=0;
02640 
02641         s=(unsigned long *)ks;
02642         E0=Eswap0;
02643         E1=Eswap1;
02644 
02645         for (j=0; j<25; j++)
02646                 {
02647                 for (i=0; i<(ITERATIONS*2); i+=4)
02648                         {
02649                         D_ENCRYPT(l,r,  i);     /*  1 */
02650                         D_ENCRYPT(r,l,  i+2);   /*  2 */
02651                         }
02652                 t=l;
02653                 l=r;
02654                 r=t;
02655                 }
02656         t=r;
02657         r=(l>>1)|(l<<31);
02658         l=(t>>1)|(t<<31);
02659         /* clear the top bits on machines with 8byte longs */
02660         l&=0xffffffff;
02661         r&=0xffffffff;
02662 
02663         PERM_OP(r,l,t, 1,0x55555555);
02664         PERM_OP(l,r,t, 8,0x00ff00ff);
02665         PERM_OP(r,l,t, 2,0x33333333);
02666         PERM_OP(l,r,t,16,0x0000ffff);
02667         PERM_OP(r,l,t, 4,0x0f0f0f0f);
02668 
02669         *out0=l;
02670         *out1=r;
02671         return(0);
02672         }
02673 
02674 /*POD
02675 =H file_CreateProcess
02676 @c Run a new program
02677 
02678 This function creates a new process using the argument as command line.
02679 The function does NOT wait the new process to be finished but returns
02680 the pid of the new process.
02681 
02682 If the new process can not be started the return value is zero.
02683 
02684 The success of the new process however can not be determined by the
02685 return value. On UNIX this value is generated by the fork system call
02686 and it still may fail to replace the executeable image calling T<exevp>.
02687 By that time the new program creation is already in the newprocess and
02688 is not able to send back any error information to the caller.
02689 
02690 The caller of this function should also check other outputs of the
02691 created process that of the pid is returned. For example if the
02692 T<execv> call failed the process exit code is T<1>. This is usually an
02693 error information of a process.
02694 
02695 /*FUNCTION*/
02696 long file_CreateProcess(char *pszCommandLine
02697   ){
02698 /*noverbatim
02699 CUT*/
02700 #ifdef WIN32
02701   STARTUPINFO SupInfo;
02702   PROCESS_INFORMATION ProcInfo;
02703 
02704   SupInfo.cb = sizeof(SupInfo);
02705   SupInfo.lpReserved = NULL;
02706   SupInfo.lpDesktop = NULL;
02707   SupInfo.lpTitle = NULL;
02708   SupInfo.dwFlags = 0;
02709   SupInfo.cbReserved2 = 0;
02710   SupInfo.lpReserved2 = NULL;
02711 
02712   if( ! CreateProcess(NULL,           /* application name */
02713                       pszCommandLine, /* command line */
02714                       NULL,           /* process security attributes */
02715                       NULL,           /* thread security attributes */
02716                       0,              /* no handle inheritance */
02717                       NORMAL_PRIORITY_CLASS,
02718                       NULL,           /* environment is same as of caller */
02719                       NULL,           /* curdir is same as caller */
02720                       &SupInfo,
02721                       &ProcInfo ) )return 0;
02722   CloseHandle(ProcInfo.hProcess);
02723   return ProcInfo.dwProcessId;
02724 #elif defined(__MACOS__)
02725   /* Macintosh doesn't support starting a program with command line parameters */
02726   return 0;
02727 #else
02728   char *pszMyCommandLine;
02729   char **argv;
02730   long i,argc;
02731   int ThePreviousCharacterWasSpace;
02732 
02733   if( i=fork() )return i;
02734 
02735   /* calculate the size of the result array with quoting */
02736   argc = 1;
02737   for( i = 0 ; pszCommandLine[i] ; i++ ){
02738      if( pszCommandLine[i] == '"' ){
02739        i ++;
02740        while( ( pszCommandLine[i] ) && ( pszCommandLine[i] != '"' ) ) i++;
02741        if( pszCommandLine[i] == '"' ) i++;
02742        }
02743      if( pszCommandLine[i] == ' ' ) {
02744        argc++;
02745        i++;
02746        while( ( pszCommandLine[i] ) && ( pszCommandLine[i] == ' ' ) ) i++;
02747        }
02748     }
02749 
02750   pszMyCommandLine = (char *)malloc(i+1);
02751   if( pszMyCommandLine == NULL )return 0;
02752   memcpy(pszMyCommandLine,pszCommandLine,i+1);
02753   argv = (char **)malloc((argc+1)*sizeof(char *));
02754   if( argv == NULL ){
02755     free(pszMyCommandLine);
02756     return 0;
02757     }
02758 
02759 /* generate result array with quoting */
02760   ThePreviousCharacterWasSpace = 1;
02761   argc = 0;
02762   for( i = 0 ; pszMyCommandLine[i] ; i++ ){
02763      if( pszMyCommandLine[i] == '"' ) {
02764        i++;
02765        if( ThePreviousCharacterWasSpace ){
02766          ThePreviousCharacterWasSpace = 0;
02767          argv[argc++] = pszMyCommandLine+i;
02768          }
02769        while( ( pszMyCommandLine[i] ) && ( pszMyCommandLine[i] != '"' ) ) i++;
02770        if( pszMyCommandLine[i] == '"' ) pszMyCommandLine[i] = (char)0;
02771      }
02772      if( ThePreviousCharacterWasSpace ){
02773        ThePreviousCharacterWasSpace = 0;
02774        argv[argc++] = pszMyCommandLine+i;
02775        }
02776      if( pszMyCommandLine[i] == ' ' ){
02777        ThePreviousCharacterWasSpace = 1;
02778        pszMyCommandLine[i] = (char)0;
02779        }
02780      }
02781   argv[argc] = NULL;
02782 
02783   execvp(argv[0],argv); /* If this returns, we should exit the forked process. */
02784   exit(1);
02785 #endif
02786   }
02787 
02788 /*
02789 TO_HEADER:
02790 #define FILESYSE_SUCCESS    0
02791 #define FILESYSE_NOTSTARTED 1
02792 #define FILESYSE_TIMEOUT    2
02793 #define FILESYSE_NOCODE     3
02794 */
02795 
02796 /*POD
02797 =H file_CreateProcessEx
02798 @c Run a new program and wait for it
02799 
02800 This function starts a new process and starts to wait for the process.
02801 The caller can specify a timeout period in seconds until the function
02802 waits.
02803 
02804 When the process terminates or the timeout period is over the function returns.
02805 /*FUNCTION*/
02806 int file_CreateProcessEx(char *pszCommandLine,
02807                           long lTimeOut,
02808                           unsigned long *plPid,
02809                           unsigned long *plExitCode
02810   ){
02811 /*noverbatim
02812 Arguments:
02813 =itemize
02814 =item T<pszCommandLine> the command to execute
02815 =item T<lTimeOut> the maximum number of seconds to wait for the process to finish. If this is zero the
02816 function will not wait for the process. If the value is T<-1> the function wait without limit until the created
02817 process finishes.
02818 =item T<plPid> pointer to variable where the PID of the new process is placed.
02819 This parameter can be T<NULL>. If the function returns after the new process has terminated this
02820 value is more or less useless. However this parameter can be used to kill processes that reach the
02821 timeout period and do not terminate.
02822 =item T<plExitCode> pointer to a variable where the exit code of the new process is placed. If the
02823 process is still running when the function returns this parameter is unaltered.
02824 =noitemize
02825 
02826 The return value indicates the success of the execution of the new process:
02827 
02828 =itemize
02829 =item T<FILESYSE_SUCCESS> The process was started and terminated within the specified timeout period.
02830 =item T<FILESYSE_NOTSTARTED> The function could not start the new process. (not used under UNIX)
02831 =item T<FILESYSE_TIMEOUT> The process was started but did not finish during the timeout period.
02832 =item T<FILESYSE_NOCODE> The process was started and finished within the timeout period but
02833 it was not possible to retrieve the exit code.
02834 =noitemize
02835 
02836 Note that the behaviour of this function is slightly different on Windows NT and on UNIX. On Windows NT
02837 the function will return T<FILESYSE_NOTSTARTED> when the new process can not be started. Under UNIX
02838 the process performs a T<fork()> and then an T<execv>. The T<fork()> does not return an error value. When the
02839 T<execvp> fails it is already in the new process and can not return an error code. It exists using the
02840 exit code 1. This may not be distinguished from the program started and returning an exit code 1.
02841 
02842 CUT*/
02843 #ifdef WIN32
02844   STARTUPINFO SupInfo;
02845   PROCESS_INFORMATION ProcInfo;
02846   int iError;
02847   unsigned long ulExitCode;
02848 
02849   SupInfo.cb = sizeof(SupInfo);
02850   SupInfo.lpReserved = NULL;
02851   SupInfo.lpDesktop = NULL;
02852   SupInfo.lpTitle = NULL;
02853   SupInfo.dwFlags = 0;
02854   SupInfo.cbReserved2 = 0;
02855   SupInfo.lpReserved2 = NULL;
02856 
02857   if( ! CreateProcess(NULL,           /* application name */
02858                       pszCommandLine, /* command line */
02859                       NULL,           /* process security attributes */
02860                       NULL,           /* thread security attributes */
02861                       0,              /* no handle inheritance */
02862                       NORMAL_PRIORITY_CLASS,
02863                       NULL,           /* environment is same as of caller */
02864                       NULL,           /* curdir is same as caller */
02865                       &SupInfo,
02866                       &ProcInfo ) )return FILESYSE_NOTSTARTED;
02867 
02868   if( plPid )*plPid = ProcInfo.dwProcessId;
02869   if( WaitForSingleObject(ProcInfo.hProcess, lTimeOut == -1 ? INFINITE : lTimeOut*1000) == WAIT_TIMEOUT ){
02870     CloseHandle(ProcInfo.hProcess);
02871     return FILESYSE_TIMEOUT;
02872     }
02873   iError = ! GetExitCodeProcess(ProcInfo.hProcess,&ulExitCode);
02874   if( plExitCode )*plExitCode = ulExitCode;
02875   CloseHandle(ProcInfo.hProcess);
02876   return iError ? FILESYSE_NOCODE : FILESYSE_SUCCESS;
02877 #elif defined(__MACOS__)
02878   /* Macintosh doesn't support starting a program with command line parameters */
02879   return 0;
02880 #else
02881   char *pszMyCommandLine;
02882   char **argv;
02883   long i,argc;
02884   int ThePreviousCharacterWasSpace;
02885   int status;
02886 
02887   if( i=fork() ){
02888     if( plPid )*plPid = i;
02889     while( lTimeOut-- ){
02890       sleep(1);
02891       waitpid(i,&status,WNOHANG);
02892       if( WIFEXITED(status) ){
02893         *plExitCode = WEXITSTATUS(status);
02894          return FILESYSE_SUCCESS;
02895          }
02896       }
02897     return FILESYSE_TIMEOUT;
02898     }
02899 
02900 /* calculate the size of the result array with quoting */
02901   argc = 1;
02902   for( i = 0 ; pszCommandLine[i] ; i++ ){
02903      if( pszCommandLine[i] == '"' ){
02904        i ++;
02905        while( ( pszCommandLine[i] ) && ( pszCommandLine[i] != '"' ) ) i++;
02906        if( pszCommandLine[i] == '"' ) i++;
02907        }
02908      if( pszCommandLine[i] == ' ' ) {
02909                 argc++;
02910                 i++;
02911                 while( ( pszCommandLine[i] ) && ( pszCommandLine[i] == ' ' ) ) i++;
02912        }
02913     }
02914 
02915   pszMyCommandLine = (char *)malloc(i+1);
02916   if( pszMyCommandLine == NULL )return 0;
02917   memcpy(pszMyCommandLine,pszCommandLine,i+1);
02918   argv = (char **)malloc((argc+1)*sizeof(char *));
02919   if( argv == NULL ){
02920     free(pszMyCommandLine);
02921     return 0;
02922     }
02923 
02924 /* generate result array with quoting */
02925   ThePreviousCharacterWasSpace = 1;
02926   argc = 0;
02927   for( i = 0 ; pszMyCommandLine[i] ; i++ ){
02928      if( pszMyCommandLine[i] == '"' ) {
02929        i++;
02930        if( ThePreviousCharacterWasSpace ){
02931          ThePreviousCharacterWasSpace = 0;
02932          argv[argc++] = pszMyCommandLine+i;
02933        }
02934        while( ( pszMyCommandLine[i] ) && ( pszMyCommandLine[i] != '"' ) ) i++;
02935        if( pszMyCommandLine[i] == '"' ) pszMyCommandLine[i] = (char)0;
02936      }
02937      if( ThePreviousCharacterWasSpace ){
02938        ThePreviousCharacterWasSpace = 0;
02939        argv[argc++] = pszMyCommandLine+i;
02940        }
02941      if( pszMyCommandLine[i] == ' ' ){
02942        ThePreviousCharacterWasSpace = 1;
02943        pszMyCommandLine[i] = (char)0;
02944        }
02945      }
02946   argv[argc] = NULL;
02947 
02948   execvp(argv[0],argv); /* If this returns, we should exit the forked process. */
02949   exit(1);
02950 #endif
02951   }
02952 /*POD
02953 =H file_waitpid
02954 @c Check on a process
02955 
02956 
02957 This function checks if a process identified by the
02958 process ID (PID) is still running.
02959 
02960 If the process is live the return value is zero (FALSE), otherwise
02961 a positive value (TRUE) is returned and the second parameter contains
02962 the exited process's final status.
02963 /*FUNCTION*/
02964 int file_waitpid(long pid,
02965                  unsigned long *plExitCode
02966    ){
02967 /*noverbatim
02968 CUT*/
02969 #ifdef WIN32
02970   HANDLE hProcess;
02971   unsigned long ulExitCode;
02972 
02973   hProcess = OpenProcess(PROCESS_QUERY_INFORMATION,0,(DWORD)pid);
02974   if( hProcess == NULL ){
02975     *plExitCode = 0; /* This is just to have some exit code instead of garbage. */
02976     return 1;
02977     }
02978 
02979   if( ! GetExitCodeProcess(hProcess,&ulExitCode) ){
02980     /* Failed */
02981     CloseHandle(hProcess);
02982     return FILESYSE_NOCODE;
02983   }
02984 
02985   if( plExitCode )*plExitCode = ulExitCode;
02986   CloseHandle(hProcess);
02987 
02988   return (ulExitCode == STILL_ACTIVE) ? 0 : 1;
02989 
02990 #else
02991   int status;
02992 
02993   waitpid(pid,&status,WNOHANG);
02994   if( WIFEXITED(status) ){
02995     *plExitCode = WEXITSTATUS(status);
02996     return 1;
02997     }
02998   return 0;
02999 #endif
03000   }
03001 

Generated on Sun Mar 12 23:56:30 2006 for ScriptBasic by  doxygen 1.4.6-NO