📄 sysutils.c
字号:
Int32get_fs_status( UChar *path, Int32 *blocksize, Real64 *bsize, Real64 *bfree, Real64 *bavail){#ifndef HAVE_STATVFS struct statfs statfsb;#else struct statvfs statfsb;#endif#ifdef HAVE_STATVFS /* sees to be well-defined */ if(statvfs(path, &statfsb) == -1)#else#if defined(_AIX) || defined(linux) || defined(__hpux) || defined(hpux) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) if(statfs(path, &statfsb) == -1)#else#if defined(sun) if(statfs(path, &statfsb, sizeof(statfsb), 0) == -1)#else#if defined(sgi) if(statfs(path, &statfsb, sizeof(statfsb), 0) == -1)#else#if defined(__osf__) if(statfs(path, &statfsb, sizeof(statfsb)) == -1)#else#if defined(UnixWare_5) if(statfs(path, &statfsb) == -1)#else#error undefined architecture#endif#endif#endif#endif#endif#endif return(-1); if(bavail)#if defined(HAVE_STRUCT_STAT_BAVAIL) || defined(HAVE_STATVFS) *bavail = (Real64) statfsb.f_bavail;#else *bavail = (Real64) statfsb.f_bfree;#endif if(bfree) *bfree = (Real64) statfsb.f_bfree; if(bsize) *bsize = (Real64) statfsb.f_blocks; if(blocksize)#ifndef HAVE_STATVFS *blocksize = (Int32) statfsb.f_bsize;#else *blocksize = (Int32) statfsb.f_frsize;#endif return(0);}#else /* defined(_WIN32) */Int32get_fs_space(UChar * path, Real64 * size){ if(size) *size = 10000000.0; return(0);}#endif /* ifelse defined(_WIN32) */static intset_eff_ugids1(uid_t uid, gid_t gid, int ngids, gid_t * gids, Flag ignerr){ int r = 0, ncgids = 0; uid_t ceuid; gid_t cegid, *cgids = NULL; ceuid = geteuid(); cegid = getegid(); if((ngids > 0 && gids) || (gid != (gid_t) -1)){ if(ceuid){#ifdef HAVE_SETEUID /* if that works, we can force group setting */ seteuid(0);#else#ifdef HAVE_SETREUID setreuid(-1, 0);#else#ifdef HAVE_SETRESUID setresuid(-1, 0, -1);#else#error No function to set the effective user id#endif#endif#endif if(!(geteuid())){ if(uid == (uid_t) -1) uid = ceuid; /* to really go back later */ ceuid = 0; } } } if(ngids > 0 && gids){ if(get_groups(&ncgids, &cgids) && !ignerr) GETOUTR(-1); r = setgroups(ngids, gids); if(r && !ignerr) GETOUTR(r); } if(gid != (gid_t) -1 && gid != cegid){ r =#ifdef HAVE_SETEGID setegid(gid);#else#ifdef HAVE_SETREGID setregid(-1, gid);#else#ifdef HAVE_SETRESGID setresgid(-1, gid, -1);#else#error No function to set the effective group id#endif#endif#endif if(r && !ignerr) GETOUTR(r); } if(uid != (uid_t) -1 && uid != ceuid){ r =#ifdef HAVE_SETEUID seteuid(uid);#else#ifdef HAVE_SETREUID setreuid(-1, uid);#else#ifdef HAVE_SETRESUID setresuid(-1, uid, -1);#else#error No function to set the effective user id#endif#endif#endif if(r && !ignerr) GETOUTR(r); } cleanup: ZFREE(cgids); return(r); getout: set_eff_ugids1(ceuid, cegid, ncgids, cgids, YES); CLEANUP;}intset_eff_ugids(uid_t uid, gid_t gid, int ngids, gid_t * gids){ return(set_eff_ugids1(uid, gid, ngids, gids, NO));}intget_groups(int * ngids, gid_t ** gids){ int ngs; gid_t *gs, g; ngs = getgroups(0, &g); if(!gids){ if(ngids) *ngids = ngs; return(0); } gs = NEWP(gid_t, ngs); if(!gs) return(-1); getgroups(ngs, gs); *gids = gs; if(ngids) *ngids = ngs; return(0);}static Int32cmp_mnt_by_devno(void * ptr1, void * ptr2){ dev_t d1, d2; d1 = ((MntEnt *) ptr1)->dev; d2 = ((MntEnt *) ptr2)->dev; return(d1 > d2 ? 1 : (d1 < d2 ? -1 : 0));}UChar *mount_tab_file(){#if defined(linux) || defined(sgi) || ( defined(sun) && ! defined(HAVE_GETMNTENT_TWO_ARGS) )#define MTABFILE "/etc/mtab"#else#if defined(sun) || defined(__hpux) || defined(hpux) || defined(UnixWare_5)#define MTABFILE "/etc/mnttab"#else#if defined(__osf__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(_AIX)#define MTABFILE NULL#endif#endif#endif return(MTABFILE);}#ifndef HAVE_ENDMNTENT#define endmntent fclose#endif#ifndef HAVE_SETMNTENT#define setmntent fopen#endifMntEnt *get_all_mounts(Int32 * num_mounts){ Int32 nmnt = 0, n, l, i; UChar *dir, *typestr, *devstr, *cptr; MntEnt *mnts = NULL; FILE *mtabfp = NULL; struct stat statb;#ifdef HAVE_GETMNTENT#ifndef HAVE_GETMNTENT_TWO_ARGS struct mntent *mntentptr;#else struct mnttab mntent;#endif#endif#ifdef HAVE_GETFSSTAT struct statfs *statfsptr, *statfsbuf = NULL;#endif UChar *mntentbuf = NULL, **vfslines = NULL; int i1; Int32 nvfslines = 0, nmntent; /* this stuff is for AIX */#ifdef HAVE_GETMNTENT mtabfp = setmntent(MTABFILE, "r"); if(!mtabfp) return(NULL);#else /* defined(HAVE_GETMNTENT) */#ifdef HAVE_MNTCTL /* the AIX stuff */ n = 8; /* die schie遝n echt den Vogel ab */ forever{ mntentbuf = ZRENEWP(mntentbuf, UChar, n); if(!mntentbuf) GETOUT; nmntent = mntctl(MCTL_QUERY, n, mntentbuf); if(nmntent < 0) GETOUT; if(nmntent == 0){ n = *((size_t *) &(mntentbuf[0])); continue; } break; } vfslines = read_asc_file("/etc/vfs", &nvfslines); if(!vfslines) GETOUT; for(i = 0; i < nvfslines; i++){ massage_string(vfslines[i]); if( (cptr = first_space(vfslines[i])) ) *cptr = '\0'; }#else#ifdef HAVE_GETFSSTAT n = getfsstat(NULL, 0, MNT_NOWAIT); statfsbuf = NEWP(struct statfs, n); if(!statfsbuf) GETOUT; mntentbuf = (UChar *) statfsbuf; /* for free below */ if((nmntent = getfsstat(statfsbuf, n * sizeof(struct statfs), MNT_NOWAIT)) < 0) GETOUT;#else#error No way to get the (status of the) mounted filesystems#endif#endif#endif#ifdef HAVE_GETMNTENT#ifndef HAVE_GETMNTENT_TWO_ARGS while( (mntentptr = getmntent(mtabfp)) ){ dir = mntentptr->mnt_dir;#else while(!getmntent(mtabfp, &mntent)){ dir = mntent.mnt_mountp;#endif#else /* defined(HAVE_GETMNTENT) */#ifdef HAVE_MNTCTL for(n = 0, cptr = mntentbuf; n < nmntent; cptr += ((struct vmount *) cptr)->vmt_length, n++){ devstr = cptr + sizeof(struct vmount); dir = devstr + align_n(strlen(devstr) + 1, 32 / 8);#else#ifdef HAVE_GETFSSTAT for(n = 0, statfsptr = statfsbuf; n < nmntent; n++, statfsptr++){ dir = statfsptr->f_mntonname;#endif#endif#endif if(lstat(dir, &statb) < 0) continue; /* can't read this -> leave out */#ifdef HAVE_GETMNTENT#ifndef HAVE_GETMNTENT_TWO_ARGS typestr = mntentptr->mnt_type; devstr = mntentptr->mnt_fsname;#else typestr = mntent.mnt_fstype; devstr = mntent.mnt_special;#endif#else /* defined(HAVE_GETMNTENT) */#ifdef HAVE_MNTCTL /* on AIX we must search in /etc/vfs */ for(i = 0; i < nvfslines; i++){ if(vfslines[i][0] == '#' || vfslines[i][0] == '%' || !vfslines[i][0]) continue; l = strlen(vfslines[i]); if(sscanf(vfslines[i] + l + 1, "%d", &i1) < 1) continue; if(((struct vmount *) cptr)->vmt_gfstype == i1){ typestr = vfslines[i]; break; } } if(i >= nvfslines) continue;#else#ifdef HAVE_GETFSSTAT devstr = statfsptr->f_mntfromname;#ifdef HAVE_MNT_NAMES typestr = mnt_names[statfsptr->f_type];#else typestr = statfsptr->f_fstypename;#endif#endif#endif#endif mnts = ZRENEWP(mnts, MntEnt, nmnt + 2); if(!mnts) CLEANUP; memset(mnts + nmnt, 0, sizeof(MntEnt) * 2); mnts[nmnt].dev = statb.st_dev; if(!(mnts[nmnt].dir = strdup(dir))) GETOUT; if(typestr) if(!(mnts[nmnt].typestr = strdup(typestr))) GETOUT; if(devstr) if(!(mnts[nmnt].devstr = strdup(devstr))) GETOUT; nmnt++; } if(num_mounts) *num_mounts = nmnt; q_sort(mnts, nmnt, sizeof(MntEnt), cmp_mnt_by_devno); cleanup: if(mtabfp){ endmntent(mtabfp); } ZFREE(mntentbuf); free_asc_file(vfslines, 0); return(mnts); getout: free_mounts(mnts); CLEANUP;}static voidcry_out_loud_shit(UChar * msg, MntEnt * mnts, Int32 nmnts){ fprintf(stderr, ">>>>> Please, if someone reads this, send a mail to af@muc.de\n" ">>>>> containing the following output:\n"); fprintf(stderr, ">>>>> %s\n", msg); while(nmnts > 0){ fprintf(stderr, ">>>>> `%s' `%s' `%s' %ld\n", mnts->dir ? mnts->dir : (UChar *) "??", mnts->typestr ? mnts->typestr : (UChar *) "??", mnts->devstr ? mnts->devstr : (UChar *) "??", (long int) mnts->dev); mnts++; nmnts--; }}MntEnt *find_mnt_by_devno_dir(MntEnt * mounts, Int32 nmnt, dev_t devno, UChar * dnam){ MntEnt cmpent, *mntptr; Int32 first, last, found, i, n, l; struct stat statb; if(dnam) dnam = resolve_path__(dnam, NULL); if(nmnt < 1) for(nmnt = 0, mntptr = mounts; mntptr->dir; nmnt++, mntptr++); cmpent.dev = devno; mntptr = b_search(&cmpent, mounts, nmnt, sizeof(MntEnt), cmp_mnt_by_devno); if(mntptr){ found = first = last = mntptr - mounts; /* there can be several with */ while(first > 0){ /* the same device number */ if(mounts[first - 1].dev != devno) /* when there are loopback */ break; /* mounts. We have to find */ /* the entry with a real */ first--; /* device as device, or */ } /* we are at the end of the */ while(last < nmnt - 1){ /* loop searching for the */ if(mounts[last + 1].dev != devno) /* entry with the device */ break; /* as directory */ last++; } if(first < last){#if 0 /* all that nice stuff does not work in practice */ forever{ if(lstat(mounts[found].devstr, &statb) < 0) break; /* may never happen */ if(S_ISBLK(statb.st_mode) || S_ISCHR(statb.st_mode)) break; /* we have a device here */ for(i = first; i <= last; i++){ if(i == found) continue; if(!strcmp(mounts[found].devstr, mounts[i].dir)) break; /* have a new entry with dir == dev of old entry */ } if(i <= last) found = i; /* continue with the found entry */ else break; /* if none found, we are at the end, no clue left */ } /* stick with the entry found before (?) */#else /* instead simply look for a real device */ n = 0; for(i = first; i <= last; i++){ if(!mounts[i].devstr || !mounts[i].typestr) continue; if(stat(mounts[i].devstr, &statb) < 0) continue; if(S_ISBLK(statb.st_mode) || S_ISCHR(statb.st_mode)){ if(dnam && mounts[i].dir){ l = strlen(mounts[i].dir); if(!strcmp(dnam, mounts[i].dir) || (!strncmp(dnam, mounts[i].dir, l) && FN_ISDIRSEP(dnam[l]))){ n++; found = i; } } else{ n++; found = i; } } } if(n > 1) cry_out_loud_shit("several devices", mounts + first, last - first + 1); if(n == 0){ /* another perverse thing, hope it only happens on Sun */ n = 0; /* a supervised automount point and the real mount */ for(i = first; i <= last; i++){ /* have the same device number */ if(!strstr(mounts[i].typestr, "auto")){ /* we prefer non-auto */ if(dnam && mounts[i].dir){ /* i *hate* such hardcoded stuff */ l = strlen(mounts[i].dir); if(!strcmp(dnam, mounts[i].dir) || (!strncmp(dnam, mounts[i].dir, l) && FN_ISDIRSEP(dnam[l]))){ n++; found = i; } } else{ n++; found = i; } } } if(n > 1) cry_out_loud_shit("several non-automount directories", mounts + first, last - first + 1); }#endif mntptr = mounts + found; } } ZFREE(dnam); return(mntptr);}UChar *get_fstype_by_devno_dir(dev_t devno, UChar * dnam) /* this is not MT-safe */{ static MntEnt *mounts = NULL; static Int32 nmounts = 0; static UChar *prev_type = NULL; static dev_t prev_dev; MntEnt *mntptr; if(prev_type && prev_dev == devno) return(prev_type); if(!mounts){ mounts = get_all_mounts(&nmounts); if(!mounts) return(NULL); } mntptr = find_mnt_by_devno_dir(mounts, nmounts, devno, dnam); if(!mntptr){ free_mounts(mounts); mounts = get_all_mounts(&nmounts); if(!mounts) return(NULL); mntptr = find_mnt_by_devno_dir(mounts, nmounts, devno, dnam); } prev_dev = devno; prev_type = (mntptr ? mntptr->typestr : NULL); return(prev_type);}voidfree_mounts(MntEnt * mounts){ MntEnt *mntptr; if( (mntptr = mounts) ){ while(mounts->dir){ free(mounts->dir); ZFREE(mounts->typestr); ZFREE(mounts->devstr); mounts++; } free(mntptr); }}static struct _fac_names_ { char *name; int value;} lfacilitynames[] = {#ifdef LOG_AUTH { "auth", LOG_AUTH },#endif#ifdef LOG_AUTHPRIV { "authpriv", LOG_AUTHPRIV },#endif#ifdef LOG_CRON { "cron", LOG_CRON },#endif#ifdef LOG_DAEMON { "daemon", LOG_DAEMON },#endif#ifdef LOG_FTP { "ftp", LOG_FTP },#endif#ifdef LOG_KERN { "kern", LOG_KERN },#endif#ifdef LOG_LPR { "lpr", LOG_LPR },#endif#ifdef LOG_MAIL { "mail", LOG_MAIL },#endif#ifdef LOG_NEWS { "news", LOG_NEWS },#endif#ifdef LOG_AUTH { "security", LOG_AUTH }, /* DEPRECATED */#endif { "syslog", LOG_SYSLOG }, /* always there !!! wow !!! */#ifdef LOG_USER { "user", LOG_USER },#endif#ifdef LOG_UUCP { "uucp", LOG_UUCP },#endif#ifdef LOG_LOCAL0 { "local0", LOG_LOCAL0 },#endif#ifdef LOG_LOCAL1 { "local1", LOG_LOCAL1 },#endif#ifdef LOG_LOCAL2 { "local2", LOG_LOCAL2 },#endif#ifdef LOG_LOCAL3 { "local3", LOG_LOCAL3 },#endif#ifdef LOG_LOCAL4 { "local4", LOG_LOCAL4 },#endif#ifdef LOG_LOCAL5 { "local5", LOG_LOCAL5 },#endif#ifdef LOG_LOCAL6 { "local6", LOG_LOCAL6 },#endif#ifdef LOG_LOCAL7 { "local7", LOG_LOCAL7 },#endif { NULL, -1 } };Uns32syslog_facility_from_string(UChar * str){ struct _fac_names_ *fnamesptr; for(fnamesptr = lfacilitynames; fnamesptr->name; fnamesptr++) if(!strcmp(fnamesptr->name, str)) break; return(fnamesptr->value);}Int32to_other_user( uid_t vuid, gid_t vgid, UGIDS *old_ugids){ Int32 i; old_ugids->uid = geteuid(); old_ugids->gid = getegid(); ZFREE(old_ugids->gids); i = get_groups(&(old_ugids->ngids), &(old_ugids->gids)); if(i) return(i); return(set_eff_ugids(vuid, vgid, 0, &vgid));}Int32to_org_user(UGIDS * old_ugids){ Int32 i; i = set_eff_ugids(old_ugids->uid, old_ugids->gid, old_ugids->ngids, old_ugids->gids); if(!i){ ZFREE(old_ugids->gids); SETZERO(*old_ugids); } return(i);}intcreate_unix_socket(UChar * path){ struct sockaddr_un addr; int usock, sock_optval; if(!access(path, F_OK)){ usock = open_uxsock_conn(path); if(usock >= 0){ close(usock); errno = EADDRINUSE; return(-2); } unlink(path); } usock = socket(AF_UNIX, SOCK_STREAM, 0); if(usock >= 0){ SETZERO(addr); addr.sun_family = AF_UNIX; strcpy(addr.sun_path, path); sock_optval = 1; setsockopt(usock, SOL_SOCKET, SO_REUSEADDR, (char *) &sock_optval, sizeof(int)); if(bind(usock, (struct sockaddr * ) (& addr), sizeof(addr))){ close(usock); usock = -1; } } return(usock);}intopen_uxsock_conn(UChar * path){ struct sockaddr_un addr; int usock; usock = socket(AF_UNIX, SOCK_STREAM, 0); if(usock >= 0){ SETZERO(addr); addr.sun_family = AF_UNIX; strcpy(addr.sun_path, path); if(connect(usock, (struct sockaddr *) (&addr), sizeof(addr))){ close(usock); usock = -1; } } return(usock);}#if 0/* implemented as macro in sysutils.h */Int32set_closeonexec(int fd){ int fl; fl = fcntl(fd, F_GETFD) | FD_CLOEXEC; return(fcntl(fd, F_SETFD, fl));}#endif#endif /* any PC-compiler *//************ end of $RCSfile: sysutils.c,v $ ******************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -