BSD 4_4_Lite1 release
[unix-history] / usr / src / usr.sbin / sendmail / src / main.c
index 05f8715..e2af9df 100644 (file)
@@ -3,7 +3,33 @@
  * Copyright (c) 1988, 1993
  *     The Regents of the University of California.  All rights reserved.
  *
  * Copyright (c) 1988, 1993
  *     The Regents of the University of California.  All rights reserved.
  *
- * %sccs.include.redist.c%
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
  */
 
 #ifndef lint
  */
 
 #ifndef lint
@@ -13,14 +39,13 @@ static char copyright[] =
 #endif /* not lint */
 
 #ifndef lint
 #endif /* not lint */
 
 #ifndef lint
-static char sccsid[] = "@(#)main.c     8.28 (Berkeley) %G%";
+static char sccsid[] = "@(#)main.c     8.55 (Berkeley) 4/15/94";
 #endif /* not lint */
 
 #define        _DEFINE
 
 #include "sendmail.h"
 #endif /* not lint */
 
 #define        _DEFINE
 
 #include "sendmail.h"
-#include <sgtty.h>
-#ifdef NAMED_BIND
+#if NAMED_BIND
 #include <arpa/nameser.h>
 #include <resolv.h>
 #endif
 #include <arpa/nameser.h>
 #include <resolv.h>
 #endif
@@ -73,6 +98,7 @@ char          *UserEnviron[MAXUSERENVIRON + 2];
                                /* saved user environment */
 char           RealUserName[256];      /* the actual user id on this host */
 char           *CommandLineArgs;       /* command line args for pid file */
                                /* saved user environment */
 char           RealUserName[256];      /* the actual user id on this host */
 char           *CommandLineArgs;       /* command line args for pid file */
+bool           Warn_Q_option = FALSE;  /* warn about Q option use */
 
 /*
 **  Pointers for setproctitle.
 
 /*
 **  Pointers for setproctitle.
@@ -101,7 +127,6 @@ main(argc, argv, envp)
 {
        register char *p;
        char **av;
 {
        register char *p;
        char **av;
-       char *locname;
        extern int finis();
        extern char Version[];
        char *ep, *from;
        extern int finis();
        extern char Version[];
        char *ep, *from;
@@ -111,6 +136,8 @@ main(argc, argv, envp)
        int j;
        bool queuemode = FALSE;         /* process queue requests */
        bool safecf = TRUE;
        int j;
        bool queuemode = FALSE;         /* process queue requests */
        bool safecf = TRUE;
+       bool warn_C_flag = FALSE;
+       char warn_f_flag = '\0';
        static bool reenter = FALSE;
        char *argv0 = argv[0];
        struct passwd *pw;
        static bool reenter = FALSE;
        char *argv0 = argv[0];
        struct passwd *pw;
@@ -127,6 +154,7 @@ main(argc, argv, envp)
        extern char *getcfname();
        extern char *optarg;
        extern char **environ;
        extern char *getcfname();
        extern char *optarg;
        extern char **environ;
+       extern void sigusr1();
 
        /*
        **  Check to see if we reentered.
 
        /*
        **  Check to see if we reentered.
@@ -140,8 +168,14 @@ main(argc, argv, envp)
                abort();
        }
        reenter = TRUE;
                abort();
        }
        reenter = TRUE;
-       extern ADDRESS *recipient();
-       bool canrename;
+
+       /* do machine-dependent initializations */
+       init_md(argc, argv);
+
+       /* arrange to dump state on signal */
+#ifdef SIGUSR1
+       setsignal(SIGUSR1, sigusr1);
+#endif
 
        /* in 4.4BSD, the table can be huge; impose a reasonable limit */
        DtableSize = getdtsize();
 
        /* in 4.4BSD, the table can be huge; impose a reasonable limit */
        DtableSize = getdtsize();
@@ -153,7 +187,7 @@ main(argc, argv, envp)
        **      But also be sure that 0, 1, & 2 are open.
        */
 
        **      But also be sure that 0, 1, & 2 are open.
        */
 
-       i = open("/dev/null", O_RDWR);
+       i = open("/dev/null", O_RDWR, 0);
        if (fstat(STDIN_FILENO, &stb) < 0 && errno != EOPNOTSUPP)
                (void) dup2(i, STDIN_FILENO);
        if (fstat(STDOUT_FILENO, &stb) < 0 && errno != EOPNOTSUPP)
        if (fstat(STDIN_FILENO, &stb) < 0 && errno != EOPNOTSUPP)
                (void) dup2(i, STDIN_FILENO);
        if (fstat(STDOUT_FILENO, &stb) < 0 && errno != EOPNOTSUPP)
@@ -171,10 +205,12 @@ main(argc, argv, envp)
        }
        errno = 0;
 
        }
        errno = 0;
 
-#ifdef LOG_MAIL
+#ifdef LOG
+# ifdef LOG_MAIL
        openlog("sendmail", LOG_PID, LOG_MAIL);
        openlog("sendmail", LOG_PID, LOG_MAIL);
-#else 
+# else 
        openlog("sendmail", LOG_PID);
        openlog("sendmail", LOG_PID);
+# endif
 #endif 
 
        /* set up the blank envelope */
 #endif 
 
        /* set up the blank envelope */
@@ -182,8 +218,8 @@ main(argc, argv, envp)
        BlankEnvelope.e_putbody = putbody;
        BlankEnvelope.e_xfp = NULL;
        STRUCTCOPY(NullAddress, BlankEnvelope.e_from);
        BlankEnvelope.e_putbody = putbody;
        BlankEnvelope.e_xfp = NULL;
        STRUCTCOPY(NullAddress, BlankEnvelope.e_from);
-       STRUCTCOPY(BlankEnvelope, MainEnvelope);
-       CurEnv = &MainEnvelope;
+       CurEnv = &BlankEnvelope;
+       STRUCTCOPY(NullAddress, MainEnvelope.e_from);
 
        /*
        **  Set default values for variables.
 
        /*
        **  Set default values for variables.
@@ -224,12 +260,15 @@ main(argc, argv, envp)
 
 #if defined(__osf__) || defined(_AIX3)
 # define OPTIONS       "B:b:C:cd:e:F:f:h:Iimno:p:q:r:sTtvX:x"
 
 #if defined(__osf__) || defined(_AIX3)
 # define OPTIONS       "B:b:C:cd:e:F:f:h:Iimno:p:q:r:sTtvX:x"
-#else
-# if defined(ultrix)
-#  define OPTIONS      "B:b:C:cd:e:F:f:h:IiM:mno:p:q:r:sTtvX:"
-# else
-#  define OPTIONS      "B:b:C:cd:e:F:f:h:Iimno:p:q:r:sTtvX:"
-# endif
+#endif
+#if defined(ultrix)
+# define OPTIONS       "B:b:C:cd:e:F:f:h:IiM:mno:p:q:r:sTtvX:"
+#endif
+#if defined(NeXT)
+# define OPTIONS       "B:b:C:cd:e:F:f:h:IimnOo:p:q:r:sTtvX:"
+#endif
+#ifndef OPTIONS
+# define OPTIONS       "B:b:C:cd:e:F:f:h:Iimno:p:q:r:sTtvX:"
 #endif
        while ((j = getopt(argc, argv, OPTIONS)) != EOF)
        {
 #endif
        while ((j = getopt(argc, argv, OPTIONS)) != EOF)
        {
@@ -283,7 +322,7 @@ main(argc, argv, envp)
        OpMode = MD_DELIVER;
        FullName = getenv("NAME");
 
        OpMode = MD_DELIVER;
        FullName = getenv("NAME");
 
-#ifdef NAMED_BIND
+#if NAMED_BIND
        if (tTd(8, 8))
                _res.options |= RES_DEBUG;
 #endif
        if (tTd(8, 8))
                _res.options |= RES_DEBUG;
 #endif
@@ -305,10 +344,9 @@ main(argc, argv, envp)
 
                if (tTd(0, 4))
                        printf("canonical name: %s\n", jbuf);
 
                if (tTd(0, 4))
                        printf("canonical name: %s\n", jbuf);
-               p = newstr(jbuf);
                define('w', newstr(jbuf), CurEnv);      /* must be new string */
                define('w', newstr(jbuf), CurEnv);      /* must be new string */
