home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 5 / FreshFish_July-August1994.bin / bbs / util / jade-3.0.lha / Jade / src / unix_misc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-04-19  |  14.6 KB  |  585 lines

  1. /* unix_misc.c -- Miscellaneous functions for Unix
  2.    Copyright (C) 1993, 1994 John Harper <jsh@ukc.ac.uk>
  3.  
  4. This file is part of Jade.
  5.  
  6. Jade is free software; you can redistribute it and/or modify it
  7. under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2, or (at your option)
  9. any later version.
  10.  
  11. Jade is distributed in the hope that it will be useful, but
  12. WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with Jade; see the file COPYING.  If not, write to
  18. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20. #include "jade.h"
  21. #include "jade_protos.h"
  22.  
  23. #include <string.h>
  24. #include <errno.h>
  25. #include <sys/stat.h>
  26. #include <time.h>
  27. #include <unistd.h>
  28. #include <fcntl.h>
  29. #include <dirent.h>
  30. #include <pwd.h>
  31. #include <netdb.h>
  32.  
  33. _PR int fileexists(u_char *);
  34. _PR u_long filemodtime(u_char *);
  35. _PR void sys_misc_init(void);
  36.  
  37. _PR bool samefiles(u_char *, u_char *);
  38. _PR u_char * filepart(u_char *);
  39. _PR VALUE geterrstring(void);
  40. _PR void doconmsg(u_char *);
  41. _PR u_char * squirrelfile(u_char *);
  42. _PR VALUE valsquirrelfile(u_char *);
  43. _PR u_long getsystime(void);
  44. _PR int addfilepart(u_char *, const u_char *, int);
  45.  
  46. bool
  47. samefiles(u_char *file1, u_char *file2)
  48. {
  49.     bool rc = FALSE;
  50.     struct stat stat1, stat2;
  51.     if(!stat(file1, &stat1))
  52.     {
  53.     if(!stat(file2, &stat2))
  54.     {
  55.         if((stat1.st_dev == stat2.st_dev) && (stat1.st_ino == stat2.st_ino))
  56.         rc = TRUE;
  57.     }
  58.     }
  59.     else
  60.     rc = !strcmp(file1, file2);
  61.     return(rc);
  62. }
  63.  
  64. u_char *
  65. filepart(u_char *fname)
  66. {
  67.     u_char *tmp = strrchr(fname, '/');
  68.     if(tmp)
  69.     return(tmp + 1);
  70.     return(fname);
  71. }
  72.  
  73. VALUE
  74. geterrstring(void)
  75. {
  76.     return(valstrdup(ERRNO_STRING));
  77. }
  78.  
  79. void
  80. doconmsg(u_char *msg)
  81. {
  82.     fputs(msg, stderr);
  83. }
  84.  
  85. u_char *
  86. squirrelfile(u_char *fileName)
  87. {
  88.     FILE *fh = fopen(fileName, "r");
  89.     if(fh)
  90.     {
  91.     struct stat stat;
  92.     if(!fstat(fileno(fh), &stat))
  93.     {
  94.         u_char *mem = mystralloc(stat.st_size + 1);
  95.         if(mem)
  96.         {
  97.         fread(mem, 1, stat.st_size, fh);
  98.         mem[stat.st_size] = 0;
  99.         fclose(fh);
  100.         return(mem);
  101.         }
  102.         else
  103.         settitle(NoMemMsg);
  104.     }
  105.     fclose(fh);
  106.     }
  107.     return(FALSE);
  108. }
  109. VALUE
  110. valsquirrelfile(u_char *fileName)
  111. {
  112.     FILE *fh = fopen(fileName, "r");
  113.     if(fh)
  114.     {
  115.     struct stat stat;
  116.     if(!fstat(fileno(fh), &stat))
  117.     {
  118.         VALUE mem = valstralloc(stat.st_size + 1);
  119.         if(mem)
  120.         {
  121.         fread(VSTR(mem), 1, stat.st_size, fh);
  122.         VSTR(mem)[stat.st_size] = 0;
  123.         fclose(fh);
  124.         return(mem);
  125.         }
  126.         else
  127.         settitle(NoMemMsg);
  128.     }
  129.     fclose(fh);
  130.     }
  131.     return(cmd_signal(sym_file_error, list_2(geterrstring(), valstrdup(fileName))));
  132. }
  133.  
  134. u_long
  135. getsystime(void)
  136. {
  137.     return(time(NULL));
  138. }
  139.  
  140. int
  141. addfilepart(u_char *buf, const u_char *part, int bufLen)
  142. {
  143.     int bufend = strlen(buf);
  144.     int partlen = strlen(part);
  145.     if((bufend > 0) && (buf[bufend-1] != '/'))
  146.     {
  147.     if(++bufend >= bufLen)
  148.         return(FALSE);
  149.     buf[bufend-1] = '/';
  150.     buf[bufend] = 0;
  151.     }
  152.     if((bufend + partlen) >= bufLen)
  153.     return(FALSE);
  154.     strcpy(buf + bufend, part);
  155.     return(TRUE);
  156. }
  157.  
  158. _PR VALUE cmd_delete_file(VALUE file);
  159. DEFUN("delete-file", cmd_delete_file, subr_delete_file, (VALUE file), V_Subr1, DOC_delete_file) /*
  160. ::doc:delete_file::
  161. (delete-file FILE-NAME)
  162. Attempts to delete the file called FILE-NAME.
  163. ::end:: */
  164. {
  165.     DECLARE1(file, STRINGP);
  166.     if(!unlink(VSTR(file)))
  167.     return(sym_t);
  168.     return(signalfileerror(file));
  169. }
  170.  
  171. _PR VALUE cmd_rename_file(VALUE src, VALUE dst);
  172. DEFUN("rename-file", cmd_rename_file, subr_rename_file, (VALUE src, VALUE dst), V_Subr2, DOC_rename_file) /*
  173. ::doc:rename_file::
  174. (rename-file SRC DEST)
  175. Tries to rename the file SRC as DEST, this doesn't work across filesystems, or
  176. if a file DEST already exists.
  177. ::end:: */
  178. {
  179.     DECLARE1(src, STRINGP);
  180.     DECLARE2(dst, STRINGP);
  181.     if(!rename(VSTR(src), VSTR(dst)))
  182.     return(sym_t);
  183.     return(signalfileerror(list_2(src, dst)));
  184. }
  185.  
  186. _PR VALUE cmd_copy_file(VALUE src, VALUE dst);
  187. DEFUN("copy-file", cmd_copy_file, subr_copy_file, (VALUE src, VALUE dst), V_Subr2, DOC_copy_file) /*
  188. ::doc:copy_file::
  189. (copy-file SRC DEST)
  190. Copies the file called SRC to the file DEST.
  191. ::end:: */
  192. {
  193.     VALUE res = sym_t;
  194.     int srcf;
  195.     DECLARE1(src, STRINGP);
  196.     DECLARE2(dst, STRINGP);
  197.     srcf = open(VSTR(src), O_RDONLY);
  198.     if(srcf != -1)
  199.     {
  200.     int dstf = open(VSTR(dst), O_WRONLY | O_CREAT, 0666);
  201.     if(dstf != -1)
  202.     {
  203.         struct stat statb;
  204.         int rd;
  205.         if(fstat(srcf, &statb) == 0)
  206.         chmod(VSTR(dst), statb.st_mode);
  207.         do {
  208.         u_char buf[BUFSIZ];
  209.         int wr;
  210.         rd = read(srcf, buf, BUFSIZ);
  211.         if(rd < 0)
  212.         {
  213.             res = signalfileerror(src);
  214.             break;
  215.         }
  216.         wr = write(dstf, buf, rd);
  217.         if(wr != rd)
  218.         {
  219.             res = signalfileerror(dst);
  220.             break;
  221.         }
  222.         } while(rd != 0);
  223.         close(dstf);
  224.     }
  225.     else
  226.         res = signalfileerror(dst);
  227.     close(srcf);
  228.     }
  229.     else
  230.     res = signalfileerror(src);
  231.     return(res);
  232. }
  233.  
  234. _PR VALUE cmd_file_readable_p(VALUE file);
  235. DEFUN("file-readable-p", cmd_file_readable_p, subr_file_readable_p, (VALUE file), V_Subr1, DOC_file_readable_p) /*
  236. ::doc:file_readable_p::
  237. (file-readable-p FILE)
  238. Returns t if FILE available for reading from.
  239. ::end:: */
  240. {
  241.     DECLARE1(file, STRINGP);
  242.     if(!access(VSTR(file), R_OK))
  243.     return(sym_t);
  244.     return(sym_nil);
  245. }
  246.  
  247. _PR VALUE cmd_file_writeable_p(VALUE file);
  248. DEFUN("file-writeable-p", cmd_file_writeable_p, subr_file_writeable_p, (VALUE file), V_Subr1, DOC_file_writeable_p) /*
  249. ::doc:file_writeable_p::
  250. (file-writeable-p FILE)
  251. Returns t if FILE available for writing to.
  252. ::end:: */
  253. {
  254.     DECLARE1(file, STRINGP);
  255.     if(!access(VSTR(file), W_OK))
  256.     return(sym_t);
  257.     return(sym_nil);
  258. }
  259.  
  260. _PR VALUE cmd_file_exists_p(VALUE file);
  261. DEFUN("file-exists-p", cmd_file_exists_p, subr_file_exists_p, (VALUE file), V_Subr1, DOC_file_exists_p) /*
  262. ::doc:file_exists_p::
  263. (file-exists-p FILE)
  264. Returns t if FILE exists.
  265. ::end:: */
  266. {
  267.     DECLARE1(file, STRINGP);
  268.     if(!access(VSTR(file), F_OK))
  269.     return(sym_t);
  270.     return(sym_nil);
  271. }
  272. int
  273. fileexists(u_char *fileName)
  274. {
  275.     if(!access(fileName, F_OK))
  276.     {
  277.     struct stat statb;
  278.     if(!stat(fileName, &statb) && !S_ISDIR(statb.st_mode))
  279.         return(TRUE);
  280.     }
  281.     return(FALSE);
  282. }
  283.  
  284. _PR VALUE cmd_file_regular_p(VALUE file);
  285. DEFUN("file-regular-p", cmd_file_regular_p, subr_file_regular_p, (VALUE file), V_Subr1, DOC_file_regular_p) /*
  286. ::doc:file_regular_p::
  287. (file-regular-p FILE)
  288. Returns t if FILE is a ``normal'' file, ie, not a directory, device, symbolic
  289. link, etc...
  290. ::end:: */
  291. {
  292.     struct stat statb;
  293.     DECLARE1(file, STRINGP);
  294.     if(!stat(VSTR(file), &statb))
  295.     {
  296.     if(S_ISREG(statb.st_mode))
  297.         return(sym_t);
  298.     }
  299.     return(sym_nil);
  300. }
  301.  
  302. _PR VALUE cmd_file_directory_p(VALUE file);
  303. DEFUN("file-directory-p", cmd_file_directory_p, subr_file_directory_p, (VALUE file), V_Subr1, DOC_file_directory_p) /*
  304. ::doc:file_directory_p::
  305. (file-directory-p FILE)
  306. Returns t if FILE is a directory.
  307. ::end:: */
  308. {
  309.     struct stat statb;
  310.     DECLARE1(file, STRINGP);
  311.     if(!stat(VSTR(file), &statb))
  312.     {
  313.     if(S_ISDIR(statb.st_mode))
  314.         return(sym_t);
  315.     }
  316.     return(sym_nil);
  317. }
  318.  
  319. _PR VALUE cmd_file_symlink_p(VALUE file);
  320. DEFUN("file-symlink-p", cmd_file_symlink_p, subr_file_symlink_p, (VALUE file), V_Subr1, DOC_file_symlink_p) /*
  321. ::doc:file_symlink_p::
  322. (file-symlink-p FILE)
  323. Returns t if FILE is a symbolic link to another file.
  324. ::end:: */
  325. {
  326.     struct stat statb;
  327.     DECLARE1(file, STRINGP);
  328.     if(!stat(VSTR(file), &statb))
  329.     {
  330.     if(S_ISLNK(statb.st_mode))
  331.         return(sym_t);
  332.     }
  333.     return(sym_nil);
  334. }
  335.  
  336. _PR VALUE cmd_file_owner_p(VALUE file);
  337. DEFUN("file-owner-p", cmd_file_owner_p, subr_file_owner_p, (VALUE file), V_Subr1, DOC_file_owner_p) /*
  338. ::doc:file_owner_p::
  339. (file-owner-p FILE)
  340. Returns t if the ownership (uid & gid) of file FILE (a string) is the same
  341. as that of any files written by the editor.
  342. ::end:: */
  343. {
  344.     struct stat statb;
  345.     DECLARE1(file, STRINGP);
  346.     if(!stat(VSTR(file), &statb))
  347.     {
  348.     if((statb.st_uid == geteuid()) && (statb.st_gid == getegid()))
  349.         return(sym_t);
  350.     }
  351.     return(sym_nil);
  352. }
  353.  
  354. _PR VALUE cmd_file_nlinks(VALUE file);
  355. DEFUN("file-nlinks", cmd_file_nlinks, subr_file_nlinks, (VALUE file), V_Subr1, DOC_file_nlinks) /*
  356. ::doc:file_nlinks::
  357. (file-nlinks FILE)
  358. Returns the number of links pointing to the file called FILE. This will be
  359. one if FILE has only one name. Doesn't count symbolic links.
  360. ::end:: */
  361. {
  362.     struct stat statb;
  363.     DECLARE1(file, STRINGP);
  364.     if(!stat(VSTR(file), &statb))
  365.     return(newnumber(statb.st_nlink));
  366.     return(sym_nil);
  367. }
  368.  
  369. _PR VALUE cmd_file_modes(VALUE file);
  370. DEFUN("file-modes", cmd_file_modes, subr_file_modes, (VALUE file), V_Subr1, DOC_file_modes) /*
  371. ::doc:file_modes::
  372. (file-modes FILE)
  373. Return the access permissions of the file called FILE, an integer. Note that
  374. the format of this integer is not defined, it differs from system to system.
  375. ::end:: */
  376. {
  377.     struct stat statb;
  378.     DECLARE1(file, STRINGP);
  379.     if(!stat(VSTR(file), &statb))
  380.     return(newnumber(statb.st_mode));
  381.     return(sym_nil);
  382. }
  383.  
  384. _PR VALUE cmd_set_file_modes(VALUE file, VALUE modes);
  385. DEFUN("set-file-modes", cmd_set_file_modes, subr_set_file_modes, (VALUE file, VALUE modes), V_Subr2, DOC_set_file_modes) /*
  386. ::doc:set_file_modes::
  387. (set-file-modes FILE MODES)
  388. Sets the access permissions of FILE to MODES, an integer. The only real way
  389. you can get this integer is from `file-modes' since it changes from system
  390. to system.
  391. ::end:: */
  392. {
  393.     DECLARE1(file, STRINGP);
  394.     DECLARE2(modes, NUMBERP);
  395.     if(chmod(VSTR(file), VNUM(modes)) == 0)
  396.     return(modes);
  397.     return(signalfileerror(file));
  398. }
  399.  
  400. u_long
  401. filemodtime(u_char *file)
  402. {
  403.     struct stat statb;
  404.     if(!stat(file, &statb))
  405.     return(statb.st_mtime);
  406.     return(0);
  407. }
  408. _PR VALUE cmd_file_modtime(VALUE file);
  409. DEFUN("file-modtime", cmd_file_modtime, subr_file_modtime, (VALUE file), V_Subr1, DOC_file_modtime) /*
  410. ::doc:file_modtime::
  411. (file-modtime FILE)
  412. Return the time (an integer) that FILE was last modified.
  413. ::end:: */
  414. {
  415.     DECLARE1(file, STRINGP);
  416.     return(newnumber(filemodtime(VSTR(file))));
  417. }
  418.  
  419. _PR VALUE cmd_directory_files(VALUE dirname);
  420. DEFUN("directory-files", cmd_directory_files, subr_directory_files, (VALUE dirname), V_Subr1, DOC_directory_files) /*
  421. ::doc:directory_files::
  422. (directory-files DIRECTORY)
  423. Returns a list of the names of all files in directory DIRECTORY, directories
  424. in DIRECTORY have a `/' character appended to their name.
  425. ::end:: */
  426. {
  427.     DIR *dir;
  428.     u_char *dname;
  429.     DECLARE1(dirname, STRINGP);
  430.     dname = VSTR(dirname);
  431.     if(*dname == 0)
  432.     dname = ".";
  433.     dir = opendir(dname);
  434.     if(dir)
  435.     {
  436.     VALUE list = sym_nil;
  437.     struct dirent *de;
  438.     while((de = readdir(dir)))
  439.     {
  440.         VALUE name;
  441.         if(!((name = valstrdup(de->d_name)) && (list = cmd_cons(name, list))))
  442.         {
  443.         settitle(NoMemMsg);
  444.         closedir(dir);
  445.         return(NULL);
  446.         }
  447.     }
  448.     closedir(dir);
  449.     return(list);
  450.     }
  451.     return(cmd_signal(sym_file_error, list_2(geterrstring(), dname)));
  452. }
  453.  
  454. _PR VALUE cmd_user_login_name(void);
  455. DEFUN("user-login-name", cmd_user_login_name, subr_user_login_name, (void), V_Subr0, DOC_user_login_name) /*
  456. ::doc:user_login_name::
  457. (user-login-name)
  458. Returns the login name of the user (a string).
  459. On the Amiga this is taken from the environment variable `USERNAME'.
  460. ::end:: */
  461. {
  462.     /* Just look this up once, then use the saved copy.     */
  463.     static VALUE user_login_name;
  464.     char *tmp;
  465.     if(user_login_name)
  466.     return(user_login_name);
  467.     if(!(tmp = getlogin()))
  468.     {
  469.     struct passwd *pwd;
  470.     if(!(pwd = getpwuid(geteuid())))
  471.         return(NULL);
  472.     tmp = pwd->pw_name;
  473.     }
  474.     user_login_name = valstrdup(tmp);
  475.     markstatic(&user_login_name);
  476.     return(user_login_name);
  477. }
  478.  
  479. _PR VALUE cmd_user_full_name(void);
  480. DEFUN("user-full-name", cmd_user_full_name, subr_user_full_name, (void), V_Subr0, DOC_user_full_name) /*
  481. ::doc:user_full_name::
  482. (user-full-name)
  483. Returns the real name of the user (a string).
  484. On the Amiga this is taken from the environment variable `REALNAME'.
  485. ::end:: */
  486. {
  487.     struct passwd *pwd;
  488.     static VALUE user_full_name;
  489.     if(user_full_name)
  490.     return(user_full_name);
  491.     if(!(pwd = getpwuid(geteuid())))
  492.     return(NULL);
  493. #ifndef FULL_NAME_TERMINATOR
  494.     user_full_name = valstrdup(pwd->pw_gecos);
  495. #else
  496.     {
  497.     char *end;
  498.     if(end = strchr(pwd->pw_gecos, FULL_NAME_TERMINATOR))
  499.         user_full_name = valstrdupn(pwd->pw_gecos, end - pwd->pw_gecos);
  500.     else
  501.         user_full_name = valstrdup(pwd->pw_gecos);
  502.     }
  503. #endif
  504.     markstatic(&user_full_name);
  505.     return(user_full_name);
  506. }
  507.  
  508. _PR VALUE cmd_user_home_directory(void);
  509. DEFUN("user-home-directory", cmd_user_home_directory, subr_user_home_directory, (void), V_Subr0, DOC_user_home_directory) /*
  510. ::doc:user_home_directory::
  511. (user-home-directory)
  512. Returns the user's home directory (a string). It will be terminated by a slash
  513. (or whatever is appropriate) so that it can be glued together with a file name
  514. making a valid path name.
  515. On the Amiga this is taken from the environment variable `HOME'.
  516. ::end:: */
  517. {
  518.     struct passwd *pwd;
  519.     static VALUE user_home_directory;
  520.     int len;
  521.     if(user_home_directory)
  522.     return(user_home_directory);
  523.     if(!(pwd = getpwuid(geteuid())))
  524.     return(NULL);
  525.     len = strlen(pwd->pw_dir);
  526.     if(pwd->pw_dir[len] != '/')
  527.     {
  528.     user_home_directory = valstrdupn(pwd->pw_dir, len + 1);
  529.     VSTR(user_home_directory)[len] = '/';
  530.     VSTR(user_home_directory)[len+1] = 0;
  531.     }
  532.     else
  533.     user_home_directory = valstrdup(pwd->pw_dir);
  534.     markstatic(&user_home_directory);
  535.     return(user_home_directory);
  536. }
  537.  
  538. _PR VALUE cmd_system_name(void);
  539. DEFUN("system-name", cmd_system_name, subr_system_name, (void), V_Subr0,  DOC_system_name) /*
  540. ::doc:system_name::
  541. (system-name)
  542. Returns the name of the host which the editor is running on.
  543. On the Amiga this is taken from the environment variable `HOSTNAME'.
  544. ::end:: */
  545. {
  546.     u_char buf[128];
  547.     struct hostent *h;
  548.     static VALUE system_name;
  549.     if(system_name)
  550.     return(system_name);
  551.     if(gethostname(buf, 128))
  552.     return(NULL);
  553.     h = gethostbyname(buf);
  554.     if(h)
  555.     system_name = valstrdup((u_char *)h->h_name);
  556.     else
  557.     system_name = valstrdup(buf);
  558.     markstatic(&system_name);
  559.     return(system_name);
  560. }
  561.  
  562. void
  563. sys_misc_init(void)
  564. {
  565.     ADD_SUBR(subr_delete_file);
  566.     ADD_SUBR(subr_rename_file);
  567.     ADD_SUBR(subr_copy_file);
  568.     ADD_SUBR(subr_file_readable_p);
  569.     ADD_SUBR(subr_file_writeable_p);
  570.     ADD_SUBR(subr_file_exists_p);
  571.     ADD_SUBR(subr_file_regular_p);
  572.     ADD_SUBR(subr_file_directory_p);
  573.     ADD_SUBR(subr_file_symlink_p);
  574.     ADD_SUBR(subr_file_owner_p);
  575.     ADD_SUBR(subr_file_nlinks);
  576.     ADD_SUBR(subr_file_modes);
  577.     ADD_SUBR(subr_set_file_modes);
  578.     ADD_SUBR(subr_file_modtime);
  579.     ADD_SUBR(subr_directory_files);
  580.     ADD_SUBR(subr_user_login_name);
  581.     ADD_SUBR(subr_user_full_name);
  582.     ADD_SUBR(subr_user_home_directory);
  583.     ADD_SUBR(subr_system_name);
  584. }
  585.