int test_stat () { int ret; struct stat st; /* Test stat */ errno = 0; ret = stat (FILENAME, &st); if (!ret) printf ("stat 1: ret = %d, errno = %d %s\n", ret, errno, st.st_size == 11 ? "OK" : ""); else printf ("stat 1: ret = %d, errno = %d\n", ret, errno); stop (); /* NULL pathname */ errno = 0; ret = stat (NULL, &st); printf ("stat 2: ret = %d, errno = %d %s\n", ret, errno, strerrno (errno)); stop (); /* Empty pathname */ errno = 0; ret = stat ("", &st); printf ("stat 3: ret = %d, errno = %d %s\n", ret, errno, strerrno (errno)); stop (); /* Nonexistant file */ errno = 0; ret = stat (NONEXISTANT, &st); printf ("stat 4: ret = %d, errno = %d %s\n", ret, errno, strerrno (errno)); stop (); }
int test_open () { int ret; /* Test opening */ errno = 0; ret = open (FILENAME, O_CREAT | O_TRUNC | O_RDWR, S_IWUSR | S_IRUSR); printf ("open 1: ret = %d, errno = %d %s\n", ret, errno, ret >= 0 ? "OK" : ""); if (ret >= 0) close (ret); stop (); /* Creating an already existing file (created by fileio.exp) */ errno = 0; ret = open (FILENAME, O_CREAT | O_EXCL | O_WRONLY, S_IWUSR | S_IRUSR); printf ("open 2: ret = %d, errno = %d %s\n", ret, errno, strerrno (errno)); if (ret >= 0) close (ret); stop (); /* Open directory (for writing) */ errno = 0; ret = open (".", O_WRONLY); printf ("open 3: ret = %d, errno = %d %s\n", ret, errno, strerrno (errno)); if (ret >= 0) close (ret); stop (); /* Opening nonexistant file */ errno = 0; ret = open (NONEXISTANT, O_RDONLY); printf ("open 4: ret = %d, errno = %d %s\n", ret, errno, strerrno (errno)); if (ret >= 0) close (ret); stop (); /* Open for write but no write permission */ errno = 0; ret = open (NOWRITE, O_CREAT | O_RDONLY, S_IRUSR); if (ret >= 0) { close (ret); stop (); errno = 0; ret = open (NOWRITE, O_WRONLY); printf ("open 5: ret = %d, errno = %d %s\n", ret, errno, strerrno (errno)); if (ret >= 0) close (ret); } else { stop (); printf ("open 5: ret = %d, errno = %d\n", ret, errno); } stop (); }
int test_rename () { int ret; struct stat st; /* Test rename */ errno = 0; ret = rename (FILENAME, RENAMED); if (!ret) { errno = 0; ret = stat (FILENAME, &st); if (ret && errno == ENOENT) { errno = 0; ret = stat (RENAMED, &st); printf ("rename 1: ret = %d, errno = %d %s\n", ret, errno, strerrno (errno)); errno = 0; } else printf ("rename 1: ret = %d, errno = %d\n", ret, errno); } else printf ("rename 1: ret = %d, errno = %d\n", ret, errno); stop (); /* newpath is existing directory, oldpath is not a directory */ errno = 0; ret = rename (RENAMED, TESTDIR2); printf ("rename 2: ret = %d, errno = %d %s\n", ret, errno, strerrno (errno)); stop (); /* newpath is a non-empty directory */ errno = 0; ret = rename (TESTDIR2, TESTDIR1); printf ("rename 3: ret = %d, errno = %d %s\n", ret, errno, strerrno (errno)); stop (); /* newpath is a subdirectory of old path */ errno = 0; ret = rename (TESTDIR1, TESTSUBDIR); printf ("rename 4: ret = %d, errno = %d %s\n", ret, errno, strerrno (errno)); stop (); /* oldpath does not exist */ errno = 0; ret = rename (NONEXISTANT, FILENAME); printf ("rename 5: ret = %d, errno = %d %s\n", ret, errno, strerrno (errno)); stop (); }
int test_fstat () { int fd, ret; struct stat st; /* Test fstat */ errno = 0; fd = open (FILENAME, O_RDONLY); if (fd >= 0) { errno = 0; ret = fstat (fd, &st); if (!ret) printf ("fstat 1: ret = %d, errno = %d %s\n", ret, errno, st.st_size == 11 ? "OK" : ""); else printf ("fstat 1: ret = %d, errno = %d\n", ret, errno); close (fd); } else printf ("fstat 1: ret = %d, errno = %d\n", ret, errno); stop (); /* Fstat using invalid file descriptor */ errno = 0; ret = fstat (999, &st); printf ("fstat 2: ret = %d, errno = %d %s\n", ret, errno, strerrno (errno)); stop (); }
int test_read () { int fd, ret; char buf[16]; /* Test reading */ errno = 0; fd = open (FILENAME, O_RDONLY); if (fd >= 0) { memset (buf, 0, 16); errno = 0; ret = read (fd, buf, 16); buf[15] = '\0'; /* Don't trust anybody... */ if (ret == strlen (STRING)) printf ("read 1: %s %s\n", buf, !strcmp (buf, STRING) ? "OK" : ""); else printf ("read 1: ret = %d, errno = %d\n", ret, errno); close (fd); } else printf ("read 1: ret = %d, errno = %d\n", ret, errno); stop (); /* Read using invalid file descriptor */ errno = 0; ret = read (999, buf, 16); printf ("read 2: ret = %d, errno = %d %s\n", ret, errno, strerrno (errno)); stop (); }
int test_close () { int fd, ret; /* Test close */ errno = 0; fd = open (FILENAME, O_RDONLY); if (fd >= 0) { errno = 0; ret = close (fd); printf ("close 1: ret = %d, errno = %d, %s\n", ret, errno, ret == 0 ? "OK" : ""); } else printf ("close 1: ret = %d, errno = %d\n", ret, errno); stop (); /* Close an invalid file descriptor */ errno = 0; ret = close (999); printf ("close 2: ret = %d, errno = %d, %s\n", ret, errno, strerrno (errno)); stop (); }
int main (void) { int errn; int errnmax; const char *name; const char *msg; char *strerror (); errnmax = errno_max (); printf ("%d entries in names table.\n", num_error_names); printf ("%d entries in messages table.\n", sys_nerr); printf ("%d is max useful index.\n", errnmax); /* Keep printing values until we get to the end of *both* tables, not *either* table. Note that knowing the maximum useful index does *not* relieve us of the responsibility of testing the return pointer for NULL. */ for (errn = 0; errn <= errnmax; errn++) { name = strerrno (errn); name = (name == NULL) ? "<NULL>" : name; msg = strerror (errn); msg = (msg == NULL) ? "<NULL>" : msg; printf ("%-4d%-18s%s\n", errn, name, msg); } return 0; }
int test_unlink () { int ret; char name[256]; char sys[512]; /* Test unlink */ errno = 0; ret = unlink (RENAMED); printf ("unlink 1: ret = %d, errno = %d %s\n", ret, errno, strerrno (errno)); stop (); /* No write access */ sprintf (name, "%s/%s", TESTDIR2, FILENAME); errno = 0; ret = open (name, O_CREAT | O_RDONLY, S_IRUSR | S_IWUSR); if (ret >= 0) { sprintf (sys, "chmod -w %s", TESTDIR2); ret = system (sys); if (!ret) { errno = 0; ret = unlink (name); printf ("unlink 2: ret = %d, errno = %d %s\n", ret, errno, strerrno (errno)); } else printf ("unlink 2: ret = %d chmod failed, errno= %d\n", ret, errno); } else printf ("unlink 2: ret = %d, errno = %d\n", ret, errno); stop (); /* pathname doesn't exist */ errno = 0; ret = unlink (NONEXISTANT); printf ("unlink 3: ret = %d, errno = %d %s\n", ret, errno, strerrno (errno)); stop (); }
int test_lseek () { int fd; off_t ret = 0; /* Test seeking */ errno = 0; fd = open (FILENAME, O_RDONLY); if (fd >= 0) { errno = 0; ret = lseek (fd, 0, SEEK_CUR); printf ("lseek 1: ret = %ld, errno = %d, %s\n", (long) ret, errno, ret == 0 ? "OK" : ""); stop (); errno = 0; ret = lseek (fd, 0, SEEK_END); printf ("lseek 2: ret = %ld, errno = %d, %s\n", (long) ret, errno, ret == 11 ? "OK" : ""); stop (); errno = 0; ret = lseek (fd, 3, SEEK_SET); printf ("lseek 3: ret = %ld, errno = %d, %s\n", (long) ret, errno, ret == 3 ? "OK" : ""); close (fd); } else { printf ("lseek 1: ret = %ld, errno = %d %s\n", (long) ret, errno, strerrno (errno)); stop (); printf ("lseek 2: ret = %ld, errno = %d %s\n", (long) ret, errno, strerrno (errno)); stop (); printf ("lseek 3: ret = %ld, errno = %d %s\n", (long) ret, errno, strerrno (errno)); } /* Seeking on an invalid file descriptor */ stop (); }
int test_write () { int fd, ret; /* Test writing */ errno = 0; fd = open (OUTDIR FILENAME, O_WRONLY); if (fd >= 0) { errno = 0; ret = write (fd, STRING, strlen (STRING)); printf ("write 1: ret = %d, errno = %d %s\n", ret, errno, ret == strlen (STRING) ? "OK" : ""); close (fd); } else printf ("write 1: ret = %d, errno = %d\n", ret, errno); stop (); /* Write using invalid file descriptor */ errno = 0; ret = write (999, STRING, strlen (STRING)); printf ("write 2: ret = %d, errno = %d, %s\n", ret, errno, strerrno (errno)); stop (); /* Write to a read-only file */ errno = 0; fd = open (OUTDIR FILENAME, O_RDONLY); if (fd >= 0) { errno = 0; ret = write (fd, STRING, strlen (STRING)); printf ("write 3: ret = %d, errno = %d %s\n", ret, errno, strerrno (errno)); close (fd); } else printf ("write 3: ret = %d, errno = %d\n", ret, errno); stop (); }
/* * inetbind() must always return 0 or value < 0. */ static int inetbind(int port) { int s; struct sockaddr_in addr = { 0 }; int len = sizeof addr; close(0); if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) { syslog(LOG_CRIT, "cannot create server socket: %s.", strerrno()); return -1; } setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof one); addr.sin_family = AF_INET; addr.sin_port = htons(port); if (bind(s, (struct sockaddr *)&addr, len) < 0) { syslog(LOG_CRIT, "cannot bind() server socket: %s.", strerrno()); return -1; } if (listen(s, 5) < 0) { syslog(LOG_CRIT, "cannot listen() server socket: %s.", strerrno()); return -1; } if (s != 0) { movesocket(s, 0); } return 0; }
int main(int argc, char * argv[]) { uid_t nobody, nogrp; memset(conns, 0, sizeof conns); memset(&G, 0, sizeof G); FD_ZERO(&G.readfds); FD_SET(0, &G.readfds); if (argv[1]) { if (argv[1][0] == '-') { if (argv[1][1] == 'V') { printversion('.'); return 0; } else { fdprintf(2, "%s: invalid option -- %c\n", argv[0], argv[1][1]); fdprintf(2, "Usage: %s [-V] " IU_IN_USAGESTR "\n", argv[0]); return 1; } } else { SET_IU(argv[1], argc - 1); } } else { SET_IU(nobodystr, 1); } #ifndef DEBUG close(1); /* not debugging, openlog() hopefully uses fd 1. */ #else close(3); /* debugging, TRACE uses fd 1, openlog() hopefully fd 3 */ #endif openlog("identd", LOG_CONS, LOG_DAEMON); { struct passwd * pw = getpwnam(nobodystr); if (pw) { nobody = pw->pw_uid; nogrp = pw->pw_gid; } else { syslog(LOG_CRIT, "Cannot find user `nobody': %s", strerrno()); return -1; } } if (inetbind(getport()) < 0) { return -1; } /* */ { int i; for (i = FCS; i < MAXCONNS + FCS; i++) { close(i); } } #ifdef DEBUG #ifndef LOG_PERROR #define LOG_PERROR 0 #endif openlog("identd", LOG_PERROR, LOG_DAEMON); #else /* not DEBUG */ godaemon(); openlog("identd", 0, LOG_DAEMON); close(2); signal(SIGHUP, SIG_IGN); #endif /* DEBUG */ signal(SIGPIPE, SIG_IGN); /* connection closed when writing (raises ???) */ writepid(nobody, nogrp); setegid(nogrp); setgid(nogrp); setuid(nobody); seteuid(nobody); { int i; for (i = 0; i < 4; i++) { char * id = (char)NULL; unsigned int rv = 0; switch (i) { case 0: rv = (unsigned int)getegid(); id = "egid"; break; case 1: rv = (unsigned int)getgid(); id = "gid"; break; case 2: rv = (unsigned int)geteuid(); id = "euid"; break; case 3: rv = (unsigned int)getuid(); id = "uid"; break; } if (rv == 0) { syslog(LOG_ERR, "Can not drop all root privileges (%s) !!! %s !!!", id, strerrno()); delpidfile(); return -1; } } } while (2) { fd_set rfds = G.readfds; struct timeval tv = { 15, 0 }; int i; int tim = time(NULL); TRACE(("calling select(): n = %d, rfds = 0x%x\n\n", G.conncnt + FCS, *(int *)&rfds)); select(G.conncnt + FCS, &rfds, NULL, NULL, G.conncnt? &tv: NULL); for (i = G.conncnt - 1; i >= 0; i--) { int s = i + FCS; if (FD_ISSET(s, &rfds)) { char * buf = conns[i].buf; unsigned int len = conns[i].len; unsigned int l; TRACE(("data socket fd_isset %d\n", s)); if ((int)(l = read(s, buf + len, sizeof conns[0].buf - len)) > 0) { if (checkInput(buf, len, l)) { reply(s, buf); goto deleteconn; } else if (len + l >= sizeof conns[0].buf) { replyError(s, "X-INVALID-REQUEST"); goto deleteconn; } else { conns[i].len += l; } } else { goto deleteconn; } conns[i].lasttime = tim; continue; deleteconn: deleteConn(s); } else { /* implement as time_after() in linux kernel sources ... */ if (conns[i].lasttime + MAXIDLETIME <= tim) { replyError(s, "X-TIMEOUT"); deleteConn(s); } } } if (FD_ISSET(0, &rfds)) { int s = accept(0, NULL, 0); TRACE(("server socket fd_isset, %d accepted\n", s)); if (s < 0) { if (errno != EINTR) /* EINTR */ { syslog(LOG_ERR, "accept: %s", strerrno()); } } else { if (G.conncnt == MAXCONNS) { i = closeOldest(); } else { i = G.conncnt++; } if (s != i + FCS) { movesocket(s, i + FCS); } FD_SET(i + FCS, &G.readfds); conns[i].len = 0; conns[i].lasttime = time(NULL); } } } }