-               define('j', p, CurEnv);
-               setclass('w', p);
+               define('j', newstr(jbuf), CurEnv);
+               setclass('w', jbuf);
 
                p = strchr(jbuf, '.');
                if (p != NULL)
 
                p = strchr(jbuf, '.');
                if (p != NULL)
@@ -331,6 +369,8 @@ main(argc, argv, envp)
                        p = utsname.nodename;
                else
                {
                        p = utsname.nodename;
                else
                {
+                       if (tTd(0, 22))
+                               printf("uname failed (%s)\n", errstring(errno));
                        makelower(jbuf);
                        p = jbuf;
                }
                        makelower(jbuf);
                        p = jbuf;
                }
@@ -338,6 +378,7 @@ main(argc, argv, envp)
                        printf("UUCP nodename: %s\n", p);
                p = newstr(p);
                define('k', p, CurEnv);
                        printf("UUCP nodename: %s\n", p);
                p = newstr(p);
                define('k', p, CurEnv);
+               setclass('k', p);
                setclass('w', p);
        }
        while (av != NULL && *av != NULL)
                setclass('w', p);
        }
        while (av != NULL && *av != NULL)
@@ -403,6 +444,9 @@ main(argc, argv, envp)
                          case MD_TEST:
                          case MD_INITALIAS:
                          case MD_PRINT:
                          case MD_TEST:
                          case MD_INITALIAS:
                          case MD_PRINT:
+#ifdef MAYBE_NEXT_RELEASE
+                         case MD_ARPAFTP:
+#endif
                                OpMode = j;
                                break;
 
                                OpMode = j;
                                break;
 
@@ -424,9 +468,7 @@ main(argc, argv, envp)
 
                  case 'C':     /* select configuration file (already done) */
                        if (RealUid != 0)
 
                  case 'C':     /* select configuration file (already done) */
                        if (RealUid != 0)
-                               auth_warning(CurEnv,
-                                       "Processed by %s with -C %s",
-                                       RealUserName, optarg);
+                               warn_C_flag = TRUE;
                        ConfFile = optarg;
                        (void) setgid(RealGid);
                        (void) setuid(RealUid);
                        ConfFile = optarg;
                        (void) setgid(RealGid);
                        (void) setuid(RealUid);
@@ -446,9 +488,7 @@ main(argc, argv, envp)
                        }
                        from = newstr(optarg);
                        if (strcmp(RealUserName, from) != 0)
                        }
                        from = newstr(optarg);
                        if (strcmp(RealUserName, from) != 0)
-                               auth_warning(CurEnv,
-                                       "%s set sender to %s using -%c",
-                                       RealUserName, from, j);
+                               warn_f_flag = j;
                        break;
 
                  case 'F':     /* set full name */
                        break;
 
                  case 'F':     /* set full name */
@@ -561,6 +601,10 @@ main(argc, argv, envp)
                  case 'x':     /* random flag that OSF/1 & AIX mailx passes */
                        break;
 # endif
                  case 'x':     /* random flag that OSF/1 & AIX mailx passes */
                        break;
 # endif
+# if defined(NeXT)
+                 case 'O':     /* random flag that NeXT Mail.app passes */
+                       break;
+# endif
 
                  default:
                        ExitStat = EX_USAGE;
 
                  default:
                        ExitStat = EX_USAGE;
@@ -576,6 +620,9 @@ main(argc, argv, envp)
        **      Extract special fields for local use.
        */
 
        **      Extract special fields for local use.
        */
 
