util.c
上传用户:tianjinjs
上传日期:2007-01-05
资源大小:309k
文件大小:6k
源码类别:

Modem编程

开发平台:

Unix_Linux

  1. /*
  2.  * util.c       Little helper routines that didn't fit anywhere else.
  3.  *
  4.  * This file is part of the minicom communications package,
  5.  * Copyright 1991-1995 Miquel van Smoorenburg.
  6.  *
  7.  * This program is free software; you can redistribute it and/or
  8.  * modify it under the terms of the GNU General Public License
  9.  * as published by the Free Software Foundation; either version
  10.  * 2 of the License, or (at your option) any later version.
  11.  *
  12.  * jseymour@jimsun.LinxNet.com (Jim Seymour) 03/26/98 - Added get_port()
  13.  *    function to support multiple port specifications in config.
  14.  */
  15. #include "port.h"
  16. #include "minicom.h"
  17. static int not_suid = -1;
  18. /*
  19.  * A modified version of the getargs routine.
  20.  */
  21. static int getargs(s, arps, maxargs)
  22. register char *s;
  23. char *arps[];
  24. int maxargs;
  25. {
  26. register int i;
  27. register char *sp;
  28. register char qchar;
  29. int literal = 0;
  30. i = 0;
  31. while (i < maxargs) {
  32. while (*s == ' ' || *s == 't')
  33. ++s;
  34. if (*s == 'n' || *s == '')
  35. break;
  36. arps[i++] = sp = s;
  37. qchar = 0;
  38. while(*s != ''  &&  *s != 'n') {
  39. if (literal) {
  40. literal = 0;
  41. *sp++ = *s++;
  42. continue;
  43. }
  44. literal = 0;
  45. if (qchar == 0 && (*s == ' ' || *s == 't')) {
  46. ++s;
  47. break;
  48. }
  49. switch(*s) {
  50. default:
  51. *sp++ = *s++;
  52. break;
  53. case '\':
  54. literal = 1;
  55. s++;
  56. break;
  57. case '"':
  58. case ''':
  59. if(qchar == *s) {
  60. qchar = 0;
  61. ++s;
  62. break;
  63. }
  64. if(qchar)
  65. *sp++ = *s++;
  66. else
  67. qchar = *s++;
  68. break;
  69. }
  70. }
  71. *sp++ = 0;
  72. }
  73. if (i >= maxargs)
  74. return -1;
  75. arps[i] = (char *)0;
  76. return i;
  77. }
  78. /*
  79.  * Is a character from s2 in s1?
  80.  */
  81. static int anys(s1, s2)
  82. char *s1, *s2;
  83. {
  84.   while(*s2)
  85.    if (strchr(s1, *s2++) != (char *)NULL) return(1);
  86.   return(0);
  87. }
  88. /*
  89.  * If there is a shell-metacharacter in "cmd",
  90.  * call a shell to do the dirty work.
  91.  */
  92. int fastexec(cmd)
  93. char *cmd;
  94. {
  95.   char *words[128];
  96.   char *p;
  97.   if (anys(cmd, "~`$&*()=|{};?><"))
  98.    return(execl("/bin/sh", "sh", "-c", cmd, (char *)0));
  99.   /* Delete escape-characters ment for the shell */
  100.   p = cmd;
  101.   while((p = strchr(p, '\')) != (char *)NULL)
  102.    strcpy(p, p + 1);
  103.   /* Split line into words */
  104.   if (getargs(cmd, words, 127) < 0) {
  105.    return(-1);
  106.   }
  107.   return (execvp(words[0], words));
  108. }
  109. /*
  110.  * Fork, then redirect I/O if neccesary.
  111.  * in    : new stdin
  112.  * out   : new stdout
  113.  * err   : new stderr
  114.  * Returns exit status of "cmd" on success, -1 on error.
  115.  */
  116. int fastsystem(cmd, in, out, err)
  117. char *cmd, *in, *out, *err;
  118. {
  119.   int pid;
  120.   int st;
  121.   int async = 0;
  122.   char *p;
  123.   /* If the command line ends with '&', don't wait for child. */
  124.   p = strrchr(cmd, '&');
  125.   if (p != (char *)0 && !p[1]) {
  126.    *p = 0;
  127.    async = 1;
  128.   }
  129.   
  130.   /* Fork. */
  131.   if ((pid = fork()) == 0) { /* child */
  132.    if (in != (char *)NULL) {
  133.    close(0);
  134.    if (open(in, O_RDONLY) < 0) exit(-1);
  135.    }
  136.    if (out != (char *)NULL) {
  137.    close(1);
  138.    if (open(out, O_WRONLY) < 0) exit(-1);
  139.    }
  140.    if (err != (char *)NULL) {
  141.    close(2);
  142.    if (open(err, O_RDWR) < 0) exit(-1);
  143.    }
  144.    exit(fastexec(cmd));
  145.   } else if (pid > 0) { /* parent */
  146.    if (async) return(0);
  147.    pid = m_wait(&st);
  148.    if (pid < 0) return(-1);
  149.    return(st);
  150.   }
  151.   return(-1);
  152. }
  153. /* Drop all priviliges (irreversable). */
  154. void drop_all_privs()
  155. {
  156. #ifdef HAS_REUID
  157.   /* Regain privs needed to drop privs :) */
  158.   setregid(real_gid, eff_gid);
  159.   setreuid(real_uid, eff_uid);
  160. #endif
  161.   /* Drop it. */
  162.   setgid(real_gid);
  163.   setuid(real_uid);
  164.   eff_uid = real_uid;
  165.   eff_gid = real_gid;
  166.   not_suid = 1;
  167. }
  168. /* Drop priviliges (swap uid's) */
  169. void drop_privs()
  170. {
  171. #ifdef HAS_REUID
  172.   setregid(eff_gid, real_gid);
  173.   if (setreuid(eff_uid, real_uid) < 0)
  174. fprintf(stderr, "minicom: cannot setreuid(%d, %d)n", eff_uid, real_uid);
  175.   not_suid = 1;
  176. #endif
  177. }
  178. /* Set priviliges (swap uid's) */
  179. void set_privs()
  180. {
  181. #ifdef HAS_REUID
  182.   setregid(real_gid, eff_gid);
  183.   if (setreuid(real_uid, eff_uid) < 0)
  184. fprintf(stderr, "minicom: cannot setreuid(%d, %d)n", real_uid, eff_uid);
  185.   not_suid = 0;
  186. #endif
  187. }
  188. /* Safe fopen for suid programs. */
  189. FILE *sfopen(file, mode)
  190. char *file;
  191. char *mode;
  192. {
  193. #ifdef HAS_REUID
  194.   int saved_errno;
  195. #else
  196.   char *p, buf[128];
  197.   struct stat stt;
  198.   int do_chown = 0;
  199. #endif
  200.   FILE *fp;
  201.   /* Initialize. */
  202.   if (not_suid < 0) not_suid = (real_uid == eff_uid);
  203.   /* If we're not running set-uid at the moment just open the file. */
  204.   if (not_suid) return (fopen(file, mode));
  205. #ifdef HAS_REUID
  206.   /* Just drop priviliges before opening the file. */
  207.   drop_privs();
  208.   fp = fopen(file, mode);
  209.   saved_errno = errno;
  210.   set_privs();
  211.   errno = saved_errno;
  212.   return(fp);
  213. #else
  214.   /* Read access? */
  215.   if (strcmp(mode, "r") == 0) {
  216. if (access(file, R_OK) < 0) return(NULL);
  217. return(fopen(file, mode));
  218.   }
  219.   /* Write access test. */
  220.   if (stat(file, &stt) == 0) {
  221. if (access(file, W_OK) < 0) return(NULL);
  222.   } else {
  223. /* Test if directory is writable. */
  224. strncpy(buf, file, sizeof(buf));
  225. if((p = strrchr(buf, '/')) == (char *)NULL)
  226.    strcpy(buf, ".");
  227. else
  228. *p = '';
  229. if (access(buf, W_OK) < 0) return(NULL);
  230. do_chown = 1;
  231.   }
  232.   /* Now open/create the file. */
  233.   if ((fp = fopen(file, mode)) == NULL) return(fp);
  234.   if (!do_chown) return(fp);
  235. #ifndef HAS_FCHOWN
  236.   /* There is a security hole / race condition here. */
  237.   (void) chown(file, (uid_t)real_uid, (gid_t)real_gid);
  238. #else
  239.   /* But this is safe. */
  240.   (void) fchown(fileno(fp), (uid_t)real_uid, (gid_t)real_gid);
  241. #endif /* HAS_FCHOWN */
  242.   return(fp);
  243. #endif /* HAS_REUID */
  244. }
  245. /*
  246.  * Get next port from a space-, comma-, colon-, or semi-colon-separated
  247.  * list (we're easy :-)) in a PARS_VAL_LEN length string.
  248.  *
  249.  * Returns NULL pointer on end-of-list.
  250.  *
  251.  * This would appear to be more complicated than it needs be.
  252.  *
  253.  * WARNING: Not MT-safe.  Multiple calls to this routine modify the same
  254.  * local static storage space.
  255.  */
  256. char *
  257. get_port(char *port_list)
  258. {
  259.   static char next_port[PARS_VAL_LEN];
  260.   static char loc_port_list[PARS_VAL_LEN];
  261.   static char *sp = NULL;
  262.   static char *ep;
  263.   /* first pass? */
  264.   if(sp == NULL) {
  265.     strncpy(loc_port_list, port_list, PARS_VAL_LEN);
  266.     loc_port_list[PARS_VAL_LEN] = (char) 0;
  267.     ep = &loc_port_list[strlen(loc_port_list)];
  268.     sp = strtok(loc_port_list, ":;, ");
  269.   }
  270.   else if(*sp != (char) 0) {
  271.     sp = strtok(sp, ":;, ");
  272.   }
  273.   else
  274.     sp = NULL;
  275.   if(sp != NULL) {
  276.        strncpy(next_port, sp, PARS_VAL_LEN);
  277.        next_port[PARS_VAL_LEN] = (char) 0;
  278.        /* point to next token--skipping multiple occurrences of delimiters */
  279.        for(sp += strlen(next_port); sp != ep && *sp != '/'; ++sp)
  280.  ;
  281.        return(next_port);
  282.   }
  283.   else {
  284.     return(NULL);
  285.   }
  286. }