PAM_EXTERN int pam_sm_open_session(pam_handle_t * pamh, int flags, int argc ,const char **argv) { int retval, ctrl; const char *user; const struct passwd *pwd; struct stat St; /* Parse the flag values */ ctrl = _pam_parse(flags, argc, argv); /* Determine the user name so we can get the home directory */ retval = pam_get_item(pamh, PAM_USER, (const void **) &user); if (retval != PAM_SUCCESS || user == NULL || *user == '\0') { _log_err(LOG_NOTICE, "user unknown"); return PAM_USER_UNKNOWN; } /* Get the password entry */ pwd = getpwnam(user); if (pwd == NULL) { D(("couldn't identify user %s", user)); return PAM_CRED_INSUFFICIENT; } /* Stat the home directory, if something exists then we assume it is correct and return a success*/ if (stat(pwd->pw_dir,&St) == 0) return PAM_SUCCESS; return create_homedir(pamh,ctrl,pwd,SkelDir,pwd->pw_dir); }
int main(int argc, char *argv[]) { struct passwd *pwd; struct stat st; if (argc < 2) { fprintf(stderr, "Usage: %s <username> [<umask> [<skeldir>]]\n", argv[0]); return PAM_SESSION_ERR; } pwd = getpwnam(argv[1]); if (pwd == NULL) { pam_syslog(NULL, LOG_ERR, "User unknown."); return PAM_CRED_INSUFFICIENT; } if (argc >= 3) { char *eptr; errno = 0; u_mask = strtoul(argv[2], &eptr, 0); if (errno != 0 || *eptr != '\0') { pam_syslog(NULL, LOG_ERR, "Bogus umask value %s", argv[2]); return PAM_SESSION_ERR; } } if (argc >= 4) { if (strlen(argv[3]) >= sizeof(skeldir)) { pam_syslog(NULL, LOG_ERR, "Too long skeldir path."); return PAM_SESSION_ERR; } strcpy(skeldir, argv[3]); } /* Stat the home directory, if something exists then we assume it is correct and return a success */ if (stat(pwd->pw_dir, &st) == 0) return PAM_SUCCESS; if (make_parent_dirs(pwd->pw_dir, 0) != PAM_SUCCESS) return PAM_PERM_DENIED; return create_homedir(pwd, skeldir, pwd->pw_dir); }
int main(int argc, const char **argv) { uid_t pc_uid = 0; const char *pc_gecos = NULL; const char *pc_home = NULL; char *pc_shell = NULL; int pc_debug = SSSDBG_DEFAULT; int pc_create_home = 0; const char *pc_username = NULL; const char *pc_skeldir = NULL; const char *pc_selinux_user = NULL; struct poptOption long_options[] = { POPT_AUTOHELP { "debug", '\0', POPT_ARG_INT | POPT_ARGFLAG_DOC_HIDDEN, &pc_debug, 0, _("The debug level to run with"), NULL }, { "uid", 'u', POPT_ARG_INT, &pc_uid, 0, _("The UID of the user"), NULL }, { "gecos", 'c', POPT_ARG_STRING, &pc_gecos, 0, _("The comment string"), NULL }, { "home", 'h', POPT_ARG_STRING, &pc_home, 0, _("Home directory"), NULL }, { "shell", 's', POPT_ARG_STRING, &pc_shell, 0, _("Login shell"), NULL }, { "groups", 'G', POPT_ARG_STRING, NULL, 'G', _("Groups"), NULL }, { "create-home", 'm', POPT_ARG_NONE, NULL, 'm', _("Create user's directory if it does not exist"), NULL }, { "no-create-home", 'M', POPT_ARG_NONE, NULL, 'M', _("Never create user's directory, overrides config"), NULL }, { "skel", 'k', POPT_ARG_STRING, &pc_skeldir, 0, _("Specify an alternative skeleton directory"), NULL }, { "selinux-user", 'Z', POPT_ARG_STRING, &pc_selinux_user, 0, _("The SELinux user for user's login"), NULL }, POPT_TABLEEND }; poptContext pc = NULL; struct tools_ctx *tctx = NULL; char *groups = NULL; char *badgroup = NULL; int ret; errno_t sret; bool in_transaction = false; debug_prg_name = argv[0]; ret = set_locale(); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "set_locale failed (%d): %s\n", ret, strerror(ret)); ERROR("Error setting the locale\n"); ret = EXIT_FAILURE; goto fini; } /* parse parameters */ pc = poptGetContext(NULL, argc, argv, long_options, 0); poptSetOtherOptionHelp(pc, "USERNAME"); while ((ret = poptGetNextOpt(pc)) > 0) { switch (ret) { case 'G': groups = poptGetOptArg(pc); if (!groups) { BAD_POPT_PARAMS(pc, _("Specify group to add to\n"), ret, fini); } break; case 'm': pc_create_home = DO_CREATE_HOME; break; case 'M': pc_create_home = DO_NOT_CREATE_HOME; break; } } DEBUG_CLI_INIT(pc_debug); if (ret != -1) { BAD_POPT_PARAMS(pc, poptStrerror(ret), ret, fini); } /* username is an argument without --option */ pc_username = poptGetArg(pc); if (pc_username == NULL) { BAD_POPT_PARAMS(pc, _("Specify user to add\n"), ret, fini); } CHECK_ROOT(ret, debug_prg_name); ret = init_sss_tools(&tctx); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "init_sss_tools failed (%d): %s\n", ret, strerror(ret)); if (ret == ENOENT) { ERROR("Error initializing the tools - no local domain\n"); } else { ERROR("Error initializing the tools\n"); } ret = EXIT_FAILURE; goto fini; } /* if the domain was not given as part of FQDN, default to local domain */ ret = parse_name_domain(tctx, pc_username); if (ret != EOK) { ERROR("Invalid domain specified in FQDN\n"); ret = EXIT_FAILURE; goto fini; } if (groups) { ret = parse_groups(tctx, groups, &tctx->octx->addgroups); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "Cannot parse groups to add the user to\n"); ERROR("Internal error while parsing parameters\n"); ret = EXIT_FAILURE; goto fini; } ret = parse_group_name_domain(tctx, tctx->octx->addgroups); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "Cannot parse FQDN groups to add the user to\n"); ERROR("Groups must be in the same domain as user\n"); ret = EXIT_FAILURE; goto fini; } /* Check group names in the LOCAL domain */ ret = check_group_names(tctx, tctx->octx->addgroups, &badgroup); if (ret != EOK) { ERROR("Cannot find group %1$s in local domain\n", badgroup); ret = EXIT_FAILURE; goto fini; } } tctx->octx->uid = pc_uid; /* * Fills in defaults for ops_ctx user did not specify. */ ret = useradd_defaults(tctx, tctx->confdb, tctx->octx, pc_gecos, pc_home, pc_shell, pc_create_home, pc_skeldir); if (ret != EOK) { ERROR("Cannot set default values\n"); ret = EXIT_FAILURE; goto fini; } /* arguments processed, go on to actual work */ if (id_in_range(tctx->octx->uid, tctx->octx->domain) != EOK) { ERROR("The selected UID is outside the allowed range\n"); ret = EXIT_FAILURE; goto fini; } tctx->error = sysdb_transaction_start(tctx->sysdb); if (tctx->error != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "Failed to start transaction\n"); goto done; } in_transaction = true; /* useradd */ tctx->error = useradd(tctx, tctx->octx); if (tctx->error) { goto done; } tctx->error = sysdb_transaction_commit(tctx->sysdb); if (tctx->error) { DEBUG(SSSDBG_CRIT_FAILURE, "Failed to commit transaction\n"); goto done; } in_transaction = false; /* Set SELinux login context - must be done after transaction is done * b/c libselinux calls getpwnam */ ret = set_seuser(tctx->octx->name, pc_selinux_user, NULL); if (ret != EOK) { ERROR("Cannot set SELinux login context\n"); ret = EXIT_FAILURE; goto fini; } /* Create user's home directory and/or mail spool */ if (tctx->octx->create_homedir) { /* We need to know the UID of the user, if * sysdb did assign it automatically, do a lookup */ if (tctx->octx->uid == 0) { ret = sysdb_getpwnam_sync(tctx, tctx->octx->name, tctx->octx); if (ret != EOK) { ERROR("Cannot get info about the user\n"); ret = EXIT_FAILURE; goto fini; } } ret = create_homedir(tctx->octx->skeldir, tctx->octx->home, tctx->octx->uid, tctx->octx->gid, tctx->octx->umask); if (ret == EEXIST) { ERROR("User's home directory already exists, not copying " "data from skeldir\n"); } else if (ret != EOK) { ERROR("Cannot create user's home directory: %1$s\n", strerror(ret)); ret = EXIT_FAILURE; goto fini; } ret = create_mail_spool(tctx, tctx->octx->name, tctx->octx->maildir, tctx->octx->uid, tctx->octx->gid); if (ret != EOK) { ERROR("Cannot create user's mail spool: %1$s\n", strerror(ret)); DEBUG(SSSDBG_CRIT_FAILURE, "Cannot create user's mail spool: [%d][%s].\n", ret, strerror(ret)); ret = EXIT_FAILURE; goto fini; } } done: if (in_transaction) { sret = sysdb_transaction_cancel(tctx->sysdb); if (sret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "Failed to cancel transaction\n"); } } if (tctx->error) { switch (tctx->error) { case ERANGE: ERROR("Could not allocate ID for the user - domain full?\n"); break; case EEXIST: ERROR("A user or group with the same name or ID already exists\n"); break; default: DEBUG(SSSDBG_CRIT_FAILURE, "sysdb operation failed (%d)[%s]\n", tctx->error, strerror(tctx->error)); ERROR("Transaction error. Could not add user.\n"); break; } ret = EXIT_FAILURE; goto fini; } ret = EXIT_SUCCESS; fini: poptFreeContext(pc); talloc_free(tctx); free(groups); exit(ret); }
/* Do the actual work of creating a home dir */ static int create_homedir(pam_handle_t * pamh, int ctrl, const struct passwd *pwd, const char *source, const char *dest) { char remark[BUFSIZ]; DIR *D; struct dirent *Dir; /* Mention what is happening, if the notification fails that is OK */ if (snprintf(remark,sizeof(remark),"Creating directory '%s'.", dest) == -1) return PAM_PERM_DENIED; make_remark(pamh, ctrl, remark); /* Create the new directory */ if (mkdir(dest,0700) != 0) { _log_err(LOG_DEBUG, "unable to create directory %s",dest); return PAM_PERM_DENIED; } if (chmod(dest,0777 & (~UMask)) != 0 || chown(dest,pwd->pw_uid,pwd->pw_gid) != 0) { _log_err(LOG_DEBUG, "unable to change perms on directory %s",dest); return PAM_PERM_DENIED; } /* See if we need to copy the skel dir over. */ if ((source == NULL) || (strlen(source) == 0)) { return PAM_SUCCESS; } /* Scan the directory */ D = opendir(source); if (D == 0) { _log_err(LOG_DEBUG, "unable to read directory %s",source); return PAM_PERM_DENIED; } for (Dir = readdir(D); Dir != 0; Dir = readdir(D)) { int SrcFd; int DestFd; int Res; struct stat St; char newsource[PATH_MAX], newdest[PATH_MAX]; /* Skip some files.. */ if (strcmp(Dir->d_name,".") == 0 || strcmp(Dir->d_name,"..") == 0) continue; /* Determine what kind of file it is. */ snprintf(newsource,sizeof(newsource),"%s/%s",source,Dir->d_name); if (lstat(newsource,&St) != 0) continue; /* We'll need the new file's name. */ snprintf(newdest,sizeof(newdest),"%s/%s",dest,Dir->d_name); /* If it's a directory, recurse. */ if (S_ISDIR(St.st_mode)) { create_homedir(pamh, ctrl, pwd, newsource, newdest); continue; } /* If it's a symlink, create a new link. */ if (S_ISLNK(St.st_mode)) { char pointed[PATH_MAX]; memset(pointed, 0, sizeof(pointed)); if(readlink(newsource, pointed, sizeof(pointed) - 1) != -1) { if(symlink(pointed, newdest) == 0) { if (lchown(newdest,pwd->pw_uid,pwd->pw_gid) != 0) { _log_err(LOG_DEBUG, "unable to chang perms on link %s", newdest); return PAM_PERM_DENIED; } } } continue; } /* If it's not a regular file, it's probably not a good idea to create * the new device node, FIFO, or whatever it is. */ if (!S_ISREG(St.st_mode)) { continue; } /* Open the source file */ if ((SrcFd = open(newsource,O_RDONLY)) < 0 || fstat(SrcFd,&St) != 0) { _log_err(LOG_DEBUG, "unable to open src file %s",newsource); return PAM_PERM_DENIED; } stat(newsource,&St); /* Open the dest file */ if ((DestFd = open(newdest,O_WRONLY | O_TRUNC | O_CREAT,0600)) < 0) { close(SrcFd); _log_err(LOG_DEBUG, "unable to open dest file %s",newdest); return PAM_PERM_DENIED; } /* Set the proper ownership and permissions for the module. We make the file a+w and then mask it with the set mask. This preseves execute bits */ if (fchmod(DestFd,(St.st_mode | 0222) & (~UMask)) != 0 || fchown(DestFd,pwd->pw_uid,pwd->pw_gid) != 0) { close(SrcFd); close(DestFd); _log_err(LOG_DEBUG, "unable to chang perms on copy %s",newdest); return PAM_PERM_DENIED; } /* Copy the file */ do { Res = read(SrcFd,remark,sizeof(remark)); if (Res < 0 || write(DestFd,remark,Res) != Res) { close(SrcFd); close(DestFd); _log_err(LOG_DEBUG, "unable to perform IO"); return PAM_PERM_DENIED; } } while (Res != 0); close(SrcFd); close(DestFd); } return PAM_SUCCESS; }
/* Do the actual work of creating a home dir */ static int create_homedir(const struct passwd *pwd, const char *source, const char *dest) { char remark[BUFSIZ]; DIR *d; struct dirent *dent; int retval = PAM_SESSION_ERR; /* Create the new directory */ if (rec_mkdir(dest, 0755) != 0) { pam_syslog(NULL, LOG_ERR, "unable to create directory %s: %m", dest); return PAM_PERM_DENIED; } /* See if we need to copy the skel dir over. */ if ((source == NULL) || (strlen(source) == 0)) { retval = PAM_SUCCESS; goto go_out; } /* Scan the directory */ d = opendir(source); if (d == NULL) { pam_syslog(NULL, LOG_DEBUG, "unable to read directory %s: %m", source); retval = PAM_PERM_DENIED; goto go_out; } for (dent = readdir(d); dent != NULL; dent = readdir(d)) { int srcfd; int destfd; int res; struct stat st; #ifndef PATH_MAX char *newsource = NULL, *newdest = NULL; /* track length of buffers */ int nslen = 0, ndlen = 0; int slen = strlen(source), dlen = strlen(dest); #else char newsource[PATH_MAX], newdest[PATH_MAX]; #endif /* Skip some files.. */ if (strcmp(dent->d_name,".") == 0 || strcmp(dent->d_name,"..") == 0) continue; /* Determine what kind of file it is. */ #ifndef PATH_MAX nslen = slen + strlen(dent->d_name) + 2; if (nslen <= 0) { retval = PAM_BUF_ERR; goto go_out; } if ((newsource = malloc(nslen)) == NULL) { retval = PAM_BUF_ERR; goto go_out; } sprintf(newsource, "%s/%s", source, dent->d_name); #else snprintf(newsource, sizeof(newsource), "%s/%s", source, dent->d_name); #endif if (lstat(newsource, &st) != 0) #ifndef PATH_MAX { free(newsource); newsource = NULL; continue; } #else continue; #endif /* We'll need the new file's name. */ #ifndef PATH_MAX ndlen = dlen + strlen(dent->d_name)+2; if (ndlen <= 0) { retval = PAM_BUF_ERR; goto go_out; } if ((newdest = malloc(ndlen)) == NULL) { free (newsource); retval = PAM_BUF_ERR; goto go_out; } sprintf (newdest, "%s/%s", dest, dent->d_name); #else snprintf (newdest, sizeof (newdest), "%s/%s", dest, dent->d_name); #endif /* If it's a directory, recurse. */ if (S_ISDIR(st.st_mode)) { retval = create_homedir(pwd, newsource, newdest); #ifndef PATH_MAX free(newsource); newsource = NULL; free(newdest); newdest = NULL; #endif if (retval != PAM_SUCCESS) { closedir(d); goto go_out; } continue; } /* If it's a symlink, create a new link. */ if (S_ISLNK(st.st_mode)) { int pointedlen = 0; #ifndef PATH_MAX char *pointed = NULL; { int size = 100; while (1) { pointed = malloc(size); if (pointed == NULL) { free(newsource); free(newdest); return PAM_BUF_ERR; } pointedlen = readlink(newsource, pointed, size); if (pointedlen < 0) break; if (pointedlen < size) break; free(pointed); size *= 2; } } if (pointedlen < 0) free(pointed); else pointed[pointedlen] = 0; #else char pointed[PATH_MAX]; memset(pointed, 0, sizeof(pointed)); pointedlen = readlink(newsource, pointed, sizeof(pointed) - 1); #endif if (pointedlen >= 0) { if(symlink(pointed, newdest) == 0) { if (lchown(newdest, pwd->pw_uid, pwd->pw_gid) != 0) { pam_syslog(NULL, LOG_DEBUG, "unable to change perms on link %s: %m", newdest); closedir(d); #ifndef PATH_MAX free(pointed); free(newsource); free(newdest); #endif return PAM_PERM_DENIED; } } #ifndef PATH_MAX free(pointed); #endif } #ifndef PATH_MAX free(newsource); newsource = NULL; free(newdest); newdest = NULL; #endif continue; } /* If it's not a regular file, it's probably not a good idea to create * the new device node, FIFO, or whatever it is. */ if (!S_ISREG(st.st_mode)) { #ifndef PATH_MAX free(newsource); newsource = NULL; free(newdest); newdest = NULL; #endif continue; } /* Open the source file */ if ((srcfd = open(newsource, O_RDONLY)) < 0 || fstat(srcfd, &st) != 0) { pam_syslog(NULL, LOG_DEBUG, "unable to open src file %s: %m", newsource); closedir(d); #ifndef PATH_MAX free(newsource); newsource = NULL; free(newdest); newdest = NULL; #endif return PAM_PERM_DENIED; } if (stat(newsource, &st) != 0) { pam_syslog(NULL, LOG_DEBUG, "unable to stat src file %s: %m", newsource); close(srcfd); closedir(d); #ifndef PATH_MAX free(newsource); newsource = NULL; free(newdest); newdest = NULL; #endif return PAM_PERM_DENIED; } /* Open the dest file */ if ((destfd = open(newdest, O_WRONLY | O_TRUNC | O_CREAT, 0600)) < 0) { pam_syslog(NULL, LOG_DEBUG, "unable to open dest file %s: %m", newdest); close(srcfd); closedir(d); #ifndef PATH_MAX free(newsource); newsource = NULL; free(newdest); newdest = NULL; #endif return PAM_PERM_DENIED; } /* Set the proper ownership and permissions for the module. We make the file a+w and then mask it with the set mask. This preseves execute bits */ if (fchmod(destfd, (st.st_mode | 0222) & (~u_mask)) != 0 || fchown(destfd, pwd->pw_uid, pwd->pw_gid) != 0) { pam_syslog(NULL, LOG_DEBUG, "unable to change perms on copy %s: %m", newdest); close(srcfd); close(destfd); closedir(d); #ifndef PATH_MAX free(newsource); newsource = NULL; free(newdest); newdest = NULL; #endif return PAM_PERM_DENIED; } /* Copy the file */ do { res = pam_modutil_read(srcfd, remark, sizeof(remark)); if (res == 0) continue; if (res > 0) { if (pam_modutil_write(destfd, remark, res) == res) continue; } /* If we get here, pam_modutil_read returned a -1 or pam_modutil_write returned something unexpected. */ pam_syslog(NULL, LOG_DEBUG, "unable to perform IO: %m"); close(srcfd); close(destfd); closedir(d); #ifndef PATH_MAX free(newsource); newsource = NULL; free(newdest); newdest = NULL; #endif return PAM_PERM_DENIED; } while (res != 0); close(srcfd); close(destfd); #ifndef PATH_MAX free(newsource); newsource = NULL; free(newdest); newdest = NULL; #endif } closedir(d); retval = PAM_SUCCESS; go_out: if (chmod(dest, 0777 & (~u_mask)) != 0 || chown(dest, pwd->pw_uid, pwd->pw_gid) != 0) { pam_syslog(NULL, LOG_DEBUG, "unable to change perms on directory %s: %m", dest); return PAM_PERM_DENIED; } return retval; }
/* * IMAPFilter: an IMAP mail filtering utility. */ int main(int argc, char *argv[]) { int c; char *cafile = NULL, *capath = NULL; setlocale(LC_CTYPE, ""); opts.verbose = 0; opts.interactive = 0; opts.log = NULL; opts.config = NULL; opts.oneline = NULL; opts.debug = NULL; opts.truststore = NULL; if (exists_dir("/etc/ssl/certs")) opts.truststore = "/etc/ssl/certs"; else if (exists_file("/etc/ssl/cert.pem")) opts.truststore = "/etc/ssl/cert.pem"; env.home = NULL; env.pathmax = -1; while ((c = getopt(argc, argv, "Vc:d:e:il:t:v?")) != -1) { switch (c) { case 'V': version(); /* NOTREACHED */ break; case 'c': opts.config = optarg; break; case 'd': opts.debug = optarg; break; case 'e': opts.oneline = optarg; break; case 'i': opts.interactive = 1; break; case 'l': opts.log = optarg; break; case 't': opts.truststore = optarg; break; case 'v': opts.verbose = 1; break; case '?': default: usage(); /* NOTREACHED */ break; } } get_pathmax(); open_debug(); create_homedir(); catch_signals(); open_log(); if (opts.config == NULL) opts.config = get_filepath("config.lua"); buffer_init(&ibuf, INPUT_BUF); buffer_init(&obuf, OUTPUT_BUF); buffer_init(&nbuf, NAMESPACE_BUF); buffer_init(&cbuf, CONVERSION_BUF); regexp_compile(responses); SSL_library_init(); SSL_load_error_strings(); ssl3ctx = SSL_CTX_new(SSLv3_client_method()); ssl23ctx = SSL_CTX_new(SSLv23_client_method()); tls1ctx = SSL_CTX_new(TLSv1_client_method()); #if OPENSSL_VERSION_NUMBER >= 0x01000100fL tls11ctx = SSL_CTX_new(TLSv1_1_client_method()); tls12ctx = SSL_CTX_new(TLSv1_2_client_method()); #endif if (exists_dir(opts.truststore)) capath = opts.truststore; else if (exists_file(opts.truststore)) cafile = opts.truststore; SSL_CTX_load_verify_locations(ssl3ctx, cafile, capath); SSL_CTX_load_verify_locations(ssl23ctx, cafile, capath); SSL_CTX_load_verify_locations(tls1ctx, cafile, capath); #if OPENSSL_VERSION_NUMBER >= 0x01000100fL SSL_CTX_load_verify_locations(tls11ctx, cafile, capath); SSL_CTX_load_verify_locations(tls12ctx, cafile, capath); #endif start_lua(); #if LUA_VERSION_NUM < 502 { list *l; session *s; l = sessions; while (l != NULL) { s = l->data; l = l->next; request_logout(s); } } #endif stop_lua(); SSL_CTX_free(ssl3ctx); SSL_CTX_free(ssl23ctx); SSL_CTX_free(tls1ctx); #if OPENSSL_VERSION_NUMBER >= 0x01000100fL SSL_CTX_free(tls11ctx); SSL_CTX_free(tls12ctx); #endif ERR_free_strings(); regexp_free(responses); buffer_free(&ibuf); buffer_free(&obuf); buffer_free(&nbuf); buffer_free(&cbuf); xfree(env.home); close_log(); close_debug(); exit(0); }
/* * IMAPFilter: an IMAP mail filtering utility. */ int main(int argc, char *argv[]) { int c; setlocale(LC_CTYPE, ""); opts.verbose = 0; opts.interactive = 0; opts.log = NULL; opts.config = NULL; opts.oneline = NULL; opts.debug = NULL; env.home = NULL; env.pathmax = -1; while ((c = getopt(argc, argv, "Vc:d:e:il:v?")) != -1) { switch (c) { case 'V': version(); /* NOTREACHED */ break; case 'c': opts.config = optarg; break; case 'd': opts.debug = optarg; break; case 'e': opts.oneline = optarg; break; case 'i': opts.interactive = 1; break; case 'l': opts.log = optarg; break; case 'v': opts.verbose = 1; break; case '?': default: usage(); /* NOTREACHED */ break; } } get_pathmax(); open_debug(); create_homedir(); catch_signals(); open_log(); if (opts.config == NULL) opts.config = get_filepath("config.lua"); buffer_init(&ibuf, INPUT_BUF); buffer_init(&obuf, OUTPUT_BUF); buffer_init(&nbuf, NAMESPACE_BUF); buffer_init(&cbuf, CONVERSION_BUF); regexp_compile(responses); SSL_library_init(); SSL_load_error_strings(); start_lua(); #if LUA_VERSION_NUM < 502 { list *l; session *s; l = sessions; while (l != NULL) { s = l->data; l = l->next; request_logout(s); } } #endif stop_lua(); ERR_free_strings(); regexp_free(responses); buffer_free(&ibuf); buffer_free(&obuf); buffer_free(&nbuf); buffer_free(&cbuf); xfree(env.home); close_log(); close_debug(); exit(0); }