+#ifdef XDEBUG
+       checkfd012("before readcf");
+#endif
        readcf(getcfname(), safecf, CurEnv);
 
        if (tTd(0, 1))
        readcf(getcfname(), safecf, CurEnv);
 
        if (tTd(0, 1))
@@ -592,6 +639,21 @@ main(argc, argv, envp)
                printf("\n");
        }
 
                printf("\n");
        }
 
+       /*
+       **  Process authorization warnings from command line.
+       */
+
+       if (warn_C_flag)
+               auth_warning(CurEnv, "Processed by %s with -C %s",
+                       RealUserName, ConfFile);
+/*
+       if (warn_f_flag != '\0')
+               auth_warning(CurEnv, "%s set sender to %s using -%c",
+                       RealUserName, from, warn_f_flag);
+*/
+       if (Warn_Q_option)
+               auth_warning(CurEnv, "Processed from queue %s", QueueDir);
+
        /* Enforce use of local time (null string overrides this) */
        if (TimeZoneSpec == NULL)
                unsetenv("TZ");
        /* Enforce use of local time (null string overrides this) */
        if (TimeZoneSpec == NULL)
                unsetenv("TZ");
@@ -650,13 +712,6 @@ main(argc, argv, envp)
                /* remove things that don't make sense in daemon mode */
                FullName = NULL;
                break;
                /* remove things that don't make sense in daemon mode */
                FullName = NULL;
                break;
-
-         case MD_SMTP:
-               if (RealUid != 0)
-                       auth_warning(CurEnv,
-                               "%s owned process doing -bs",
-                               RealUserName);
-               break;
        }
 
        /* do heuristic mode adjustment */
        }
 
        /* do heuristic mode adjustment */
@@ -721,6 +776,10 @@ main(argc, argv, envp)
                exit(ExitStat);
        }
 
                exit(ExitStat);
        }
 
+#ifdef XDEBUG
+       checkfd012("before main() initmaps");
+#endif
+
        /*
        **  Do operation-mode-dependent initialization.
        */
        /*
        **  Do operation-mode-dependent initialization.
        */
@@ -819,6 +878,7 @@ main(argc, argv, envp)
                        char *q;
                        auto char *delimptr;
                        extern bool invalidaddr();
                        char *q;
                        auto char *delimptr;
                        extern bool invalidaddr();
+                       extern char *crackaddr();
 
                        if (Verbose)
                                printf("> ");
 
                        if (Verbose)
                                printf("> ");
@@ -827,8 +887,20 @@ main(argc, argv, envp)
                                finis();
                        if (!Verbose)
                                printf("> %s", buf);
                                finis();
                        if (!Verbose)
                                printf("> %s", buf);
-                       if (buf[0] == '#')
+                       switch (buf[0])
+                       {
+                         case '#':
                                continue;
                                continue;
+
+#ifdef MAYBENEXTRELEASE
+                         case 'C':             /* try crackaddr */
+                               q = crackaddr(&buf[1]);
+                               xputs(q);
+                               printf("\n");
+                               continue;
+#endif
+                       }
+
                        for (p = buf; isascii(*p) && isspace(*p); p++)
                                continue;
                        q = p;
                        for (p = buf; isascii(*p) && isspace(*p); p++)
                                continue;
                        q = p;
@@ -840,13 +912,14 @@ main(argc, argv, envp)
                                continue;
                        }
                        *p = '\0';
                                continue;
                        }
                        *p = '\0';
