util.c
上传用户:tianjinjs
上传日期:2007-01-05
资源大小:309k
文件大小:6k
- /*
- * util.c Little helper routines that didn't fit anywhere else.
- *
- * This file is part of the minicom communications package,
- * Copyright 1991-1995 Miquel van Smoorenburg.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- *
- * jseymour@jimsun.LinxNet.com (Jim Seymour) 03/26/98 - Added get_port()
- * function to support multiple port specifications in config.
- */
- #include "port.h"
- #include "minicom.h"
- static int not_suid = -1;
- /*
- * A modified version of the getargs routine.
- */
- static int getargs(s, arps, maxargs)
- register char *s;
- char *arps[];
- int maxargs;
- {
- register int i;
- register char *sp;
- register char qchar;
- int literal = 0;
- i = 0;
- while (i < maxargs) {
- while (*s == ' ' || *s == 't')
- ++s;
- if (*s == 'n' || *s == ' ')
- break;
- arps[i++] = sp = s;
- qchar = 0;
- while(*s != ' ' && *s != 'n') {
- if (literal) {
- literal = 0;
- *sp++ = *s++;
- continue;
- }
- literal = 0;
- if (qchar == 0 && (*s == ' ' || *s == 't')) {
- ++s;
- break;
- }
- switch(*s) {
- default:
- *sp++ = *s++;
- break;
- case '\':
- literal = 1;
- s++;
- break;
- case '"':
- case ''':
- if(qchar == *s) {
- qchar = 0;
- ++s;
- break;
- }
- if(qchar)
- *sp++ = *s++;
- else
- qchar = *s++;
- break;
- }
- }
- *sp++ = 0;
- }
- if (i >= maxargs)
- return -1;
- arps[i] = (char *)0;
- return i;
- }
- /*
- * Is a character from s2 in s1?
- */
- static int anys(s1, s2)
- char *s1, *s2;
- {
- while(*s2)
- if (strchr(s1, *s2++) != (char *)NULL) return(1);
- return(0);
- }
- /*
- * If there is a shell-metacharacter in "cmd",
- * call a shell to do the dirty work.
- */
- int fastexec(cmd)
- char *cmd;
- {
- char *words[128];
- char *p;
- if (anys(cmd, "~`$&*()=|{};?><"))
- return(execl("/bin/sh", "sh", "-c", cmd, (char *)0));
- /* Delete escape-characters ment for the shell */
- p = cmd;
- while((p = strchr(p, '\')) != (char *)NULL)
- strcpy(p, p + 1);
- /* Split line into words */
- if (getargs(cmd, words, 127) < 0) {
- return(-1);
- }
- return (execvp(words[0], words));
- }
- /*
- * Fork, then redirect I/O if neccesary.
- * in : new stdin
- * out : new stdout
- * err : new stderr
- * Returns exit status of "cmd" on success, -1 on error.
- */
- int fastsystem(cmd, in, out, err)
- char *cmd, *in, *out, *err;
- {
- int pid;
- int st;
- int async = 0;
- char *p;
- /* If the command line ends with '&', don't wait for child. */
- p = strrchr(cmd, '&');
- if (p != (char *)0 && !p[1]) {
- *p = 0;
- async = 1;
- }
-
- /* Fork. */
- if ((pid = fork()) == 0) { /* child */
- if (in != (char *)NULL) {
- close(0);
- if (open(in, O_RDONLY) < 0) exit(-1);
- }
- if (out != (char *)NULL) {
- close(1);
- if (open(out, O_WRONLY) < 0) exit(-1);
- }
- if (err != (char *)NULL) {
- close(2);
- if (open(err, O_RDWR) < 0) exit(-1);
- }
- exit(fastexec(cmd));
- } else if (pid > 0) { /* parent */
- if (async) return(0);
- pid = m_wait(&st);
- if (pid < 0) return(-1);
- return(st);
- }
- return(-1);
- }
- /* Drop all priviliges (irreversable). */
- void drop_all_privs()
- {
- #ifdef HAS_REUID
- /* Regain privs needed to drop privs :) */
- setregid(real_gid, eff_gid);
- setreuid(real_uid, eff_uid);
- #endif
- /* Drop it. */
- setgid(real_gid);
- setuid(real_uid);
- eff_uid = real_uid;
- eff_gid = real_gid;
- not_suid = 1;
- }
- /* Drop priviliges (swap uid's) */
- void drop_privs()
- {
- #ifdef HAS_REUID
- setregid(eff_gid, real_gid);
- if (setreuid(eff_uid, real_uid) < 0)
- fprintf(stderr, "minicom: cannot setreuid(%d, %d)n", eff_uid, real_uid);
- not_suid = 1;
- #endif
- }
- /* Set priviliges (swap uid's) */
- void set_privs()
- {
- #ifdef HAS_REUID
- setregid(real_gid, eff_gid);
- if (setreuid(real_uid, eff_uid) < 0)
- fprintf(stderr, "minicom: cannot setreuid(%d, %d)n", real_uid, eff_uid);
- not_suid = 0;
- #endif
- }
- /* Safe fopen for suid programs. */
- FILE *sfopen(file, mode)
- char *file;
- char *mode;
- {
- #ifdef HAS_REUID
- int saved_errno;
- #else
- char *p, buf[128];
- struct stat stt;
- int do_chown = 0;
- #endif
- FILE *fp;
- /* Initialize. */
- if (not_suid < 0) not_suid = (real_uid == eff_uid);
- /* If we're not running set-uid at the moment just open the file. */
- if (not_suid) return (fopen(file, mode));
- #ifdef HAS_REUID
- /* Just drop priviliges before opening the file. */
- drop_privs();
- fp = fopen(file, mode);
- saved_errno = errno;
- set_privs();
- errno = saved_errno;
- return(fp);
- #else
- /* Read access? */
- if (strcmp(mode, "r") == 0) {
- if (access(file, R_OK) < 0) return(NULL);
- return(fopen(file, mode));
- }
- /* Write access test. */
- if (stat(file, &stt) == 0) {
- if (access(file, W_OK) < 0) return(NULL);
- } else {
- /* Test if directory is writable. */
- strncpy(buf, file, sizeof(buf));
- if((p = strrchr(buf, '/')) == (char *)NULL)
- strcpy(buf, ".");
- else
- *p = ' ';
- if (access(buf, W_OK) < 0) return(NULL);
- do_chown = 1;
- }
- /* Now open/create the file. */
- if ((fp = fopen(file, mode)) == NULL) return(fp);
- if (!do_chown) return(fp);
- #ifndef HAS_FCHOWN
- /* There is a security hole / race condition here. */
- (void) chown(file, (uid_t)real_uid, (gid_t)real_gid);
- #else
- /* But this is safe. */
- (void) fchown(fileno(fp), (uid_t)real_uid, (gid_t)real_gid);
- #endif /* HAS_FCHOWN */
- return(fp);
- #endif /* HAS_REUID */
- }
- /*
- * Get next port from a space-, comma-, colon-, or semi-colon-separated
- * list (we're easy :-)) in a PARS_VAL_LEN length string.
- *
- * Returns NULL pointer on end-of-list.
- *
- * This would appear to be more complicated than it needs be.
- *
- * WARNING: Not MT-safe. Multiple calls to this routine modify the same
- * local static storage space.
- */
- char *
- get_port(char *port_list)
- {
- static char next_port[PARS_VAL_LEN];
- static char loc_port_list[PARS_VAL_LEN];
- static char *sp = NULL;
- static char *ep;
- /* first pass? */
- if(sp == NULL) {
- strncpy(loc_port_list, port_list, PARS_VAL_LEN);
- loc_port_list[PARS_VAL_LEN] = (char) 0;
- ep = &loc_port_list[strlen(loc_port_list)];
- sp = strtok(loc_port_list, ":;, ");
- }
- else if(*sp != (char) 0) {
- sp = strtok(sp, ":;, ");
- }
- else
- sp = NULL;
- if(sp != NULL) {
- strncpy(next_port, sp, PARS_VAL_LEN);
- next_port[PARS_VAL_LEN] = (char) 0;
- /* point to next token--skipping multiple occurrences of delimiters */
- for(sp += strlen(next_port); sp != ep && *sp != '/'; ++sp)
- ;
- return(next_port);
- }
- else {
- return(NULL);
- }
- }