-                       if (invalidaddr(p + 1))
+                       if (invalidaddr(p + 1, NULL))
                                continue;
                        do
                        {
                                char pvpbuf[PSBUFSIZE];
 
                                continue;
                        do
                        {
                                char pvpbuf[PSBUFSIZE];
 
-                               pvp = prescan(++p, ',', pvpbuf, &delimptr);
+                               pvp = prescan(++p, ',', pvpbuf, sizeof pvpbuf,
+                                             &delimptr);
                                if (pvp == NULL)
                                        continue;
                                p = q;
                                if (pvp == NULL)
                                        continue;
                                p = q;
@@ -854,7 +927,7 @@ main(argc, argv, envp)
                                {
                                        int stat;
 
                                {
                                        int stat;
 
-                                       stat = rewrite(pvp, atoi(p), CurEnv);
+                                       stat = rewrite(pvp, atoi(p), 0, CurEnv);
                                        if (stat != EX_OK)
                                                printf("== Ruleset %s status %d\n",
                                                        p, stat);
                                        if (stat != EX_OK)
                                                printf("== Ruleset %s status %d\n",
                                                        p, stat);
@@ -914,7 +987,9 @@ main(argc, argv, envp)
                if (tTd(0, 1))
                        strcat(dtype, "+debugging");
 
                if (tTd(0, 1))
                        strcat(dtype, "+debugging");
 
+#ifdef LOG
                syslog(LOG_INFO, "starting daemon (%s): %s", Version, dtype + 1);
                syslog(LOG_INFO, "starting daemon (%s): %s", Version, dtype + 1);
+#endif
 #ifdef XLA
                xla_create_file();
 #endif
 #ifdef XLA
                xla_create_file();
 #endif
@@ -952,7 +1027,7 @@ main(argc, argv, envp)
        **  commands.  This will never return.
        */
 
        **  commands.  This will never return.
        */
 
-       if (OpMode == MD_SMTP)
+       if (OpMode == MD_SMTP || OpMode == MD_DAEMON)
                smtp(CurEnv);
 # endif /* SMTP */
 
                smtp(CurEnv);
 # endif /* SMTP */
 
@@ -1052,6 +1127,8 @@ finis()
                printf("\n====finis: stat %d e_flags %o, e_id=%s\n",
                        ExitStat, CurEnv->e_flags,
                        CurEnv->e_id == NULL ? "NOQUEUE" : CurEnv->e_id);
                printf("\n====finis: stat %d e_flags %o, e_id=%s\n",
                        ExitStat, CurEnv->e_flags,
                        CurEnv->e_id == NULL ? "NOQUEUE" : CurEnv->e_id);
+       if (tTd(2, 9))
+               printopenfds(FALSE);
 
        /* clean up temp files */
        CurEnv->e_to = NULL;
 
        /* clean up temp files */
        CurEnv->e_to = NULL;
@@ -1133,7 +1210,6 @@ struct metamac    MetaMacros[] =
        /* these are RHS metasymbols */
        '#', CANONNET,          '@', CANONHOST,         ':', CANONUSER,
        '>', CALLSUBR,
        /* these are RHS metasymbols */
        '#', CANONNET,          '@', CANONHOST,         ':', CANONUSER,
        '>', CALLSUBR,
-       '{', MATCHLOOKUP,               '}', MATCHELOOKUP,
 
        /* the conditional operations */
        '?', CONDIF,            '|', CONDELSE,          '.', CONDFI,
 
        /* the conditional operations */
        '?', CONDIF,            '|', CONDELSE,          '.', CONDFI,
@@ -1220,6 +1296,7 @@ disconnect(droplev, e)
        HoldErrs = TRUE;
        CurEnv->e_errormode = EM_MAIL;
        Verbose = FALSE;
        HoldErrs = TRUE;
        CurEnv->e_errormode = EM_MAIL;
        Verbose = FALSE;
+       DisConnected = TRUE;
 
        /* all input from /dev/null */
        if (InChannel != stdin)
 
        /* all input from /dev/null */
        if (InChannel != stdin)
@@ -1271,7 +1348,8 @@ static void
 obsolete(argv)
        char *argv[];
 {
 obsolete(argv)
        char *argv[];
 {
-       char *ap;
+       register char *ap;
+       register char *op;
 
        while ((ap = *++argv) != NULL)
        {
 
        while ((ap = *++argv) != NULL)
        {
@@ -1279,10 +1357,18 @@ obsolete(argv)
                if (ap[0] != '-' || ap[1] == '-')
                        return;
 
                if (ap[0] != '-' || ap[1] == '-')
                        return;
 
+               /* skip over options that do have a value */
+               op = strchr(OPTIONS, ap[1]);
+               if (op != NULL && *++op == ':' && ap[2] == '\0' &&
+                   ap[1] != 'd' && argv[1] != NULL && argv[1][0] != '-')
+               {
+                       argv++;
+                       continue;
+               }
+
                /* If -C doesn't have an argument, use sendmail.cf. */
 #define        __DEFPATH       "sendmail.cf"
                /* If -C doesn't have an argument, use sendmail.cf. */
 #define        __DEFPATH       "sendmail.cf"
-               if (ap[1] == 'C' && ap[2] == '\0' &&
-                   (argv[1] == NULL || argv[1][0] == '-'))
+               if (ap[1] == 'C' && ap[2] == '\0')
                {
                        *argv = xalloc(sizeof(__DEFPATH) + 2);
                        argv[0][0] = '-';
                {
                        *argv = xalloc(sizeof(__DEFPATH) + 2);
                        argv[0][0] = '-';
@@ -1291,13 +1377,11 @@ obsolete(argv)
                }
 
                /* If -q doesn't have an argument, run it once. */
                }
 
                /* If -q doesn't have an argument, run it once. */
-               if (ap[1] == 'q' && ap[2] == '\0' &&
-                   (argv[1] == NULL || argv[1][0] == '-'))
+               if (ap[1] == 'q' && ap[2] == '\0')
                        *argv = "-q0";
 
                /* if -d doesn't have an argument, use 0-99.1 */
                        *argv = "-q0";
 
                /* if -d doesn't have an argument, use 0-99.1 */
-               if (ap[1] == 'd' && ap[2] == '\0' &&
-                   (argv[1] == NULL || !isdigit(argv[1][0])))
+               if (ap[1] == 'd' && ap[2] == '\0')
                        *argv = "-d0-99.1";
        }
 }
                        *argv = "-d0-99.1";
        }
 }
@@ -1343,3 +1427,53 @@ auth_warning(e, msg, va_alist)
                addheader("X-Authentication-Warning", buf, e);
        }
 }
                addheader("X-Authentication-Warning", buf, e);
        }
 }
+\f/*
+**  DUMPSTATE -- dump state
+**
+**     For debugging.
+*/
+
+void
+dumpstate(when)
+       char *when;
+{
+#ifdef LOG
+       register char *j = macvalue('j', CurEnv);
+       register STAB *s;
+
+       syslog(LOG_DEBUG, "--- dumping state on %s: $j = %s ---",
+               when,
+               j == NULL ? "<NULL>" : j);
+       if (j != NULL)
+       {
+               s = stab(j, ST_CLASS, ST_FIND);
+               if (s == NULL || !bitnset('w', s->s_class))
+                       syslog(LOG_DEBUG, "*** $j not in $=w ***");
+       }
+       syslog(LOG_DEBUG, "--- open file descriptors: ---");
+       printopenfds(TRUE);
+       syslog(LOG_DEBUG, "--- connection cache: ---");
+       mci_dump_all(TRUE);
+       if (RewriteRules[89] != NULL)
+       {
+               int stat;
+               register char **pvp;
+               char *pv[MAXATOM + 1];
+
+               pv[0] = NULL;
+               stat = rewrite(pv, 89, 0, CurEnv);
+               syslog(LOG_DEBUG, "--- ruleset 89 returns stat %d, pv: ---",
+                       stat);
+               for (pvp = pv; *pvp != NULL; pvp++)
+                       syslog(LOG_DEBUG, "%s", *pvp);
+       }
+       syslog(LOG_DEBUG, "--- end of state dump ---");
+#endif
+}
+
+
+void
+sigusr1()
+{
+       dumpstate("user signal");
+}